2
0

miniwget.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /* $Id: miniwget.c,v 1.22 2009/02/28 10:36:35 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. #if _MSC_VER < 1900
  18. #define snprintf _snprintf
  19. #endif
  20. #define herror
  21. #define socklen_t int
  22. #else
  23. #include <unistd.h>
  24. #include <sys/time.h>
  25. #include <sys/types.h>
  26. #include <sys/param.h>
  27. #include <sys/socket.h>
  28. #include <netdb.h>
  29. #include <netinet/in.h>
  30. #include <arpa/inet.h>
  31. #include <fcntl.h>
  32. #define closesocket close
  33. #endif
  34. #if defined(__sun) || defined(sun)
  35. #define MIN(x,y) (((x)<(y))?(x):(y))
  36. #endif
  37. #include "miniupnpcstrings.h"
  38. /* miniwget2() :
  39. * */
  40. static void *
  41. miniwget2(const char * url, const char * host,
  42. unsigned short port, const char * path,
  43. int * size, char * addr_str, int addr_str_len)
  44. {
  45. char buf[2048];
  46. #ifdef WIN32
  47. SOCKET s;
  48. #else
  49. int s;
  50. int fd_flags;
  51. #endif
  52. struct sockaddr_in dest;
  53. struct hostent *hp;
  54. *size = 0;
  55. hp = gethostbyname(host);
  56. if(hp==NULL)
  57. {
  58. herror(host);
  59. return NULL;
  60. }
  61. /* memcpy((char *)&dest.sin_addr, hp->h_addr, hp->h_length); */
  62. memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
  63. memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
  64. s = socket(PF_INET, SOCK_STREAM, 0);
  65. if(s < 0)
  66. {
  67. perror("socket");
  68. return NULL;
  69. }
  70. dest.sin_family = AF_INET;
  71. dest.sin_port = htons(port);
  72. {
  73. #ifdef WIN32
  74. u_long arg = 1;
  75. if (ioctlsocket((SOCKET) s, FIONBIO, &arg) == SOCKET_ERROR) {
  76. return NULL;
  77. }
  78. #else
  79. fd_flags = fcntl(s, F_GETFL, 0);
  80. if (fcntl(s, F_SETFL, fd_flags | O_NONBLOCK)) {
  81. return NULL;
  82. }
  83. #endif
  84. }
  85. connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
  86. {
  87. fd_set wfds;
  88. struct timeval tv = { 2, 0 };
  89. int r;
  90. FD_ZERO(&wfds);
  91. FD_SET(s, &wfds);
  92. r = select(s + 1, NULL, &wfds, NULL, &tv);
  93. if (r <= 0) {
  94. return NULL;
  95. }
  96. if (!FD_ISSET(s, &wfds)) {
  97. return NULL;
  98. }
  99. }
  100. #ifdef WIN32
  101. {
  102. u_long arg = 0;
  103. if (ioctlsocket((SOCKET) s, FIONBIO, &arg) == SOCKET_ERROR) {
  104. return NULL;
  105. }
  106. }
  107. #else
  108. fcntl(s, F_SETFL, fd_flags);
  109. #endif
  110. /* get address for caller ! */
  111. if(addr_str)
  112. {
  113. struct sockaddr_in saddr;
  114. socklen_t len;
  115. len = sizeof(saddr);
  116. getsockname(s, (struct sockaddr *)&saddr, &len);
  117. #ifndef WIN32
  118. inet_ntop(AF_INET, &saddr.sin_addr, addr_str, addr_str_len);
  119. #else
  120. /* using INT WINAPI WSAAddressToStringA(LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFOA, LPSTR, LPDWORD);
  121. * But his function make a string with the port : nn.nn.nn.nn:port */
  122. /* if(WSAAddressToStringA((SOCKADDR *)&saddr, sizeof(saddr),
  123. NULL, addr_str, (DWORD *)&addr_str_len))
  124. {
  125. printf("WSAAddressToStringA() failed : %d\n", WSAGetLastError());
  126. }*/
  127. strncpy(addr_str, inet_ntoa(saddr.sin_addr), addr_str_len);
  128. #endif
  129. #ifdef DEBUG
  130. printf("address miniwget : %s\n", addr_str);
  131. #endif
  132. }
  133. snprintf(buf, sizeof(buf),
  134. "GET %s HTTP/1.1\r\n"
  135. "Host: %s:%d\r\n"
  136. "Connection: Close\r\n"
  137. "User-Agent: " OS_STRING ", UPnP/1.0, MiniUPnPc/" MINIUPNPC_VERSION_STRING "\r\n"
  138. "\r\n",
  139. path, host, port);
  140. /*write(s, buf, strlen(buf));*/
  141. send(s, buf, strlen(buf), 0);
  142. {
  143. int n, headers=1;
  144. char * respbuffer = NULL;
  145. int allreadyread = 0;
  146. /*while((n = recv(s, buf, 2048, 0)) > 0)*/
  147. while((n = ReceiveData(s, buf, 2048, 5000)) > 0)
  148. {
  149. if(headers)
  150. {
  151. int i=0;
  152. while(i<n-3)
  153. {
  154. if(buf[i]=='\r' && buf[i+1]=='\n'
  155. && buf[i+2]=='\r' && buf[i+3]=='\n')
  156. {
  157. headers = 0; /* end */
  158. if(i<n-4)
  159. {
  160. respbuffer = (char *)realloc((void *)respbuffer,
  161. allreadyread+(n-i-4));
  162. memcpy(respbuffer+allreadyread, buf + i + 4, n-i-4);
  163. allreadyread += (n-i-4);
  164. }
  165. break;
  166. }
  167. i++;
  168. }
  169. }
  170. else
  171. {
  172. respbuffer = (char *)realloc((void *)respbuffer,
  173. allreadyread+n);
  174. memcpy(respbuffer+allreadyread, buf, n);
  175. allreadyread += n;
  176. }
  177. }
  178. *size = allreadyread;
  179. #ifdef DEBUG
  180. printf("%d bytes read\n", *size);
  181. #endif
  182. closesocket(s);
  183. return respbuffer;
  184. }
  185. }
  186. /* parseURL()
  187. * arguments :
  188. * url : source string not modified
  189. * hostname : hostname destination string (size of MAXHOSTNAMELEN+1)
  190. * port : port (destination)
  191. * path : pointer to the path part of the URL
  192. *
  193. * Return values :
  194. * 0 - Failure
  195. * 1 - Success */
  196. int parseURL(const char * url, char * hostname, unsigned short * port, char * * path)
  197. {
  198. char * p1, *p2, *p3;
  199. p1 = strstr(url, "://");
  200. if(!p1)
  201. return 0;
  202. p1 += 3;
  203. if( (url[0]!='h') || (url[1]!='t')
  204. ||(url[2]!='t') || (url[3]!='p'))
  205. return 0;
  206. p2 = strchr(p1, ':');
  207. p3 = strchr(p1, '/');
  208. if(!p3)
  209. return 0;
  210. memset(hostname, 0, MAXHOSTNAMELEN + 1);
  211. if(!p2 || (p2>p3))
  212. {
  213. strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1)));
  214. *port = 80;
  215. }
  216. else
  217. {
  218. strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1)));
  219. *port = 0;
  220. p2++;
  221. while( (*p2 >= '0') && (*p2 <= '9'))
  222. {
  223. *port *= 10;
  224. *port += (unsigned short)(*p2 - '0');
  225. p2++;
  226. }
  227. }
  228. *path = p3;
  229. return 1;
  230. }
  231. void * miniwget(const char * url, int * size)
  232. {
  233. unsigned short port;
  234. char * path;
  235. /* protocol://host:port/chemin */
  236. char hostname[MAXHOSTNAMELEN+1];
  237. *size = 0;
  238. if(!parseURL(url, hostname, &port, &path)) {
  239. return NULL;
  240. }
  241. return miniwget2(url, hostname, port, path, size, 0, 0);
  242. }
  243. void * miniwget_getaddr(const char * url, int * size, char * addr, int addrlen)
  244. {
  245. unsigned short port;
  246. char * path;
  247. /* protocol://host:port/chemin */
  248. char hostname[MAXHOSTNAMELEN+1];
  249. *size = 0;
  250. if(addr)
  251. addr[0] = '\0';
  252. if(!parseURL(url, hostname, &port, &path))
  253. return NULL;
  254. return miniwget2(url, hostname, port, path, size, addr, addrlen);
  255. }