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

Last change on this file since 3731 was 3731, checked in by charles, 14 years ago

use Thomas Bernard's miniupnp library instead of rolling our own.

File size: 5.0 KB
Line 
1/* $Id: miniwget.c,v 1.19 2007/11/02 14:16:19 nanard Exp $ */
2/* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005 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/socket.h>
24#include <netdb.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27#define closesocket close
28#endif
29/* for MIN() macro : */
30#if defined(__sun) || defined(sun)
31#include <utility.h>
32#endif
33
34/* miniwget2() :
35 * */
36static void *
37miniwget2(const char * url, const char * host,
38                  unsigned short port, const char * path,
39                  int * size, char * addr_str, int addr_str_len)
40{
41        char buf[2048];
42    int s;
43        struct sockaddr_in dest;
44        struct hostent *hp;
45        *size = 0;
46        hp = gethostbyname(host);
47        if(hp==NULL)
48        {
49                herror(host);
50                return NULL;
51        }
52        /*  memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length);  */
53        memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
54        memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
55        s = socket(PF_INET, SOCK_STREAM, 0);
56        if(s < 0)
57        {
58                perror("socket");
59                return NULL;
60        }
61        dest.sin_family = AF_INET;
62        dest.sin_port = htons(port);
63        if(connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in))<0)
64        {
65                perror("connect");
66                closesocket(s);
67                return NULL;
68        }
69
70        /* get address for caller ! */
71        if(addr_str)
72        {
73                struct sockaddr_in saddr;
74                socklen_t len;
75
76                len = sizeof(saddr);
77                getsockname(s, (struct sockaddr *)&saddr, &len);
78#ifndef WIN32
79                inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
80#else
81        /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
82     * But his function make a string with the port :  nn.nn.nn.nn:port */
83/*              if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
84                            NULL, addr_str, (DWORD *)&addr_str_len))
85                {
86                    printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
87                }*/
88                strncpy(addr_str, inet_ntoa(saddr.sin_addr), addr_str_len);
89#endif
90#ifdef DEBUG
91                printf("address miniwget : %s\n", addr_str);
92#endif
93        }
94
95        snprintf(buf, sizeof(buf),
96                 "GET %s HTTP/1.1\r\n"
97                             "Host: %s:%d\r\n"
98                                 "Connection: Close\r\n"
99                                 "\r\n",
100                    path, host, port);
101        /*write(s, buf, strlen(buf));*/
102        send(s, buf, strlen(buf), 0);
103        {
104                int n, headers=1;
105                char * respbuffer = NULL;
106                int allreadyread = 0;
107                /*while((n = recv(s, buf, 2048, 0)) > 0)*/
108                while((n = ReceiveData(s, buf, 2048, 5000)) > 0)
109                {
110                        if(headers)
111                        {
112                                int i=0;
113                                while(i<n-3)
114                                {
115                                        if(buf[i]=='\r' && buf[i+1]=='\n'
116                                           && buf[i+2]=='\r' && buf[i+3]=='\n')
117                                        {
118                                                headers = 0;    /* end */
119                                                if(i<n-4)
120                                                {
121                                                        respbuffer = (char *)realloc((void *)respbuffer, 
122                                                                                                                 allreadyread+(n-i-4));
123                                                        memcpy(respbuffer+allreadyread, buf + i + 4, n-i-4);
124                                                        allreadyread += (n-i-4);
125                                                }
126                                                break;
127                                        }
128                                        i++;
129                                }
130                        }
131                        else
132                        {
133                                respbuffer = (char *)realloc((void *)respbuffer, 
134                                                                 allreadyread+n);
135                                memcpy(respbuffer+allreadyread, buf, n);
136                                allreadyread += n;
137                        }
138                }
139                *size = allreadyread;
140#ifndef NDEBUG
141                printf("%d bytes read\n", *size);
142#endif
143                closesocket(s);
144                return respbuffer;
145        }
146}
147
148/* parseURL()
149 * arguments :
150 *   url :              source string not modified
151 *   hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
152 *   port :             port (destination)
153 *   path :             pointer to the path part of the URL
154 *
155 * Return values :
156 *    0 - Failure
157 *    1 - Success         */
158int parseURL(const char * url, char * hostname, unsigned short * port, char * * path)
159{
160        char * p1, *p2, *p3;
161        p1 = strstr(url, "://");
162        if(!p1)
163                return 0;
164        p1 += 3;
165        if(  (url[0]!='h') || (url[1]!='t')
166           ||(url[2]!='t') || (url[3]!='p'))
167                return 0;
168        p2 = strchr(p1, ':');
169        p3 = strchr(p1, '/');
170        if(!p3)
171                return 0;
172        memset(hostname, 0, MAXHOSTNAMELEN + 1);
173        if(!p2 || (p2>p3))
174        {
175                strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
176                *port = 80;
177        }
178        else
179        {
180                strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
181                *port = 0;
182                p2++;
183                while( (*p2 >= '0') && (*p2 <= '9'))
184                {
185                        *port *= 10;
186                        *port += (unsigned short)(*p2 - '0');
187                        p2++;
188                }
189        }
190        *path = p3;
191        return 1;
192}
193
194void * miniwget(const char * url, int * size)
195{
196        unsigned short port;
197        char * path;
198        /* protocol://host:port/chemin */
199        char hostname[MAXHOSTNAMELEN+1];
200        *size = 0;
201        if(!parseURL(url, hostname, &port, &path))
202                return NULL;
203        return miniwget2(url, hostname, port, path, size, 0, 0);
204}
205
206void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
207{
208        unsigned short port;
209        char * path;
210        /* protocol://host:port/chemin */
211        char hostname[MAXHOSTNAMELEN+1];
212        *size = 0;
213        if(addr)
214                addr[0] = '\0';
215        if(!parseURL(url, hostname, &port, &path))
216                return NULL;
217        return miniwget2(url, hostname, port, path, size, addr, addrlen);
218}
219
Note: See TracBrowser for help on using the repository browser.