source: trunk/third-party/miniupnp/miniwget.c @ 9167

Last change on this file since 9167 was 9167, checked in by charles, 13 years ago

(trunk third-party) get miniupnpc building again. the breakage has been reported upstream @ http://miniupnp.tuxfamily.org/forum/viewtopic.php?p=1452#1452

File size: 6.5 KB
Line 
1/* $Id: miniwget.c,v 1.26 2009/09/21 12:57:42 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005-2009 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution.
7 * */
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include "miniupnpc.h"
12#ifdef WIN32
13#include <winsock2.h>
14#include <io.h>
15#define MAXHOSTNAMELEN 64
16#define MIN(x,y) (((x)<(y))?(x):(y))
17#define snprintf _snprintf
18#define herror
19#define socklen_t int
20#else
21#include <unistd.h>
22#include <sys/param.h>
23#include <sys/select.h> /* fd_set */
24#include <sys/socket.h>
25#include <netdb.h>
26#include <netinet/in.h>
27#include <arpa/inet.h>
28#include <errno.h>
29#define closesocket close
30#define MINIUPNPC_IGNORE_EINTR
31#endif
32#if defined(__sun) || defined(sun)
33#define MIN(x,y) (((x)<(y))?(x):(y))
34#endif
35
36#include "miniupnpcstrings.h"
37#include "miniwget.h"
38
39/* miniwget2() :
40 * */
41static void *
42miniwget2(const char * url, const char * host,
43                  unsigned short port, const char * path,
44                  int * size, char * addr_str, int addr_str_len)
45{
46        char buf[2048];
47    int s;
48        struct sockaddr_in dest;
49        struct hostent *hp;
50        int n;
51        int len;
52        int sent;
53#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
54        struct timeval timeout;
55#endif
56        *size = 0;
57        hp = gethostbyname(host);
58        if(hp==NULL)
59        {
60                herror(host);
61                return NULL;
62        }
63        /*  memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length);  */
64        memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
65        memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
66        s = socket(PF_INET, SOCK_STREAM, 0);
67        if(s < 0)
68        {
69                perror("socket");
70                return NULL;
71        }
72#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
73        /* setting a 3 seconds timeout for the connect() call */
74        timeout.tv_sec = 3;
75        timeout.tv_usec = 0;
76        if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
77        {
78                perror("setsockopt");
79        }
80        timeout.tv_sec = 3;
81        timeout.tv_usec = 0;
82        if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
83        {
84                perror("setsockopt");
85        }
86#endif
87        dest.sin_family = AF_INET;
88        dest.sin_port = htons(port);
89        n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
90#ifdef MINIUPNPC_IGNORE_EINTR
91        while(n < 0 && errno == EINTR)
92        {
93                socklen_t len;
94                fd_set wset;
95                int err;
96                FD_ZERO(&wset);
97                FD_SET(s, &wset);
98                if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
99                        continue;
100                /*len = 0;*/
101                /*n = getpeername(s, NULL, &len);*/
102                len = sizeof(err);
103                if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
104                        perror("getsockopt");
105                        closesocket(s);
106                        return NULL;
107                }
108                if(err != 0) {
109                        errno = err;
110                        n = -1;
111                }
112        }
113#endif
114        if(n<0)
115        {
116                perror("connect");
117                closesocket(s);
118                return NULL;
119        }
120
121        /* get address for caller ! */
122        if(addr_str)
123        {
124                struct sockaddr_in saddr;
125                socklen_t saddrlen;
126
127                saddrlen = sizeof(saddr);
128                if(getsockname(s, (struct sockaddr *)&saddr, &saddrlen) < 0)
129                {
130                        perror("getsockname");
131                }
132                else
133                {
134#ifndef WIN32
135                        inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
136#else
137        /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
138     * But his function make a string with the port :  nn.nn.nn.nn:port */
139/*              if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
140                            NULL, addr_str, (DWORD *)&addr_str_len))
141                {
142                    printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
143                }*/
144                        strncpy(addr_str, inet_ntoa(saddr.sin_addr), addr_str_len);
145#endif
146                }
147#ifdef DEBUG
148                printf("address miniwget : %s\n", addr_str);
149#endif
150        }
151
152        len = snprintf(buf, sizeof(buf),
153                 "GET %s HTTP/1.1\r\n"
154                             "Host: %s:%d\r\n"
155                                 "Connection: Close\r\n"
156                                 "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
157
158                                 "\r\n",
159                    path, host, port);
160        sent = 0;
161        /* sending the HTTP request */
162        while(sent < len)
163        {
164                n = send(s, buf+sent, len-sent, 0);
165                if(n < 0)
166                {
167                        perror("send");
168                        closesocket(s);
169                        return NULL;
170                }
171                else
172                {
173                        sent += n;
174                }
175        }
176        {
177                int headers=1;
178                char * respbuffer = NULL;
179                int allreadyread = 0;
180                /*while((n = recv(s, buf, 2048, 0)) > 0)*/
181                while((n = ReceiveData(s, buf, 2048, 5000)) > 0)
182                {
183                        if(headers)
184                        {
185                                int i=0;
186                                while(i<n-3)
187                                {
188                                        /* searching for the end of the HTTP headers */
189                                        if(buf[i]=='\r' && buf[i+1]=='\n'
190                                           && buf[i+2]=='\r' && buf[i+3]=='\n')
191                                        {
192                                                headers = 0;    /* end */
193                                                if(i<n-4)
194                                                {
195                                                        /* Copy the content into respbuffet */
196                                                        respbuffer = (char *)realloc((void *)respbuffer, 
197                                                                                                                 allreadyread+(n-i-4));
198                                                        memcpy(respbuffer+allreadyread, buf + i + 4, n-i-4);
199                                                        allreadyread += (n-i-4);
200                                                }
201                                                break;
202                                        }
203                                        i++;
204                                }
205                        }
206                        else
207                        {
208                                respbuffer = (char *)realloc((void *)respbuffer, 
209                                                                 allreadyread+n);
210                                memcpy(respbuffer+allreadyread, buf, n);
211                                allreadyread += n;
212                        }
213                }
214                *size = allreadyread;
215#ifdef DEBUG
216                printf("%d bytes read\n", *size);
217#endif
218                closesocket(s);
219                return respbuffer;
220        }
221}
222
223/* parseURL()
224 * arguments :
225 *   url :              source string not modified
226 *   hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
227 *   port :             port (destination)
228 *   path :             pointer to the path part of the URL
229 *
230 * Return values :
231 *    0 - Failure
232 *    1 - Success         */
233int parseURL(const char * url, char * hostname, unsigned short * port, char * * path)
234{
235        char * p1, *p2, *p3;
236        p1 = strstr(url, "://");
237        if(!p1)
238                return 0;
239        p1 += 3;
240        if(  (url[0]!='h') || (url[1]!='t')
241           ||(url[2]!='t') || (url[3]!='p'))
242                return 0;
243        p2 = strchr(p1, ':');
244        p3 = strchr(p1, '/');
245        if(!p3)
246                return 0;
247        memset(hostname, 0, MAXHOSTNAMELEN + 1);
248        if(!p2 || (p2>p3))
249        {
250                strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
251                *port = 80;
252        }
253        else
254        {
255                strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
256                *port = 0;
257                p2++;
258                while( (*p2 >= '0') && (*p2 <= '9'))
259                {
260                        *port *= 10;
261                        *port += (unsigned short)(*p2 - '0');
262                        p2++;
263                }
264        }
265        *path = p3;
266        return 1;
267}
268
269void * miniwget(const char * url, int * size)
270{
271        unsigned short port;
272        char * path;
273        /* protocol://host:port/chemin */
274        char hostname[MAXHOSTNAMELEN+1];
275        *size = 0;
276        if(!parseURL(url, hostname, &port, &path))
277                return NULL;
278        return miniwget2(url, hostname, port, path, size, 0, 0);
279}
280
281void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
282{
283        unsigned short port;
284        char * path;
285        /* protocol://host:port/chemin */
286        char hostname[MAXHOSTNAMELEN+1];
287        *size = 0;
288        if(addr)
289                addr[0] = '\0';
290        if(!parseURL(url, hostname, &port, &path))
291                return NULL;
292        return miniwget2(url, hostname, port, path, size, addr, addrlen);
293}
294
Note: See TracBrowser for help on using the repository browser.