Mercurial > pidgin.yaz
annotate src/network.c @ 8246:e7524f4b4ed2
[gaim-migrate @ 8969]
Change some listening stuff.
Also, the autorecon thing, the signals should get removed
when the hash table is destroyed, so that check should not
be necessary. If the function really is getting called
then I guess this should be re-added or something...
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 12 Feb 2004 20:58:36 +0000 |
parents | 91c6629b1ee8 |
children | fabcfd9a7c1c |
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 | |
33 void | |
34 gaim_network_set_local_ip(const char *ip) | |
35 { | |
36 g_return_if_fail(ip != NULL); | |
37 | |
38 gaim_prefs_set_string("/core/network/public_ip", ip); | |
39 } | |
40 | |
41 const char * | |
42 gaim_network_get_local_ip(void) | |
43 { | |
44 const char *ip; | |
45 | |
46 if (gaim_prefs_get_bool("/core/network/auto_ip")) | |
47 return NULL; | |
48 | |
49 ip = gaim_prefs_get_string("/core/network/public_ip"); | |
50 | |
51 if (ip == NULL || *ip == '\0') | |
52 return NULL; | |
53 | |
54 return ip; | |
55 } | |
56 | |
57 static const char * | |
58 gaim_network_get_local_ip_from_fd(int fd) | |
59 { | |
60 struct sockaddr_in addr; | |
61 socklen_t len; | |
62 static char ip[16]; | |
63 const char *tmp; | |
64 | |
65 g_return_val_if_fail(fd > 0, NULL); | |
66 | |
67 len = sizeof(addr); | |
68 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
69 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
70 return NULL; | |
71 } | |
72 | |
73 tmp = inet_ntoa(addr.sin_addr); | |
74 strncpy(ip, tmp, sizeof(ip)); | |
75 return ip; | |
76 } | |
77 | |
78 const char * | |
79 gaim_network_get_local_system_ip(int fd) | |
80 { | |
81 struct hostent *host; | |
82 char localhost[129]; | |
83 long unsigned add; | |
84 static char ip[46]; | |
85 const char *tmp = NULL; | |
86 | |
87 if (fd != -1) | |
88 tmp = gaim_network_get_local_ip_from_fd(fd); | |
89 | |
90 if (tmp) | |
91 return tmp; | |
92 | |
93 if (gethostname(localhost, 128) < 0) | |
94 return NULL; | |
95 | |
96 if ((host = gethostbyname(localhost)) == NULL) | |
97 return NULL; | |
98 | |
99 memcpy(&add, host->h_addr_list[0], 4); | |
100 add = htonl(add); | |
101 | |
102 g_snprintf(ip, 16, "%lu.%lu.%lu.%lu", | |
103 ((add >> 24) & 255), | |
104 ((add >> 16) & 255), | |
105 ((add >> 8) & 255), | |
106 add & 255); | |
107 | |
108 return ip; | |
109 } | |
110 | |
111 const char * | |
112 gaim_network_get_ip_for_account(const GaimAccount *account, int fd) | |
113 { | |
114 if (account && (gaim_account_get_public_ip(account) != NULL)) | |
115 return gaim_account_get_public_ip(account); | |
116 else if (gaim_network_get_local_ip() != NULL) | |
117 return gaim_network_get_local_ip(); | |
118 else | |
119 return gaim_network_get_local_system_ip(fd); | |
120 } | |
121 | |
122 static int gaim_network_do_listen(short portnum) | |
123 { | |
124 #if HAVE_GETADDRINFO | |
125 int listenfd; | |
126 const int on = 1; | |
127 struct addrinfo hints, *res, *ressave; | |
128 char serv[5]; | |
129 | |
130 snprintf(serv, sizeof(serv), "%d", portnum); | |
131 memset(&hints, 0, sizeof(struct addrinfo)); | |
132 hints.ai_flags = AI_PASSIVE; | |
133 hints.ai_family = AF_UNSPEC; | |
134 hints.ai_socktype = SOCK_STREAM; | |
135 if (getaddrinfo(NULL /* any IP */, serv, &hints, &res) != 0) { | |
136 gaim_debug_warning("network", "getaddrinfo: %s\n", strerror(errno)); | |
137 return -1; | |
138 } | |
139 ressave = res; | |
140 do { | |
141 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | |
142 if (listenfd < 0) | |
143 continue; | |
144 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | |
145 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) | |
146 break; /* success */ | |
147 close(listenfd); | |
148 } while ( (res = res->ai_next) ); | |
149 | |
150 if (!res) | |
151 return -1; | |
152 | |
153 freeaddrinfo(ressave); | |
154 #else | |
155 int listenfd; | |
156 const int on = 1; | |
157 struct sockaddr_in sockin; | |
158 | |
159 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
160 gaim_debug_warning("network", "socket: %s\n", strerror(errno)); | |
161 return -1; | |
162 } | |
163 | |
164 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) { | |
165 gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); | |
166 close(listenfd); | |
167 return -1; | |
168 } | |
169 | |
170 memset(&sockin, 0, sizeof(struct sockaddr_in)); | |
171 sockin.sin_family = AF_INET; | |
172 sockin.sin_port = htons(portnum); | |
173 | |
174 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { | |
175 gaim_debug_warning("network", "bind: %s\n", strerror(errno)); | |
176 close(listenfd); | |
177 return -1; | |
178 } | |
179 #endif | |
180 | |
181 if (listen(listenfd, 4) != 0) { | |
182 gaim_debug_warning("network", "listen: %s\n", strerror(errno)); | |
183 close(listenfd); | |
184 return -1; | |
185 } | |
186 fcntl(listenfd, F_SETFL, O_NONBLOCK); | |
187 | |
188 gaim_debug_info("network", "Listening on port: %hu\n", gaim_network_get_port_from_fd(listenfd)); | |
189 return listenfd; | |
190 } | |
191 | |
8246 | 192 int gaim_network_listen(short port) |
193 { | |
194 return gaim_network_do_listen(port); | |
195 } | |
196 | |
197 int gaim_network_listen_range(short start, short end) | |
8231 | 198 { |
8240 | 199 int ret = -1; |
8231 | 200 |
8239 | 201 if (gaim_prefs_get_bool("/core/network/ports_range_use") || |
202 (start > end) || (start < 1024) || (end < 1024)) { | |
203 start = gaim_prefs_get_int("/core/network/ports_range_start"); | |
204 end = gaim_prefs_get_int("/core/network/ports_range_end"); | |
205 } | |
8231 | 206 |
207 for (; start <= end; start++) { | |
208 ret = gaim_network_do_listen(start); | |
209 if (ret >= 0) | |
210 break; | |
211 } | |
212 | |
213 return ret; | |
214 } | |
215 | |
216 short gaim_network_get_port_from_fd(int fd) | |
217 { | |
218 struct sockaddr_in addr; | |
219 socklen_t len; | |
220 | |
221 g_return_val_if_fail(fd > 0, 0); | |
222 | |
223 len = sizeof(addr); | |
224 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
225 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
226 return 0; | |
227 } | |
228 | |
229 return ntohs(addr.sin_port); | |
230 } | |
231 | |
232 void | |
233 gaim_network_init(void) | |
234 { | |
235 gaim_prefs_add_none ("/core/network"); | |
236 gaim_prefs_add_bool ("/core/network/auto_ip", TRUE); | |
237 gaim_prefs_add_string("/core/network/public_ip", ""); | |
238 gaim_prefs_add_bool ("/core/network/ports_range_use", FALSE); | |
239 gaim_prefs_add_int ("/core/network/ports_range_start", 1024); | |
240 gaim_prefs_add_int ("/core/network/ports_range_end", 2048); | |
241 } |