Changeset 599


Ignore:
Timestamp:
Jul 10, 2006 9:35:27 PM (18 years ago)
Author:
bennylp
Message:

Fixed several bugs in WinNT IOCP: (1) accept() does not return correct addresses, (2) handle error condition when accept() returns -1 as the new socket

Location:
pjproject/trunk/pjlib/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/ioqueue_winnt.c

    r582 r599  
    2727#include <pj/assert.h> 
    2828#include <pj/errno.h> 
     29#include <pj/compat/socket.h> 
    2930 
    3031 
     
    174175                          &remote, 
    175176                          &remotelen); 
    176     if (*accept_overlapped->addrlen > locallen) { 
     177    if (*accept_overlapped->addrlen >= locallen) { 
    177178        pj_memcpy(accept_overlapped->local, local, locallen); 
    178179        pj_memcpy(accept_overlapped->remote, remote, locallen); 
     
    628629            if (key->cb.on_accept_complete) { 
    629630                ioqueue_accept_rec *accept_rec = (ioqueue_accept_rec*)pOv; 
     631                pj_status_t status = PJ_SUCCESS; 
     632 
     633                if (accept_rec->newsock == PJ_INVALID_SOCKET) { 
     634                    int dwError = WSAGetLastError(); 
     635                    if (dwError == 0) dwError = OSERR_ENOTCONN; 
     636                    status = PJ_RETURN_OS_ERROR(dwError); 
     637                } 
     638 
    630639                key->cb.on_accept_complete(key,  
    631640                                           (pj_ioqueue_op_key_t*)pOv,  
    632641                                           accept_rec->newsock, 
    633                                            PJ_SUCCESS); 
     642                                           status); 
    634643                accept_rec->newsock = PJ_INVALID_SOCKET; 
    635644            } 
  • pjproject/trunk/pjlib/src/pjlib-test/ioq_tcp.c

    r592 r599  
    531531} 
    532532 
     533 
     534/* 
     535 * Repeated connect/accept on the same listener socket. 
     536 */ 
     537static int compliance_test_2(void) 
     538{ 
     539    enum { MAX_PAIR = 4, TEST_LOOP = 2 }; 
     540 
     541    struct listener 
     542    { 
     543        pj_sock_t            sock; 
     544        pj_ioqueue_key_t    *key; 
     545        pj_sockaddr_in       addr; 
     546        int                  addr_len; 
     547    } listener; 
     548 
     549    struct server 
     550    { 
     551        pj_sock_t            sock; 
     552        pj_ioqueue_key_t    *key; 
     553        pj_sockaddr_in       local_addr; 
     554        pj_sockaddr_in       rem_addr; 
     555        int                  rem_addr_len; 
     556        pj_ioqueue_op_key_t  accept_op; 
     557    } server[MAX_PAIR]; 
     558 
     559    struct client 
     560    { 
     561        pj_sock_t            sock; 
     562        pj_ioqueue_key_t    *key; 
     563    } client[MAX_PAIR]; 
     564 
     565    pj_pool_t *pool = NULL; 
     566    char *send_buf, *recv_buf; 
     567    pj_ioqueue_t *ioque = NULL; 
     568    int i, bufsize = BUF_MIN_SIZE; 
     569    pj_ssize_t status; 
     570    int test_loop, pending_op = 0; 
     571    pj_timestamp t_elapsed; 
     572    pj_str_t s; 
     573    pj_status_t rc; 
     574 
     575    // Create pool. 
     576    pool = pj_pool_create(mem, NULL, POOL_SIZE, 4000, NULL); 
     577 
     578 
     579    // Create I/O Queue. 
     580    rc = pj_ioqueue_create(pool, PJ_IOQUEUE_MAX_HANDLES, &ioque); 
     581    if (rc != PJ_SUCCESS) { 
     582        app_perror("...ERROR in pj_ioqueue_create()", rc); 
     583        return -10; 
     584    } 
     585 
     586 
     587    // Allocate buffers for send and receive. 
     588    send_buf = (char*)pj_pool_alloc(pool, bufsize); 
     589    recv_buf = (char*)pj_pool_alloc(pool, bufsize); 
     590 
     591    // Create listener socket 
     592    rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_STREAM, 0, &listener.sock); 
     593    if (rc != PJ_SUCCESS) { 
     594        app_perror("...error creating socket", rc); 
     595        status=-20; goto on_error; 
     596    } 
     597 
     598    // Bind listener socket. 
     599    pj_sockaddr_in_init(&listener.addr, 0, 0); 
     600    if ((rc=pj_sock_bind(listener.sock, &listener.addr, sizeof(listener.addr))) != 0 ) { 
     601        app_perror("...bind error", rc); 
     602        status=-30; goto on_error; 
     603    } 
     604 
     605    // Get listener address. 
     606    listener.addr_len = sizeof(listener.addr); 
     607    rc = pj_sock_getsockname(listener.sock, &listener.addr, &listener.addr_len); 
     608    if (rc != PJ_SUCCESS) { 
     609        app_perror("...ERROR in pj_sock_getsockname()", rc); 
     610        status=-40; goto on_error; 
     611    } 
     612    listener.addr.sin_addr = pj_inet_addr(pj_cstr(&s, "127.0.0.1")); 
     613 
     614 
     615    // Register listener socket. 
     616    rc = pj_ioqueue_register_sock(pool, ioque, listener.sock, NULL, &test_cb,  
     617                                  &listener.key); 
     618    if (rc != PJ_SUCCESS) { 
     619        app_perror("...ERROR", rc); 
     620        status=-50; goto on_error; 
     621    } 
     622 
     623 
     624    // Listener socket listen(). 
     625    if (pj_sock_listen(listener.sock, 5)) { 
     626        app_perror("...ERROR in pj_sock_listen()", rc); 
     627        status=-60; goto on_error; 
     628    } 
     629 
     630 
     631    for (test_loop=0; test_loop < TEST_LOOP; ++test_loop) { 
     632        // Client connect and server accept. 
     633        for (i=0; i<MAX_PAIR; ++i) { 
     634            rc = pj_sock_socket(PJ_AF_INET, PJ_SOCK_STREAM, 0, &client[i].sock); 
     635            if (rc != PJ_SUCCESS) { 
     636                app_perror("...error creating socket", rc); 
     637                status=-70; goto on_error; 
     638            } 
     639 
     640            rc = pj_ioqueue_register_sock(pool, ioque, client[i].sock, NULL,  
     641                                          &test_cb, &client[i].key); 
     642            if (rc != PJ_SUCCESS) { 
     643                app_perror("...error ", rc); 
     644                status=-80; goto on_error; 
     645            } 
     646 
     647            // Server socket accept() 
     648            pj_ioqueue_op_key_init(&server[i].accept_op,  
     649                                   sizeof(server[i].accept_op)); 
     650            server[i].rem_addr_len = sizeof(pj_sockaddr_in); 
     651            status = pj_ioqueue_accept(listener.key, &server[i].accept_op,  
     652                                       &server[i].sock, &server[i].local_addr,  
     653                                       &server[i].rem_addr,  
     654                                       &server[i].rem_addr_len); 
     655            if (status!=PJ_SUCCESS && status != PJ_EPENDING) { 
     656                app_perror("...ERROR in pj_ioqueue_accept()", rc); 
     657                status=-90; goto on_error; 
     658            } 
     659            if (status==PJ_EPENDING) { 
     660                ++pending_op; 
     661            } 
     662 
     663 
     664            // Client socket connect() 
     665            status = pj_ioqueue_connect(client[i].key, &listener.addr,  
     666                                        sizeof(listener.addr)); 
     667            if (status!=PJ_SUCCESS && status != PJ_EPENDING) { 
     668                app_perror("...ERROR in pj_ioqueue_connect()", rc); 
     669                status=-100; goto on_error; 
     670            } 
     671            if (status==PJ_EPENDING) { 
     672                ++pending_op; 
     673            } 
     674 
     675        } 
     676 
     677 
     678        // Poll until all connected 
     679        while (pending_op) { 
     680            pj_time_val timeout = {1, 0}; 
     681 
     682            status=pj_ioqueue_poll(ioque, &timeout); 
     683            if (status > 0) { 
     684                if (status > pending_op) { 
     685                    PJ_LOG(3,(THIS_FILE, 
     686                              "...error: pj_ioqueue_poll() returned %d " 
     687                              "(only expecting %d)", 
     688                              status, pending_op)); 
     689                    return -110; 
     690                } 
     691                pending_op -= status; 
     692 
     693                if (pending_op == 0) { 
     694                    status = 0; 
     695                } 
     696            } 
     697        } 
     698 
     699        // There's no pending operation. 
     700        // When we poll the ioqueue, there must not be events. 
     701        if (pending_op == 0) { 
     702            pj_time_val timeout = {1, 0}; 
     703            status = pj_ioqueue_poll(ioque, &timeout); 
     704            if (status != 0) { 
     705                status=-120; goto on_error; 
     706            } 
     707        } 
     708 
     709        for (i=0; i<MAX_PAIR; ++i) { 
     710            // Check server socket. 
     711            if (server[i].sock == PJ_INVALID_SOCKET) { 
     712                status = -130; 
     713                app_perror("...accept() error", pj_get_os_error()); 
     714                goto on_error; 
     715            } 
     716 
     717            // Check addresses 
     718            if (server[i].local_addr.sin_family != PJ_AF_INET || 
     719                server[i].local_addr.sin_addr.s_addr == 0 || 
     720                server[i].local_addr.sin_port == 0) 
     721            { 
     722                app_perror("...ERROR address not set", rc); 
     723                status = -140; 
     724                goto on_error; 
     725            } 
     726 
     727            if (server[i].rem_addr.sin_family != PJ_AF_INET || 
     728                server[i].rem_addr.sin_addr.s_addr == 0 || 
     729                server[i].rem_addr.sin_port == 0) 
     730            { 
     731                app_perror("...ERROR address not set", rc); 
     732                status = -150; 
     733                goto on_error; 
     734            } 
     735 
     736 
     737            // Register newly accepted socket. 
     738            rc = pj_ioqueue_register_sock(pool, ioque, server[i].sock, NULL, 
     739                                          &test_cb, &server[i].key); 
     740            if (rc != PJ_SUCCESS) { 
     741                app_perror("...ERROR in pj_ioqueue_register_sock", rc); 
     742                status = -160; 
     743                goto on_error; 
     744            } 
     745 
     746            // Test send and receive. 
     747            t_elapsed.u32.lo = 0; 
     748            status = send_recv_test(ioque, server[i].key, client[i].key,  
     749                                    send_buf, recv_buf, bufsize, &t_elapsed); 
     750            if (status != 0) { 
     751                goto on_error; 
     752            } 
     753        } 
     754 
     755        // Success 
     756        status = 0; 
     757 
     758        for (i=0; i<MAX_PAIR; ++i) { 
     759            if (server[i].key != NULL) { 
     760                pj_ioqueue_unregister(server[i].key); 
     761                server[i].key = NULL; 
     762                server[i].sock = PJ_INVALID_SOCKET; 
     763            } else if (server[i].sock != PJ_INVALID_SOCKET) { 
     764                pj_sock_close(server[i].sock); 
     765                server[i].sock = PJ_INVALID_SOCKET; 
     766            } 
     767 
     768            if (client[i].key != NULL) { 
     769                pj_ioqueue_unregister(client[i].key); 
     770                client[i].key = NULL; 
     771                client[i].sock = PJ_INVALID_SOCKET; 
     772            } else if (client[i].sock != PJ_INVALID_SOCKET) { 
     773                pj_sock_close(client[i].sock); 
     774                client[i].sock = PJ_INVALID_SOCKET; 
     775            } 
     776        } 
     777    } 
     778 
     779    status = 0; 
     780 
     781on_error: 
     782    for (i=0; i<MAX_PAIR; ++i) { 
     783        if (server[i].key != NULL) { 
     784            pj_ioqueue_unregister(server[i].key); 
     785            server[i].key = NULL; 
     786            server[i].sock = PJ_INVALID_SOCKET; 
     787        } else if (server[i].sock != PJ_INVALID_SOCKET) { 
     788            pj_sock_close(server[i].sock); 
     789            server[i].sock = PJ_INVALID_SOCKET; 
     790        } 
     791 
     792        if (client[i].key != NULL) { 
     793            pj_ioqueue_unregister(client[i].key); 
     794            client[i].key = NULL; 
     795            server[i].sock = PJ_INVALID_SOCKET; 
     796        } else if (client[i].sock != PJ_INVALID_SOCKET) { 
     797            pj_sock_close(client[i].sock); 
     798            client[i].sock = PJ_INVALID_SOCKET; 
     799        } 
     800    } 
     801 
     802    if (listener.key) { 
     803        pj_ioqueue_unregister(listener.key); 
     804        listener.key = NULL; 
     805    } else if (listener.sock != PJ_INVALID_SOCKET) { 
     806        pj_sock_close(listener.sock); 
     807        listener.sock = PJ_INVALID_SOCKET; 
     808    } 
     809 
     810    if (ioque != NULL) 
     811        pj_ioqueue_destroy(ioque); 
     812    pj_pool_release(pool); 
     813    return status; 
     814 
     815} 
     816 
     817 
    533818int tcp_ioqueue_test() 
    534819{ 
     
    544829               pj_ioqueue_name())); 
    545830    if ((status=compliance_test_1()) != 0) { 
     831        PJ_LOG(1, (THIS_FILE, "....FAILED (status=%d)\n", status)); 
     832        return status; 
     833    } 
     834 
     835    PJ_LOG(3, (THIS_FILE, "..%s compliance test 2 (repeated accept)", 
     836               pj_ioqueue_name())); 
     837    if ((status=compliance_test_2()) != 0) { 
    546838        PJ_LOG(1, (THIS_FILE, "....FAILED (status=%d)\n", status)); 
    547839        return status; 
  • pjproject/trunk/pjlib/src/pjlib-test/test.h

    r592 r599  
    2222#include <pj/types.h> 
    2323 
    24 #define GROUP_LIBC                  0 
    25 #define GROUP_OS                    0 
    26 #define GROUP_DATA_STRUCTURE        0 
     24#define GROUP_LIBC                  1 
     25#define GROUP_OS                    1 
     26#define GROUP_DATA_STRUCTURE        1 
    2727#define GROUP_NETWORK               1 
    28 #define GROUP_FILE                  0 
     28#define GROUP_FILE                  1 
    2929 
    3030#define INCLUDE_ERRNO_TEST          GROUP_LIBC 
Note: See TracChangeset for help on using the changeset viewer.