Mercurial > pidgin.yaz
comparison src/network.c @ 9449:ad93d76666dd
[gaim-migrate @ 10273]
Minor changes to the listen function in network.c
We were using strerror() to print the string form of
errno when getaddrinfo() failed, but that is incorrect.
getaddrinfo() does not use errno or strerror. It retuns an
integer error code which can be converted to a string with
gai_strerror(errorcode)
When we didn't have getaddrinfo, and we were unable to set
SO_REUSEADDR, we would abort the listen attempt. That's not
necessary becuase SO_REUSEADDR isn't vital, it's just nice
to have (right?)
struct addrinfo *res was not getting freed when we did not have
any interfaces to listen on (incredibly rare)
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 05 Jul 2004 15:43:26 +0000 |
parents | e40f9afd420e |
children | 0de62d92fb3b |
comparison
equal
deleted
inserted
replaced
9448:18f760b306ad | 9449:ad93d76666dd |
---|---|
147 } | 147 } |
148 | 148 |
149 static int | 149 static int |
150 gaim_network_do_listen(unsigned short port) | 150 gaim_network_do_listen(unsigned short port) |
151 { | 151 { |
152 #if HAVE_GETADDRINFO | |
153 int listenfd; | 152 int listenfd; |
154 const int on = 1; | 153 const int on = 1; |
155 struct addrinfo hints, *res, *ressave; | 154 #if HAVE_GETADDRINFO |
155 int errnum; | |
156 struct addrinfo hints, *res, *next; | |
156 char serv[5]; | 157 char serv[5]; |
157 | 158 |
158 snprintf(serv, sizeof(serv), "%d", port); | 159 /* |
160 * Get a list of addresses on this machine. | |
161 */ | |
162 snprintf(serv, sizeof(serv), "%hu", port); | |
159 memset(&hints, 0, sizeof(struct addrinfo)); | 163 memset(&hints, 0, sizeof(struct addrinfo)); |
160 hints.ai_flags = AI_PASSIVE; | 164 hints.ai_flags = AI_PASSIVE; |
161 hints.ai_family = AF_UNSPEC; | 165 hints.ai_family = AF_UNSPEC; |
162 hints.ai_socktype = SOCK_STREAM; | 166 hints.ai_socktype = SOCK_STREAM; |
163 if (getaddrinfo(NULL /* any IP */, serv, &hints, &res) != 0) { | 167 errnum = getaddrinfo(NULL /* any IP */, serv, &hints, &res); |
164 gaim_debug_warning("network", "getaddrinfo: %s\n", strerror(errno)); | 168 if (errnum != 0) { |
165 return -1; | 169 gaim_debug_warning("network", "getaddrinfo: %s\n", gai_strerror(errnum)); |
166 } | 170 if (errnum == EAI_SYSTEM) |
167 ressave = res; | 171 gaim_debug_warning("network", "getaddrinfo: system error: %s\n", strerror(errno)); |
168 do { | 172 return -1; |
173 } | |
174 | |
175 /* | |
176 * Go through the list of addresses and attempt to listen on | |
177 * one of them. | |
178 * XXX - Try IPv6 addresses first? | |
179 */ | |
180 for (next = res; next != NULL; next = next->ai_next) { | |
169 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | 181 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); |
170 if (listenfd < 0) | 182 if (listenfd < 0) |
171 continue; | 183 continue; |
172 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | 184 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) |
185 gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); | |
173 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) | 186 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) |
174 break; /* success */ | 187 break; /* success */ |
175 close(listenfd); | 188 close(listenfd); |
176 } while ( (res = res->ai_next) ); | 189 } |
177 | 190 |
178 if (!res) | 191 freeaddrinfo(res); |
179 return -1; | 192 |
180 | 193 if (next == NULL) |
181 freeaddrinfo(ressave); | 194 return -1; |
182 #else | 195 #else |
183 int listenfd; | |
184 const int on = 1; | |
185 struct sockaddr_in sockin; | 196 struct sockaddr_in sockin; |
186 | 197 |
187 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | 198 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
188 gaim_debug_warning("network", "socket: %s\n", strerror(errno)); | 199 gaim_debug_warning("network", "socket: %s\n", strerror(errno)); |
189 return -1; | 200 return -1; |
190 } | 201 } |
191 | 202 |
192 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) { | 203 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) |
193 gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); | 204 gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); |
194 close(listenfd); | |
195 return -1; | |
196 } | |
197 | 205 |
198 memset(&sockin, 0, sizeof(struct sockaddr_in)); | 206 memset(&sockin, 0, sizeof(struct sockaddr_in)); |
199 sockin.sin_family = AF_INET; | 207 sockin.sin_family = PF_INET; |
200 sockin.sin_port = htons(port); | 208 sockin.sin_port = htons(port); |
201 | 209 |
202 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { | 210 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { |
203 gaim_debug_warning("network", "bind: %s\n", strerror(errno)); | 211 gaim_debug_warning("network", "bind: %s\n", strerror(errno)); |
204 close(listenfd); | 212 close(listenfd); |
251 gaim_network_get_port_from_fd(int fd) | 259 gaim_network_get_port_from_fd(int fd) |
252 { | 260 { |
253 struct sockaddr_in addr; | 261 struct sockaddr_in addr; |
254 socklen_t len; | 262 socklen_t len; |
255 | 263 |
256 g_return_val_if_fail(fd > 0, 0); | 264 g_return_val_if_fail(fd >= 0, 0); |
257 | 265 |
258 len = sizeof(addr); | 266 len = sizeof(addr); |
259 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | 267 if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { |
260 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | 268 gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); |
261 return 0; | 269 return 0; |