Mercurial > pidgin
annotate src/network.c @ 8730:8b935eddeb10
[gaim-migrate @ 9485]
Solaris iconv-related buildage fixes from Etan. He has a great name. In
fact, the anglicanized version of his name may be the coolest name I can
think of. Seriously.
committer: Tailor Script <tailor@pidgin.im>
author | Ethan Blanton <elb@pidgin.im> |
---|---|
date | Tue, 20 Apr 2004 22:40:05 +0000 |
parents | 86b8d8b4287e |
children | beb7be215db3 |
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 | |
8251 | 122 static int gaim_network_do_listen(unsigned short port) |
8231 | 123 { |
124 #if HAVE_GETADDRINFO | |
125 int listenfd; | |
126 const int on = 1; | |
127 struct addrinfo hints, *res, *ressave; | |
128 char serv[5]; | |
129 | |
8251 | 130 snprintf(serv, sizeof(serv), "%d", port); |
8231 | 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; | |
8251 | 172 sockin.sin_port = htons(port); |
8231 | 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 | |
8250 | 192 int gaim_network_listen(unsigned short port) |
8246 | 193 { |
8250 | 194 g_return_val_if_fail(port != 0, -1); |
195 | |
8246 | 196 return gaim_network_do_listen(port); |
197 } | |
198 | |
8250 | 199 int gaim_network_listen_range(unsigned short start, unsigned short end) |
8231 | 200 { |
8240 | 201 int ret = -1; |
8231 | 202 |
8250 | 203 if (gaim_prefs_get_bool("/core/network/ports_range_use")) { |
8239 | 204 start = gaim_prefs_get_int("/core/network/ports_range_start"); |
205 end = gaim_prefs_get_int("/core/network/ports_range_end"); | |
8250 | 206 } else { |
207 if (end < start) | |
208 end = start; | |
8239 | 209 } |
8231 | 210 |
211 for (; start <= end; start++) { | |
212 ret = gaim_network_do_listen(start); | |
213 if (ret >= 0) | |
214 break; | |
215 } | |
216 | |
217 return ret; | |
218 } | |
219 | |
220 short gaim_network_get_port_from_fd(int fd) | |
221 { | |
222 struct sockaddr_in addr; | |
223 socklen_t len; | |
224 | |
225 g_return_val_if_fail(fd > 0, 0); | |
226 | |
227 len = sizeof(addr); | |
228 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
229 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
230 return 0; | |
231 } | |
232 | |
233 return ntohs(addr.sin_port); | |
234 } | |
235 | |
236 void | |
237 gaim_network_init(void) | |
238 { | |
239 gaim_prefs_add_none ("/core/network"); | |
240 gaim_prefs_add_bool ("/core/network/auto_ip", TRUE); | |
241 gaim_prefs_add_string("/core/network/public_ip", ""); | |
242 gaim_prefs_add_bool ("/core/network/ports_range_use", FALSE); | |
243 gaim_prefs_add_int ("/core/network/ports_range_start", 1024); | |
244 gaim_prefs_add_int ("/core/network/ports_range_end", 2048); | |
245 } |