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