Mercurial > pidgin
annotate src/upnp.c @ 11709:cae2fb7e8594
[gaim-migrate @ 14000]
This is a patch from Casey Harkins to significantly overhaul the docklet plugin. I'm pretty happy about this because it enables us to remove a win32 GTK+ dependency on the core and all the prpls.
committer: Tailor Script <tailor@pidgin.im>
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Sat, 22 Oct 2005 01:18:08 +0000 |
parents | f9c5480ad0ce |
children | 201be1b681a4 |
rev | line source |
---|---|
11195 | 1 /** |
2 * @file upnp.c UPnP Implementation | |
3 * @ingroup core | |
4 * | |
5 * gaim | |
6 * | |
7 * Gaim is the legal property of its developers, whose names are too numerous | |
8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
9 * source distribution. | |
10 * | |
11 * This program is free software; you can redistribute it and/or modify | |
12 * it under the terms of the GNU General Public License as published by | |
13 * the Free Software Foundation; either version 2 of the License, or | |
14 * (at your option) any later version. | |
15 * | |
16 * This program is distributed in the hope that it will be useful, | |
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 * GNU General Public License for more details. | |
20 * | |
21 * You should have received a copy of the GNU General Public License | |
22 * along with this program; if not, write to the Free Software | |
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
24 */ | |
25 #include "internal.h" | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
26 #include "gaim.h" |
11195 | 27 |
28 #include "debug.h" | |
11391 | 29 #include "util.h" |
30 #include "proxy.h" | |
31 #include "xmlnode.h" | |
11195 | 32 #include "network.h" |
33 #include "eventloop.h" | |
34 #include "upnp.h" | |
35 | |
36 | |
37 /** | |
38 * Information on the httpResponse callback | |
39 */ | |
40 typedef struct | |
41 { | |
42 guint inpa; /* gaim_input_add handle */ | |
43 guint tima; /* gaim_timout_add handle */ | |
11391 | 44 gchar* sendBuffer; /* send data */ |
45 gchar* recvBuffer; /* response data */ | |
11195 | 46 guint totalSizeRecv; |
47 gboolean done; | |
48 | |
11391 | 49 } NetResponseData; |
11195 | 50 |
51 | |
52 /*************************************************************** | |
53 ** General Defines * | |
54 ****************************************************************/ | |
55 #define HTTP_OK "200 OK" | |
11391 | 56 #define DEFAULT_HTTP_PORT 80 |
57 #define MAX_PORT_SIZE 6 | |
58 #define SIZEOF_HTTP 7 /* size of "http://" string */ | |
11492 | 59 #define RECEIVE_TIMEOUT 10000 |
60 #define CONSECUTIVE_RECEIVE_TIMEOUT 500 | |
11195 | 61 #define DISCOVERY_TIMEOUT 1000 |
62 | |
63 | |
64 /*************************************************************** | |
65 ** Discovery/Description Defines * | |
66 ****************************************************************/ | |
67 #define NUM_UDP_ATTEMPTS 2 | |
68 | |
69 /* Address and port of an SSDP request used for discovery */ | |
70 #define HTTPMU_HOST_ADDRESS "239.255.255.250" | |
71 #define HTTPMU_HOST_PORT 1900 | |
72 | |
73 #define SEARCH_REQUEST_DEVICE "urn:schemas-upnp-org:service:" \ | |
11391 | 74 "%s" |
11195 | 75 |
76 #define SEARCH_REQUEST_STRING "M-SEARCH * HTTP/1.1\r\n" \ | |
77 "MX: 2\r\n" \ | |
78 "HOST: 239.255.255.250:1900\r\n" \ | |
79 "MAN: \"ssdp:discover\"\r\n" \ | |
80 "ST: urn:schemas-upnp-org:service:" \ | |
11391 | 81 "%s\r\n" \ |
11195 | 82 "\r\n" |
83 | |
11492 | 84 #define MAX_DISCOVERY_RECEIVE_SIZE 400 |
85 #define MAX_DESCRIPTION_RECEIVE_SIZE 7000 | |
11195 | 86 #define MAX_DESCRIPTION_HTTP_HEADER_SIZE 100 |
87 | |
88 | |
89 /****************************************************************** | |
90 ** Action Defines * | |
91 *******************************************************************/ | |
11391 | 92 #define HTTP_HEADER_ACTION "POST /%s HTTP/1.1\r\n" \ |
11195 | 93 "HOST: %s\r\n" \ |
94 "SOAPACTION: " \ | |
95 "\"urn:schemas-upnp-org:" \ | |
96 "service:%s#%s\"\r\n" \ | |
97 "CONTENT-TYPE: text/xml ; charset=\"utf-8\"\r\n"\ | |
11656
f9c5480ad0ce
[gaim-migrate @ 13940]
Richard Laager <rlaager@wiktel.com>
parents:
11586
diff
changeset
|
98 "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n" |
11195 | 99 |
100 #define SOAP_ACTION "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" \ | |
101 "<s:Envelope xmlns:s=" \ | |
102 "\"http://schemas.xmlsoap.org/soap/envelope/\" " \ | |
103 "s:encodingStyle=" \ | |
104 "\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n" \ | |
105 "<s:Body>\r\n" \ | |
106 "<u:%s xmlns:u=" \ | |
107 "\"urn:schemas-upnp-org:service:%s\">\r\n%s" \ | |
108 "</u:%s>\r\n" \ | |
109 "</s:Body>\r\n" \ | |
110 "</s:Envelope>\r\n" | |
111 | |
112 #define PORT_MAPPING_LEASE_TIME "0" | |
113 #define PORT_MAPPING_DESCRIPTION "GAIM_UPNP_PORT_FORWARD" | |
114 | |
115 #define ADD_PORT_MAPPING_PARAMS "<NewRemoteHost></NewRemoteHost>\r\n" \ | |
116 "<NewExternalPort>%i</NewExternalPort>\r\n"\ | |
117 "<NewProtocol>%s</NewProtocol>\r\n" \ | |
118 "<NewInternalPort>%i</NewInternalPort>\r\n"\ | |
119 "<NewInternalClient>%s" \ | |
120 "</NewInternalClient>\r\n" \ | |
121 "<NewEnabled>1</NewEnabled>\r\n" \ | |
122 "<NewPortMappingDescription>" \ | |
123 PORT_MAPPING_DESCRIPTION \ | |
124 "</NewPortMappingDescription>\r\n" \ | |
125 "<NewLeaseDuration>" \ | |
126 PORT_MAPPING_LEASE_TIME \ | |
127 "</NewLeaseDuration>\r\n" | |
128 | |
129 #define DELETE_PORT_MAPPING_PARAMS "<NewRemoteHost></NewRemoteHost>\r\n" \ | |
130 "<NewExternalPort>%i" \ | |
131 "</NewExternalPort>\r\n" \ | |
132 "<NewProtocol>%s</NewProtocol>\r\n" | |
133 | |
134 | |
135 static void | |
136 gaim_upnp_timeout(gpointer data, | |
11213 | 137 gint source, |
11195 | 138 GaimInputCondition cond) |
139 { | |
11391 | 140 NetResponseData* nrd = data; |
11195 | 141 |
11391 | 142 gaim_input_remove(nrd->inpa); |
143 gaim_timeout_remove(nrd->tima); | |
11195 | 144 |
11391 | 145 if(nrd->totalSizeRecv == 0 && nrd->recvBuffer != NULL) { |
146 g_free(nrd->recvBuffer); | |
147 nrd->recvBuffer = NULL; | |
148 } else if(nrd->recvBuffer != NULL) { | |
149 nrd->recvBuffer[nrd->totalSizeRecv] = '\0'; | |
11195 | 150 } |
151 | |
11391 | 152 nrd->done = TRUE; |
11195 | 153 } |
154 | |
155 | |
156 static void | |
157 gaim_upnp_http_read(gpointer data, | |
158 gint sock, | |
159 GaimInputCondition cond) | |
160 { | |
161 int sizeRecv; | |
162 extern int errno; | |
11391 | 163 NetResponseData* nrd = data; |
11195 | 164 |
11391 | 165 sizeRecv = recv(sock, &(nrd->recvBuffer[nrd->totalSizeRecv]), |
11492 | 166 MAX_DESCRIPTION_RECEIVE_SIZE-nrd->totalSizeRecv, 0); |
11195 | 167 if(sizeRecv < 0 && errno != EINTR) { |
11391 | 168 gaim_debug_error("upnp", |
11195 | 169 "gaim_upnp_http_read(): recv < 0: %i!\n\n", errno); |
11391 | 170 g_free(nrd->recvBuffer); |
171 nrd->recvBuffer = NULL; | |
172 gaim_timeout_remove(nrd->tima); | |
173 gaim_input_remove(nrd->inpa); | |
174 nrd->done = TRUE; | |
11195 | 175 return; |
176 }else if(errno == EINTR) { | |
177 sizeRecv = 0; | |
178 } | |
11391 | 179 nrd->totalSizeRecv += sizeRecv; |
11195 | 180 |
181 if(sizeRecv == 0) { | |
11391 | 182 gaim_timeout_remove(nrd->tima); |
183 gaim_input_remove(nrd->inpa); | |
184 if(nrd->totalSizeRecv == 0) { | |
185 gaim_debug_error("upnp", | |
11195 | 186 "gaim_upnp_http_read(): totalSizeRecv == 0\n\n"); |
11391 | 187 g_free(nrd->recvBuffer); |
188 nrd->recvBuffer = NULL; | |
11195 | 189 } else { |
11391 | 190 nrd->recvBuffer[nrd->totalSizeRecv] = '\0'; |
11195 | 191 } |
11391 | 192 nrd->done = TRUE; |
11195 | 193 } else { |
11391 | 194 gaim_timeout_remove(nrd->tima); |
195 gaim_input_remove(nrd->inpa); | |
11492 | 196 nrd->tima = gaim_timeout_add(CONSECUTIVE_RECEIVE_TIMEOUT, |
11391 | 197 (GSourceFunc)gaim_upnp_timeout, nrd); |
198 nrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, | |
199 gaim_upnp_http_read, nrd); | |
11195 | 200 } |
201 } | |
202 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
203 static void |
11391 | 204 gaim_upnp_http_send(gpointer data, |
205 gint sock, | |
206 GaimInputCondition cond) | |
11195 | 207 { |
11586 | 208 gsize sizeSent, totalSizeSent = 0; |
11195 | 209 extern int errno; |
11391 | 210 NetResponseData* nrd = data; |
11195 | 211 |
11391 | 212 gaim_timeout_remove(nrd->tima); |
213 while(totalSizeSent < strlen(nrd->sendBuffer)) { | |
11586 | 214 sizeSent = send(sock,(gchar*)(nrd->sendBuffer+totalSizeSent), |
11391 | 215 strlen(nrd->sendBuffer)-totalSizeSent,0); |
11195 | 216 if(sizeSent <= 0 && errno != EINTR) { |
11391 | 217 gaim_debug_error("upnp", |
11195 | 218 "gaim_upnp_http_request(): Failed In send\n\n"); |
11391 | 219 nrd->done = TRUE; |
220 g_free(nrd->recvBuffer); | |
221 nrd->recvBuffer = NULL; | |
11195 | 222 close(sock); |
11391 | 223 return; |
11195 | 224 }else if(errno == EINTR) { |
225 sizeSent = 0; | |
226 } | |
227 totalSizeSent += sizeSent; | |
228 } | |
229 | |
11492 | 230 nrd->tima = gaim_timeout_add(RECEIVE_TIMEOUT, |
11391 | 231 (GSourceFunc)gaim_upnp_timeout, nrd); |
232 nrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, | |
233 gaim_upnp_http_read, nrd); | |
234 while (!nrd->done) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
235 g_main_context_iteration(NULL, TRUE); |
11195 | 236 } |
237 close(sock); | |
11391 | 238 } |
11195 | 239 |
11391 | 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; | |
11492 | 248 nrd->recvBuffer = (gchar*)g_malloc(MAX_DESCRIPTION_RECEIVE_SIZE); |
11391 | 249 |
11492 | 250 nrd->tima = gaim_timeout_add(RECEIVE_TIMEOUT, |
11391 | 251 (GSourceFunc)gaim_upnp_timeout, nrd); |
252 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
253 if(gaim_proxy_connect(NULL, address, port, |
11391 | 254 gaim_upnp_http_send, nrd)) { |
255 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
256 gaim_debug_error("upnp", "Connect Failed: Address: %s @@@ Port %d @@@ Request %s\n\n", |
11391 | 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) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
264 g_main_context_iteration(NULL, TRUE); |
11391 | 265 } |
266 } | |
267 | |
268 recvBuffer = nrd->recvBuffer; | |
269 g_free(nrd); | |
270 | |
11195 | 271 return recvBuffer; |
272 } | |
273 | |
274 | |
275 | |
11391 | 276 static gboolean |
277 gaim_upnp_compare_device(const xmlnode* device, | |
278 const gchar* deviceType) | |
279 { | |
280 xmlnode* deviceTypeNode = xmlnode_get_child(device, "deviceType"); | |
281 if(deviceTypeNode == NULL) { | |
282 return FALSE; | |
283 } | |
284 return !g_ascii_strcasecmp(xmlnode_get_data(deviceTypeNode), deviceType); | |
285 } | |
11195 | 286 |
11391 | 287 |
288 static gboolean | |
289 gaim_upnp_compare_service(const xmlnode* service, | |
290 const gchar* serviceType) | |
11195 | 291 { |
11391 | 292 xmlnode* serviceTypeNode = xmlnode_get_child(service, "serviceType"); |
293 if(serviceTypeNode == NULL) { | |
294 return FALSE; | |
295 } | |
296 return !g_ascii_strcasecmp(xmlnode_get_data(serviceTypeNode), serviceType); | |
297 } | |
298 | |
299 | |
11195 | 300 |
11391 | 301 static gchar* |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
302 gaim_upnp_parse_description_response(const gchar* httpResponse, |
11391 | 303 const gchar* httpURL, |
304 const gchar* serviceType) | |
305 { | |
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", | |
11195 | 318 "parse_description_response(): Failed In HTTP_OK\n\n"); |
319 return NULL; | |
320 } | |
321 | |
11391 | 322 /* find the root of the xml document */ |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
323 if((xmlRoot = g_strstr_len(httpResponse, strlen(httpResponse), |
11391 | 324 "<root")) == NULL) { |
325 gaim_debug_error("upnp", | |
326 "parse_description_response(): Failed finding root\n\n"); | |
327 return NULL; | |
328 } | |
329 | |
330 /* create the xml root node */ | |
331 if((xmlRootNode = xmlnode_from_str(xmlRoot, -1)) == NULL) { | |
332 gaim_debug_error("upnp", | |
333 "parse_description_response(): Could not parse xml root node\n\n"); | |
11195 | 334 return NULL; |
335 } | |
11391 | 336 |
337 /* get the baseURL of the device */ | |
338 if((baseURLNode = xmlnode_get_child(xmlRootNode, | |
339 "URLBase")) != NULL) { | |
340 baseURL = g_strdup(xmlnode_get_data(baseURLNode)); | |
341 } else { | |
342 baseURL = g_strdup(httpURL); | |
343 } | |
344 | |
345 /* get the serviceType child that has the service type as it's data */ | |
346 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
347 /* get urn:schemas-upnp-org:device:InternetGatewayDevice:1 |
11391 | 348 and it's devicelist */ |
349 serviceTypeNode = xmlnode_get_child(xmlRootNode, "device"); | |
350 while(!gaim_upnp_compare_device(serviceTypeNode, | |
351 "urn:schemas-upnp-org:device:InternetGatewayDevice:1") && | |
352 serviceTypeNode != NULL) { | |
353 serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); | |
354 } | |
355 if(serviceTypeNode == NULL) { | |
356 gaim_debug_error("upnp", | |
357 "parse_description_response(): could not get serviceTypeNode 1\n\n"); | |
11195 | 358 return NULL; |
359 } | |
11391 | 360 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "deviceList"); |
361 if(serviceTypeNode == NULL) { | |
362 gaim_debug_error("upnp", | |
363 "parse_description_response(): could not get serviceTypeNode 2\n\n"); | |
11195 | 364 return NULL; |
365 } | |
366 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
367 /* get urn:schemas-upnp-org:device:WANDevice:1 |
11391 | 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 } | |
11195 | 386 |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
387 /* get urn:schemas-upnp-org:device:WANConnectionDevice:1 |
11391 | 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"); | |
11195 | 398 return NULL; |
399 } | |
11391 | 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 } | |
11195 | 406 |
11391 | 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); | |
11195 | 413 } |
414 | |
11391 | 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 */ | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
423 if((controlURLNode = xmlnode_get_child(serviceTypeNode, |
11391 | 424 "controlURL")) == NULL) { |
425 gaim_debug_error("upnp", | |
426 "parse_description_response(): Could not find controlURL\n\n"); | |
427 return NULL; | |
428 } | |
429 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
430 if(g_strstr_len(xmlnode_get_data(controlURLNode), |
11391 | 431 SIZEOF_HTTP, "http://") == NULL && |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
432 g_strstr_len(xmlnode_get_data(controlURLNode), |
11391 | 433 SIZEOF_HTTP, "HTTP://") == NULL) { |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
434 controlURL = g_strdup_printf("%s%s", baseURL, |
11391 | 435 xmlnode_get_data(controlURLNode)); |
11195 | 436 }else{ |
11391 | 437 controlURL = g_strdup(xmlnode_get_data(controlURLNode)); |
11195 | 438 } |
11391 | 439 g_free(baseURL); |
440 xmlnode_free(xmlRootNode); | |
11195 | 441 |
442 return controlURL; | |
443 } | |
444 | |
445 | |
11391 | 446 static gchar* |
447 gaim_upnp_parse_description(const gchar* descriptionURL, | |
448 const gchar* serviceType) | |
11195 | 449 { |
11391 | 450 gchar* fullURL; |
451 gchar* controlURL; | |
452 gchar* httpResponse; | |
453 gchar* httpRequest; | |
11195 | 454 |
11391 | 455 gchar* descriptionXMLAddress; |
456 gchar* descriptionAddressPort; | |
457 gchar* descriptionAddress; | |
458 gchar descriptionPort[MAX_PORT_SIZE]; | |
459 int port = 0; | |
11195 | 460 |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
461 /* parse the 4 above variables out of the descriptionURL |
11195 | 462 example description URL: http://192.168.1.1:5678/rootDesc.xml */ |
463 | |
464 /* parse the url into address, port, path variables */ | |
11391 | 465 if(!gaim_url_parse(descriptionURL, &descriptionAddress, |
466 &port, &descriptionXMLAddress, NULL, NULL)) { | |
11195 | 467 return NULL; |
468 } | |
11391 | 469 if(port == 0 || port == -1) { |
470 port = DEFAULT_HTTP_PORT; | |
11195 | 471 } |
11391 | 472 g_ascii_dtostr(descriptionPort, MAX_PORT_SIZE, port); |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
473 descriptionAddressPort = g_strdup_printf("%s:%s", descriptionAddress, |
11391 | 474 descriptionPort); |
11195 | 475 |
11391 | 476 fullURL = g_strdup_printf("http://%s", descriptionAddressPort); |
11195 | 477 |
478 /* for example... | |
479 GET /rootDesc.xml HTTP/1.1\r\nHost: 192.168.1.1:5678\r\n\r\n */ | |
11391 | 480 httpRequest = g_strdup_printf("GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", |
481 descriptionXMLAddress, descriptionAddressPort); | |
11195 | 482 |
483 httpResponse = gaim_upnp_http_request(descriptionAddress, | |
484 port, httpRequest); | |
485 if(httpResponse == NULL) { | |
11391 | 486 gaim_debug_error("upnp", |
11195 | 487 "gaim_upnp_parse_description(): httpResponse is NULL\n\n"); |
11391 | 488 g_free(descriptionXMLAddress); |
489 g_free(descriptionAddress); | |
490 g_free(descriptionAddressPort); | |
491 g_free(httpRequest); | |
492 g_free(fullURL); | |
11195 | 493 return NULL; |
494 } | |
495 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
496 controlURL = gaim_upnp_parse_description_response(httpResponse, |
11391 | 497 fullURL, serviceType); |
11195 | 498 |
11391 | 499 g_free(descriptionXMLAddress); |
500 g_free(descriptionAddress); | |
501 g_free(descriptionAddressPort); | |
502 g_free(fullURL); | |
503 g_free(httpRequest); | |
504 g_free(httpResponse); | |
11195 | 505 |
506 if(controlURL == NULL) { | |
11391 | 507 gaim_debug_error("upnp", |
11195 | 508 "gaim_upnp_parse_description(): controlURL is NULL\n\n"); |
509 return NULL; | |
510 } | |
511 | |
512 return controlURL; | |
513 } | |
514 | |
515 | |
11391 | 516 static gchar* |
517 gaim_upnp_parse_discover_response(const gchar* buf, | |
518 unsigned int bufSize, | |
519 const gchar* serviceType) | |
11195 | 520 { |
11391 | 521 gchar* startDescURL; |
522 gchar* endDescURL; | |
523 gchar* descURL; | |
524 gchar* retVal; | |
11195 | 525 |
11391 | 526 if(g_strstr_len(buf, strlen(buf), HTTP_OK) == NULL) { |
527 gaim_debug_error("upnp", | |
11195 | 528 "parse_discover_response(): Failed In HTTP_OK\n\n"); |
529 return NULL; | |
530 } | |
531 | |
11391 | 532 if((startDescURL = g_strstr_len(buf, strlen(buf), "http://")) == NULL) { |
533 gaim_debug_error("upnp", | |
534 "parse_discover_response(): Failed In finding http://\n\n"); | |
11195 | 535 return NULL; |
536 } | |
537 | |
11391 | 538 endDescURL = g_strstr_len(startDescURL, strlen(startDescURL), "\r"); |
11195 | 539 if(endDescURL == NULL) { |
11391 | 540 endDescURL = g_strstr_len(startDescURL, strlen(startDescURL), "\n"); |
11195 | 541 if(endDescURL == NULL) { |
11391 | 542 gaim_debug_error("upnp", |
543 "parse_discover_response(): Failed In endDescURL\n\n"); | |
11195 | 544 return NULL; |
545 }else if(endDescURL == startDescURL) { | |
11391 | 546 gaim_debug_error("upnp", |
547 "parse_discover_response(): endDescURL == startDescURL\n\n"); | |
11195 | 548 return NULL; |
549 } | |
550 }else if(endDescURL == startDescURL) { | |
11391 | 551 gaim_debug_error("upnp", |
552 "parse_discover_response(): 2nd endDescURL == startDescURL\n\n"); | |
11195 | 553 return NULL; |
554 } | |
11391 | 555 descURL = g_strndup(startDescURL, endDescURL-startDescURL); |
11195 | 556 |
11391 | 557 retVal = gaim_upnp_parse_description(descURL, serviceType); |
558 g_free(descURL); | |
11195 | 559 return retVal; |
560 } | |
561 | |
562 | |
563 | |
564 static void | |
565 gaim_upnp_discover_udp_read(gpointer data, | |
566 gint sock, | |
567 GaimInputCondition cond) | |
568 { | |
569 unsigned int length; | |
570 extern int errno; | |
571 struct sockaddr_in from; | |
572 int sizeRecv; | |
11391 | 573 NetResponseData* nrd = data; |
11195 | 574 |
11391 | 575 gaim_timeout_remove(nrd->tima); |
11195 | 576 length = sizeof(struct sockaddr_in); |
577 | |
578 do { | |
11391 | 579 sizeRecv = recvfrom(sock, nrd->recvBuffer, |
11492 | 580 MAX_DISCOVERY_RECEIVE_SIZE, 0, |
11195 | 581 (struct sockaddr*)&from, &length); |
582 | |
583 if(sizeRecv > 0) { | |
11391 | 584 nrd->recvBuffer[sizeRecv] = '\0'; |
11195 | 585 }else if(errno != EINTR) { |
11391 | 586 g_free(nrd->recvBuffer); |
587 nrd->recvBuffer = NULL; | |
11195 | 588 } |
589 }while(errno == EINTR); | |
590 | |
11391 | 591 gaim_input_remove(nrd->inpa); |
592 nrd->done = TRUE; | |
11195 | 593 return; |
594 } | |
595 | |
596 | |
11213 | 597 |
11391 | 598 GaimUPnPControlInfo* |
11195 | 599 gaim_upnp_discover(void) |
600 { | |
11391 | 601 /* Socket Setup Variables */ |
11195 | 602 int sock, i; |
603 extern int errno; | |
604 struct sockaddr_in server; | |
11391 | 605 struct hostent* hp; |
11195 | 606 |
11391 | 607 /* UDP SEND VARIABLES */ |
608 gboolean sentSuccess, recvSuccess; | |
609 int sizeSent, totalSizeSent; | |
610 gchar wanIP[] = "WANIPConnection:1"; | |
611 gchar wanPPP[] = "WANPPPConnection:1"; | |
612 gchar* serviceToUse; | |
613 gchar* sendMessage = NULL; | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
614 |
11492 | 615 /* UDP RECEIVE VARIABLES */ |
11391 | 616 GaimUPnPControlInfo* controlInfo = g_malloc(sizeof(GaimUPnPControlInfo)); |
617 NetResponseData* nrd = g_malloc(sizeof(NetResponseData)); | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
618 |
11391 | 619 /* Set up the sockets */ |
11195 | 620 sock = socket(AF_INET, SOCK_DGRAM, 0); |
621 if (sock == -1) { | |
622 close(sock); | |
11391 | 623 gaim_debug_error("upnp", |
11195 | 624 "gaim_upnp_discover(): Failed In sock creation\n\n"); |
11391 | 625 g_free(nrd); |
626 g_free(controlInfo); | |
11195 | 627 return NULL; |
628 } | |
629 memset(&server, 0, sizeof(struct sockaddr)); | |
630 server.sin_family = AF_INET; | |
631 if((hp = gethostbyname(HTTPMU_HOST_ADDRESS)) == NULL) { | |
632 close(sock); | |
11391 | 633 gaim_debug_error("upnp", |
11195 | 634 "gaim_upnp_discover(): Failed In gethostbyname\n\n"); |
11391 | 635 g_free(nrd); |
636 g_free(controlInfo); | |
11195 | 637 return NULL; |
638 } | |
639 memcpy(&server.sin_addr, | |
640 hp->h_addr_list[0], | |
641 hp->h_length); | |
642 server.sin_port = htons(HTTPMU_HOST_PORT); | |
643 | |
644 /* because we are sending over UDP, if there is a failure | |
11391 | 645 we should retry the send NUM_UDP_ATTEMPTS times. Also, |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
646 try different requests for WANIPConnection and |
11391 | 647 WANPPPConnection*/ |
11195 | 648 for(i = 0; i < NUM_UDP_ATTEMPTS; i++) { |
649 sentSuccess = TRUE; | |
650 recvSuccess = TRUE; | |
651 totalSizeSent = 0; | |
652 | |
11391 | 653 nrd->recvBuffer = NULL; |
654 nrd->totalSizeRecv = 0; | |
655 nrd->done = FALSE; | |
656 | |
657 if(sendMessage != NULL) { | |
658 g_free(sendMessage); | |
659 } | |
11213 | 660 |
11391 | 661 if(i%2 == 0) { |
662 serviceToUse = wanIP; | |
663 } else { | |
664 serviceToUse = wanPPP; | |
11213 | 665 } |
11391 | 666 sendMessage = g_strdup_printf(SEARCH_REQUEST_STRING, serviceToUse); |
667 | |
11492 | 668 nrd->recvBuffer = (char*)g_malloc(MAX_DISCOVERY_RECEIVE_SIZE); |
11213 | 669 |
11195 | 670 while(totalSizeSent < strlen(sendMessage)) { |
671 sizeSent = sendto(sock,(void*)&sendMessage[totalSizeSent], | |
672 strlen(&sendMessage[totalSizeSent]),0, | |
673 (struct sockaddr*)&server, | |
674 sizeof(struct sockaddr_in)); | |
675 if(sizeSent <= 0 && errno != EINTR) { | |
676 sentSuccess = FALSE; | |
677 break; | |
678 }else if(errno == EINTR) { | |
679 sizeSent = 0; | |
680 } | |
681 totalSizeSent += sizeSent; | |
682 } | |
683 | |
684 if(sentSuccess) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
685 nrd->tima = gaim_timeout_add(DISCOVERY_TIMEOUT, |
11391 | 686 (GSourceFunc)gaim_upnp_timeout, nrd); |
687 nrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, | |
688 gaim_upnp_discover_udp_read, nrd); | |
689 while (!nrd->done) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
690 g_main_context_iteration(NULL, TRUE); |
11195 | 691 } |
11391 | 692 if(nrd->recvBuffer == NULL) { |
11195 | 693 recvSuccess = FALSE; |
694 } else { | |
695 /* parse the response, and see if it was a success */ | |
696 close(sock); | |
11391 | 697 if((controlInfo->controlURL= |
698 gaim_upnp_parse_discover_response(nrd->recvBuffer, | |
699 strlen(nrd->recvBuffer), | |
700 serviceToUse))==NULL) { | |
701 gaim_debug_error("upnp", | |
11195 | 702 "gaim_upnp_discover(): Failed In parse response\n\n"); |
11391 | 703 g_free(nrd->recvBuffer); |
704 g_free(nrd); | |
705 g_free(controlInfo); | |
11195 | 706 return NULL; |
707 } | |
11391 | 708 |
709 controlInfo->serviceType = g_strdup(serviceToUse); | |
11195 | 710 } |
711 } | |
712 | |
713 /* if sent success and recv successful, then break */ | |
714 if(sentSuccess && recvSuccess) { | |
715 i = NUM_UDP_ATTEMPTS; | |
716 } | |
717 } | |
11213 | 718 |
11391 | 719 if(nrd->recvBuffer != NULL) { |
720 g_free(nrd->recvBuffer); | |
11213 | 721 } |
11391 | 722 g_free(sendMessage); |
723 g_free(nrd); | |
11213 | 724 |
11195 | 725 if(!sentSuccess || !recvSuccess) { |
726 close(sock); | |
11391 | 727 gaim_debug_error("upnp", |
11195 | 728 "gaim_upnp_discover(): Failed In sent/recv success\n\n"); |
11391 | 729 g_free(controlInfo); |
11195 | 730 return NULL; |
731 } | |
732 | |
11391 | 733 return controlInfo; |
11195 | 734 } |
735 | |
736 | |
737 static char* | |
11391 | 738 gaim_upnp_generate_action_message_and_send(const GaimUPnPControlInfo* controlInfo, |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
739 const gchar* actionName, |
11391 | 740 const gchar* actionParams) |
11195 | 741 { |
11391 | 742 gchar* actionMessage; |
743 gchar* soapMessage; | |
744 gchar* totalSendMessage; | |
745 gchar* httpResponse; | |
11195 | 746 |
11391 | 747 gchar* pathOfControl; |
748 gchar* addressOfControl; | |
749 gchar* addressPortOfControl; | |
750 gchar portOfControl[MAX_PORT_SIZE]; | |
751 int port=0; | |
11195 | 752 |
753 /* set the soap message */ | |
11391 | 754 soapMessage = g_strdup_printf(SOAP_ACTION, actionName, |
755 controlInfo->serviceType, | |
756 actionParams, actionName); | |
11195 | 757 |
758 /* parse the url into address, port, path variables */ | |
11391 | 759 if(!gaim_url_parse(controlInfo->controlURL, &addressOfControl, |
760 &port, &pathOfControl, NULL, NULL)) { | |
761 gaim_debug_error("upnp", | |
11195 | 762 "generate_action_message_and_send(): Failed In Parse URL\n\n"); |
11391 | 763 g_free(soapMessage); |
11195 | 764 return NULL; |
765 } | |
11391 | 766 if(port == 0 || port == -1) { |
767 port = DEFAULT_HTTP_PORT; | |
768 } | |
769 g_ascii_dtostr(portOfControl, MAX_PORT_SIZE, port); | |
11195 | 770 |
771 /* set the addressPortOfControl variable which should have a | |
772 form like the following: 192.168.1.1:8000 */ | |
11391 | 773 addressPortOfControl = g_strdup_printf("%s:%s", |
774 addressOfControl, portOfControl); | |
11195 | 775 |
776 /* set the HTTP Header */ | |
11391 | 777 actionMessage = g_strdup_printf(HTTP_HEADER_ACTION, |
778 pathOfControl, addressPortOfControl, | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
779 controlInfo->serviceType, actionName, |
11391 | 780 strlen(soapMessage)); |
11195 | 781 |
782 /* append to the header the body */ | |
11391 | 783 totalSendMessage = g_strdup_printf("%s%s", actionMessage, soapMessage); |
11195 | 784 |
785 /* get the return of the http response */ | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
786 httpResponse = gaim_upnp_http_request(addressOfControl, |
11391 | 787 port, totalSendMessage); |
11195 | 788 if(httpResponse == NULL) { |
11391 | 789 gaim_debug_error("upnp", |
11195 | 790 "generate_action_message_and_send(): Failed In httpResponse\n\n"); |
791 } | |
792 | |
11391 | 793 g_free(actionMessage); |
794 g_free(soapMessage); | |
795 g_free(totalSendMessage); | |
796 g_free(pathOfControl); | |
797 g_free(addressOfControl); | |
798 g_free(addressPortOfControl); | |
11195 | 799 |
800 return httpResponse; | |
801 } | |
802 | |
803 | |
804 | |
805 | |
11391 | 806 gchar* |
807 gaim_upnp_get_public_ip(const GaimUPnPControlInfo* controlInfo) | |
11195 | 808 { |
11391 | 809 gchar* extIPAddress; |
810 gchar* httpResponse; | |
811 gchar actionName[] = "GetExternalIPAddress"; | |
812 gchar actionParams[] = ""; | |
813 gchar* temp, *temp2; | |
11195 | 814 |
11391 | 815 httpResponse = gaim_upnp_generate_action_message_and_send(controlInfo, |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
816 actionName, |
11195 | 817 actionParams); |
818 if(httpResponse == NULL) { | |
11391 | 819 gaim_debug_error("upnp", |
11195 | 820 "gaim_upnp_get_public_ip(): Failed In httpResponse\n\n"); |
821 return NULL; | |
822 } | |
823 | |
824 /* extract the ip, or see if there is an error */ | |
11391 | 825 if((temp = g_strstr_len(httpResponse, strlen(httpResponse), |
826 "<NewExternalIPAddress")) == NULL) { | |
827 gaim_debug_error("upnp", | |
11195 | 828 "gaim_upnp_get_public_ip(): Failed Finding <NewExternalIPAddress\n\n"); |
11391 | 829 g_free(httpResponse); |
11195 | 830 return NULL; |
831 } | |
11391 | 832 if((temp = g_strstr_len(temp, strlen(temp), ">")) == NULL) { |
833 gaim_debug_error("upnp", | |
11195 | 834 "gaim_upnp_get_public_ip(): Failed In Finding >\n\n"); |
11391 | 835 g_free(httpResponse); |
11195 | 836 return NULL; |
837 } | |
11391 | 838 if((temp2 = g_strstr_len(temp, strlen(temp), "<")) == NULL) { |
839 gaim_debug_error("upnp", | |
11195 | 840 "gaim_upnp_get_public_ip(): Failed In Finding <\n\n"); |
11391 | 841 g_free(httpResponse); |
11195 | 842 return NULL; |
843 } | |
11391 | 844 |
845 extIPAddress = g_strndup(&temp[1], (temp2-1)-temp); | |
11195 | 846 |
11391 | 847 g_free(httpResponse); |
848 | |
849 gaim_debug_info("upnp", "NAT Returned IP: %s\n", extIPAddress); | |
11195 | 850 return extIPAddress; |
851 } | |
852 | |
11391 | 853 static void |
854 gaim_upnp_get_local_system_ip(gpointer data, | |
855 gint sock, | |
856 GaimInputCondition cond) | |
857 { | |
858 NetResponseData* nrd = data; | |
11443
d9d60002065b
[gaim-migrate @ 13682]
Richard Laager <rlaager@wiktel.com>
parents:
11391
diff
changeset
|
859 nrd->recvBuffer = g_strdup(gaim_network_get_local_system_ip(sock)); |
11195 | 860 |
11391 | 861 gaim_timeout_remove(nrd->tima); |
862 nrd->done = TRUE; | |
11195 | 863 |
11391 | 864 close(sock); |
865 } | |
11195 | 866 |
11492 | 867 static gchar* |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
868 gaim_upnp_get_local_ip_address(const gchar* address) |
11391 | 869 { |
11492 | 870 gchar* ip; |
11391 | 871 gchar* pathOfControl; |
872 gchar* addressOfControl; | |
873 int port = 0; | |
874 NetResponseData* nrd = (NetResponseData*)g_malloc0(sizeof(NetResponseData)); | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
875 |
11391 | 876 if(!gaim_url_parse(address, &addressOfControl, |
877 &port, &pathOfControl, NULL, NULL)) { | |
878 gaim_debug_error("upnp", | |
11195 | 879 "get_local_ip_address(): Failed In Parse URL\n\n"); |
880 return NULL; | |
881 } | |
11391 | 882 if(port == 0 || port == -1) { |
883 port = DEFAULT_HTTP_PORT; | |
11195 | 884 } |
885 | |
11492 | 886 nrd->tima = gaim_timeout_add(RECEIVE_TIMEOUT, |
11391 | 887 (GSourceFunc)gaim_upnp_timeout, nrd); |
888 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
889 if(gaim_proxy_connect(NULL, addressOfControl, port, |
11391 | 890 gaim_upnp_get_local_system_ip, nrd)) { |
11195 | 891 |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
892 gaim_debug_error("upnp", "Get Local IP Connect Failed: Address: %s @@@ Port %d @@@ Request %s\n\n", |
11391 | 893 address, port, nrd->sendBuffer); |
894 | |
895 gaim_timeout_remove(nrd->tima); | |
896 } else { | |
897 while (!nrd->done) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
898 g_main_context_iteration(NULL, TRUE); |
11391 | 899 } |
11195 | 900 } |
901 | |
11391 | 902 ip = nrd->recvBuffer; |
903 g_free(nrd); | |
11195 | 904 |
11391 | 905 gaim_debug_info("upnp", "local ip: %s\n", ip); |
906 | |
11195 | 907 return ip; |
908 } | |
909 | |
910 | |
911 | |
912 gboolean | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
913 gaim_upnp_set_port_mapping(const GaimUPnPControlInfo* controlInfo, |
11391 | 914 unsigned short portMap, |
915 const gchar* protocol) | |
11195 | 916 { |
11391 | 917 gchar* httpResponse; |
918 gchar actionName[] = "AddPortMapping"; | |
919 gchar* actionParams; | |
11492 | 920 gchar* internalIP; |
11195 | 921 |
922 /* get the internal IP */ | |
11391 | 923 if((internalIP = gaim_upnp_get_local_ip_address(controlInfo->controlURL)) |
924 == NULL) { | |
925 gaim_debug_error("upnp", | |
11195 | 926 "gaim_upnp_set_port_mapping(): couldn't get local ip\n\n"); |
927 return FALSE; | |
928 } | |
929 | |
930 /* make the portMappingParams variable */ | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
931 actionParams = g_strdup_printf(ADD_PORT_MAPPING_PARAMS, portMap, |
11391 | 932 protocol, portMap, internalIP); |
11195 | 933 |
11391 | 934 httpResponse = gaim_upnp_generate_action_message_and_send(controlInfo, |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
935 actionName, |
11195 | 936 actionParams); |
937 if(httpResponse == NULL) { | |
11391 | 938 gaim_debug_error("upnp", |
11195 | 939 "gaim_upnp_set_port_mapping(): Failed In httpResponse\n\n"); |
11391 | 940 g_free(actionParams); |
11492 | 941 g_free(internalIP); |
11195 | 942 return FALSE; |
943 } | |
944 | |
945 /* determine if port mapping was a success */ | |
946 if(strstr(httpResponse, HTTP_OK) == NULL) { | |
11391 | 947 gaim_debug_error("upnp", |
11195 | 948 "gaim_upnp_set_port_mapping(): Failed HTTP_OK\n\n%s\n\n", httpResponse); |
11391 | 949 g_free(actionParams); |
950 g_free(httpResponse); | |
11492 | 951 g_free(internalIP); |
11195 | 952 return FALSE; |
953 } | |
954 | |
11391 | 955 g_free(actionParams); |
956 g_free(httpResponse); | |
957 | |
958 gaim_debug_info("upnp", "NAT Added Port Forward On Port: %d: To IP: %s\n", portMap, internalIP); | |
11492 | 959 g_free(internalIP); |
11195 | 960 return TRUE; |
961 } | |
962 | |
963 | |
964 gboolean | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
965 gaim_upnp_remove_port_mapping(const GaimUPnPControlInfo* controlInfo, |
11391 | 966 unsigned short portMap, |
967 const char* protocol) | |
11195 | 968 { |
11391 | 969 gchar* httpResponse; |
970 gchar actionName[] = "DeletePortMapping"; | |
971 gchar* actionParams; | |
11195 | 972 |
973 /* make the portMappingParams variable */ | |
11391 | 974 actionParams = g_strdup_printf(DELETE_PORT_MAPPING_PARAMS, |
975 portMap, protocol); | |
11195 | 976 |
11391 | 977 httpResponse = gaim_upnp_generate_action_message_and_send(controlInfo, |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
978 actionName, |
11195 | 979 actionParams); |
980 | |
981 if(httpResponse == NULL) { | |
11391 | 982 gaim_debug_error("upnp", |
983 "gaim_upnp_remove_port_mapping(): Failed In httpResponse\n\n"); | |
984 g_free(actionParams); | |
11195 | 985 return FALSE; |
986 } | |
987 | |
988 /* determine if port mapping was a success */ | |
989 if(strstr(httpResponse, HTTP_OK) == NULL) { | |
11391 | 990 gaim_debug_error("upnp", |
11195 | 991 "gaim_upnp_set_port_mapping(): Failed HTTP_OK\n\n%s\n\n", httpResponse); |
11391 | 992 g_free(actionParams); |
993 g_free(httpResponse); | |
11195 | 994 return FALSE; |
995 } | |
996 | |
11391 | 997 g_free(actionParams); |
998 g_free(httpResponse); | |
999 | |
1000 gaim_debug_info("upnp", "NAT Removed Port Forward On Port: %d\n", portMap); | |
11195 | 1001 return TRUE; |
1002 } |