Changeset 4317


Ignore:
Timestamp:
Jan 15, 2013 2:21:07 PM (7 years ago)
Author:
nanang
Message:

Fix #1603: reinit UDP socket of DNS resolver when sendto() returning EPIPE.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/src/pjlib-util/resolver.c

    r4220 r4317  
    224224 
    225225 
     226/* Close UDP socket */ 
     227static void close_sock(pj_dns_resolver *resv) 
     228{ 
     229    /* Close existing socket */ 
     230    if (resv->udp_key != NULL) { 
     231        pj_ioqueue_unregister(resv->udp_key); 
     232        resv->udp_key = NULL; 
     233        resv->udp_sock = PJ_INVALID_SOCKET; 
     234    } else if (resv->udp_sock != PJ_INVALID_SOCKET) { 
     235        pj_sock_close(resv->udp_sock); 
     236        resv->udp_sock = PJ_INVALID_SOCKET; 
     237    } 
     238} 
     239 
     240 
     241/* Initialize UDP socket */ 
     242static pj_status_t init_sock(pj_dns_resolver *resv) 
     243{ 
     244    pj_ioqueue_callback socket_cb; 
     245    pj_status_t status; 
     246 
     247    /* Create the UDP socket */ 
     248    status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &resv->udp_sock); 
     249    if (status != PJ_SUCCESS) 
     250        return status; 
     251 
     252    /* Bind to any address/port */ 
     253    status = pj_sock_bind_in(resv->udp_sock, 0, 0); 
     254    if (status != PJ_SUCCESS) 
     255        return status; 
     256 
     257    /* Register to ioqueue */ 
     258    pj_bzero(&socket_cb, sizeof(socket_cb)); 
     259    socket_cb.on_read_complete = &on_read_complete; 
     260    status = pj_ioqueue_register_sock(resv->pool, resv->ioqueue, 
     261                                      resv->udp_sock, resv, &socket_cb, 
     262                                      &resv->udp_key); 
     263    if (status != PJ_SUCCESS) 
     264        return status; 
     265 
     266    pj_ioqueue_op_key_init(&resv->udp_op_key, sizeof(resv->udp_op_key)); 
     267 
     268    /* Start asynchronous read to the UDP socket */ 
     269    resv->udp_len = sizeof(resv->udp_rx_pkt); 
     270    resv->udp_addr_len = sizeof(resv->udp_src_addr); 
     271    status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_key, 
     272                                 resv->udp_rx_pkt, &resv->udp_len, 
     273                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
     274                                 &resv->udp_src_addr, &resv->udp_addr_len); 
     275    if (status != PJ_EPENDING) 
     276        return status; 
     277 
     278    return PJ_SUCCESS; 
     279} 
     280 
     281 
    226282/* Initialize DNS settings with default values */ 
    227283PJ_DEF(void) pj_dns_settings_default(pj_dns_settings *s) 
     
    248304    pj_pool_t *pool; 
    249305    pj_dns_resolver *resv; 
    250     pj_ioqueue_callback socket_cb; 
    251306    pj_status_t status; 
    252307 
     
    303358    pj_list_init(&resv->query_free_nodes); 
    304359 
    305     /* Create the UDP socket */ 
    306     status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &resv->udp_sock); 
     360    /* Initialize the UDP socket */ 
     361    status = init_sock(resv); 
    307362    if (status != PJ_SUCCESS) 
    308363        goto on_error; 
    309  
    310     /* Bind to any address/port */ 
    311     status = pj_sock_bind_in(resv->udp_sock, 0, 0); 
    312     if (status != PJ_SUCCESS) 
    313         goto on_error; 
    314  
    315     /* Register to ioqueue */ 
    316     pj_bzero(&socket_cb, sizeof(socket_cb)); 
    317     socket_cb.on_read_complete = &on_read_complete; 
    318     status = pj_ioqueue_register_sock(pool, resv->ioqueue, resv->udp_sock, 
    319                                       resv, &socket_cb, &resv->udp_key); 
    320     if (status != PJ_SUCCESS) 
    321         goto on_error; 
    322  
    323     pj_ioqueue_op_key_init(&resv->udp_op_key, sizeof(resv->udp_op_key)); 
    324  
    325     /* Start asynchronous read to the UDP socket */ 
    326     resv->udp_len = sizeof(resv->udp_rx_pkt); 
    327     resv->udp_addr_len = sizeof(resv->udp_src_addr); 
    328     status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_key,  
    329                                  resv->udp_rx_pkt, &resv->udp_len,  
    330                                  PJ_IOQUEUE_ALWAYS_ASYNC, 
    331                                  &resv->udp_src_addr, &resv->udp_addr_len); 
    332     if (status != PJ_EPENDING) 
    333         goto on_error; 
    334  
    335364 
    336365    /* Looks like everything is okay */ 
     
    393422    } 
    394423 
    395     if (resolver->udp_key != NULL) { 
    396         pj_ioqueue_unregister(resolver->udp_key); 
    397         resolver->udp_key = NULL; 
    398         resolver->udp_sock = PJ_INVALID_SOCKET; 
    399     } else if (resolver->udp_sock != PJ_INVALID_SOCKET) { 
    400         pj_sock_close(resolver->udp_sock); 
    401         resolver->udp_sock = PJ_INVALID_SOCKET; 
    402     } 
     424    close_sock(resolver); 
    403425 
    404426    if (resolver->own_ioqueue && resolver->ioqueue) { 
     
    604626        struct nameserver *ns = &resolver->ns[servers[i]]; 
    605627 
    606         pj_sock_sendto(resolver->udp_sock, resolver->udp_tx_pkt, &sent, 0, 
    607                        &resolver->ns[servers[i]].addr, sizeof(pj_sockaddr_in)); 
    608  
    609         PJ_LOG(4,(resolver->name.ptr,  
     628        status = pj_sock_sendto(resolver->udp_sock, resolver->udp_tx_pkt, 
     629                                &sent, 0, &resolver->ns[servers[i]].addr, 
     630                                sizeof(pj_sockaddr_in)); 
     631 
     632#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ 
     633            PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 
     634        /* Re-init dead UDP sockets, see ticket #1107 & #1603. 
     635         * Note: PJ_STATUS_FROM_OS(EPIPE) == PJ_ERRNO_START_SYS + 32. 
     636         */ 
     637        if (status == PJ_ERRNO_START_SYS + 32) { 
     638            close_sock(resolver); 
     639            status = init_sock(resolver); 
     640            if (status != PJ_SUCCESS) { 
     641                PJ_PERROR(1,(THIS_FILE, status, "Error reinit UDP socket")); 
     642                return status; 
     643            } 
     644 
     645            PJ_LOG(3,(THIS_FILE, "UDP socket reinitialized.")); 
     646 
     647            /* Try to send again */ 
     648            status = pj_sock_sendto(resolver->udp_sock, resolver->udp_tx_pkt, 
     649                                    &sent, 0, &resolver->ns[servers[i]].addr, 
     650                                    sizeof(pj_sockaddr_in)); 
     651        } 
     652#endif 
     653 
     654        PJ_PERROR(4,(resolver->name.ptr, status, 
    610655                  "%s %d bytes to NS %d (%s:%d): DNS %s query for %s", 
    611656                  (q->transmit_cnt==0? "Transmitting":"Re-transmitting"), 
    612                   (int)sent, servers[i], 
     657                  (int)pkt_size, servers[i], 
    613658                  pj_inet_ntoa(ns->addr.sin_addr),  
    614659                  (int)pj_ntohs(ns->addr.sin_port), 
Note: See TracChangeset for help on using the changeset viewer.