Mercurial > pidgin
annotate src/network.c @ 12692:4da7062a06c2
[gaim-migrate @ 15035]
SF Patch #1277888 from Douglas Thrift
I modified this a bit, but the end result is: This patch adds a logging preference that defaults to off. When enabled, the date is included in messages' timestamps in logs (in addition to the time).
This can be useful if you leave conversations open for days (for me, that's chats). The original patch had this affect timestamps in the conversation window as well, but I didn't like that. I figured it probably wasn't necessary, and I was dreading adding another conversation pref. I welcome feedback on this issue.
committer: Tailor Script <tailor@pidgin.im>
| author | Richard Laager <rlaager@wiktel.com> |
|---|---|
| date | Tue, 03 Jan 2006 06:33:00 +0000 |
| parents | 5f65a0cca87c |
| children | fb3b7466e3d2 |
| rev | line source |
|---|---|
| 8231 | 1 /** |
| 2 * @file network.c Network 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 | |
|
8245
91c6629b1ee8
[gaim-migrate @ 8968]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
8240
diff
changeset
|
26 #include "internal.h" |
| 8231 | 27 |
| 28 #include "debug.h" | |
| 29 #include "account.h" | |
| 30 #include "network.h" | |
| 31 #include "prefs.h" | |
| 11411 | 32 #include "stun.h" |
| 11195 | 33 #include "upnp.h" |
| 8231 | 34 |
| 11391 | 35 |
| 8838 | 36 const unsigned char * |
| 37 gaim_network_ip_atoi(const char *ip) | |
| 38 { | |
| 39 static unsigned char ret[4]; | |
| 8981 | 40 gchar *delimiter = "."; |
| 8838 | 41 gchar **split; |
| 42 int i; | |
| 43 | |
| 44 g_return_val_if_fail(ip != NULL, NULL); | |
| 45 | |
| 8981 | 46 split = g_strsplit(ip, delimiter, 4); |
| 8838 | 47 for (i = 0; split[i] != NULL; i++) |
| 48 ret[i] = atoi(split[i]); | |
| 49 g_strfreev(split); | |
| 50 | |
| 51 /* i should always be 4 */ | |
| 52 if (i != 4) | |
| 53 return NULL; | |
| 54 | |
| 55 return ret; | |
| 56 } | |
| 57 | |
| 8231 | 58 void |
| 8834 | 59 gaim_network_set_public_ip(const char *ip) |
| 8231 | 60 { |
| 61 g_return_if_fail(ip != NULL); | |
| 62 | |
| 8838 | 63 /* XXX - Ensure the IP address is valid */ |
| 64 | |
| 8231 | 65 gaim_prefs_set_string("/core/network/public_ip", ip); |
| 66 } | |
| 67 | |
| 68 const char * | |
| 8834 | 69 gaim_network_get_public_ip(void) |
| 8231 | 70 { |
| 71 const char *ip; | |
|
12686
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
72 GaimStunNatDiscovery *stun; |
| 11391 | 73 |
| 8231 | 74 ip = gaim_prefs_get_string("/core/network/public_ip"); |
| 75 | |
| 11411 | 76 if (ip == NULL || *ip == '\0') { |
| 77 /* Check if STUN discovery was already done */ | |
| 78 stun = gaim_stun_discover(NULL); | |
|
12686
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
79 if (stun != NULL && stun->status == GAIM_STUN_STATUS_DISCOVERED) |
| 11411 | 80 return stun->publicip; |
| 8231 | 81 return NULL; |
| 11411 | 82 } |
| 8231 | 83 |
| 84 return ip; | |
| 85 } | |
| 86 | |
| 87 static const char * | |
| 88 gaim_network_get_local_ip_from_fd(int fd) | |
| 89 { | |
| 90 struct sockaddr_in addr; | |
| 91 socklen_t len; | |
| 92 static char ip[16]; | |
| 93 const char *tmp; | |
| 94 | |
| 8840 | 95 g_return_val_if_fail(fd >= 0, NULL); |
| 8231 | 96 |
| 97 len = sizeof(addr); | |
| 98 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
| 99 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
| 100 return NULL; | |
| 101 } | |
| 102 | |
| 103 tmp = inet_ntoa(addr.sin_addr); | |
| 104 strncpy(ip, tmp, sizeof(ip)); | |
| 8838 | 105 |
| 8231 | 106 return ip; |
| 107 } | |
| 108 | |
| 109 const char * | |
| 110 gaim_network_get_local_system_ip(int fd) | |
| 111 { | |
| 112 struct hostent *host; | |
| 113 char localhost[129]; | |
| 114 long unsigned add; | |
| 115 static char ip[46]; | |
| 116 const char *tmp = NULL; | |
| 117 | |
| 8840 | 118 if (fd >= 0) |
| 8231 | 119 tmp = gaim_network_get_local_ip_from_fd(fd); |
| 120 | |
| 121 if (tmp) | |
| 122 return tmp; | |
| 123 | |
| 124 if (gethostname(localhost, 128) < 0) | |
| 125 return NULL; | |
| 126 | |
| 127 if ((host = gethostbyname(localhost)) == NULL) | |
| 128 return NULL; | |
| 129 | |
| 130 memcpy(&add, host->h_addr_list[0], 4); | |
| 131 add = htonl(add); | |
| 132 | |
| 133 g_snprintf(ip, 16, "%lu.%lu.%lu.%lu", | |
| 134 ((add >> 24) & 255), | |
| 135 ((add >> 16) & 255), | |
| 136 ((add >> 8) & 255), | |
| 137 add & 255); | |
| 138 | |
| 139 return ip; | |
| 140 } | |
| 141 | |
| 142 const char * | |
| 8838 | 143 gaim_network_get_my_ip(int fd) |
| 8231 | 144 { |
|
12686
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
145 const char *ip = NULL; |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
146 GaimUPnPControlInfo* controlInfo = NULL; |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
147 GaimStunNatDiscovery *stun; |
| 8834 | 148 |
| 149 /* Check if the user specified an IP manually */ | |
| 150 if (!gaim_prefs_get_bool("/core/network/auto_ip")) { | |
| 151 ip = gaim_network_get_public_ip(); | |
| 152 if (ip != NULL) | |
| 153 return ip; | |
| 154 } | |
| 155 | |
| 11424 | 156 if (ip == NULL || *ip == '\0') { |
| 157 /* Check if STUN discovery was already done */ | |
| 158 stun = gaim_stun_discover(NULL); | |
|
12686
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
159 if (stun != NULL && stun->status == GAIM_STUN_STATUS_DISCOVERED) |
| 11424 | 160 return stun->publicip; |
| 161 } | |
| 162 | |
| 163 | |
|
12686
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
164 /* attempt to get the ip from a NAT device */ |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
165 if ((controlInfo = gaim_upnp_discover()) != NULL) { |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
166 ip = gaim_upnp_get_public_ip(controlInfo); |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
167 |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
168 g_free(controlInfo->controlURL); |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
169 g_free(controlInfo->serviceType); |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
170 g_free(controlInfo); |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
171 |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
172 if (ip != NULL) |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
173 return ip; |
|
5f65a0cca87c
[gaim-migrate @ 15029]
Richard Laager <rlaager@wiktel.com>
parents:
11424
diff
changeset
|
174 } |
| 11195 | 175 |
| 8834 | 176 /* Just fetch the IP of the local system */ |
| 177 return gaim_network_get_local_system_ip(fd); | |
| 8231 | 178 } |
| 179 | |
| 11391 | 180 |
| 8834 | 181 static int |
| 182 gaim_network_do_listen(unsigned short port) | |
| 8231 | 183 { |
| 9452 | 184 int listenfd = -1; |
| 8231 | 185 const int on = 1; |
| 11391 | 186 GaimUPnPControlInfo* controlInfo = NULL; |
| 9449 | 187 #if HAVE_GETADDRINFO |
| 188 int errnum; | |
| 189 struct addrinfo hints, *res, *next; | |
| 9456 | 190 char serv[6]; |
| 8231 | 191 |
| 9449 | 192 /* |
| 193 * Get a list of addresses on this machine. | |
| 194 */ | |
| 195 snprintf(serv, sizeof(serv), "%hu", port); | |
| 8231 | 196 memset(&hints, 0, sizeof(struct addrinfo)); |
| 197 hints.ai_flags = AI_PASSIVE; | |
| 198 hints.ai_family = AF_UNSPEC; | |
| 199 hints.ai_socktype = SOCK_STREAM; | |
| 9449 | 200 errnum = getaddrinfo(NULL /* any IP */, serv, &hints, &res); |
| 201 if (errnum != 0) { | |
|
11221
5ed33bb06a84
[gaim-migrate @ 13353]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11215
diff
changeset
|
202 #ifndef _WIN32 |
| 9449 | 203 gaim_debug_warning("network", "getaddrinfo: %s\n", gai_strerror(errnum)); |
| 204 if (errnum == EAI_SYSTEM) | |
| 205 gaim_debug_warning("network", "getaddrinfo: system error: %s\n", strerror(errno)); | |
|
11221
5ed33bb06a84
[gaim-migrate @ 13353]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11215
diff
changeset
|
206 #else |
|
5ed33bb06a84
[gaim-migrate @ 13353]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11215
diff
changeset
|
207 gaim_debug_warning("network", "getaddrinfo: Error Code = %d\n", errnum); |
|
5ed33bb06a84
[gaim-migrate @ 13353]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11215
diff
changeset
|
208 #endif |
| 8231 | 209 return -1; |
| 210 } | |
| 9449 | 211 |
| 212 /* | |
| 213 * Go through the list of addresses and attempt to listen on | |
| 214 * one of them. | |
| 215 * XXX - Try IPv6 addresses first? | |
| 216 */ | |
| 217 for (next = res; next != NULL; next = next->ai_next) { | |
| 9455 | 218 listenfd = socket(next->ai_family, next->ai_socktype, next->ai_protocol); |
| 8231 | 219 if (listenfd < 0) |
| 220 continue; | |
| 9449 | 221 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) |
| 222 gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); | |
| 9455 | 223 if (bind(listenfd, next->ai_addr, next->ai_addrlen) == 0) |
| 8231 | 224 break; /* success */ |
| 225 close(listenfd); | |
| 9449 | 226 } |
| 8231 | 227 |
| 9449 | 228 freeaddrinfo(res); |
| 8231 | 229 |
| 9449 | 230 if (next == NULL) |
| 231 return -1; | |
| 8231 | 232 #else |
| 233 struct sockaddr_in sockin; | |
| 234 | |
| 235 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
| 236 gaim_debug_warning("network", "socket: %s\n", strerror(errno)); | |
| 237 return -1; | |
| 238 } | |
| 239 | |
| 9449 | 240 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) |
| 8231 | 241 gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); |
| 242 | |
| 243 memset(&sockin, 0, sizeof(struct sockaddr_in)); | |
| 9449 | 244 sockin.sin_family = PF_INET; |
| 8251 | 245 sockin.sin_port = htons(port); |
| 8231 | 246 |
| 247 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { | |
| 248 gaim_debug_warning("network", "bind: %s\n", strerror(errno)); | |
| 249 close(listenfd); | |
| 250 return -1; | |
| 251 } | |
| 252 #endif | |
| 253 | |
| 254 if (listen(listenfd, 4) != 0) { | |
| 255 gaim_debug_warning("network", "listen: %s\n", strerror(errno)); | |
| 256 close(listenfd); | |
| 257 return -1; | |
| 258 } | |
| 259 fcntl(listenfd, F_SETFL, O_NONBLOCK); | |
| 260 | |
| 11391 | 261 if((controlInfo = gaim_upnp_discover()) != NULL) { |
| 262 if(!gaim_upnp_set_port_mapping(controlInfo, | |
| 263 gaim_network_get_port_from_fd(listenfd), | |
| 264 "TCP")) { | |
| 265 gaim_upnp_remove_port_mapping(controlInfo, | |
| 266 gaim_network_get_port_from_fd(listenfd), "TCP"); | |
| 267 gaim_upnp_set_port_mapping(controlInfo, | |
| 268 gaim_network_get_port_from_fd(listenfd), "TCP"); | |
| 269 | |
| 270 } | |
| 271 g_free(controlInfo->serviceType); | |
| 272 g_free(controlInfo->controlURL); | |
| 273 g_free(controlInfo); | |
| 11195 | 274 } |
| 275 | |
| 8231 | 276 gaim_debug_info("network", "Listening on port: %hu\n", gaim_network_get_port_from_fd(listenfd)); |
| 277 return listenfd; | |
| 278 } | |
| 279 | |
| 8834 | 280 int |
| 281 gaim_network_listen(unsigned short port) | |
| 8246 | 282 { |
| 8250 | 283 g_return_val_if_fail(port != 0, -1); |
| 284 | |
| 8246 | 285 return gaim_network_do_listen(port); |
| 286 } | |
| 287 | |
| 8834 | 288 int |
| 289 gaim_network_listen_range(unsigned short start, unsigned short end) | |
| 8231 | 290 { |
| 8240 | 291 int ret = -1; |
| 8231 | 292 |
| 8250 | 293 if (gaim_prefs_get_bool("/core/network/ports_range_use")) { |
| 8239 | 294 start = gaim_prefs_get_int("/core/network/ports_range_start"); |
| 295 end = gaim_prefs_get_int("/core/network/ports_range_end"); | |
| 8250 | 296 } else { |
| 297 if (end < start) | |
| 298 end = start; | |
| 8239 | 299 } |
| 8231 | 300 |
| 301 for (; start <= end; start++) { | |
| 302 ret = gaim_network_do_listen(start); | |
| 303 if (ret >= 0) | |
| 304 break; | |
| 305 } | |
| 306 | |
| 307 return ret; | |
| 308 } | |
| 309 | |
| 8834 | 310 unsigned short |
| 311 gaim_network_get_port_from_fd(int fd) | |
| 8231 | 312 { |
| 313 struct sockaddr_in addr; | |
| 314 socklen_t len; | |
| 315 | |
| 9449 | 316 g_return_val_if_fail(fd >= 0, 0); |
| 8231 | 317 |
| 318 len = sizeof(addr); | |
| 319 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
| 320 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
| 321 return 0; | |
| 322 } | |
| 323 | |
| 324 return ntohs(addr.sin_port); | |
| 325 } | |
| 326 | |
| 327 void | |
| 328 gaim_network_init(void) | |
| 329 { | |
| 330 gaim_prefs_add_none ("/core/network"); | |
| 331 gaim_prefs_add_bool ("/core/network/auto_ip", TRUE); | |
| 332 gaim_prefs_add_string("/core/network/public_ip", ""); | |
| 333 gaim_prefs_add_bool ("/core/network/ports_range_use", FALSE); | |
| 334 gaim_prefs_add_int ("/core/network/ports_range_start", 1024); | |
| 335 gaim_prefs_add_int ("/core/network/ports_range_end", 2048); | |
| 336 } |
