Mercurial > pidgin.yaz
comparison src/upnp.c @ 11391:d3755a7ddd82
[gaim-migrate @ 13620]
*** empty log message ***
committer: Tailor Script <tailor@pidgin.im>
author | Adam Warrington <awarring> |
---|---|
date | Wed, 31 Aug 2005 18:50:38 +0000 |
parents | ff728e84d59a |
children | d9d60002065b |
comparison
equal
deleted
inserted
replaced
11390:869cef00a947 | 11391:d3755a7ddd82 |
---|---|
24 */ | 24 */ |
25 #include "internal.h" | 25 #include "internal.h" |
26 #include "gtkgaim.h" | 26 #include "gtkgaim.h" |
27 | 27 |
28 #include "debug.h" | 28 #include "debug.h" |
29 #include "util.h" | |
30 #include "proxy.h" | |
31 #include "xmlnode.h" | |
29 #include "network.h" | 32 #include "network.h" |
30 #include "eventloop.h" | 33 #include "eventloop.h" |
31 #include "upnp.h" | 34 #include "upnp.h" |
32 | 35 |
33 | 36 |
36 */ | 39 */ |
37 typedef struct | 40 typedef struct |
38 { | 41 { |
39 guint inpa; /* gaim_input_add handle */ | 42 guint inpa; /* gaim_input_add handle */ |
40 guint tima; /* gaim_timout_add handle */ | 43 guint tima; /* gaim_timout_add handle */ |
41 char* recvBuffer; /* response data */ | 44 gchar* sendBuffer; /* send data */ |
45 gchar* recvBuffer; /* response data */ | |
42 guint totalSizeRecv; | 46 guint totalSizeRecv; |
43 gboolean done; | 47 gboolean done; |
44 | 48 |
45 } HRD; | 49 } NetResponseData; |
46 | 50 |
47 | 51 |
48 /*************************************************************** | 52 /*************************************************************** |
49 ** General Defines * | 53 ** General Defines * |
50 ****************************************************************/ | 54 ****************************************************************/ |
51 #define HTTP_OK "200 OK" | 55 #define HTTP_OK "200 OK" |
52 #define SIZEOF_HTTP 7 /* size of "http://" */ | 56 #define DEFAULT_HTTP_PORT 80 |
57 #define MAX_PORT_SIZE 6 | |
58 #define SIZEOF_HTTP 7 /* size of "http://" string */ | |
53 #define RECIEVE_TIMEOUT 10000 | 59 #define RECIEVE_TIMEOUT 10000 |
54 #define CONSECUTIVE_RECIEVE_TIMEOUT 500 | 60 #define CONSECUTIVE_RECIEVE_TIMEOUT 500 |
55 #define DISCOVERY_TIMEOUT 1000 | 61 #define DISCOVERY_TIMEOUT 1000 |
56 | 62 |
57 | 63 |
63 /* Address and port of an SSDP request used for discovery */ | 69 /* Address and port of an SSDP request used for discovery */ |
64 #define HTTPMU_HOST_ADDRESS "239.255.255.250" | 70 #define HTTPMU_HOST_ADDRESS "239.255.255.250" |
65 #define HTTPMU_HOST_PORT 1900 | 71 #define HTTPMU_HOST_PORT 1900 |
66 | 72 |
67 #define SEARCH_REQUEST_DEVICE "urn:schemas-upnp-org:service:" \ | 73 #define SEARCH_REQUEST_DEVICE "urn:schemas-upnp-org:service:" \ |
68 "WANIPConnection:1" | 74 "%s" |
69 | 75 |
70 #define SEARCH_REQUEST_STRING "M-SEARCH * HTTP/1.1\r\n" \ | 76 #define SEARCH_REQUEST_STRING "M-SEARCH * HTTP/1.1\r\n" \ |
71 "MX: 2\r\n" \ | 77 "MX: 2\r\n" \ |
72 "HOST: 239.255.255.250:1900\r\n" \ | 78 "HOST: 239.255.255.250:1900\r\n" \ |
73 "MAN: \"ssdp:discover\"\r\n" \ | 79 "MAN: \"ssdp:discover\"\r\n" \ |
74 "ST: urn:schemas-upnp-org:service:" \ | 80 "ST: urn:schemas-upnp-org:service:" \ |
75 "WANIPConnection:1\r\n" \ | 81 "%s\r\n" \ |
76 "\r\n" | 82 "\r\n" |
77 | 83 |
78 #define MAX_DISCOVERY_RECIEVE_SIZE 400 | 84 #define MAX_DISCOVERY_RECIEVE_SIZE 400 |
79 #define MAX_DESCRIPTION_RECIEVE_SIZE 7000 | 85 #define MAX_DESCRIPTION_RECIEVE_SIZE 7000 |
80 #define MAX_DESCRIPTION_HTTP_HEADER_SIZE 100 | 86 #define MAX_DESCRIPTION_HTTP_HEADER_SIZE 100 |
81 | 87 |
82 | 88 |
83 /****************************************************************** | 89 /****************************************************************** |
84 ** Action Defines * | 90 ** Action Defines * |
85 *******************************************************************/ | 91 *******************************************************************/ |
86 #define HTTP_HEADER_ACTION "POST %s HTTP/1.1\r\n" \ | 92 #define HTTP_HEADER_ACTION "POST /%s HTTP/1.1\r\n" \ |
87 "HOST: %s\r\n" \ | 93 "HOST: %s\r\n" \ |
88 "SOAPACTION: " \ | 94 "SOAPACTION: " \ |
89 "\"urn:schemas-upnp-org:" \ | 95 "\"urn:schemas-upnp-org:" \ |
90 "service:%s#%s\"\r\n" \ | 96 "service:%s#%s\"\r\n" \ |
91 "CONTENT-TYPE: text/xml ; charset=\"utf-8\"\r\n"\ | 97 "CONTENT-TYPE: text/xml ; charset=\"utf-8\"\r\n"\ |
124 "<NewExternalPort>%i" \ | 130 "<NewExternalPort>%i" \ |
125 "</NewExternalPort>\r\n" \ | 131 "</NewExternalPort>\r\n" \ |
126 "<NewProtocol>%s</NewProtocol>\r\n" | 132 "<NewProtocol>%s</NewProtocol>\r\n" |
127 | 133 |
128 | 134 |
129 | |
130 /* validate an http url without a port */ | |
131 static gboolean | |
132 gaim_upnp_validate_url(const char* url) | |
133 { | |
134 int i1, i2, i3, i4, r; | |
135 | |
136 if(url == NULL) { | |
137 gaim_debug_info("upnp", | |
138 "gaim_upnp_validate_url(): url == NULL\n\n"); | |
139 return FALSE; | |
140 } | |
141 r = sscanf(url, "http://%3i.%3i.%3i.%3i/", &i1, &i2, &i3, &i4); | |
142 if(r == 4) { | |
143 return TRUE; | |
144 } | |
145 | |
146 gaim_debug_info("upnp", | |
147 "gaim_upnp_validate_url(): Failed In validate URL\n\n"); | |
148 return FALSE; | |
149 } | |
150 | |
151 | |
152 static void | 135 static void |
153 gaim_upnp_timeout(gpointer data, | 136 gaim_upnp_timeout(gpointer data, |
154 gint source, | 137 gint source, |
155 GaimInputCondition cond) | 138 GaimInputCondition cond) |
156 { | 139 { |
157 HRD* hrd = data; | 140 NetResponseData* nrd = data; |
158 | 141 |
159 gaim_input_remove(hrd->inpa); | 142 gaim_input_remove(nrd->inpa); |
160 gaim_timeout_remove(hrd->tima); | 143 gaim_timeout_remove(nrd->tima); |
161 | 144 |
162 if(hrd->totalSizeRecv == 0) { | 145 if(nrd->totalSizeRecv == 0 && nrd->recvBuffer != NULL) { |
163 free(hrd->recvBuffer); | 146 g_free(nrd->recvBuffer); |
164 hrd->recvBuffer = NULL; | 147 nrd->recvBuffer = NULL; |
165 } else { | 148 } else if(nrd->recvBuffer != NULL) { |
166 hrd->recvBuffer[hrd->totalSizeRecv] = '\0'; | 149 nrd->recvBuffer[nrd->totalSizeRecv] = '\0'; |
167 } | 150 } |
168 | 151 |
169 hrd->done = TRUE; | 152 nrd->done = TRUE; |
170 } | 153 } |
171 | 154 |
172 | 155 |
173 static void | 156 static void |
174 gaim_upnp_http_read(gpointer data, | 157 gaim_upnp_http_read(gpointer data, |
175 gint sock, | 158 gint sock, |
176 GaimInputCondition cond) | 159 GaimInputCondition cond) |
177 { | 160 { |
178 int sizeRecv; | 161 int sizeRecv; |
179 extern int errno; | 162 extern int errno; |
180 HRD* hrd = data; | 163 NetResponseData* nrd = data; |
181 | 164 |
182 sizeRecv = recv(sock, &(hrd->recvBuffer[hrd->totalSizeRecv]), | 165 sizeRecv = recv(sock, &(nrd->recvBuffer[nrd->totalSizeRecv]), |
183 MAX_DESCRIPTION_RECIEVE_SIZE-hrd->totalSizeRecv, 0); | 166 MAX_DESCRIPTION_RECIEVE_SIZE-nrd->totalSizeRecv, 0); |
184 if(sizeRecv < 0 && errno != EINTR) { | 167 if(sizeRecv < 0 && errno != EINTR) { |
185 gaim_debug_info("upnp", | 168 gaim_debug_error("upnp", |
186 "gaim_upnp_http_read(): recv < 0: %i!\n\n", errno); | 169 "gaim_upnp_http_read(): recv < 0: %i!\n\n", errno); |
187 free(hrd->recvBuffer); | 170 g_free(nrd->recvBuffer); |
188 hrd->recvBuffer = NULL; | 171 nrd->recvBuffer = NULL; |
189 gaim_timeout_remove(hrd->tima); | 172 gaim_timeout_remove(nrd->tima); |
190 gaim_input_remove(hrd->inpa); | 173 gaim_input_remove(nrd->inpa); |
191 hrd->done = TRUE; | 174 nrd->done = TRUE; |
192 return; | 175 return; |
193 }else if(errno == EINTR) { | 176 }else if(errno == EINTR) { |
194 sizeRecv = 0; | 177 sizeRecv = 0; |
195 } | 178 } |
196 hrd->totalSizeRecv += sizeRecv; | 179 nrd->totalSizeRecv += sizeRecv; |
197 | 180 |
198 if(sizeRecv == 0) { | 181 if(sizeRecv == 0) { |
199 if(hrd->totalSizeRecv == 0) { | 182 gaim_timeout_remove(nrd->tima); |
200 gaim_debug_info("upnp", | 183 gaim_input_remove(nrd->inpa); |
184 if(nrd->totalSizeRecv == 0) { | |
185 gaim_debug_error("upnp", | |
201 "gaim_upnp_http_read(): totalSizeRecv == 0\n\n"); | 186 "gaim_upnp_http_read(): totalSizeRecv == 0\n\n"); |
202 free(hrd->recvBuffer); | 187 g_free(nrd->recvBuffer); |
203 hrd->recvBuffer = NULL; | 188 nrd->recvBuffer = NULL; |
204 } else { | 189 } else { |
205 hrd->recvBuffer[hrd->totalSizeRecv] = '\0'; | 190 nrd->recvBuffer[nrd->totalSizeRecv] = '\0'; |
206 } | 191 } |
207 gaim_timeout_remove(hrd->tima); | 192 nrd->done = TRUE; |
208 gaim_input_remove(hrd->inpa); | |
209 hrd->done = TRUE; | |
210 } else { | 193 } else { |
211 gaim_timeout_remove(hrd->tima); | 194 gaim_timeout_remove(nrd->tima); |
212 gaim_input_remove(hrd->inpa); | 195 gaim_input_remove(nrd->inpa); |
213 hrd->tima = gaim_timeout_add(CONSECUTIVE_RECIEVE_TIMEOUT, | 196 nrd->tima = gaim_timeout_add(CONSECUTIVE_RECIEVE_TIMEOUT, |
214 (GSourceFunc)gaim_upnp_timeout, hrd); | 197 (GSourceFunc)gaim_upnp_timeout, nrd); |
215 hrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, | 198 nrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, |
216 gaim_upnp_http_read, hrd); | 199 gaim_upnp_http_read, nrd); |
217 } | 200 } |
218 | 201 } |
219 } | 202 |
220 | 203 static void |
221 | 204 gaim_upnp_http_send(gpointer data, |
222 | 205 gint sock, |
223 static char* | 206 GaimInputCondition cond) |
224 gaim_upnp_http_request(const char* address, | 207 { |
225 unsigned short port, | |
226 const char* httpRequest) | |
227 { | |
228 int sock; | |
229 int sizeSent, totalSizeSent = 0; | 208 int sizeSent, totalSizeSent = 0; |
230 extern int errno; | 209 extern int errno; |
231 struct sockaddr_in serv_addr; | 210 NetResponseData* nrd = data; |
232 struct hostent *server; | 211 |
233 char* recvBuffer; | 212 gaim_timeout_remove(nrd->tima); |
234 | 213 while(totalSizeSent < strlen(nrd->sendBuffer)) { |
235 HRD* hrd = (HRD*)malloc(sizeof(HRD)); | 214 sizeSent = send(sock,(gchar*)((int)nrd->sendBuffer+totalSizeSent), |
236 if(hrd == NULL) { | 215 strlen(nrd->sendBuffer)-totalSizeSent,0); |
237 gaim_debug_info("upnp", | |
238 "gaim_upnp_http_request(): Failed in hrd MALLOC\n\n"); | |
239 return NULL; | |
240 } | |
241 | |
242 hrd->recvBuffer = NULL; | |
243 hrd->totalSizeRecv = 0; | |
244 hrd->done = FALSE; | |
245 | |
246 hrd->recvBuffer = (char*)malloc(MAX_DESCRIPTION_RECIEVE_SIZE); | |
247 if(hrd->recvBuffer == NULL) { | |
248 gaim_debug_info("upnp", | |
249 "gaim_upnp_http_request(): Failed in recvBuffer MALLOC\n\n"); | |
250 free(hrd); | |
251 return NULL; | |
252 } | |
253 | |
254 sock = socket(AF_INET, SOCK_STREAM, 0); | |
255 if(sock < 0) { | |
256 gaim_debug_info("upnp", | |
257 "gaim_upnp_http_request(): Failed In sock creation\n\n"); | |
258 free(hrd->recvBuffer); | |
259 free(hrd); | |
260 return NULL; | |
261 } | |
262 | |
263 server = gethostbyname(address); | |
264 if(server == NULL) { | |
265 gaim_debug_info("upnp", | |
266 "gaim_upnp_http_request(): Failed In gethostbyname\n\n"); | |
267 free(hrd->recvBuffer); | |
268 free(hrd); | |
269 close(sock); | |
270 return NULL; | |
271 } | |
272 memset((char*)&serv_addr, 0, sizeof(serv_addr)); | |
273 serv_addr.sin_family = AF_INET; | |
274 memcpy(&serv_addr.sin_addr, | |
275 server->h_addr_list[0], | |
276 server->h_length); | |
277 serv_addr.sin_port = htons(port); | |
278 | |
279 if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0) { | |
280 gaim_debug_info("upnp", | |
281 "gaim_upnp_http_request(): Failed In connect\n\n"); | |
282 free(hrd->recvBuffer); | |
283 free(hrd); | |
284 close(sock); | |
285 return NULL; | |
286 } | |
287 | |
288 while(totalSizeSent < strlen(httpRequest)) { | |
289 sizeSent = send(sock,(char*)((int)httpRequest+totalSizeSent), | |
290 strlen(httpRequest),0); | |
291 if(sizeSent <= 0 && errno != EINTR) { | 216 if(sizeSent <= 0 && errno != EINTR) { |
292 gaim_debug_info("upnp", | 217 gaim_debug_error("upnp", |
293 "gaim_upnp_http_request(): Failed In send\n\n"); | 218 "gaim_upnp_http_request(): Failed In send\n\n"); |
294 free(hrd->recvBuffer); | 219 nrd->done = TRUE; |
295 free(hrd); | 220 g_free(nrd->recvBuffer); |
221 nrd->recvBuffer = NULL; | |
296 close(sock); | 222 close(sock); |
297 return NULL; | 223 return; |
298 }else if(errno == EINTR) { | 224 }else if(errno == EINTR) { |
299 sizeSent = 0; | 225 sizeSent = 0; |
300 } | 226 } |
301 totalSizeSent += sizeSent; | 227 totalSizeSent += sizeSent; |
302 } | 228 } |
303 | 229 |
304 hrd->tima = gaim_timeout_add(RECIEVE_TIMEOUT, | 230 nrd->tima = gaim_timeout_add(RECIEVE_TIMEOUT, |
305 (GSourceFunc)gaim_upnp_timeout, hrd); | 231 (GSourceFunc)gaim_upnp_timeout, nrd); |
306 hrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, | 232 nrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, |
307 gaim_upnp_http_read, hrd); | 233 gaim_upnp_http_read, nrd); |
308 while (!hrd->done) { | 234 while (!nrd->done) { |
309 gtk_main_iteration(); | 235 gtk_main_iteration(); |
310 } | 236 } |
311 close(sock); | 237 close(sock); |
312 | 238 } |
313 recvBuffer = hrd->recvBuffer; | 239 |
314 free(hrd); | 240 static gchar* |
241 gaim_upnp_http_request(const gchar* address, | |
242 int port, | |
243 gchar* httpRequest) | |
244 { | |
245 gchar* recvBuffer; | |
246 NetResponseData* nrd = (NetResponseData*)g_malloc0(sizeof(NetResponseData)); | |
247 nrd->sendBuffer = httpRequest; | |
248 nrd->recvBuffer = (gchar*)g_malloc(MAX_DESCRIPTION_RECIEVE_SIZE); | |
249 | |
250 nrd->tima = gaim_timeout_add(RECIEVE_TIMEOUT, | |
251 (GSourceFunc)gaim_upnp_timeout, nrd); | |
252 | |
253 if(gaim_proxy_connect(NULL, address, port, | |
254 gaim_upnp_http_send, nrd)) { | |
255 | |
256 gaim_debug_error("upnp", "Connect Failed: Address: %s @@@ Port %d @@@ Request %s\n\n", | |
257 address, port, nrd->sendBuffer); | |
258 | |
259 gaim_timeout_remove(nrd->tima); | |
260 g_free(nrd->recvBuffer); | |
261 nrd->recvBuffer = NULL; | |
262 } else { | |
263 while (!nrd->done) { | |
264 gtk_main_iteration(); | |
265 } | |
266 } | |
267 | |
268 recvBuffer = nrd->recvBuffer; | |
269 g_free(nrd); | |
270 | |
315 return recvBuffer; | 271 return recvBuffer; |
316 } | 272 } |
317 | 273 |
318 | 274 |
319 | 275 |
320 /* This function takes the HTTP response requesting the description xml from | 276 static gboolean |
321 * the UPnP enabled IGD. It also takes as input the URL the request was sent | 277 gaim_upnp_compare_device(const xmlnode* device, |
322 * to. | 278 const gchar* deviceType) |
323 * | 279 { |
324 * The description contains the URL needed to control the actions of the UPnP | 280 xmlnode* deviceTypeNode = xmlnode_get_child(device, "deviceType"); |
325 * enabled IGD. This URL can be in the form of just a path, in whcih case we | 281 if(deviceTypeNode == NULL) { |
326 * have to append the path to the base URL. The base URL might be specified | 282 return FALSE; |
327 * in the XML, or it might not, in which case u append to the httpURL. | 283 } |
328 */ | 284 return !g_ascii_strcasecmp(xmlnode_get_data(deviceTypeNode), deviceType); |
329 | 285 } |
330 /* at some point, maybe parse the description response using an xml library */ | 286 |
331 static char* | 287 |
332 gaim_upnp_parse_description_response(const char* httpResponse, | 288 static gboolean |
333 const char* httpURL) | 289 gaim_upnp_compare_service(const xmlnode* service, |
334 { | 290 const gchar* serviceType) |
335 char* wanIPConnectionStart; | 291 { |
336 char urlBaseTag[] = "<URLBase>"; | 292 xmlnode* serviceTypeNode = xmlnode_get_child(service, "serviceType"); |
337 char urlBaseEndTag[] = "</URLBase>"; | 293 if(serviceTypeNode == NULL) { |
338 char controlURLTag[] = "<controlURL>"; | 294 return FALSE; |
339 char controlURLEndTag[] = "</controlURL>"; | 295 } |
340 char* urlBaseTagLoc; | 296 return !g_ascii_strcasecmp(xmlnode_get_data(serviceTypeNode), serviceType); |
341 char* urlBaseEndTagLoc; | 297 } |
342 char* controlURLTagLoc; | 298 |
343 char* controlURLEndTagLoc; | 299 |
344 int controlURLSize; | 300 |
345 int baseURLSize; | 301 static gchar* |
346 char* controlURL; | 302 gaim_upnp_parse_description_response(const gchar* httpResponse, |
347 char* baseURL; | 303 const gchar* httpURL, |
348 | 304 const gchar* serviceType) |
349 if(strstr(httpResponse, HTTP_OK) == NULL) { | 305 { |
350 gaim_debug_info("upnp", | 306 gchar* xmlRoot; |
307 gchar* baseURL; | |
308 gchar* controlURL; | |
309 gchar* service; | |
310 xmlnode* xmlRootNode; | |
311 xmlnode* serviceTypeNode; | |
312 xmlnode* controlURLNode; | |
313 xmlnode* baseURLNode; | |
314 | |
315 /* make sure we have a valid http response */ | |
316 if(g_strstr_len(httpResponse, strlen(httpResponse), HTTP_OK) == NULL) { | |
317 gaim_debug_error("upnp", | |
351 "parse_description_response(): Failed In HTTP_OK\n\n"); | 318 "parse_description_response(): Failed In HTTP_OK\n\n"); |
352 return NULL; | 319 return NULL; |
353 } | 320 } |
354 | 321 |
355 if((wanIPConnectionStart = | 322 /* find the root of the xml document */ |
356 strstr(httpResponse, SEARCH_REQUEST_DEVICE)) == NULL) { | 323 if((xmlRoot = g_strstr_len(httpResponse, strlen(httpResponse), |
357 gaim_debug_info("upnp", | 324 "<root")) == NULL) { |
358 "parse_description_response(): Failed SEARCH_REQUEST_DEVICE\n\n"); | 325 gaim_debug_error("upnp", |
359 return NULL; | 326 "parse_description_response(): Failed finding root\n\n"); |
360 } | 327 return NULL; |
361 if((controlURLTagLoc = strstr(wanIPConnectionStart, controlURLTag)) | 328 } |
362 == NULL) { | 329 |
363 gaim_debug_info("upnp", | 330 /* create the xml root node */ |
364 "parse_description_response(): Failed In controlURLTagLoc\n\n"); | 331 if((xmlRootNode = xmlnode_from_str(xmlRoot, -1)) == NULL) { |
365 return NULL; | 332 gaim_debug_error("upnp", |
366 } | 333 "parse_description_response(): Could not parse xml root node\n\n"); |
367 if((controlURLEndTagLoc = | 334 return NULL; |
368 strstr(wanIPConnectionStart, controlURLEndTag)) == NULL) { | 335 } |
369 gaim_debug_info("upnp", | 336 |
370 "parse_description_response(): Failed In controlURLEndTagLoc\n\n"); | 337 /* get the baseURL of the device */ |
371 return NULL; | 338 if((baseURLNode = xmlnode_get_child(xmlRootNode, |
372 } | 339 "URLBase")) != NULL) { |
373 | 340 baseURL = g_strdup(xmlnode_get_data(baseURLNode)); |
374 | |
375 controlURLSize = | |
376 controlURLEndTagLoc-&controlURLTagLoc[strlen(controlURLTag)]; | |
377 if((controlURL = (char*)malloc(controlURLSize+1)) == NULL) { | |
378 gaim_debug_info("upnp", | |
379 "parse_description_response(): Failed In MALLOC controlURL\n\n"); | |
380 return NULL; | |
381 } | |
382 memcpy(controlURL, &controlURLTagLoc[strlen(controlURLTag)], | |
383 controlURLSize); | |
384 controlURL[controlURLSize] = '\0'; | |
385 | |
386 | |
387 if((urlBaseTagLoc = strstr(httpResponse, urlBaseTag)) == NULL) { | |
388 if((baseURL = (char*)malloc(strlen(httpURL)+controlURLSize+1)) == NULL) { | |
389 gaim_debug_info("upnp", | |
390 "parse_description_response(): Failed In MALLOC baseURL\n\n"); | |
391 return NULL; | |
392 } | |
393 memcpy(baseURL, httpURL, strlen(httpURL)); | |
394 baseURL[strlen(httpURL)] = '\0'; | |
395 } else { | 341 } else { |
396 if((urlBaseEndTagLoc = strstr(httpResponse, urlBaseEndTag)) == NULL) { | 342 baseURL = g_strdup(httpURL); |
397 gaim_debug_info("upnp", | 343 } |
398 "parse_description_response(): Failed In urlBaseEndTagLoc\n\n"); | 344 |
399 return NULL; | 345 /* get the serviceType child that has the service type as it's data */ |
400 } | 346 |
401 baseURLSize = | 347 /* get urn:schemas-upnp-org:device:InternetGatewayDevice:1 |
402 urlBaseEndTagLoc - &urlBaseTagLoc[strlen(urlBaseTag)]; | 348 and it's devicelist */ |
403 if((baseURL = (char*)malloc(baseURLSize+controlURLSize+1)) == NULL) { | 349 serviceTypeNode = xmlnode_get_child(xmlRootNode, "device"); |
404 gaim_debug_info("upnp", | 350 while(!gaim_upnp_compare_device(serviceTypeNode, |
405 "parse_description_response(): Failed 2nd MALLOC baseURL\n\n"); | 351 "urn:schemas-upnp-org:device:InternetGatewayDevice:1") && |
406 return NULL; | 352 serviceTypeNode != NULL) { |
407 } | 353 serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); |
408 memcpy(baseURL, &urlBaseTagLoc[strlen(urlBaseTag)], baseURLSize); | 354 } |
409 baseURL[baseURLSize] = '\0'; | 355 if(serviceTypeNode == NULL) { |
410 } | 356 gaim_debug_error("upnp", |
411 | 357 "parse_description_response(): could not get serviceTypeNode 1\n\n"); |
412 if(strstr(controlURL, "http://") == NULL) { | 358 return NULL; |
413 memcpy(&baseURL[strlen(baseURL)], controlURL, strlen(controlURL)+1); | 359 } |
414 free(controlURL); | 360 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "deviceList"); |
415 controlURL = baseURL; | 361 if(serviceTypeNode == NULL) { |
362 gaim_debug_error("upnp", | |
363 "parse_description_response(): could not get serviceTypeNode 2\n\n"); | |
364 return NULL; | |
365 } | |
366 | |
367 /* get urn:schemas-upnp-org:device:WANDevice:1 | |
368 and it's devicelist */ | |
369 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "device"); | |
370 while(!gaim_upnp_compare_device(serviceTypeNode, | |
371 "urn:schemas-upnp-org:device:WANDevice:1") && | |
372 serviceTypeNode != NULL) { | |
373 serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); | |
374 } | |
375 if(serviceTypeNode == NULL) { | |
376 gaim_debug_error("upnp", | |
377 "parse_description_response(): could not get serviceTypeNode 3\n\n"); | |
378 return NULL; | |
379 } | |
380 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "deviceList"); | |
381 if(serviceTypeNode == NULL) { | |
382 gaim_debug_error("upnp", | |
383 "parse_description_response(): could not get serviceTypeNode 4\n\n"); | |
384 return NULL; | |
385 } | |
386 | |
387 /* get urn:schemas-upnp-org:device:WANConnectionDevice:1 | |
388 and it's servicelist */ | |
389 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "device"); | |
390 while(!gaim_upnp_compare_device(serviceTypeNode, | |
391 "urn:schemas-upnp-org:device:WANConnectionDevice:1") && | |
392 serviceTypeNode != NULL) { | |
393 serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); | |
394 } | |
395 if(serviceTypeNode == NULL) { | |
396 gaim_debug_error("upnp", | |
397 "parse_description_response(): could not get serviceTypeNode 5\n\n"); | |
398 return NULL; | |
399 } | |
400 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "serviceList"); | |
401 if(serviceTypeNode == NULL) { | |
402 gaim_debug_error("upnp", | |
403 "parse_description_response(): could not get serviceTypeNode 6\n\n"); | |
404 return NULL; | |
405 } | |
406 | |
407 /* get the serviceType variable passed to this function */ | |
408 service = g_strdup_printf(SEARCH_REQUEST_DEVICE, serviceType); | |
409 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "service"); | |
410 while(!gaim_upnp_compare_service(serviceTypeNode, service) && | |
411 serviceTypeNode != NULL) { | |
412 serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); | |
413 } | |
414 | |
415 g_free(service); | |
416 if(serviceTypeNode == NULL) { | |
417 gaim_debug_error("upnp", | |
418 "parse_description_response(): could not get serviceTypeNode 7\n\n"); | |
419 return NULL; | |
420 } | |
421 | |
422 /* get the controlURL of the service */ | |
423 if((controlURLNode = xmlnode_get_child(serviceTypeNode, | |
424 "controlURL")) == NULL) { | |
425 gaim_debug_error("upnp", | |
426 "parse_description_response(): Could not find controlURL\n\n"); | |
427 return NULL; | |
428 } | |
429 | |
430 if(g_strstr_len(xmlnode_get_data(controlURLNode), | |
431 SIZEOF_HTTP, "http://") == NULL && | |
432 g_strstr_len(xmlnode_get_data(controlURLNode), | |
433 SIZEOF_HTTP, "HTTP://") == NULL) { | |
434 controlURL = g_strdup_printf("%s%s", baseURL, | |
435 xmlnode_get_data(controlURLNode)); | |
416 }else{ | 436 }else{ |
417 free(baseURL); | 437 controlURL = g_strdup(xmlnode_get_data(controlURLNode)); |
418 } | 438 } |
439 g_free(baseURL); | |
440 xmlnode_free(xmlRootNode); | |
419 | 441 |
420 return controlURL; | 442 return controlURL; |
421 } | 443 } |
422 | 444 |
423 | 445 |
424 | 446 static gchar* |
425 | 447 gaim_upnp_parse_description(const gchar* descriptionURL, |
426 /* parse a url into it's approrpiate parts: | 448 const gchar* serviceType) |
427 address, port, path. return true on success, | 449 { |
428 false on failure */ | 450 gchar* fullURL; |
429 static gboolean | 451 gchar* controlURL; |
430 gaim_upnp_parse_url(const char* url, char** path, | 452 gchar* httpResponse; |
431 char** address, char** port) | 453 gchar* httpRequest; |
432 { | 454 |
433 char* temp, *temp2; | 455 gchar* descriptionXMLAddress; |
434 | 456 gchar* descriptionAddressPort; |
435 /* get the path */ | 457 gchar* descriptionAddress; |
436 if((temp = strchr(&url[SIZEOF_HTTP], '/')) < 0) { | 458 gchar descriptionPort[MAX_PORT_SIZE]; |
437 gaim_debug_info("upnp", | 459 int port = 0; |
438 "gaim_upnp_parse_url(): Failed In 1\n\n"); | |
439 return FALSE; | |
440 } | |
441 if((*path = (char*)malloc(strlen(temp)+1)) == NULL) { | |
442 gaim_debug_info("upnp", | |
443 "gaim_upnp_parse_url(): Failed In 2\n\n"); | |
444 return FALSE; | |
445 } | |
446 memcpy(*path, temp, strlen(temp)); | |
447 (*path)[strlen(temp)] = '\0'; | |
448 | |
449 /* get the port */ | |
450 if((temp2 = strchr(&url[SIZEOF_HTTP], ':')) == NULL) { | |
451 gaim_debug_info("upnp", | |
452 "gaim_upnp_parse_url(): Failed In 3\n\n"); | |
453 free(*path); | |
454 return FALSE; | |
455 } | |
456 if((*port = (char*)malloc(temp-temp2)) == NULL) { | |
457 gaim_debug_info("upnp", | |
458 "gaim_upnp_parse_url(): Failed In 4\n\n"); | |
459 free(*path); | |
460 return FALSE; | |
461 } | |
462 memcpy(*port, &temp2[1], (temp-1)-temp2); | |
463 (*port)[(temp-1)-temp2] = '\0'; | |
464 | |
465 /* get the address */ | |
466 if((*address = (char*)malloc((temp2-&url[SIZEOF_HTTP])+1)) == NULL) { | |
467 gaim_debug_info("upnp", | |
468 "gaim_upnp_parse_url(): Failed In 5\n\n"); | |
469 free(*path); | |
470 free(*port); | |
471 return FALSE; | |
472 } | |
473 memcpy(*address, &url[SIZEOF_HTTP], | |
474 temp2-&url[SIZEOF_HTTP]); | |
475 (*address)[temp2-&url[SIZEOF_HTTP]] = '\0'; | |
476 | |
477 return TRUE; | |
478 } | |
479 | |
480 | |
481 | |
482 /* | |
483 * This function takes the URL where the UPnP enabled IGD description is | |
484 * located at, and sends an HTTP request to retrieve that description. Once | |
485 * the description is retrieved, we send the response to the | |
486 * gaim_upnp_parse_description_response() function. This will parse the | |
487 * description, and return the control URL needed to control the IGD, which | |
488 * this function returns. | |
489 */ | |
490 static char* | |
491 gaim_upnp_parse_description(const char* descriptionURL) | |
492 { | |
493 char* fullURL; | |
494 char* controlURL; | |
495 char* httpResponse; | |
496 char httpRequest[MAX_DESCRIPTION_HTTP_HEADER_SIZE]; | |
497 | |
498 char* descriptionXMLAddress; | |
499 char* descriptionAddressPort; | |
500 char* descriptionAddress; | |
501 char* descriptionPort; | |
502 unsigned short port; | |
503 | 460 |
504 /* parse the 4 above variables out of the descriptionURL | 461 /* parse the 4 above variables out of the descriptionURL |
505 example description URL: http://192.168.1.1:5678/rootDesc.xml */ | 462 example description URL: http://192.168.1.1:5678/rootDesc.xml */ |
506 | 463 |
507 /* parse the url into address, port, path variables */ | 464 /* parse the url into address, port, path variables */ |
508 if(!gaim_upnp_parse_url(descriptionURL, &descriptionXMLAddress, | 465 if(!gaim_url_parse(descriptionURL, &descriptionAddress, |
509 &descriptionAddress, &descriptionPort)) { | 466 &port, &descriptionXMLAddress, NULL, NULL)) { |
510 return NULL; | 467 return NULL; |
511 } | 468 } |
512 if((port = atoi(descriptionPort)) == 0) { | 469 if(port == 0 || port == -1) { |
513 gaim_debug_info("upnp", | 470 port = DEFAULT_HTTP_PORT; |
514 "gaim_upnp_parse_description(): failed atoi\n\n"); | 471 } |
515 free(descriptionXMLAddress); | 472 g_ascii_dtostr(descriptionPort, MAX_PORT_SIZE, port); |
516 free(descriptionAddress); | 473 descriptionAddressPort = g_strdup_printf("%s:%s", descriptionAddress, |
517 free(descriptionPort); | 474 descriptionPort); |
518 return NULL; | 475 |
519 } | 476 fullURL = g_strdup_printf("http://%s", descriptionAddressPort); |
520 | |
521 if((descriptionAddressPort = (char*)malloc(strlen(descriptionAddress) + | |
522 strlen(descriptionPort) + 2)) | |
523 == NULL) { | |
524 gaim_debug_info("upnp", | |
525 "gaim_upnp_parse_description(): failed MALLOC desAddPort\n\n"); | |
526 free(descriptionXMLAddress); | |
527 free(descriptionAddress); | |
528 free(descriptionPort); | |
529 return NULL; | |
530 } | |
531 sprintf(descriptionAddressPort, "%s:%s", | |
532 descriptionAddress, descriptionPort); | |
533 | |
534 if((fullURL = (char*)malloc(strlen(descriptionAddressPort) + | |
535 SIZEOF_HTTP + 1)) == NULL) { | |
536 gaim_debug_info("upnp", | |
537 "gaim_upnp_parse_description(): failed MALLOC fullURL\n\n"); | |
538 free(descriptionXMLAddress); | |
539 free(descriptionAddress); | |
540 free(descriptionPort); | |
541 free(descriptionAddressPort); | |
542 } | |
543 sprintf(fullURL, "http://%s", descriptionAddressPort); | |
544 | 477 |
545 /* for example... | 478 /* for example... |
546 GET /rootDesc.xml HTTP/1.1\r\nHost: 192.168.1.1:5678\r\n\r\n */ | 479 GET /rootDesc.xml HTTP/1.1\r\nHost: 192.168.1.1:5678\r\n\r\n */ |
547 sprintf(httpRequest, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", | 480 httpRequest = g_strdup_printf("GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", |
548 descriptionXMLAddress, descriptionAddressPort); | 481 descriptionXMLAddress, descriptionAddressPort); |
549 | 482 |
550 httpResponse = gaim_upnp_http_request(descriptionAddress, | 483 httpResponse = gaim_upnp_http_request(descriptionAddress, |
551 port, httpRequest); | 484 port, httpRequest); |
552 if(httpResponse == NULL) { | 485 if(httpResponse == NULL) { |
553 gaim_debug_info("upnp", | 486 gaim_debug_error("upnp", |
554 "gaim_upnp_parse_description(): httpResponse is NULL\n\n"); | 487 "gaim_upnp_parse_description(): httpResponse is NULL\n\n"); |
555 free(descriptionXMLAddress); | 488 g_free(descriptionXMLAddress); |
556 free(descriptionAddress); | 489 g_free(descriptionAddress); |
557 free(descriptionPort); | 490 g_free(descriptionAddressPort); |
558 free(descriptionAddressPort); | 491 g_free(httpRequest); |
559 free(fullURL); | 492 g_free(fullURL); |
560 return NULL; | 493 return NULL; |
561 } | 494 } |
562 | 495 |
563 controlURL = gaim_upnp_parse_description_response(httpResponse, fullURL); | 496 controlURL = gaim_upnp_parse_description_response(httpResponse, |
564 | 497 fullURL, serviceType); |
565 free(descriptionXMLAddress); | 498 |
566 free(descriptionAddress); | 499 g_free(descriptionXMLAddress); |
567 free(descriptionPort); | 500 g_free(descriptionAddress); |
568 free(descriptionAddressPort); | 501 g_free(descriptionAddressPort); |
569 free(fullURL); | 502 g_free(fullURL); |
570 free(httpResponse); | 503 g_free(httpRequest); |
504 g_free(httpResponse); | |
571 | 505 |
572 if(controlURL == NULL) { | 506 if(controlURL == NULL) { |
573 gaim_debug_info("upnp", | 507 gaim_debug_error("upnp", |
574 "gaim_upnp_parse_description(): controlURL is NULL\n\n"); | 508 "gaim_upnp_parse_description(): controlURL is NULL\n\n"); |
575 return NULL; | 509 return NULL; |
576 } | 510 } |
577 | 511 |
578 return controlURL; | 512 return controlURL; |
579 } | 513 } |
580 | 514 |
581 | 515 |
582 static char* | 516 static gchar* |
583 gaim_upnp_parse_discover_response(const char* buf, | 517 gaim_upnp_parse_discover_response(const gchar* buf, |
584 unsigned int bufSize) | 518 unsigned int bufSize, |
585 { | 519 const gchar* serviceType) |
586 char* startDescURL; | 520 { |
587 char* endDescURL; | 521 gchar* startDescURL; |
588 char* descURL; | 522 gchar* endDescURL; |
589 unsigned int descURLSize; | 523 gchar* descURL; |
590 char* retVal; | 524 gchar* retVal; |
591 | 525 |
592 if(strstr(buf, HTTP_OK) == NULL) { | 526 if(g_strstr_len(buf, strlen(buf), HTTP_OK) == NULL) { |
593 gaim_debug_info("upnp", | 527 gaim_debug_error("upnp", |
594 "parse_discover_response(): Failed In HTTP_OK\n\n"); | 528 "parse_discover_response(): Failed In HTTP_OK\n\n"); |
595 return NULL; | 529 return NULL; |
596 } | 530 } |
597 | 531 |
598 if((startDescURL = strstr(buf, "http://")) == NULL) { | 532 if((startDescURL = g_strstr_len(buf, strlen(buf), "http://")) == NULL) { |
599 gaim_debug_info("upnp", | 533 gaim_debug_error("upnp", |
600 "parse_description_response(): Failed In finding http://\n\n"); | 534 "parse_discover_response(): Failed In finding http://\n\n"); |
601 return NULL; | 535 return NULL; |
602 } | 536 } |
603 | 537 |
604 endDescURL = strchr(startDescURL, '\r'); | 538 endDescURL = g_strstr_len(startDescURL, strlen(startDescURL), "\r"); |
605 if(endDescURL == NULL) { | 539 if(endDescURL == NULL) { |
606 endDescURL = strchr(startDescURL, '\n'); | 540 endDescURL = g_strstr_len(startDescURL, strlen(startDescURL), "\n"); |
607 if(endDescURL == NULL) { | 541 if(endDescURL == NULL) { |
608 gaim_debug_info("upnp", | 542 gaim_debug_error("upnp", |
609 "parse_description_response(): Failed In endDescURL\n\n"); | 543 "parse_discover_response(): Failed In endDescURL\n\n"); |
610 return NULL; | 544 return NULL; |
611 }else if(endDescURL == startDescURL) { | 545 }else if(endDescURL == startDescURL) { |
612 gaim_debug_info("upnp", | 546 gaim_debug_error("upnp", |
613 "parse_description_response(): endDescURL == startDescURL\n\n"); | 547 "parse_discover_response(): endDescURL == startDescURL\n\n"); |
614 return NULL; | 548 return NULL; |
615 } | 549 } |
616 }else if(endDescURL == startDescURL) { | 550 }else if(endDescURL == startDescURL) { |
617 gaim_debug_info("upnp", | 551 gaim_debug_error("upnp", |
618 "parse_description_response(): 2nd endDescURL == startDescURL\n\n"); | 552 "parse_discover_response(): 2nd endDescURL == startDescURL\n\n"); |
619 return NULL; | 553 return NULL; |
620 } | 554 } |
621 | 555 descURL = g_strndup(startDescURL, endDescURL-startDescURL); |
622 descURLSize = (endDescURL-startDescURL)+1; | 556 |
623 descURL = (char*)malloc(descURLSize); | 557 retVal = gaim_upnp_parse_description(descURL, serviceType); |
624 memcpy(descURL, startDescURL, descURLSize-1); | 558 g_free(descURL); |
625 descURL[descURLSize-1] = '\0'; | |
626 | |
627 retVal = gaim_upnp_parse_description(descURL); | |
628 free(descURL); | |
629 return retVal; | 559 return retVal; |
630 } | 560 } |
631 | 561 |
632 | 562 |
633 | 563 |
638 { | 568 { |
639 unsigned int length; | 569 unsigned int length; |
640 extern int errno; | 570 extern int errno; |
641 struct sockaddr_in from; | 571 struct sockaddr_in from; |
642 int sizeRecv; | 572 int sizeRecv; |
643 HRD* hrd = data; | 573 NetResponseData* nrd = data; |
644 | 574 |
645 gaim_timeout_remove(hrd->tima); | 575 gaim_timeout_remove(nrd->tima); |
646 length = sizeof(struct sockaddr_in); | 576 length = sizeof(struct sockaddr_in); |
647 | 577 |
648 do { | 578 do { |
649 sizeRecv = recvfrom(sock, hrd->recvBuffer, | 579 sizeRecv = recvfrom(sock, nrd->recvBuffer, |
650 MAX_DISCOVERY_RECIEVE_SIZE, 0, | 580 MAX_DISCOVERY_RECIEVE_SIZE, 0, |
651 (struct sockaddr*)&from, &length); | 581 (struct sockaddr*)&from, &length); |
652 | 582 |
653 if(sizeRecv > 0) { | 583 if(sizeRecv > 0) { |
654 hrd->recvBuffer[sizeRecv] = '\0'; | 584 nrd->recvBuffer[sizeRecv] = '\0'; |
655 }else if(errno != EINTR) { | 585 }else if(errno != EINTR) { |
656 free(hrd->recvBuffer); | 586 g_free(nrd->recvBuffer); |
657 hrd->recvBuffer = NULL; | 587 nrd->recvBuffer = NULL; |
658 } | 588 } |
659 }while(errno == EINTR); | 589 }while(errno == EINTR); |
660 | 590 |
661 gaim_input_remove(hrd->inpa); | 591 gaim_input_remove(nrd->inpa); |
662 hrd->done = TRUE; | 592 nrd->done = TRUE; |
663 return; | 593 return; |
664 } | 594 } |
665 | 595 |
666 | 596 |
667 | 597 |
668 char* | 598 GaimUPnPControlInfo* |
669 gaim_upnp_discover(void) | 599 gaim_upnp_discover(void) |
670 { | 600 { |
601 /* Socket Setup Variables */ | |
671 int sock, i; | 602 int sock, i; |
603 extern int errno; | |
604 struct sockaddr_in server; | |
605 struct hostent* hp; | |
606 | |
607 /* UDP SEND VARIABLES */ | |
608 gboolean sentSuccess, recvSuccess; | |
672 int sizeSent, totalSizeSent; | 609 int sizeSent, totalSizeSent; |
673 extern int errno; | 610 gchar wanIP[] = "WANIPConnection:1"; |
674 gboolean sentSuccess, recvSuccess; | 611 gchar wanPPP[] = "WANPPPConnection:1"; |
675 struct sockaddr_in server; | 612 gchar* serviceToUse; |
676 struct hostent *hp; | 613 gchar* sendMessage = NULL; |
677 char sendMessage[] = SEARCH_REQUEST_STRING; | 614 |
678 char *controlURL = NULL; | 615 /* UDP RECIEVE VARIABLES */ |
679 | 616 GaimUPnPControlInfo* controlInfo = g_malloc(sizeof(GaimUPnPControlInfo)); |
680 HRD* hrd = (HRD*)malloc(sizeof(HRD)); | 617 NetResponseData* nrd = g_malloc(sizeof(NetResponseData)); |
681 if(hrd == NULL) { | 618 |
682 gaim_debug_info("upnp", | 619 /* Set up the sockets */ |
683 "gaim_upnp_discover(): Failed in hrd MALLOC\n\n"); | |
684 return NULL; | |
685 } | |
686 | |
687 sock = socket(AF_INET, SOCK_DGRAM, 0); | 620 sock = socket(AF_INET, SOCK_DGRAM, 0); |
688 if (sock == -1) { | 621 if (sock == -1) { |
689 close(sock); | 622 close(sock); |
690 gaim_debug_info("upnp", | 623 gaim_debug_error("upnp", |
691 "gaim_upnp_discover(): Failed In sock creation\n\n"); | 624 "gaim_upnp_discover(): Failed In sock creation\n\n"); |
692 free(hrd->recvBuffer); | 625 g_free(nrd); |
693 free(hrd); | 626 g_free(controlInfo); |
694 return NULL; | 627 return NULL; |
695 } | 628 } |
696 | |
697 memset(&server, 0, sizeof(struct sockaddr)); | 629 memset(&server, 0, sizeof(struct sockaddr)); |
698 server.sin_family = AF_INET; | 630 server.sin_family = AF_INET; |
699 if((hp = gethostbyname(HTTPMU_HOST_ADDRESS)) == NULL) { | 631 if((hp = gethostbyname(HTTPMU_HOST_ADDRESS)) == NULL) { |
700 close(sock); | 632 close(sock); |
701 gaim_debug_info("upnp", | 633 gaim_debug_error("upnp", |
702 "gaim_upnp_discover(): Failed In gethostbyname\n\n"); | 634 "gaim_upnp_discover(): Failed In gethostbyname\n\n"); |
703 free(hrd->recvBuffer); | 635 g_free(nrd); |
704 free(hrd); | 636 g_free(controlInfo); |
705 return NULL; | 637 return NULL; |
706 } | 638 } |
707 | |
708 memcpy(&server.sin_addr, | 639 memcpy(&server.sin_addr, |
709 hp->h_addr_list[0], | 640 hp->h_addr_list[0], |
710 hp->h_length); | 641 hp->h_length); |
711 server.sin_port = htons(HTTPMU_HOST_PORT); | 642 server.sin_port = htons(HTTPMU_HOST_PORT); |
712 | 643 |
713 /* because we are sending over UDP, if there is a failure | 644 /* because we are sending over UDP, if there is a failure |
714 we should retry the send NUM_UDP_ATTEMPTS times */ | 645 we should retry the send NUM_UDP_ATTEMPTS times. Also, |
646 try different requests for WANIPConnection and | |
647 WANPPPConnection*/ | |
715 for(i = 0; i < NUM_UDP_ATTEMPTS; i++) { | 648 for(i = 0; i < NUM_UDP_ATTEMPTS; i++) { |
716 sentSuccess = TRUE; | 649 sentSuccess = TRUE; |
717 recvSuccess = TRUE; | 650 recvSuccess = TRUE; |
718 totalSizeSent = 0; | 651 totalSizeSent = 0; |
719 | 652 |
720 hrd->recvBuffer = NULL; | 653 nrd->recvBuffer = NULL; |
721 hrd->totalSizeRecv = 0; | 654 nrd->totalSizeRecv = 0; |
722 hrd->done = FALSE; | 655 nrd->done = FALSE; |
723 | 656 |
724 hrd->recvBuffer = (char*)malloc(MAX_DISCOVERY_RECIEVE_SIZE); | 657 if(sendMessage != NULL) { |
725 if(hrd->recvBuffer == NULL) { | 658 g_free(sendMessage); |
726 gaim_debug_info("upnp", | 659 } |
727 "gaim_upnp_discover(): Failed in hrd->recvBuffer MALLOC\n\n"); | 660 |
728 free(hrd); | 661 if(i%2 == 0) { |
729 return NULL; | 662 serviceToUse = wanIP; |
730 } | 663 } else { |
664 serviceToUse = wanPPP; | |
665 } | |
666 sendMessage = g_strdup_printf(SEARCH_REQUEST_STRING, serviceToUse); | |
667 | |
668 nrd->recvBuffer = (char*)g_malloc(MAX_DISCOVERY_RECIEVE_SIZE); | |
731 | 669 |
732 while(totalSizeSent < strlen(sendMessage)) { | 670 while(totalSizeSent < strlen(sendMessage)) { |
733 sizeSent = sendto(sock,(void*)&sendMessage[totalSizeSent], | 671 sizeSent = sendto(sock,(void*)&sendMessage[totalSizeSent], |
734 strlen(&sendMessage[totalSizeSent]),0, | 672 strlen(&sendMessage[totalSizeSent]),0, |
735 (struct sockaddr*)&server, | 673 (struct sockaddr*)&server, |
742 } | 680 } |
743 totalSizeSent += sizeSent; | 681 totalSizeSent += sizeSent; |
744 } | 682 } |
745 | 683 |
746 if(sentSuccess) { | 684 if(sentSuccess) { |
747 hrd->tima = gaim_timeout_add(DISCOVERY_TIMEOUT, | 685 nrd->tima = gaim_timeout_add(DISCOVERY_TIMEOUT, |
748 (GSourceFunc)gaim_upnp_timeout, hrd); | 686 (GSourceFunc)gaim_upnp_timeout, nrd); |
749 hrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, | 687 nrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, |
750 gaim_upnp_discover_udp_read, hrd); | 688 gaim_upnp_discover_udp_read, nrd); |
751 while (!hrd->done) { | 689 while (!nrd->done) { |
752 gtk_main_iteration(); | 690 gtk_main_iteration(); |
753 } | 691 } |
754 if(hrd->recvBuffer == NULL) { | 692 if(nrd->recvBuffer == NULL) { |
755 recvSuccess = FALSE; | 693 recvSuccess = FALSE; |
756 } else { | 694 } else { |
757 /* parse the response, and see if it was a success */ | 695 /* parse the response, and see if it was a success */ |
758 close(sock); | 696 close(sock); |
759 if((controlURL= | 697 if((controlInfo->controlURL= |
760 gaim_upnp_parse_discover_response(hrd->recvBuffer, | 698 gaim_upnp_parse_discover_response(nrd->recvBuffer, |
761 strlen(hrd->recvBuffer)))==NULL) { | 699 strlen(nrd->recvBuffer), |
762 gaim_debug_info("upnp", | 700 serviceToUse))==NULL) { |
701 gaim_debug_error("upnp", | |
763 "gaim_upnp_discover(): Failed In parse response\n\n"); | 702 "gaim_upnp_discover(): Failed In parse response\n\n"); |
764 free(hrd->recvBuffer); | 703 g_free(nrd->recvBuffer); |
765 free(hrd); | 704 g_free(nrd); |
705 g_free(controlInfo); | |
766 return NULL; | 706 return NULL; |
767 } | 707 } |
708 | |
709 controlInfo->serviceType = g_strdup(serviceToUse); | |
768 } | 710 } |
769 } | 711 } |
770 | 712 |
771 /* if sent success and recv successful, then break */ | 713 /* if sent success and recv successful, then break */ |
772 if(sentSuccess && recvSuccess) { | 714 if(sentSuccess && recvSuccess) { |
773 i = NUM_UDP_ATTEMPTS; | 715 i = NUM_UDP_ATTEMPTS; |
774 } | 716 } |
775 } | 717 } |
776 | 718 |
777 if(hrd->recvBuffer != NULL) { | 719 if(nrd->recvBuffer != NULL) { |
778 free(hrd->recvBuffer); | 720 g_free(nrd->recvBuffer); |
779 } | 721 } |
780 free(hrd); | 722 g_free(sendMessage); |
723 g_free(nrd); | |
781 | 724 |
782 if(!sentSuccess || !recvSuccess) { | 725 if(!sentSuccess || !recvSuccess) { |
783 close(sock); | 726 close(sock); |
784 gaim_debug_info("upnp", | 727 gaim_debug_error("upnp", |
785 "gaim_upnp_discover(): Failed In sent/recv success\n\n"); | 728 "gaim_upnp_discover(): Failed In sent/recv success\n\n"); |
786 return NULL; | 729 g_free(controlInfo); |
787 } | 730 return NULL; |
788 | 731 } |
789 return controlURL; | 732 |
790 } | 733 return controlInfo; |
791 | 734 } |
792 | |
793 | 735 |
794 | 736 |
795 static char* | 737 static char* |
796 gaim_upnp_generate_action_message_and_send(const char* controlURL, | 738 gaim_upnp_generate_action_message_and_send(const GaimUPnPControlInfo* controlInfo, |
797 const char* actionName, | 739 const gchar* actionName, |
798 const char* actionParams) | 740 const gchar* actionParams) |
799 { | 741 { |
800 char serviceType[] = "WANIPConnection:1"; | 742 gchar* actionMessage; |
801 char* actionMessage; | 743 gchar* soapMessage; |
802 char* soapMessage; | 744 gchar* totalSendMessage; |
803 char* httpResponse; | 745 gchar* httpResponse; |
804 | 746 |
805 char* pathOfControl; | 747 gchar* pathOfControl; |
806 char* addressOfControl; | 748 gchar* addressOfControl; |
807 char* addressPortOfControl; | 749 gchar* addressPortOfControl; |
808 char* portOfControl; | 750 gchar portOfControl[MAX_PORT_SIZE]; |
809 unsigned short port; | 751 int port=0; |
810 | 752 |
811 /* set the soap message */ | 753 /* set the soap message */ |
812 if((soapMessage = (char*)malloc(strlen(SOAP_ACTION) + | 754 soapMessage = g_strdup_printf(SOAP_ACTION, actionName, |
813 strlen(serviceType) + | 755 controlInfo->serviceType, |
814 strlen(actionParams) + | 756 actionParams, actionName); |
815 strlen(actionName) + | |
816 strlen(actionName))) == NULL) { | |
817 gaim_debug_info("upnp", | |
818 "generate_action_message_and_send(): Failed MALLOC soapMessage\n\n"); | |
819 return NULL; | |
820 } | |
821 sprintf(soapMessage, SOAP_ACTION, actionName, serviceType, | |
822 actionParams, actionName); | |
823 | 757 |
824 /* parse the url into address, port, path variables */ | 758 /* parse the url into address, port, path variables */ |
825 if(!gaim_upnp_parse_url(controlURL, &pathOfControl, | 759 if(!gaim_url_parse(controlInfo->controlURL, &addressOfControl, |
826 &addressOfControl, &portOfControl)) { | 760 &port, &pathOfControl, NULL, NULL)) { |
827 gaim_debug_info("upnp", | 761 gaim_debug_error("upnp", |
828 "generate_action_message_and_send(): Failed In Parse URL\n\n"); | 762 "generate_action_message_and_send(): Failed In Parse URL\n\n"); |
829 free(soapMessage); | 763 g_free(soapMessage); |
830 return NULL; | 764 return NULL; |
831 } | 765 } |
766 if(port == 0 || port == -1) { | |
767 port = DEFAULT_HTTP_PORT; | |
768 } | |
769 g_ascii_dtostr(portOfControl, MAX_PORT_SIZE, port); | |
832 | 770 |
833 /* set the addressPortOfControl variable which should have a | 771 /* set the addressPortOfControl variable which should have a |
834 form like the following: 192.168.1.1:8000 */ | 772 form like the following: 192.168.1.1:8000 */ |
835 if((addressPortOfControl = (char*)malloc(strlen(addressOfControl) + | 773 addressPortOfControl = g_strdup_printf("%s:%s", |
836 strlen(portOfControl) + | 774 addressOfControl, portOfControl); |
837 2)) == NULL) { | |
838 gaim_debug_info("upnp", | |
839 "generate_action_message_and_send(): MALLOC addressPortOfControl\n\n"); | |
840 free(soapMessage); | |
841 free(pathOfControl); | |
842 free(addressOfControl); | |
843 free(portOfControl); | |
844 return NULL; | |
845 } | |
846 sprintf(addressPortOfControl, "%s:%s", addressOfControl, portOfControl); | |
847 if((port = atoi(portOfControl)) == 0) { | |
848 gaim_debug_info("upnp", | |
849 "generate_action_message_and_send(): Failed In port = atoi\n\n"); | |
850 free(soapMessage); | |
851 free(pathOfControl); | |
852 free(addressOfControl); | |
853 free(portOfControl); | |
854 free(addressPortOfControl); | |
855 return NULL; | |
856 } | |
857 | 775 |
858 /* set the HTTP Header */ | 776 /* set the HTTP Header */ |
859 if((actionMessage = (char*)malloc(strlen(HTTP_HEADER_ACTION) + | 777 actionMessage = g_strdup_printf(HTTP_HEADER_ACTION, |
860 strlen(pathOfControl) + | 778 pathOfControl, addressPortOfControl, |
861 strlen(addressPortOfControl) + | 779 controlInfo->serviceType, actionName, |
862 strlen(serviceType) + | 780 strlen(soapMessage)); |
863 strlen(actionName) + | |
864 strlen(soapMessage))) == NULL) { | |
865 gaim_debug_info("upnp", | |
866 "generate_action_message_and_send(): Failed MALLOC actionMessage\n\n"); | |
867 free(soapMessage); | |
868 free(pathOfControl); | |
869 free(addressOfControl); | |
870 free(portOfControl); | |
871 free(addressPortOfControl); | |
872 return NULL; | |
873 } | |
874 sprintf(actionMessage, HTTP_HEADER_ACTION, | |
875 pathOfControl, addressPortOfControl, | |
876 serviceType, actionName, strlen(soapMessage)); | |
877 | 781 |
878 /* append to the header the body */ | 782 /* append to the header the body */ |
879 strcat(actionMessage, soapMessage); | 783 totalSendMessage = g_strdup_printf("%s%s", actionMessage, soapMessage); |
880 | 784 |
881 /* get the return of the http response */ | 785 /* get the return of the http response */ |
882 httpResponse = gaim_upnp_http_request(addressOfControl, | 786 httpResponse = gaim_upnp_http_request(addressOfControl, |
883 port, actionMessage); | 787 port, totalSendMessage); |
884 if(httpResponse == NULL) { | 788 if(httpResponse == NULL) { |
885 gaim_debug_info("upnp", | 789 gaim_debug_error("upnp", |
886 "generate_action_message_and_send(): Failed In httpResponse\n\n"); | 790 "generate_action_message_and_send(): Failed In httpResponse\n\n"); |
887 } | 791 } |
888 | 792 |
889 free(actionMessage); | 793 g_free(actionMessage); |
890 free(soapMessage); | 794 g_free(soapMessage); |
891 free(pathOfControl); | 795 g_free(totalSendMessage); |
892 free(addressOfControl); | 796 g_free(pathOfControl); |
893 free(portOfControl); | 797 g_free(addressOfControl); |
894 free(addressPortOfControl); | 798 g_free(addressPortOfControl); |
895 | 799 |
896 return httpResponse; | 800 return httpResponse; |
897 } | 801 } |
898 | 802 |
899 | 803 |
900 | 804 |
901 | 805 |
902 char* | 806 gchar* |
903 gaim_upnp_get_public_ip(const char* controlURL) | 807 gaim_upnp_get_public_ip(const GaimUPnPControlInfo* controlInfo) |
904 { | 808 { |
905 char* extIPAddress; | 809 gchar* extIPAddress; |
906 char* httpResponse; | 810 gchar* httpResponse; |
907 char actionName[] = "GetExternalIPAddress"; | 811 gchar actionName[] = "GetExternalIPAddress"; |
908 char actionParams[] = ""; | 812 gchar actionParams[] = ""; |
909 char* temp, *temp2; | 813 gchar* temp, *temp2; |
910 | 814 |
911 /* make sure controlURL is a valid URL */ | 815 httpResponse = gaim_upnp_generate_action_message_and_send(controlInfo, |
912 if(!gaim_upnp_validate_url(controlURL)) { | |
913 gaim_debug_info("upnp", | |
914 "gaim_upnp_get_public_ip(): Failed In Validate URL\n\n"); | |
915 return NULL; | |
916 } | |
917 | |
918 httpResponse = gaim_upnp_generate_action_message_and_send(controlURL, | |
919 actionName, | 816 actionName, |
920 actionParams); | 817 actionParams); |
921 if(httpResponse == NULL) { | 818 if(httpResponse == NULL) { |
922 gaim_debug_info("upnp", | 819 gaim_debug_error("upnp", |
923 "gaim_upnp_get_public_ip(): Failed In httpResponse\n\n"); | 820 "gaim_upnp_get_public_ip(): Failed In httpResponse\n\n"); |
924 return NULL; | 821 return NULL; |
925 } | 822 } |
926 | 823 |
927 /* extract the ip, or see if there is an error */ | 824 /* extract the ip, or see if there is an error */ |
928 /* at some point, maybe extract the ip using an xml library */ | 825 if((temp = g_strstr_len(httpResponse, strlen(httpResponse), |
929 if((temp = strstr(httpResponse, "<NewExternalIPAddress")) == NULL) { | 826 "<NewExternalIPAddress")) == NULL) { |
930 gaim_debug_info("upnp", | 827 gaim_debug_error("upnp", |
931 "gaim_upnp_get_public_ip(): Failed Finding <NewExternalIPAddress\n\n"); | 828 "gaim_upnp_get_public_ip(): Failed Finding <NewExternalIPAddress\n\n"); |
932 free(httpResponse); | 829 g_free(httpResponse); |
933 return NULL; | 830 return NULL; |
934 } | 831 } |
935 if((temp = strchr(temp, '>')) == NULL) { | 832 if((temp = g_strstr_len(temp, strlen(temp), ">")) == NULL) { |
936 gaim_debug_info("upnp", | 833 gaim_debug_error("upnp", |
937 "gaim_upnp_get_public_ip(): Failed In Finding >\n\n"); | 834 "gaim_upnp_get_public_ip(): Failed In Finding >\n\n"); |
938 free(httpResponse); | 835 g_free(httpResponse); |
939 return NULL; | 836 return NULL; |
940 } | 837 } |
941 if((temp2 = strchr(temp, '<')) == NULL) { | 838 if((temp2 = g_strstr_len(temp, strlen(temp), "<")) == NULL) { |
942 gaim_debug_info("upnp", | 839 gaim_debug_error("upnp", |
943 "gaim_upnp_get_public_ip(): Failed In Finding <\n\n"); | 840 "gaim_upnp_get_public_ip(): Failed In Finding <\n\n"); |
944 free(httpResponse); | 841 g_free(httpResponse); |
945 return NULL; | 842 return NULL; |
946 } | 843 } |
947 if((extIPAddress = (char*)malloc(temp2-temp)) == NULL) { | 844 |
948 gaim_debug_info("upnp", | 845 extIPAddress = g_strndup(&temp[1], (temp2-1)-temp); |
949 "gaim_upnp_get_public_ip(): Failed In MALLOC extIPAddress\n\n"); | 846 |
950 free(httpResponse); | 847 g_free(httpResponse); |
951 return NULL; | 848 |
952 } | 849 gaim_debug_info("upnp", "NAT Returned IP: %s\n", extIPAddress); |
953 memcpy(extIPAddress, &temp[1], (temp2-1)-temp); | |
954 extIPAddress[(temp2-1)-temp] = '\0'; | |
955 | |
956 free(httpResponse); | |
957 gaim_debug_info("upnp", | |
958 "gaim_upnp_get_public_ip() IP: %s\n\n", extIPAddress); | |
959 return extIPAddress; | 850 return extIPAddress; |
960 } | 851 } |
961 | 852 |
962 | 853 static void |
963 | 854 gaim_upnp_get_local_system_ip(gpointer data, |
964 static const char* | 855 gint sock, |
965 gaim_upnp_get_local_ip_address(const char* address) { | 856 GaimInputCondition cond) |
966 const char* ip; | 857 { |
967 int sock; | 858 NetResponseData* nrd = data; |
968 struct sockaddr_in serv_addr; | 859 nrd->recvBuffer = gaim_network_get_local_system_ip(sock); |
969 struct hostent *server; | 860 |
970 char* pathOfControl; | 861 gaim_timeout_remove(nrd->tima); |
971 char* addressOfControl; | 862 nrd->done = TRUE; |
972 char* portOfControl; | 863 |
973 unsigned short port; | 864 close(sock); |
974 | 865 } |
975 /* parse the url into address, port, path variables */ | 866 |
976 if(!gaim_upnp_parse_url(address, &pathOfControl, | 867 static const gchar* |
977 &addressOfControl, &portOfControl)) { | 868 gaim_upnp_get_local_ip_address(const gchar* address) |
978 gaim_debug_info("upnp", | 869 { |
870 const gchar* ip; | |
871 gchar* pathOfControl; | |
872 gchar* addressOfControl; | |
873 int port = 0; | |
874 NetResponseData* nrd = (NetResponseData*)g_malloc0(sizeof(NetResponseData)); | |
875 | |
876 if(!gaim_url_parse(address, &addressOfControl, | |
877 &port, &pathOfControl, NULL, NULL)) { | |
878 gaim_debug_error("upnp", | |
979 "get_local_ip_address(): Failed In Parse URL\n\n"); | 879 "get_local_ip_address(): Failed In Parse URL\n\n"); |
980 return NULL; | 880 return NULL; |
981 } | 881 } |
982 if((port = atoi(portOfControl)) == 0) { | 882 if(port == 0 || port == -1) { |
983 gaim_debug_info("upnp", | 883 port = DEFAULT_HTTP_PORT; |
984 "get_local_ip_address(): Failed In port = atoi\n\n"); | 884 } |
985 return NULL; | 885 |
986 } | 886 nrd->tima = gaim_timeout_add(RECIEVE_TIMEOUT, |
987 | 887 (GSourceFunc)gaim_upnp_timeout, nrd); |
988 sock = socket(AF_INET, SOCK_STREAM, 0); | 888 |
989 if(sock < 0) { | 889 if(gaim_proxy_connect(NULL, addressOfControl, port, |
990 gaim_debug_info("upnp", | 890 gaim_upnp_get_local_system_ip, nrd)) { |
991 "get_local_ip_address(): Failed In sock creation\n\n"); | 891 |
992 return NULL; | 892 gaim_debug_error("upnp", "Get Local IP Connect Failed: Address: %s @@@ Port %d @@@ Request %s\n\n", |
993 } | 893 address, port, nrd->sendBuffer); |
994 | 894 |
995 server = gethostbyname(addressOfControl); | 895 gaim_timeout_remove(nrd->tima); |
996 if(server == NULL) { | 896 } else { |
997 gaim_debug_info("upnp", | 897 while (!nrd->done) { |
998 "get_local_ip_address(): Failed In gethostbyname\n\n"); | 898 gtk_main_iteration(); |
999 close(sock); | 899 } |
1000 return NULL; | 900 } |
1001 } | 901 |
1002 memset((char*)&serv_addr, 0, sizeof(serv_addr)); | 902 ip = nrd->recvBuffer; |
1003 serv_addr.sin_family = AF_INET; | 903 g_free(nrd); |
1004 memcpy(&serv_addr.sin_addr, | 904 |
1005 server->h_addr_list[0], | 905 gaim_debug_info("upnp", "local ip: %s\n", ip); |
1006 server->h_length); | 906 |
1007 serv_addr.sin_port = htons(port); | |
1008 | |
1009 if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0) { | |
1010 gaim_debug_info("upnp", | |
1011 "get_local_ip_address(): Failed In connect\n\n"); | |
1012 close(sock); | |
1013 return NULL; | |
1014 } | |
1015 | |
1016 ip = gaim_network_get_local_system_ip(sock); | |
1017 | |
1018 close(sock); | |
1019 return ip; | 907 return ip; |
1020 } | 908 } |
1021 | 909 |
1022 | 910 |
1023 | 911 |
1024 gboolean | 912 gboolean |
1025 gaim_upnp_set_port_mapping(const char* controlURL, unsigned short portMap, | 913 gaim_upnp_set_port_mapping(const GaimUPnPControlInfo* controlInfo, |
1026 const char* protocol) | 914 unsigned short portMap, |
1027 { | 915 const gchar* protocol) |
1028 char* httpResponse; | 916 { |
1029 char actionName[] = "AddPortMapping"; | 917 gchar* httpResponse; |
1030 char* actionParams; | 918 gchar actionName[] = "AddPortMapping"; |
1031 const char* internalIP; | 919 gchar* actionParams; |
1032 | 920 const gchar* internalIP; |
1033 /* make sure controlURL is a valid URL */ | |
1034 if(!gaim_upnp_validate_url(controlURL)) { | |
1035 gaim_debug_info("upnp", | |
1036 "gaim_upnp_set_port_mapping(): Failed In Validate URL\n\n"); | |
1037 return FALSE; | |
1038 } | |
1039 | 921 |
1040 /* get the internal IP */ | 922 /* get the internal IP */ |
1041 if((internalIP = gaim_upnp_get_local_ip_address(controlURL)) == NULL) { | 923 if((internalIP = gaim_upnp_get_local_ip_address(controlInfo->controlURL)) |
1042 gaim_debug_info("upnp", | 924 == NULL) { |
925 gaim_debug_error("upnp", | |
1043 "gaim_upnp_set_port_mapping(): couldn't get local ip\n\n"); | 926 "gaim_upnp_set_port_mapping(): couldn't get local ip\n\n"); |
1044 return FALSE; | 927 return FALSE; |
1045 } | 928 } |
1046 | 929 |
1047 /* make the portMappingParams variable */ | 930 /* make the portMappingParams variable */ |
1048 if((actionParams = (char*)malloc(strlen(ADD_PORT_MAPPING_PARAMS) + | 931 actionParams = g_strdup_printf(ADD_PORT_MAPPING_PARAMS, portMap, |
1049 strlen(internalIP) + | 932 protocol, portMap, internalIP); |
1050 10 + /* size of port as int * 2 */ | 933 |
1051 strlen(protocol))) == NULL) { | 934 httpResponse = gaim_upnp_generate_action_message_and_send(controlInfo, |
1052 gaim_debug_info("upnp", | |
1053 "gaim_upnp_set_port_mapping(): Failed MALLOC portMappingParams\n\n"); | |
1054 return FALSE; | |
1055 } | |
1056 sprintf(actionParams, ADD_PORT_MAPPING_PARAMS, portMap, | |
1057 protocol, portMap, internalIP); | |
1058 | |
1059 httpResponse = gaim_upnp_generate_action_message_and_send(controlURL, | |
1060 actionName, | 935 actionName, |
1061 actionParams); | 936 actionParams); |
1062 | |
1063 if(httpResponse == NULL) { | 937 if(httpResponse == NULL) { |
1064 gaim_debug_info("upnp", | 938 gaim_debug_error("upnp", |
1065 "gaim_upnp_set_port_mapping(): Failed In httpResponse\n\n"); | 939 "gaim_upnp_set_port_mapping(): Failed In httpResponse\n\n"); |
1066 free(actionParams); | 940 g_free(actionParams); |
1067 return FALSE; | 941 return FALSE; |
1068 } | 942 } |
1069 | 943 |
1070 /* determine if port mapping was a success */ | 944 /* determine if port mapping was a success */ |
1071 if(strstr(httpResponse, HTTP_OK) == NULL) { | 945 if(strstr(httpResponse, HTTP_OK) == NULL) { |
1072 gaim_debug_info("upnp", | 946 gaim_debug_error("upnp", |
1073 "gaim_upnp_set_port_mapping(): Failed HTTP_OK\n\n%s\n\n", httpResponse); | 947 "gaim_upnp_set_port_mapping(): Failed HTTP_OK\n\n%s\n\n", httpResponse); |
1074 free(actionParams); | 948 g_free(actionParams); |
1075 free(httpResponse); | 949 g_free(httpResponse); |
1076 return FALSE; | 950 return FALSE; |
1077 } | 951 } |
1078 | 952 |
1079 free(actionParams); | 953 g_free(actionParams); |
1080 free(httpResponse); | 954 g_free(httpResponse); |
955 | |
956 gaim_debug_info("upnp", "NAT Added Port Forward On Port: %d: To IP: %s\n", portMap, internalIP); | |
1081 return TRUE; | 957 return TRUE; |
1082 } | 958 } |
1083 | 959 |
1084 | 960 |
1085 gboolean | 961 gboolean |
1086 gaim_upnp_remove_port_mapping(const char* controlURL, unsigned short portMap, | 962 gaim_upnp_remove_port_mapping(const GaimUPnPControlInfo* controlInfo, |
1087 const char* protocol) | 963 unsigned short portMap, |
1088 { | 964 const char* protocol) |
1089 char* httpResponse; | 965 { |
1090 char actionName[] = "DeletePortMapping"; | 966 gchar* httpResponse; |
1091 char* actionParams; | 967 gchar actionName[] = "DeletePortMapping"; |
1092 | 968 gchar* actionParams; |
1093 /* make sure controlURL is a valid URL */ | |
1094 if(!gaim_upnp_validate_url(controlURL)) { | |
1095 gaim_debug_info("upnp", | |
1096 "gaim_upnp_set_port_mapping(): Failed In Validate URL\n\n"); | |
1097 return FALSE; | |
1098 } | |
1099 | 969 |
1100 /* make the portMappingParams variable */ | 970 /* make the portMappingParams variable */ |
1101 if((actionParams = (char*)malloc(strlen(DELETE_PORT_MAPPING_PARAMS) + | 971 actionParams = g_strdup_printf(DELETE_PORT_MAPPING_PARAMS, |
1102 5 + /* size of port as int */ | 972 portMap, protocol); |
1103 strlen(protocol))) == NULL) { | 973 |
1104 gaim_debug_info("upnp", | 974 httpResponse = gaim_upnp_generate_action_message_and_send(controlInfo, |
1105 "gaim_upnp_set_port_mapping(): Failed MALLOC portMappingParams\n\n"); | |
1106 return FALSE; | |
1107 } | |
1108 sprintf(actionParams, DELETE_PORT_MAPPING_PARAMS, | |
1109 portMap, protocol); | |
1110 | |
1111 httpResponse = gaim_upnp_generate_action_message_and_send(controlURL, | |
1112 actionName, | 975 actionName, |
1113 actionParams); | 976 actionParams); |
1114 | 977 |
1115 if(httpResponse == NULL) { | 978 if(httpResponse == NULL) { |
1116 gaim_debug_info("upnp", | 979 gaim_debug_error("upnp", |
1117 "gaim_upnp_set_port_mapping(): Failed In httpResponse\n\n"); | 980 "gaim_upnp_remove_port_mapping(): Failed In httpResponse\n\n"); |
1118 free(actionParams); | 981 g_free(actionParams); |
1119 return FALSE; | 982 return FALSE; |
1120 } | 983 } |
1121 | 984 |
1122 /* determine if port mapping was a success */ | 985 /* determine if port mapping was a success */ |
1123 if(strstr(httpResponse, HTTP_OK) == NULL) { | 986 if(strstr(httpResponse, HTTP_OK) == NULL) { |
1124 gaim_debug_info("upnp", | 987 gaim_debug_error("upnp", |
1125 "gaim_upnp_set_port_mapping(): Failed HTTP_OK\n\n%s\n\n", httpResponse); | 988 "gaim_upnp_set_port_mapping(): Failed HTTP_OK\n\n%s\n\n", httpResponse); |
1126 free(actionParams); | 989 g_free(actionParams); |
1127 free(httpResponse); | 990 g_free(httpResponse); |
1128 return FALSE; | 991 return FALSE; |
1129 } | 992 } |
1130 | 993 |
1131 free(actionParams); | 994 g_free(actionParams); |
1132 free(httpResponse); | 995 g_free(httpResponse); |
996 | |
997 gaim_debug_info("upnp", "NAT Removed Port Forward On Port: %d\n", portMap); | |
1133 return TRUE; | 998 return TRUE; |
1134 } | 999 } |