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;