Mercurial > pidgin
annotate src/network.c @ 11052:8a68c933a5dd
[gaim-migrate @ 12990]
Patch #1227165 from sadrul
This patch probes plugins when the plugin page is loaded in preferences. This allows users to activate newly installed plugins without restarting Gaim.
The only way I can see this being a problem is if you installed a plugin which was version-compatible but binary incompatible. (For example, you're working on Gaim HEAD and change a public struct in a way that's binary backwards incompatible, build a plugin against it, install the plugin, and open the preferences page of a running copy of Gaim from before the change.) Even then, depending on the particular plugin and binary incompatibility, you might have to activate the plugin before Gaim would crash.
So, unless I'm missing something, this should be safe. Let's see how it goes.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 03 Jul 2005 05:28:57 +0000 |
parents | 50224ac8184d |
children | 3aeb85cc9cda |
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" | |
32 | |
8838 | 33 const unsigned char * |
34 gaim_network_ip_atoi(const char *ip) | |
35 { | |
36 static unsigned char ret[4]; | |
8981 | 37 gchar *delimiter = "."; |
8838 | 38 gchar **split; |
39 int i; | |
40 | |
41 g_return_val_if_fail(ip != NULL, NULL); | |
42 | |
8981 | 43 split = g_strsplit(ip, delimiter, 4); |
8838 | 44 for (i = 0; split[i] != NULL; i++) |
45 ret[i] = atoi(split[i]); | |
46 g_strfreev(split); | |
47 | |
48 /* i should always be 4 */ | |
49 if (i != 4) | |
50 return NULL; | |
51 | |
52 return ret; | |
53 } | |
54 | |
8231 | 55 void |
8834 | 56 gaim_network_set_public_ip(const char *ip) |
8231 | 57 { |
58 g_return_if_fail(ip != NULL); | |
59 | |
8838 | 60 /* XXX - Ensure the IP address is valid */ |
61 | |
8231 | 62 gaim_prefs_set_string("/core/network/public_ip", ip); |
63 } | |
64 | |
65 const char * | |
8834 | 66 gaim_network_get_public_ip(void) |
8231 | 67 { |
68 const char *ip; | |
69 | |
70 ip = gaim_prefs_get_string("/core/network/public_ip"); | |
71 | |
72 if (ip == NULL || *ip == '\0') | |
73 return NULL; | |
74 | |
75 return ip; | |
76 } | |
77 | |
78 static const char * | |
79 gaim_network_get_local_ip_from_fd(int fd) | |
80 { | |
81 struct sockaddr_in addr; | |
82 socklen_t len; | |
83 static char ip[16]; | |
84 const char *tmp; | |
85 | |
8840 | 86 g_return_val_if_fail(fd >= 0, NULL); |
8231 | 87 |
88 len = sizeof(addr); | |
89 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
90 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
91 return NULL; | |
92 } | |
93 | |
94 tmp = inet_ntoa(addr.sin_addr); | |
95 strncpy(ip, tmp, sizeof(ip)); | |
8838 | 96 |
8231 | 97 return ip; |
98 } | |
99 | |
100 const char * | |
101 gaim_network_get_local_system_ip(int fd) | |
102 { | |
103 struct hostent *host; | |
104 char localhost[129]; | |
105 long unsigned add; | |
106 static char ip[46]; | |
107 const char *tmp = NULL; | |
108 | |
8840 | 109 if (fd >= 0) |
8231 | 110 tmp = gaim_network_get_local_ip_from_fd(fd); |
111 | |
112 if (tmp) | |
113 return tmp; | |
114 | |
115 if (gethostname(localhost, 128) < 0) | |
116 return NULL; | |
117 | |
118 if ((host = gethostbyname(localhost)) == NULL) | |
119 return NULL; | |
120 | |
121 memcpy(&add, host->h_addr_list[0], 4); | |
122 add = htonl(add); | |
123 | |
124 g_snprintf(ip, 16, "%lu.%lu.%lu.%lu", | |
125 ((add >> 24) & 255), | |
126 ((add >> 16) & 255), | |
127 ((add >> 8) & 255), | |
128 add & 255); | |
129 | |
130 return ip; | |
131 } | |
132 | |
133 const char * | |
8838 | 134 gaim_network_get_my_ip(int fd) |
8231 | 135 { |
8834 | 136 const char *ip = NULL; |
137 | |
138 /* Check if the user specified an IP manually */ | |
139 if (!gaim_prefs_get_bool("/core/network/auto_ip")) { | |
140 ip = gaim_network_get_public_ip(); | |
141 if (ip != NULL) | |
142 return ip; | |
143 } | |
144 | |
145 /* Just fetch the IP of the local system */ | |
146 return gaim_network_get_local_system_ip(fd); | |
8231 | 147 } |
148 | |
8834 | 149 static int |
150 gaim_network_do_listen(unsigned short port) | |
8231 | 151 { |
9452 | 152 int listenfd = -1; |
8231 | 153 const int on = 1; |
9449 | 154 #if HAVE_GETADDRINFO |
155 int errnum; | |
156 struct addrinfo hints, *res, *next; | |
9456 | 157 char serv[6]; |
8231 | 158 |
9449 | 159 /* |
160 * Get a list of addresses on this machine. | |
161 */ | |
162 snprintf(serv, sizeof(serv), "%hu", port); | |
8231 | 163 memset(&hints, 0, sizeof(struct addrinfo)); |
164 hints.ai_flags = AI_PASSIVE; | |
165 hints.ai_family = AF_UNSPEC; | |
166 hints.ai_socktype = SOCK_STREAM; | |
9449 | 167 errnum = getaddrinfo(NULL /* any IP */, serv, &hints, &res); |
168 if (errnum != 0) { | |
10671
c6dedd37ea5c
[gaim-migrate @ 12211]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
9456
diff
changeset
|
169 #ifndef _WIN32 |
9449 | 170 gaim_debug_warning("network", "getaddrinfo: %s\n", gai_strerror(errnum)); |
171 if (errnum == EAI_SYSTEM) | |
172 gaim_debug_warning("network", "getaddrinfo: system error: %s\n", strerror(errno)); | |
10671
c6dedd37ea5c
[gaim-migrate @ 12211]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
9456
diff
changeset
|
173 #else |
c6dedd37ea5c
[gaim-migrate @ 12211]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
9456
diff
changeset
|
174 gaim_debug_warning("network", "getaddrinfo: Error Code = %d\n", errnum); |
c6dedd37ea5c
[gaim-migrate @ 12211]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
9456
diff
changeset
|
175 #endif |
8231 | 176 return -1; |
177 } | |
9449 | 178 |
179 /* | |
180 * Go through the list of addresses and attempt to listen on | |
181 * one of them. | |
182 * XXX - Try IPv6 addresses first? | |
183 */ | |
184 for (next = res; next != NULL; next = next->ai_next) { | |
9455 | 185 listenfd = socket(next->ai_family, next->ai_socktype, next->ai_protocol); |
8231 | 186 if (listenfd < 0) |
187 continue; | |
9449 | 188 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) |
189 gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); | |
9455 | 190 if (bind(listenfd, next->ai_addr, next->ai_addrlen) == 0) |
8231 | 191 break; /* success */ |
192 close(listenfd); | |
9449 | 193 } |
8231 | 194 |
9449 | 195 freeaddrinfo(res); |
8231 | 196 |
9449 | 197 if (next == NULL) |
198 return -1; | |
8231 | 199 #else |
200 struct sockaddr_in sockin; | |
201 | |
202 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
203 gaim_debug_warning("network", "socket: %s\n", strerror(errno)); | |
204 return -1; | |
205 } | |
206 | |
9449 | 207 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) |
8231 | 208 gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); |
209 | |
210 memset(&sockin, 0, sizeof(struct sockaddr_in)); | |
9449 | 211 sockin.sin_family = PF_INET; |
8251 | 212 sockin.sin_port = htons(port); |
8231 | 213 |
214 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { | |
215 gaim_debug_warning("network", "bind: %s\n", strerror(errno)); | |
216 close(listenfd); | |
217 return -1; | |
218 } | |
219 #endif | |
220 | |
221 if (listen(listenfd, 4) != 0) { | |
222 gaim_debug_warning("network", "listen: %s\n", strerror(errno)); | |
223 close(listenfd); | |
224 return -1; | |
225 } | |
226 fcntl(listenfd, F_SETFL, O_NONBLOCK); | |
227 | |
228 gaim_debug_info("network", "Listening on port: %hu\n", gaim_network_get_port_from_fd(listenfd)); | |
229 return listenfd; | |
230 } | |
231 | |
8834 | 232 int |
233 gaim_network_listen(unsigned short port) | |
8246 | 234 { |
8250 | 235 g_return_val_if_fail(port != 0, -1); |
236 | |
8246 | 237 return gaim_network_do_listen(port); |
238 } | |
239 | |
8834 | 240 int |
241 gaim_network_listen_range(unsigned short start, unsigned short end) | |
8231 | 242 { |
8240 | 243 int ret = -1; |
8231 | 244 |
8250 | 245 if (gaim_prefs_get_bool("/core/network/ports_range_use")) { |
8239 | 246 start = gaim_prefs_get_int("/core/network/ports_range_start"); |
247 end = gaim_prefs_get_int("/core/network/ports_range_end"); | |
8250 | 248 } else { |
249 if (end < start) | |
250 end = start; | |
8239 | 251 } |
8231 | 252 |
253 for (; start <= end; start++) { | |
254 ret = gaim_network_do_listen(start); | |
255 if (ret >= 0) | |
256 break; | |
257 } | |
258 | |
259 return ret; | |
260 } | |
261 | |
8834 | 262 unsigned short |
263 gaim_network_get_port_from_fd(int fd) | |
8231 | 264 { |
265 struct sockaddr_in addr; | |
266 socklen_t len; | |
267 | |
9449 | 268 g_return_val_if_fail(fd >= 0, 0); |
8231 | 269 |
270 len = sizeof(addr); | |
271 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
272 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
273 return 0; | |
274 } | |
275 | |
276 return ntohs(addr.sin_port); | |
277 } | |
278 | |
279 void | |
280 gaim_network_init(void) | |
281 { | |
11033
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10671
diff
changeset
|
282 gaim_debug_register_category("network"); |
50224ac8184d
[gaim-migrate @ 12919]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10671
diff
changeset
|
283 |
8231 | 284 gaim_prefs_add_none ("/core/network"); |
285 gaim_prefs_add_bool ("/core/network/auto_ip", TRUE); | |
286 gaim_prefs_add_string("/core/network/public_ip", ""); | |
287 gaim_prefs_add_bool ("/core/network/ports_range_use", FALSE); | |
288 gaim_prefs_add_int ("/core/network/ports_range_start", 1024); | |
289 gaim_prefs_add_int ("/core/network/ports_range_end", 2048); | |
290 } |