Mercurial > pidgin
annotate src/network.c @ 9205:5b35a6b96726
[gaim-migrate @ 10000]
Buddy pounce defaults are now more sane, and apply to the state the buddy
is currently in. For example, if the buddy is idle, set "Return from idle"
by default. The action is now set to "Popup notification" by default,
as well. Also, cleaned up the code a little bit.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Sun, 06 Jun 2004 04:21:33 +0000 |
parents | e40f9afd420e |
children | ad93d76666dd |
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 { |
152 #if HAVE_GETADDRINFO | |
153 int listenfd; | |
154 const int on = 1; | |
155 struct addrinfo hints, *res, *ressave; | |
156 char serv[5]; | |
157 | |
8251 | 158 snprintf(serv, sizeof(serv), "%d", port); |
8231 | 159 memset(&hints, 0, sizeof(struct addrinfo)); |
160 hints.ai_flags = AI_PASSIVE; | |
161 hints.ai_family = AF_UNSPEC; | |
162 hints.ai_socktype = SOCK_STREAM; | |
163 if (getaddrinfo(NULL /* any IP */, serv, &hints, &res) != 0) { | |
164 gaim_debug_warning("network", "getaddrinfo: %s\n", strerror(errno)); | |
165 return -1; | |
166 } | |
167 ressave = res; | |
168 do { | |
169 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | |
170 if (listenfd < 0) | |
171 continue; | |
172 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | |
173 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) | |
174 break; /* success */ | |
175 close(listenfd); | |
176 } while ( (res = res->ai_next) ); | |
177 | |
178 if (!res) | |
179 return -1; | |
180 | |
181 freeaddrinfo(ressave); | |
182 #else | |
183 int listenfd; | |
184 const int on = 1; | |
185 struct sockaddr_in sockin; | |
186 | |
187 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
188 gaim_debug_warning("network", "socket: %s\n", strerror(errno)); | |
189 return -1; | |
190 } | |
191 | |
192 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) { | |
193 gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); | |
194 close(listenfd); | |
195 return -1; | |
196 } | |
197 | |
198 memset(&sockin, 0, sizeof(struct sockaddr_in)); | |
199 sockin.sin_family = AF_INET; | |
8251 | 200 sockin.sin_port = htons(port); |
8231 | 201 |
202 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { | |
203 gaim_debug_warning("network", "bind: %s\n", strerror(errno)); | |
204 close(listenfd); | |
205 return -1; | |
206 } | |
207 #endif | |
208 | |
209 if (listen(listenfd, 4) != 0) { | |
210 gaim_debug_warning("network", "listen: %s\n", strerror(errno)); | |
211 close(listenfd); | |
212 return -1; | |
213 } | |
214 fcntl(listenfd, F_SETFL, O_NONBLOCK); | |
215 | |
216 gaim_debug_info("network", "Listening on port: %hu\n", gaim_network_get_port_from_fd(listenfd)); | |
217 return listenfd; | |
218 } | |
219 | |
8834 | 220 int |
221 gaim_network_listen(unsigned short port) | |
8246 | 222 { |
8250 | 223 g_return_val_if_fail(port != 0, -1); |
224 | |
8246 | 225 return gaim_network_do_listen(port); |
226 } | |
227 | |
8834 | 228 int |
229 gaim_network_listen_range(unsigned short start, unsigned short end) | |
8231 | 230 { |
8240 | 231 int ret = -1; |
8231 | 232 |
8250 | 233 if (gaim_prefs_get_bool("/core/network/ports_range_use")) { |
8239 | 234 start = gaim_prefs_get_int("/core/network/ports_range_start"); |
235 end = gaim_prefs_get_int("/core/network/ports_range_end"); | |
8250 | 236 } else { |
237 if (end < start) | |
238 end = start; | |
8239 | 239 } |
8231 | 240 |
241 for (; start <= end; start++) { | |
242 ret = gaim_network_do_listen(start); | |
243 if (ret >= 0) | |
244 break; | |
245 } | |
246 | |
247 return ret; | |
248 } | |
249 | |
8834 | 250 unsigned short |
251 gaim_network_get_port_from_fd(int fd) | |
8231 | 252 { |
253 struct sockaddr_in addr; | |
254 socklen_t len; | |
255 | |
256 g_return_val_if_fail(fd > 0, 0); | |
257 | |
258 len = sizeof(addr); | |
259 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
260 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
261 return 0; | |
262 } | |
263 | |
264 return ntohs(addr.sin_port); | |
265 } | |
266 | |
267 void | |
268 gaim_network_init(void) | |
269 { | |
270 gaim_prefs_add_none ("/core/network"); | |
271 gaim_prefs_add_bool ("/core/network/auto_ip", TRUE); | |
272 gaim_prefs_add_string("/core/network/public_ip", ""); | |
273 gaim_prefs_add_bool ("/core/network/ports_range_use", FALSE); | |
274 gaim_prefs_add_int ("/core/network/ports_range_start", 1024); | |
275 gaim_prefs_add_int ("/core/network/ports_range_end", 2048); | |
276 } |