Mercurial > pidgin
annotate src/upnp.c @ 12278:25d7ef365dbf
[gaim-migrate @ 14582]
sf patch #1370473, from Sadrul Habib Chowdhury
"This patch fixes the idle time tracking for systems
that don't use xscreensaver."
Seems like it would just get rid of some warnings? But
whatever, definitely an improvement
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 01 Dec 2005 01:01:26 +0000 |
parents | 201be1b681a4 |
children | 0f499f27b29a |
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; | |
11391 | 162 NetResponseData* nrd = data; |
11195 | 163 |
11391 | 164 sizeRecv = recv(sock, &(nrd->recvBuffer[nrd->totalSizeRecv]), |
11492 | 165 MAX_DESCRIPTION_RECEIVE_SIZE-nrd->totalSizeRecv, 0); |
11195 | 166 if(sizeRecv < 0 && errno != EINTR) { |
11391 | 167 gaim_debug_error("upnp", |
11195 | 168 "gaim_upnp_http_read(): recv < 0: %i!\n\n", errno); |
11391 | 169 g_free(nrd->recvBuffer); |
170 nrd->recvBuffer = NULL; | |
171 gaim_timeout_remove(nrd->tima); | |
172 gaim_input_remove(nrd->inpa); | |
173 nrd->done = TRUE; | |
11195 | 174 return; |
175 }else if(errno == EINTR) { | |
176 sizeRecv = 0; | |
177 } | |
11391 | 178 nrd->totalSizeRecv += sizeRecv; |
11195 | 179 |
180 if(sizeRecv == 0) { | |
11391 | 181 gaim_timeout_remove(nrd->tima); |
182 gaim_input_remove(nrd->inpa); | |
183 if(nrd->totalSizeRecv == 0) { | |
184 gaim_debug_error("upnp", | |
11195 | 185 "gaim_upnp_http_read(): totalSizeRecv == 0\n\n"); |
11391 | 186 g_free(nrd->recvBuffer); |
187 nrd->recvBuffer = NULL; | |
11195 | 188 } else { |
11391 | 189 nrd->recvBuffer[nrd->totalSizeRecv] = '\0'; |
11195 | 190 } |
11391 | 191 nrd->done = TRUE; |
11195 | 192 } else { |
11391 | 193 gaim_timeout_remove(nrd->tima); |
194 gaim_input_remove(nrd->inpa); | |
11492 | 195 nrd->tima = gaim_timeout_add(CONSECUTIVE_RECEIVE_TIMEOUT, |
11391 | 196 (GSourceFunc)gaim_upnp_timeout, nrd); |
197 nrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, | |
198 gaim_upnp_http_read, nrd); | |
11195 | 199 } |
200 } | |
201 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
202 static void |
11391 | 203 gaim_upnp_http_send(gpointer data, |
204 gint sock, | |
205 GaimInputCondition cond) | |
11195 | 206 { |
11586 | 207 gsize sizeSent, totalSizeSent = 0; |
11391 | 208 NetResponseData* nrd = data; |
11195 | 209 |
11391 | 210 gaim_timeout_remove(nrd->tima); |
211 while(totalSizeSent < strlen(nrd->sendBuffer)) { | |
11586 | 212 sizeSent = send(sock,(gchar*)(nrd->sendBuffer+totalSizeSent), |
11391 | 213 strlen(nrd->sendBuffer)-totalSizeSent,0); |
11195 | 214 if(sizeSent <= 0 && errno != EINTR) { |
11391 | 215 gaim_debug_error("upnp", |
11195 | 216 "gaim_upnp_http_request(): Failed In send\n\n"); |
11391 | 217 nrd->done = TRUE; |
218 g_free(nrd->recvBuffer); | |
219 nrd->recvBuffer = NULL; | |
11195 | 220 close(sock); |
11391 | 221 return; |
11195 | 222 }else if(errno == EINTR) { |
223 sizeSent = 0; | |
224 } | |
225 totalSizeSent += sizeSent; | |
226 } | |
227 | |
11492 | 228 nrd->tima = gaim_timeout_add(RECEIVE_TIMEOUT, |
11391 | 229 (GSourceFunc)gaim_upnp_timeout, nrd); |
230 nrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, | |
231 gaim_upnp_http_read, nrd); | |
232 while (!nrd->done) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
233 g_main_context_iteration(NULL, TRUE); |
11195 | 234 } |
235 close(sock); | |
11391 | 236 } |
11195 | 237 |
11391 | 238 static gchar* |
239 gaim_upnp_http_request(const gchar* address, | |
240 int port, | |
241 gchar* httpRequest) | |
242 { | |
243 gchar* recvBuffer; | |
244 NetResponseData* nrd = (NetResponseData*)g_malloc0(sizeof(NetResponseData)); | |
245 nrd->sendBuffer = httpRequest; | |
11492 | 246 nrd->recvBuffer = (gchar*)g_malloc(MAX_DESCRIPTION_RECEIVE_SIZE); |
11391 | 247 |
11492 | 248 nrd->tima = gaim_timeout_add(RECEIVE_TIMEOUT, |
11391 | 249 (GSourceFunc)gaim_upnp_timeout, nrd); |
250 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
251 if(gaim_proxy_connect(NULL, address, port, |
11391 | 252 gaim_upnp_http_send, nrd)) { |
253 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
254 gaim_debug_error("upnp", "Connect Failed: Address: %s @@@ Port %d @@@ Request %s\n\n", |
11391 | 255 address, port, nrd->sendBuffer); |
256 | |
257 gaim_timeout_remove(nrd->tima); | |
258 g_free(nrd->recvBuffer); | |
259 nrd->recvBuffer = NULL; | |
260 } else { | |
261 while (!nrd->done) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
262 g_main_context_iteration(NULL, TRUE); |
11391 | 263 } |
264 } | |
265 | |
266 recvBuffer = nrd->recvBuffer; | |
267 g_free(nrd); | |
268 | |
11195 | 269 return recvBuffer; |
270 } | |
271 | |
272 | |
273 | |
11391 | 274 static gboolean |
275 gaim_upnp_compare_device(const xmlnode* device, | |
276 const gchar* deviceType) | |
277 { | |
278 xmlnode* deviceTypeNode = xmlnode_get_child(device, "deviceType"); | |
279 if(deviceTypeNode == NULL) { | |
280 return FALSE; | |
281 } | |
282 return !g_ascii_strcasecmp(xmlnode_get_data(deviceTypeNode), deviceType); | |
283 } | |
11195 | 284 |
11391 | 285 |
286 static gboolean | |
287 gaim_upnp_compare_service(const xmlnode* service, | |
288 const gchar* serviceType) | |
11195 | 289 { |
11391 | 290 xmlnode* serviceTypeNode = xmlnode_get_child(service, "serviceType"); |
291 if(serviceTypeNode == NULL) { | |
292 return FALSE; | |
293 } | |
294 return !g_ascii_strcasecmp(xmlnode_get_data(serviceTypeNode), serviceType); | |
295 } | |
296 | |
297 | |
11195 | 298 |
11391 | 299 static gchar* |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
300 gaim_upnp_parse_description_response(const gchar* httpResponse, |
11391 | 301 const gchar* httpURL, |
302 const gchar* serviceType) | |
303 { | |
304 gchar* xmlRoot; | |
305 gchar* baseURL; | |
306 gchar* controlURL; | |
307 gchar* service; | |
308 xmlnode* xmlRootNode; | |
309 xmlnode* serviceTypeNode; | |
310 xmlnode* controlURLNode; | |
311 xmlnode* baseURLNode; | |
312 | |
313 /* make sure we have a valid http response */ | |
314 if(g_strstr_len(httpResponse, strlen(httpResponse), HTTP_OK) == NULL) { | |
315 gaim_debug_error("upnp", | |
11195 | 316 "parse_description_response(): Failed In HTTP_OK\n\n"); |
317 return NULL; | |
318 } | |
319 | |
11391 | 320 /* find the root of the xml document */ |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
321 if((xmlRoot = g_strstr_len(httpResponse, strlen(httpResponse), |
11391 | 322 "<root")) == NULL) { |
323 gaim_debug_error("upnp", | |
324 "parse_description_response(): Failed finding root\n\n"); | |
325 return NULL; | |
326 } | |
327 | |
328 /* create the xml root node */ | |
329 if((xmlRootNode = xmlnode_from_str(xmlRoot, -1)) == NULL) { | |
330 gaim_debug_error("upnp", | |
331 "parse_description_response(): Could not parse xml root node\n\n"); | |
11195 | 332 return NULL; |
333 } | |
11391 | 334 |
335 /* get the baseURL of the device */ | |
336 if((baseURLNode = xmlnode_get_child(xmlRootNode, | |
337 "URLBase")) != NULL) { | |
338 baseURL = g_strdup(xmlnode_get_data(baseURLNode)); | |
339 } else { | |
340 baseURL = g_strdup(httpURL); | |
341 } | |
342 | |
343 /* get the serviceType child that has the service type as it's data */ | |
344 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
345 /* get urn:schemas-upnp-org:device:InternetGatewayDevice:1 |
11391 | 346 and it's devicelist */ |
347 serviceTypeNode = xmlnode_get_child(xmlRootNode, "device"); | |
348 while(!gaim_upnp_compare_device(serviceTypeNode, | |
349 "urn:schemas-upnp-org:device:InternetGatewayDevice:1") && | |
350 serviceTypeNode != NULL) { | |
351 serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); | |
352 } | |
353 if(serviceTypeNode == NULL) { | |
354 gaim_debug_error("upnp", | |
355 "parse_description_response(): could not get serviceTypeNode 1\n\n"); | |
11195 | 356 return NULL; |
357 } | |
11391 | 358 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "deviceList"); |
359 if(serviceTypeNode == NULL) { | |
360 gaim_debug_error("upnp", | |
361 "parse_description_response(): could not get serviceTypeNode 2\n\n"); | |
11195 | 362 return NULL; |
363 } | |
364 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
365 /* get urn:schemas-upnp-org:device:WANDevice:1 |
11391 | 366 and it's devicelist */ |
367 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "device"); | |
368 while(!gaim_upnp_compare_device(serviceTypeNode, | |
369 "urn:schemas-upnp-org:device:WANDevice:1") && | |
370 serviceTypeNode != NULL) { | |
371 serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); | |
372 } | |
373 if(serviceTypeNode == NULL) { | |
374 gaim_debug_error("upnp", | |
375 "parse_description_response(): could not get serviceTypeNode 3\n\n"); | |
376 return NULL; | |
377 } | |
378 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "deviceList"); | |
379 if(serviceTypeNode == NULL) { | |
380 gaim_debug_error("upnp", | |
381 "parse_description_response(): could not get serviceTypeNode 4\n\n"); | |
382 return NULL; | |
383 } | |
11195 | 384 |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
385 /* get urn:schemas-upnp-org:device:WANConnectionDevice:1 |
11391 | 386 and it's servicelist */ |
387 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "device"); | |
388 while(!gaim_upnp_compare_device(serviceTypeNode, | |
389 "urn:schemas-upnp-org:device:WANConnectionDevice:1") && | |
390 serviceTypeNode != NULL) { | |
391 serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); | |
392 } | |
393 if(serviceTypeNode == NULL) { | |
394 gaim_debug_error("upnp", | |
395 "parse_description_response(): could not get serviceTypeNode 5\n\n"); | |
11195 | 396 return NULL; |
397 } | |
11391 | 398 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "serviceList"); |
399 if(serviceTypeNode == NULL) { | |
400 gaim_debug_error("upnp", | |
401 "parse_description_response(): could not get serviceTypeNode 6\n\n"); | |
402 return NULL; | |
403 } | |
11195 | 404 |
11391 | 405 /* get the serviceType variable passed to this function */ |
406 service = g_strdup_printf(SEARCH_REQUEST_DEVICE, serviceType); | |
407 serviceTypeNode = xmlnode_get_child(serviceTypeNode, "service"); | |
408 while(!gaim_upnp_compare_service(serviceTypeNode, service) && | |
409 serviceTypeNode != NULL) { | |
410 serviceTypeNode = xmlnode_get_next_twin(serviceTypeNode); | |
11195 | 411 } |
412 | |
11391 | 413 g_free(service); |
414 if(serviceTypeNode == NULL) { | |
415 gaim_debug_error("upnp", | |
416 "parse_description_response(): could not get serviceTypeNode 7\n\n"); | |
417 return NULL; | |
418 } | |
419 | |
420 /* get the controlURL of the service */ | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
421 if((controlURLNode = xmlnode_get_child(serviceTypeNode, |
11391 | 422 "controlURL")) == NULL) { |
423 gaim_debug_error("upnp", | |
424 "parse_description_response(): Could not find controlURL\n\n"); | |
425 return NULL; | |
426 } | |
427 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
428 if(g_strstr_len(xmlnode_get_data(controlURLNode), |
11391 | 429 SIZEOF_HTTP, "http://") == NULL && |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
430 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 controlURL = g_strdup_printf("%s%s", baseURL, |
11391 | 433 xmlnode_get_data(controlURLNode)); |
11195 | 434 }else{ |
11391 | 435 controlURL = g_strdup(xmlnode_get_data(controlURLNode)); |
11195 | 436 } |
11391 | 437 g_free(baseURL); |
438 xmlnode_free(xmlRootNode); | |
11195 | 439 |
440 return controlURL; | |
441 } | |
442 | |
443 | |
11391 | 444 static gchar* |
445 gaim_upnp_parse_description(const gchar* descriptionURL, | |
446 const gchar* serviceType) | |
11195 | 447 { |
11391 | 448 gchar* fullURL; |
449 gchar* controlURL; | |
450 gchar* httpResponse; | |
451 gchar* httpRequest; | |
11195 | 452 |
11391 | 453 gchar* descriptionXMLAddress; |
454 gchar* descriptionAddressPort; | |
455 gchar* descriptionAddress; | |
456 gchar descriptionPort[MAX_PORT_SIZE]; | |
457 int port = 0; | |
11195 | 458 |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
459 /* parse the 4 above variables out of the descriptionURL |
11195 | 460 example description URL: http://192.168.1.1:5678/rootDesc.xml */ |
461 | |
462 /* parse the url into address, port, path variables */ | |
11391 | 463 if(!gaim_url_parse(descriptionURL, &descriptionAddress, |
464 &port, &descriptionXMLAddress, NULL, NULL)) { | |
11195 | 465 return NULL; |
466 } | |
11391 | 467 if(port == 0 || port == -1) { |
468 port = DEFAULT_HTTP_PORT; | |
11195 | 469 } |
11391 | 470 g_ascii_dtostr(descriptionPort, MAX_PORT_SIZE, port); |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
471 descriptionAddressPort = g_strdup_printf("%s:%s", descriptionAddress, |
11391 | 472 descriptionPort); |
11195 | 473 |
11391 | 474 fullURL = g_strdup_printf("http://%s", descriptionAddressPort); |
11195 | 475 |
476 /* for example... | |
477 GET /rootDesc.xml HTTP/1.1\r\nHost: 192.168.1.1:5678\r\n\r\n */ | |
11391 | 478 httpRequest = g_strdup_printf("GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", |
479 descriptionXMLAddress, descriptionAddressPort); | |
11195 | 480 |
481 httpResponse = gaim_upnp_http_request(descriptionAddress, | |
482 port, httpRequest); | |
483 if(httpResponse == NULL) { | |
11391 | 484 gaim_debug_error("upnp", |
11195 | 485 "gaim_upnp_parse_description(): httpResponse is NULL\n\n"); |
11391 | 486 g_free(descriptionXMLAddress); |
487 g_free(descriptionAddress); | |
488 g_free(descriptionAddressPort); | |
489 g_free(httpRequest); | |
490 g_free(fullURL); | |
11195 | 491 return NULL; |
492 } | |
493 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
494 controlURL = gaim_upnp_parse_description_response(httpResponse, |
11391 | 495 fullURL, serviceType); |
11195 | 496 |
11391 | 497 g_free(descriptionXMLAddress); |
498 g_free(descriptionAddress); | |
499 g_free(descriptionAddressPort); | |
500 g_free(fullURL); | |
501 g_free(httpRequest); | |
502 g_free(httpResponse); | |
11195 | 503 |
504 if(controlURL == NULL) { | |
11391 | 505 gaim_debug_error("upnp", |
11195 | 506 "gaim_upnp_parse_description(): controlURL is NULL\n\n"); |
507 return NULL; | |
508 } | |
509 | |
510 return controlURL; | |
511 } | |
512 | |
513 | |
11391 | 514 static gchar* |
515 gaim_upnp_parse_discover_response(const gchar* buf, | |
516 unsigned int bufSize, | |
517 const gchar* serviceType) | |
11195 | 518 { |
11391 | 519 gchar* startDescURL; |
520 gchar* endDescURL; | |
521 gchar* descURL; | |
522 gchar* retVal; | |
11195 | 523 |
11391 | 524 if(g_strstr_len(buf, strlen(buf), HTTP_OK) == NULL) { |
525 gaim_debug_error("upnp", | |
11195 | 526 "parse_discover_response(): Failed In HTTP_OK\n\n"); |
527 return NULL; | |
528 } | |
529 | |
11391 | 530 if((startDescURL = g_strstr_len(buf, strlen(buf), "http://")) == NULL) { |
531 gaim_debug_error("upnp", | |
532 "parse_discover_response(): Failed In finding http://\n\n"); | |
11195 | 533 return NULL; |
534 } | |
535 | |
11391 | 536 endDescURL = g_strstr_len(startDescURL, strlen(startDescURL), "\r"); |
11195 | 537 if(endDescURL == NULL) { |
11391 | 538 endDescURL = g_strstr_len(startDescURL, strlen(startDescURL), "\n"); |
11195 | 539 if(endDescURL == NULL) { |
11391 | 540 gaim_debug_error("upnp", |
541 "parse_discover_response(): Failed In endDescURL\n\n"); | |
11195 | 542 return NULL; |
543 }else if(endDescURL == startDescURL) { | |
11391 | 544 gaim_debug_error("upnp", |
545 "parse_discover_response(): endDescURL == startDescURL\n\n"); | |
11195 | 546 return NULL; |
547 } | |
548 }else if(endDescURL == startDescURL) { | |
11391 | 549 gaim_debug_error("upnp", |
550 "parse_discover_response(): 2nd endDescURL == startDescURL\n\n"); | |
11195 | 551 return NULL; |
552 } | |
11391 | 553 descURL = g_strndup(startDescURL, endDescURL-startDescURL); |
11195 | 554 |
11391 | 555 retVal = gaim_upnp_parse_description(descURL, serviceType); |
556 g_free(descURL); | |
11195 | 557 return retVal; |
558 } | |
559 | |
560 | |
561 | |
562 static void | |
563 gaim_upnp_discover_udp_read(gpointer data, | |
564 gint sock, | |
565 GaimInputCondition cond) | |
566 { | |
567 unsigned int length; | |
568 struct sockaddr_in from; | |
569 int sizeRecv; | |
11391 | 570 NetResponseData* nrd = data; |
11195 | 571 |
11391 | 572 gaim_timeout_remove(nrd->tima); |
11195 | 573 length = sizeof(struct sockaddr_in); |
574 | |
575 do { | |
11391 | 576 sizeRecv = recvfrom(sock, nrd->recvBuffer, |
11492 | 577 MAX_DISCOVERY_RECEIVE_SIZE, 0, |
11195 | 578 (struct sockaddr*)&from, &length); |
579 | |
580 if(sizeRecv > 0) { | |
11391 | 581 nrd->recvBuffer[sizeRecv] = '\0'; |
11195 | 582 }else if(errno != EINTR) { |
11391 | 583 g_free(nrd->recvBuffer); |
584 nrd->recvBuffer = NULL; | |
11195 | 585 } |
586 }while(errno == EINTR); | |
587 | |
11391 | 588 gaim_input_remove(nrd->inpa); |
589 nrd->done = TRUE; | |
11195 | 590 return; |
591 } | |
592 | |
593 | |
11213 | 594 |
11391 | 595 GaimUPnPControlInfo* |
11195 | 596 gaim_upnp_discover(void) |
597 { | |
11391 | 598 /* Socket Setup Variables */ |
11195 | 599 int sock, i; |
600 struct sockaddr_in server; | |
11391 | 601 struct hostent* hp; |
11195 | 602 |
11391 | 603 /* UDP SEND VARIABLES */ |
604 gboolean sentSuccess, recvSuccess; | |
12207
201be1b681a4
[gaim-migrate @ 14509]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
605 ssize_t sizeSent; |
201be1b681a4
[gaim-migrate @ 14509]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
606 ssize_t totalSizeSent; |
11391 | 607 gchar wanIP[] = "WANIPConnection:1"; |
608 gchar wanPPP[] = "WANPPPConnection:1"; | |
609 gchar* serviceToUse; | |
610 gchar* sendMessage = NULL; | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
611 |
11492 | 612 /* UDP RECEIVE VARIABLES */ |
11391 | 613 GaimUPnPControlInfo* controlInfo = g_malloc(sizeof(GaimUPnPControlInfo)); |
614 NetResponseData* nrd = g_malloc(sizeof(NetResponseData)); | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
615 |
11391 | 616 /* Set up the sockets */ |
11195 | 617 sock = socket(AF_INET, SOCK_DGRAM, 0); |
618 if (sock == -1) { | |
619 close(sock); | |
11391 | 620 gaim_debug_error("upnp", |
11195 | 621 "gaim_upnp_discover(): Failed In sock creation\n\n"); |
11391 | 622 g_free(nrd); |
623 g_free(controlInfo); | |
11195 | 624 return NULL; |
625 } | |
626 memset(&server, 0, sizeof(struct sockaddr)); | |
627 server.sin_family = AF_INET; | |
628 if((hp = gethostbyname(HTTPMU_HOST_ADDRESS)) == NULL) { | |
629 close(sock); | |
11391 | 630 gaim_debug_error("upnp", |
11195 | 631 "gaim_upnp_discover(): Failed In gethostbyname\n\n"); |
11391 | 632 g_free(nrd); |
633 g_free(controlInfo); | |
11195 | 634 return NULL; |
635 } | |
636 memcpy(&server.sin_addr, | |
637 hp->h_addr_list[0], | |
638 hp->h_length); | |
639 server.sin_port = htons(HTTPMU_HOST_PORT); | |
640 | |
641 /* because we are sending over UDP, if there is a failure | |
11391 | 642 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
|
643 try different requests for WANIPConnection and |
11391 | 644 WANPPPConnection*/ |
11195 | 645 for(i = 0; i < NUM_UDP_ATTEMPTS; i++) { |
646 sentSuccess = TRUE; | |
647 recvSuccess = TRUE; | |
648 totalSizeSent = 0; | |
649 | |
11391 | 650 nrd->recvBuffer = NULL; |
651 nrd->totalSizeRecv = 0; | |
652 nrd->done = FALSE; | |
653 | |
654 if(sendMessage != NULL) { | |
655 g_free(sendMessage); | |
656 } | |
11213 | 657 |
11391 | 658 if(i%2 == 0) { |
659 serviceToUse = wanIP; | |
660 } else { | |
661 serviceToUse = wanPPP; | |
11213 | 662 } |
11391 | 663 sendMessage = g_strdup_printf(SEARCH_REQUEST_STRING, serviceToUse); |
664 | |
11492 | 665 nrd->recvBuffer = (char*)g_malloc(MAX_DISCOVERY_RECEIVE_SIZE); |
11213 | 666 |
12207
201be1b681a4
[gaim-migrate @ 14509]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
667 while(totalSizeSent < (ssize_t)strlen(sendMessage)) { |
11195 | 668 sizeSent = sendto(sock,(void*)&sendMessage[totalSizeSent], |
669 strlen(&sendMessage[totalSizeSent]),0, | |
670 (struct sockaddr*)&server, | |
671 sizeof(struct sockaddr_in)); | |
672 if(sizeSent <= 0 && errno != EINTR) { | |
673 sentSuccess = FALSE; | |
674 break; | |
675 }else if(errno == EINTR) { | |
676 sizeSent = 0; | |
677 } | |
678 totalSizeSent += sizeSent; | |
679 } | |
680 | |
681 if(sentSuccess) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
682 nrd->tima = gaim_timeout_add(DISCOVERY_TIMEOUT, |
11391 | 683 (GSourceFunc)gaim_upnp_timeout, nrd); |
684 nrd->inpa = gaim_input_add(sock, GAIM_INPUT_READ, | |
685 gaim_upnp_discover_udp_read, nrd); | |
686 while (!nrd->done) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
687 g_main_context_iteration(NULL, TRUE); |
11195 | 688 } |
11391 | 689 if(nrd->recvBuffer == NULL) { |
11195 | 690 recvSuccess = FALSE; |
691 } else { | |
692 /* parse the response, and see if it was a success */ | |
693 close(sock); | |
11391 | 694 if((controlInfo->controlURL= |
695 gaim_upnp_parse_discover_response(nrd->recvBuffer, | |
696 strlen(nrd->recvBuffer), | |
697 serviceToUse))==NULL) { | |
698 gaim_debug_error("upnp", | |
11195 | 699 "gaim_upnp_discover(): Failed In parse response\n\n"); |
11391 | 700 g_free(nrd->recvBuffer); |
701 g_free(nrd); | |
702 g_free(controlInfo); | |
11195 | 703 return NULL; |
704 } | |
11391 | 705 |
706 controlInfo->serviceType = g_strdup(serviceToUse); | |
11195 | 707 } |
708 } | |
709 | |
710 /* if sent success and recv successful, then break */ | |
711 if(sentSuccess && recvSuccess) { | |
712 i = NUM_UDP_ATTEMPTS; | |
713 } | |
714 } | |
11213 | 715 |
11391 | 716 if(nrd->recvBuffer != NULL) { |
717 g_free(nrd->recvBuffer); | |
11213 | 718 } |
11391 | 719 g_free(sendMessage); |
720 g_free(nrd); | |
11213 | 721 |
11195 | 722 if(!sentSuccess || !recvSuccess) { |
723 close(sock); | |
11391 | 724 gaim_debug_error("upnp", |
11195 | 725 "gaim_upnp_discover(): Failed In sent/recv success\n\n"); |
11391 | 726 g_free(controlInfo); |
11195 | 727 return NULL; |
728 } | |
729 | |
11391 | 730 return controlInfo; |
11195 | 731 } |
732 | |
733 | |
734 static char* | |
11391 | 735 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
|
736 const gchar* actionName, |
11391 | 737 const gchar* actionParams) |
11195 | 738 { |
11391 | 739 gchar* actionMessage; |
740 gchar* soapMessage; | |
741 gchar* totalSendMessage; | |
742 gchar* httpResponse; | |
11195 | 743 |
11391 | 744 gchar* pathOfControl; |
745 gchar* addressOfControl; | |
746 gchar* addressPortOfControl; | |
747 gchar portOfControl[MAX_PORT_SIZE]; | |
748 int port=0; | |
11195 | 749 |
750 /* set the soap message */ | |
11391 | 751 soapMessage = g_strdup_printf(SOAP_ACTION, actionName, |
752 controlInfo->serviceType, | |
753 actionParams, actionName); | |
11195 | 754 |
755 /* parse the url into address, port, path variables */ | |
11391 | 756 if(!gaim_url_parse(controlInfo->controlURL, &addressOfControl, |
757 &port, &pathOfControl, NULL, NULL)) { | |
758 gaim_debug_error("upnp", | |
11195 | 759 "generate_action_message_and_send(): Failed In Parse URL\n\n"); |
11391 | 760 g_free(soapMessage); |
11195 | 761 return NULL; |
762 } | |
11391 | 763 if(port == 0 || port == -1) { |
764 port = DEFAULT_HTTP_PORT; | |
765 } | |
766 g_ascii_dtostr(portOfControl, MAX_PORT_SIZE, port); | |
11195 | 767 |
768 /* set the addressPortOfControl variable which should have a | |
769 form like the following: 192.168.1.1:8000 */ | |
11391 | 770 addressPortOfControl = g_strdup_printf("%s:%s", |
771 addressOfControl, portOfControl); | |
11195 | 772 |
773 /* set the HTTP Header */ | |
11391 | 774 actionMessage = g_strdup_printf(HTTP_HEADER_ACTION, |
775 pathOfControl, addressPortOfControl, | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
776 controlInfo->serviceType, actionName, |
11391 | 777 strlen(soapMessage)); |
11195 | 778 |
779 /* append to the header the body */ | |
11391 | 780 totalSendMessage = g_strdup_printf("%s%s", actionMessage, soapMessage); |
11195 | 781 |
782 /* get the return of the http response */ | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
783 httpResponse = gaim_upnp_http_request(addressOfControl, |
11391 | 784 port, totalSendMessage); |
11195 | 785 if(httpResponse == NULL) { |
11391 | 786 gaim_debug_error("upnp", |
11195 | 787 "generate_action_message_and_send(): Failed In httpResponse\n\n"); |
788 } | |
789 | |
11391 | 790 g_free(actionMessage); |
791 g_free(soapMessage); | |
792 g_free(totalSendMessage); | |
793 g_free(pathOfControl); | |
794 g_free(addressOfControl); | |
795 g_free(addressPortOfControl); | |
11195 | 796 |
797 return httpResponse; | |
798 } | |
799 | |
800 | |
801 | |
802 | |
11391 | 803 gchar* |
804 gaim_upnp_get_public_ip(const GaimUPnPControlInfo* controlInfo) | |
11195 | 805 { |
11391 | 806 gchar* extIPAddress; |
807 gchar* httpResponse; | |
808 gchar actionName[] = "GetExternalIPAddress"; | |
809 gchar actionParams[] = ""; | |
810 gchar* temp, *temp2; | |
11195 | 811 |
11391 | 812 httpResponse = gaim_upnp_generate_action_message_and_send(controlInfo, |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
813 actionName, |
11195 | 814 actionParams); |
815 if(httpResponse == NULL) { | |
11391 | 816 gaim_debug_error("upnp", |
11195 | 817 "gaim_upnp_get_public_ip(): Failed In httpResponse\n\n"); |
818 return NULL; | |
819 } | |
820 | |
821 /* extract the ip, or see if there is an error */ | |
11391 | 822 if((temp = g_strstr_len(httpResponse, strlen(httpResponse), |
823 "<NewExternalIPAddress")) == NULL) { | |
824 gaim_debug_error("upnp", | |
11195 | 825 "gaim_upnp_get_public_ip(): Failed Finding <NewExternalIPAddress\n\n"); |
11391 | 826 g_free(httpResponse); |
11195 | 827 return NULL; |
828 } | |
11391 | 829 if((temp = g_strstr_len(temp, strlen(temp), ">")) == NULL) { |
830 gaim_debug_error("upnp", | |
11195 | 831 "gaim_upnp_get_public_ip(): Failed In Finding >\n\n"); |
11391 | 832 g_free(httpResponse); |
11195 | 833 return NULL; |
834 } | |
11391 | 835 if((temp2 = g_strstr_len(temp, strlen(temp), "<")) == NULL) { |
836 gaim_debug_error("upnp", | |
11195 | 837 "gaim_upnp_get_public_ip(): Failed In Finding <\n\n"); |
11391 | 838 g_free(httpResponse); |
11195 | 839 return NULL; |
840 } | |
11391 | 841 |
842 extIPAddress = g_strndup(&temp[1], (temp2-1)-temp); | |
11195 | 843 |
11391 | 844 g_free(httpResponse); |
845 | |
846 gaim_debug_info("upnp", "NAT Returned IP: %s\n", extIPAddress); | |
11195 | 847 return extIPAddress; |
848 } | |
849 | |
11391 | 850 static void |
851 gaim_upnp_get_local_system_ip(gpointer data, | |
852 gint sock, | |
853 GaimInputCondition cond) | |
854 { | |
855 NetResponseData* nrd = data; | |
11443
d9d60002065b
[gaim-migrate @ 13682]
Richard Laager <rlaager@wiktel.com>
parents:
11391
diff
changeset
|
856 nrd->recvBuffer = g_strdup(gaim_network_get_local_system_ip(sock)); |
11195 | 857 |
11391 | 858 gaim_timeout_remove(nrd->tima); |
859 nrd->done = TRUE; | |
11195 | 860 |
11391 | 861 close(sock); |
862 } | |
11195 | 863 |
11492 | 864 static gchar* |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
865 gaim_upnp_get_local_ip_address(const gchar* address) |
11391 | 866 { |
11492 | 867 gchar* ip; |
11391 | 868 gchar* pathOfControl; |
869 gchar* addressOfControl; | |
870 int port = 0; | |
871 NetResponseData* nrd = (NetResponseData*)g_malloc0(sizeof(NetResponseData)); | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
872 |
11391 | 873 if(!gaim_url_parse(address, &addressOfControl, |
874 &port, &pathOfControl, NULL, NULL)) { | |
875 gaim_debug_error("upnp", | |
11195 | 876 "get_local_ip_address(): Failed In Parse URL\n\n"); |
877 return NULL; | |
878 } | |
11391 | 879 if(port == 0 || port == -1) { |
880 port = DEFAULT_HTTP_PORT; | |
11195 | 881 } |
882 | |
11492 | 883 nrd->tima = gaim_timeout_add(RECEIVE_TIMEOUT, |
11391 | 884 (GSourceFunc)gaim_upnp_timeout, nrd); |
885 | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
886 if(gaim_proxy_connect(NULL, addressOfControl, port, |
11391 | 887 gaim_upnp_get_local_system_ip, nrd)) { |
11195 | 888 |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
889 gaim_debug_error("upnp", "Get Local IP Connect Failed: Address: %s @@@ Port %d @@@ Request %s\n\n", |
11391 | 890 address, port, nrd->sendBuffer); |
891 | |
892 gaim_timeout_remove(nrd->tima); | |
893 } else { | |
894 while (!nrd->done) { | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
895 g_main_context_iteration(NULL, TRUE); |
11391 | 896 } |
11195 | 897 } |
898 | |
11391 | 899 ip = nrd->recvBuffer; |
900 g_free(nrd); | |
11195 | 901 |
11391 | 902 gaim_debug_info("upnp", "local ip: %s\n", ip); |
903 | |
11195 | 904 return ip; |
905 } | |
906 | |
907 | |
908 | |
909 gboolean | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
910 gaim_upnp_set_port_mapping(const GaimUPnPControlInfo* controlInfo, |
11391 | 911 unsigned short portMap, |
912 const gchar* protocol) | |
11195 | 913 { |
11391 | 914 gchar* httpResponse; |
915 gchar actionName[] = "AddPortMapping"; | |
916 gchar* actionParams; | |
11492 | 917 gchar* internalIP; |
11195 | 918 |
919 /* get the internal IP */ | |
11391 | 920 if((internalIP = gaim_upnp_get_local_ip_address(controlInfo->controlURL)) |
921 == NULL) { | |
922 gaim_debug_error("upnp", | |
11195 | 923 "gaim_upnp_set_port_mapping(): couldn't get local ip\n\n"); |
924 return FALSE; | |
925 } | |
926 | |
927 /* make the portMappingParams variable */ | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
928 actionParams = g_strdup_printf(ADD_PORT_MAPPING_PARAMS, portMap, |
11391 | 929 protocol, portMap, internalIP); |
11195 | 930 |
11391 | 931 httpResponse = gaim_upnp_generate_action_message_and_send(controlInfo, |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
932 actionName, |
11195 | 933 actionParams); |
934 if(httpResponse == NULL) { | |
11391 | 935 gaim_debug_error("upnp", |
11195 | 936 "gaim_upnp_set_port_mapping(): Failed In httpResponse\n\n"); |
11391 | 937 g_free(actionParams); |
11492 | 938 g_free(internalIP); |
11195 | 939 return FALSE; |
940 } | |
941 | |
942 /* determine if port mapping was a success */ | |
943 if(strstr(httpResponse, HTTP_OK) == NULL) { | |
11391 | 944 gaim_debug_error("upnp", |
11195 | 945 "gaim_upnp_set_port_mapping(): Failed HTTP_OK\n\n%s\n\n", httpResponse); |
11391 | 946 g_free(actionParams); |
947 g_free(httpResponse); | |
11492 | 948 g_free(internalIP); |
11195 | 949 return FALSE; |
950 } | |
951 | |
11391 | 952 g_free(actionParams); |
953 g_free(httpResponse); | |
954 | |
955 gaim_debug_info("upnp", "NAT Added Port Forward On Port: %d: To IP: %s\n", portMap, internalIP); | |
11492 | 956 g_free(internalIP); |
11195 | 957 return TRUE; |
958 } | |
959 | |
960 | |
961 gboolean | |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
962 gaim_upnp_remove_port_mapping(const GaimUPnPControlInfo* controlInfo, |
11391 | 963 unsigned short portMap, |
964 const char* protocol) | |
11195 | 965 { |
11391 | 966 gchar* httpResponse; |
967 gchar actionName[] = "DeletePortMapping"; | |
968 gchar* actionParams; | |
11195 | 969 |
970 /* make the portMappingParams variable */ | |
11391 | 971 actionParams = g_strdup_printf(DELETE_PORT_MAPPING_PARAMS, |
972 portMap, protocol); | |
11195 | 973 |
11391 | 974 httpResponse = gaim_upnp_generate_action_message_and_send(controlInfo, |
11566
7897207b522d
[gaim-migrate @ 13832]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11492
diff
changeset
|
975 actionName, |
11195 | 976 actionParams); |
977 | |
978 if(httpResponse == NULL) { | |
11391 | 979 gaim_debug_error("upnp", |
980 "gaim_upnp_remove_port_mapping(): Failed In httpResponse\n\n"); | |
981 g_free(actionParams); | |
11195 | 982 return FALSE; |
983 } | |
984 | |
985 /* determine if port mapping was a success */ | |
986 if(strstr(httpResponse, HTTP_OK) == NULL) { | |
11391 | 987 gaim_debug_error("upnp", |
11195 | 988 "gaim_upnp_set_port_mapping(): Failed HTTP_OK\n\n%s\n\n", httpResponse); |
11391 | 989 g_free(actionParams); |
990 g_free(httpResponse); | |
11195 | 991 return FALSE; |
992 } | |
993 | |
11391 | 994 g_free(actionParams); |
995 g_free(httpResponse); | |
996 | |
997 gaim_debug_info("upnp", "NAT Removed Port Forward On Port: %d\n", portMap); | |
11195 | 998 return TRUE; |
999 } |