comparison src/proxy.c @ 4434:6b83a532eeb2

[gaim-migrate @ 4709] Async DNS was leaking 2 file desriptors per lost DNS child. It also corrects the async DNS function interface. thanks niqueco committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Mon, 27 Jan 2003 07:51:05 +0000
parents 3fa2941a5323
children 1f9cd40abb4a
comparison
equal deleted inserted replaced
4433:289efc79a242 4434:6b83a532eeb2
141 * a free child process. 141 * a free child process.
142 */ 142 */
143 typedef struct { 143 typedef struct {
144 char *host; 144 char *host;
145 int port; 145 int port;
146 int socktype;
147 dns_callback_t callback; 146 dns_callback_t callback;
148 gpointer data; 147 gpointer data;
149 gint inpa; 148 gint inpa;
150 int fd_in, fd_out; 149 int fd_in, fd_out;
151 pid_t dns_pid; 150 pid_t dns_pid;
159 const int MAX_DNS_CHILDREN = 2; 158 const int MAX_DNS_CHILDREN = 2;
160 159
161 typedef struct { 160 typedef struct {
162 char hostname[512]; 161 char hostname[512];
163 int port; 162 int port;
164 int socktype;
165 } dns_params_t; 163 } dns_params_t;
166 164
167 typedef struct { 165 typedef struct {
168 dns_params_t params; 166 dns_params_t params;
169 dns_callback_t callback; 167 dns_callback_t callback;
170 gpointer data; 168 gpointer data;
171 } queued_dns_request_t; 169 } queued_dns_request_t;
172 170
171 static void req_free(pending_dns_request_t *req)
172 {
173 g_return_if_fail(req != NULL);
174 if(req->host)
175 g_free(req->host);
176 close(req->fd_in);
177 close(req->fd_out);
178 g_free(req);
179 number_of_dns_children--;
180 }
181
173 static int send_dns_request_to_child(pending_dns_request_t *req, dns_params_t *dns_params) 182 static int send_dns_request_to_child(pending_dns_request_t *req, dns_params_t *dns_params)
174 { 183 {
175 char ch; 184 char ch;
176 int rc; 185 int rc;
177 186
183 192
184 /* Let's contact this lost child! */ 193 /* Let's contact this lost child! */
185 rc = write(req->fd_in, dns_params, sizeof(*dns_params)); 194 rc = write(req->fd_in, dns_params, sizeof(*dns_params));
186 if(rc<0) { 195 if(rc<0) {
187 debug_printf("Error writing to DNS child %d: %s\n", req->dns_pid, strerror(errno)); 196 debug_printf("Error writing to DNS child %d: %s\n", req->dns_pid, strerror(errno));
197 close(req->fd_in);
188 return -1; 198 return -1;
189 } 199 }
190 200
191 g_return_val_if_fail(rc == sizeof(*dns_params), -1); 201 g_return_val_if_fail(rc == sizeof(*dns_params), -1);
192 202
205 static void host_resolved(gpointer data, gint source, GaimInputCondition cond); 215 static void host_resolved(gpointer data, gint source, GaimInputCondition cond);
206 216
207 static void release_dns_child(pending_dns_request_t *req) 217 static void release_dns_child(pending_dns_request_t *req)
208 { 218 {
209 g_free(req->host); 219 g_free(req->host);
220 req->host=NULL;
210 221
211 if(queued_requests && !g_queue_is_empty(queued_requests)) { 222 if(queued_requests && !g_queue_is_empty(queued_requests)) {
212 queued_dns_request_t *r = g_queue_pop_head(queued_requests); 223 queued_dns_request_t *r = g_queue_pop_head(queued_requests);
213 req->host = g_strdup(r->params.hostname); 224 req->host = g_strdup(r->params.hostname);
214 req->port = r->params.port; 225 req->port = r->params.port;
215 req->socktype = r->params.socktype;
216 req->callback = r->callback; 226 req->callback = r->callback;
217 req->data = r->data; 227 req->data = r->data;
218 228
219 debug_printf("Processing queued DNS query for '%s' with child %d\n", req->host, req->dns_pid); 229 debug_printf("Processing queued DNS query for '%s' with child %d\n", req->host, req->dns_pid);
220 230
221 if(send_dns_request_to_child(req, &(r->params)) != 0) { 231 if(send_dns_request_to_child(req, &(r->params)) != 0) {
222 g_free(req->host); 232 req_free(req);
223 g_free(req);
224 req = NULL; 233 req = NULL;
225 number_of_dns_children--;
226
227 debug_printf("Intent of process queued query of '%s' failed, requeing...\n", 234 debug_printf("Intent of process queued query of '%s' failed, requeing...\n",
228 r->params.hostname); 235 r->params.hostname);
229 g_queue_push_head(queued_requests, r); 236 g_queue_push_head(queued_requests, r);
230 } else { 237 } else {
231 req->inpa = gaim_input_add(req->fd_out, GAIM_INPUT_READ, host_resolved, req); 238 req->inpa = gaim_input_add(req->fd_out, GAIM_INPUT_READ, host_resolved, req);
274 } 281 }
275 if(rc==-1) { 282 if(rc==-1) {
276 char message[1024]; 283 char message[1024];
277 g_snprintf(message, sizeof(message), "Error reading from DNS child: %s",strerror(errno)); 284 g_snprintf(message, sizeof(message), "Error reading from DNS child: %s",strerror(errno));
278 debug_printf("%s\n",message); 285 debug_printf("%s\n",message);
279 close(req->fd_out);
280 req->callback(NULL, 0, req->data, message); 286 req->callback(NULL, 0, req->data, message);
281 g_free(req->host); 287 req_free(req);
282 g_free(req);
283 number_of_dns_children--;
284 return; 288 return;
285 } 289 }
286 if(rc==0) { 290 if(rc==0) {
287 char message[1024]; 291 char message[1024];
288 g_snprintf(message, sizeof(message), "EOF reading from DNS child"); 292 g_snprintf(message, sizeof(message), "EOF reading from DNS child");
289 close(req->fd_out); 293 close(req->fd_out);
290 debug_printf("%s\n",message); 294 debug_printf("%s\n",message);
291 req->callback(NULL, 0, req->data, message); 295 req->callback(NULL, 0, req->data, message);
292 g_free(req->host); 296 req_free(req);
293 g_free(req);
294 number_of_dns_children--;
295 return; 297 return;
296 } 298 }
297 299
298 /* wait4(req->dns_pid, NULL, WNOHANG, NULL); */ 300 /* wait4(req->dns_pid, NULL, WNOHANG, NULL); */
299 301
341 gethostbyname("x.x.x.x.x"); 343 gethostbyname("x.x.x.x.x");
342 } 344 }
343 #endif 345 #endif
344 } 346 }
345 347
346 int gaim_gethostbyname_async(const char *hostname, int port, int socktype, dns_callback_t callback, gpointer data) 348 int gaim_gethostbyname_async(const char *hostname, int port, dns_callback_t callback, gpointer data)
347 { 349 {
348 pending_dns_request_t *req = NULL; 350 pending_dns_request_t *req = NULL;
349 dns_params_t dns_params; 351 dns_params_t dns_params;
350 352
351 strncpy(dns_params.hostname, hostname, sizeof(dns_params.hostname)-1); 353 strncpy(dns_params.hostname, hostname, sizeof(dns_params.hostname)-1);
352 dns_params.hostname[sizeof(dns_params.hostname)-1] = '\0'; 354 dns_params.hostname[sizeof(dns_params.hostname)-1] = '\0';
353 dns_params.port = port; 355 dns_params.port = port;
354 dns_params.socktype = socktype;
355 356
356 /* Is there a free available child? */ 357 /* Is there a free available child? */
357 while(free_dns_children && !req) { 358 while(free_dns_children && !req) {
358 GSList *l = free_dns_children; 359 GSList *l = free_dns_children;
359 free_dns_children = g_slist_remove_link(free_dns_children, l); 360 free_dns_children = g_slist_remove_link(free_dns_children, l);
360 req = l->data; 361 req = l->data;
361 g_slist_free(l); 362 g_slist_free(l);
362 363
363 if(send_dns_request_to_child(req, &dns_params) != 0) { 364 if(send_dns_request_to_child(req, &dns_params) != 0) {
364 g_free(req); 365 req_free(req);
365 req = NULL; 366 req = NULL;
366 number_of_dns_children--;
367 continue; 367 continue;
368 } 368 }
369 369
370 } 370 }
371 371
450 } 450 }
451 451
452 #ifdef HAVE_GETADDRINFO 452 #ifdef HAVE_GETADDRINFO
453 g_snprintf(servname, sizeof(servname), "%d", dns_params.port); 453 g_snprintf(servname, sizeof(servname), "%d", dns_params.port);
454 memset(&hints,0,sizeof(hints)); 454 memset(&hints,0,sizeof(hints));
455 hints.ai_socktype = dns_params.socktype; 455
456 /* This is only used to convert a service
457 * name to a port number. As we know we are
458 * passing a number already, we know this
459 * value will not be really used by the C
460 * library.
461 */
462 hints.ai_socktype = SOCK_STREAM;
456 rc = getaddrinfo(dns_params.hostname, servname, &hints, &res); 463 rc = getaddrinfo(dns_params.hostname, servname, &hints, &res);
457 if(rc) { 464 if(rc) {
458 write(child_out[1], &rc, sizeof(int)); 465 write(child_out[1], &rc, sizeof(int));
459 close(child_out[1]); 466 close(child_out[1]);
460 if(opt_debug) 467 if(opt_debug)
529 g_free(req->addr); 536 g_free(req->addr);
530 g_free(req); 537 g_free(req);
531 return FALSE; 538 return FALSE;
532 } 539 }
533 540
534 int gaim_gethostbyname_async(const char *hostname, int port, int socktype, dns_callback_t callback, gpointer data) 541 int gaim_gethostbyname_async(const char *hostname, int port, dns_callback_t callback, gpointer data)
535 { 542 {
536 struct sockaddr_in sin; 543 struct sockaddr_in sin;
537 pending_dns_request_t *req; 544 pending_dns_request_t *req;
538 545
539 if (!inet_aton(hostname, &sin.sin_addr)) { 546 if (!inet_aton(hostname, &sin.sin_addr)) {
1183 g_free(phb->host); 1190 g_free(phb->host);
1184 g_free(phb); 1191 g_free(phb);
1185 return -1; 1192 return -1;
1186 } 1193 }
1187 1194
1188 gaim_gethostbyname_async(connecthost, connectport, SOCK_STREAM, connection_host_resolved, phb); 1195 gaim_gethostbyname_async(connecthost, connectport, connection_host_resolved, phb);
1189 return 1; 1196 return 1;
1190 } 1197 }