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

Last change on this file since 9282 was 9282, checked in by livings124, 13 years ago

update to miniupnpc-20091010

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