Changeset 2986


Ignore:
Timestamp:
Nov 4, 2009 5:08:32 PM (9 years ago)
Author:
nanang
Message:

Ticket #957:

  • Applied workaround solution for getting local address problem with getsockname on win IOCP by using parent local address instead.
  • Fixed SSL socket not to return PJ_FALSE in active socket accept callback, to keep accepting connections.
  • Applied workaround solution for OpenSSL error mapping, as OpenSSL error codes are big numbers that won't fit pj_status_t.
  • Minor updates, e.g: using pj_perror(), removing some logs, OpenSSL error print callback.
  • Minor updates on SSL unit test, e.g: start_read() before start sending, additional ioqueue poll to cleanup sockets, add timeout feature to https client test.
Location:
pjproject/trunk/pjlib/src
Files:
2 edited

Legend:

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

    r2972 r2986  
    193193                                         PJ_ERRNO_SPACE_SIZE*6) 
    194194 
    195 #define PJ_SSL_ERRNO_SPACE_SIZE         5000 
    196  
    197 #define PJ_STATUS_FROM_OSSL(ossl_err)   (ossl_err == SSL_ERROR_NONE? \ 
    198                                          PJ_SUCCESS : \ 
    199                                          (PJ_SSL_ERRNO_START + ossl_err)) 
    200  
    201 #define PJ_STATUS_TO_OSSL(status)       (status == PJ_SUCCESS? \ 
    202                                          SSL_ERROR_NONE : \ 
    203                                         (status - PJ_SSL_ERRNO_START)) 
    204  
     195#define PJ_SSL_ERRNO_SPACE_SIZE         PJ_ERRNO_SPACE_SIZE 
     196 
     197#define GET_SSL_STATUS(status) { \ 
     198    unsigned long e = ERR_get_error();\ 
     199    status = ERR_GET_LIB(e)*300 + ERR_GET_REASON(e);\ 
     200    pj_assert(status < PJ_SSL_ERRNO_SPACE_SIZE);\ 
     201    if (status) status += PJ_SSL_ERRNO_START;\ 
     202} 
    205203 
    206204/* 
     
    211209{ 
    212210    pj_str_t errstr; 
    213     unsigned long ssl_err = PJ_STATUS_TO_OSSL(status); 
     211    unsigned long ssl_err = status; 
     212 
     213    if (ssl_err) { 
     214        unsigned long l, r; 
     215        ssl_err -= PJ_SSL_ERRNO_START; 
     216        l = ssl_err/300; 
     217        r = ssl_err%300; 
     218        ssl_err = ERR_PACK(l, 0, r); 
     219    } 
    214220 
    215221#if defined(PJ_HAS_ERROR_STRING) && (PJ_HAS_ERROR_STRING != 0) 
    216222 
    217     ERR_error_string_n(ssl_err, buf, bufsize); 
    218     errstr = pj_str(buf); 
    219  
    220 #else 
     223    { 
     224        const char *tmp = NULL; 
     225        tmp = ERR_reason_error_string(ssl_err); 
     226 
     227        if (tmp) { 
     228            pj_ansi_strncpy(buf, tmp, bufsize); 
     229            errstr = pj_str(buf); 
     230            return errstr; 
     231        } 
     232    } 
     233 
     234#endif  /* PJ_HAS_ERROR_STRING */ 
    221235 
    222236    errstr.ptr = buf; 
     
    224238                                   "Unknown OpenSSL error %d", 
    225239                                   ssl_err); 
    226  
    227 #endif  /* PJ_HAS_ERROR_STRING */ 
    228240 
    229241    return errstr; 
     
    337349    pj_ssl_cert_t *cert; 
    338350    int mode, rc; 
     351    pj_status_t status; 
    339352         
    340353    pj_assert(ssock && p_ctx); 
     
    370383    ctx = SSL_CTX_new(ssl_method); 
    371384    if (ctx == NULL) { 
    372         PJ_LOG(1,(ssock->pool->obj_name, "Error creating OpenSSL context")); 
    373         return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     385        GET_SSL_STATUS(status); 
     386        return status; 
    374387    } 
    375388 
     
    382395 
    383396            if (rc != 1) { 
     397                GET_SSL_STATUS(status); 
    384398                PJ_LOG(1,(ssock->pool->obj_name, "Error loading CA list file " 
    385399                          "'%s'", cert->CA_file.ptr)); 
    386400                SSL_CTX_free(ctx); 
    387                 return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     401                return status; 
    388402            } 
    389403        } 
     
    403417 
    404418            if(rc != 1) { 
     419                GET_SSL_STATUS(status); 
    405420                PJ_LOG(1,(ssock->pool->obj_name, "Error loading certificate " 
    406421                          "chain file '%s'", cert->cert_file.ptr)); 
    407422                SSL_CTX_free(ctx); 
    408                 return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     423                return status; 
    409424            } 
    410425        } 
     
    418433 
    419434            if(rc != 1) { 
     435                GET_SSL_STATUS(status); 
    420436                PJ_LOG(1,(ssock->pool->obj_name, "Error adding private key " 
    421437                          "from '%s'", cert->privkey_file.ptr)); 
    422438                SSL_CTX_free(ctx); 
    423                 return PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     439                return status; 
    424440            } 
    425441        } 
     
    543559    /* Finally, set chosen cipher list */ 
    544560    ret = SSL_set_cipher_list(ssock->ossl_ssl, buf); 
    545     if (ret < 1) 
    546         return PJ_STATUS_FROM_OSSL(SSL_get_error(ssock->ossl_ssl, ret)); 
     561    if (ret < 1) { 
     562        pj_status_t status; 
     563        GET_SSL_STATUS(status); 
     564        return status; 
     565    } 
    547566 
    548567    return PJ_SUCCESS; 
     
    688707        if (status != PJ_SUCCESS) { 
    689708            /* Handshake failed in accepting, destroy our self silently. */ 
     709 
     710            char errmsg[PJ_ERR_MSG_SIZE]; 
     711            char buf[PJ_INET6_ADDRSTRLEN+10]; 
     712 
     713            pj_strerror(status, errmsg, sizeof(errmsg)); 
     714            PJ_LOG(3,(ssock->pool->obj_name, "Handshake failed in accepting " 
     715                      "%s: %s", 
     716                      pj_sockaddr_print(&ssock->rem_addr, buf, sizeof(buf), 3), 
     717                      errmsg)); 
     718 
    690719            pj_ssl_sock_close(ssock); 
    691720            return PJ_FALSE; 
     
    875904        { 
    876905            /* Handshake fails */ 
     906            GET_SSL_STATUS(status); 
    877907            pj_lock_release(ssock->write_mutex); 
    878             return PJ_STATUS_FROM_OSSL(err); 
     908            return status; 
    879909        } 
    880910    } 
     
    922952        nwritten = BIO_write(ssock->ossl_rbio, data, size); 
    923953        if (nwritten < size) { 
    924             status = PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     954            GET_SSL_STATUS(status); 
    925955            goto on_error; 
    926956        } 
     
    9951025                if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ) 
    9961026                { 
    997                     char errmsg[PJ_ERR_MSG_SIZE]; 
    998  
    999                     pj_strerror(status, errmsg, sizeof(errmsg)); 
    1000                     PJ_LOG(1,(ssock->pool->obj_name, "SSL_read() failed: %s", 
    1001                               errmsg)); 
    1002  
    10031027                    /* Reset SSL socket state, then return PJ_FALSE */ 
     1028                    GET_SSL_STATUS(status); 
    10041029                    reset_ssl_sock_state(ssock); 
    10051030                    goto on_error; 
     
    10181043 
    10191044                    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
    1020                         char errmsg[PJ_ERR_MSG_SIZE]; 
    1021  
    1022                         pj_strerror(status, errmsg, sizeof(errmsg)); 
    1023                         PJ_LOG(1,(ssock->pool->obj_name, "Failed to flush " 
    1024                                   "delayed send: %s", errmsg)); 
     1045                        pj_perror(1, ssock->pool->obj_name, status,  
     1046                                  "Failed to flush delayed send", 0); 
    10251047                        goto on_error; 
    10261048                    } 
    10271049                } else if (status != PJ_EPENDING) { 
    1028                     char errmsg[PJ_ERR_MSG_SIZE]; 
    1029  
    1030                     pj_strerror(status, errmsg, sizeof(errmsg)); 
    1031                     PJ_LOG(1,(ssock->pool->obj_name, "Renegotiation failed: " 
    1032                               "%s", errmsg)); 
     1050                    pj_perror(1, ssock->pool->obj_name, status,  
     1051                              "Renegotiation failed", 0); 
    10331052                    goto on_error; 
    10341053                } 
     
    11221141    unsigned i; 
    11231142    pj_status_t status; 
    1124     char buf[64]; 
    11251143 
    11261144    PJ_UNUSED_ARG(src_addr_len); 
    1127  
    1128     PJ_LOG(4,(ssock_parent->pool->obj_name, "Incoming connection from %s", 
    1129               pj_sockaddr_print(src_addr, buf, sizeof(buf), 3))); 
    11301145 
    11311146    /* Create new SSL socket instance */ 
     
    11501165    status = pj_sock_getsockname(ssock->sock, &ssock->local_addr,  
    11511166                                 &ssock->addr_len); 
    1152     if (status != PJ_SUCCESS) 
    1153         goto on_return; 
     1167    if (status != PJ_SUCCESS) { 
     1168        /* This fails on few envs, e.g: win IOCP, just tolerate this and 
     1169         * use parent local address instead. 
     1170         */ 
     1171        pj_sockaddr_cp(&ssock->local_addr, &ssock_parent->local_addr); 
     1172    } 
    11541173 
    11551174    /* Set remote address */ 
     
    11641183    ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    11651184    if (ssock->ossl_ssl == NULL) { 
    1166         PJ_LOG(1,(ssock->pool->obj_name, "Error creating SSL instance")); 
    1167         status = PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     1185        GET_SSL_STATUS(status); 
    11681186        goto on_return; 
    11691187    } 
     
    12451263    SSL_set_accept_state(ssock->ossl_ssl); 
    12461264    status = do_handshake(ssock); 
    1247     if (status != PJ_EPENDING) 
    1248         goto on_return; 
    1249  
     1265 
     1266on_return: 
     1267    if (ssock && status != PJ_EPENDING) 
     1268        on_handshake_complete(ssock, status); 
     1269 
     1270    /* Must return PJ_TRUE whatever happened, as active socket must  
     1271     * continue listening. 
     1272     */ 
    12501273    return PJ_TRUE; 
    1251  
    1252 on_return: 
    1253     return on_handshake_complete(ssock, status); 
    12541274} 
    12551275 
     
    12801300    ssock->ossl_ssl = SSL_new(ssock->ossl_ctx); 
    12811301    if (ssock->ossl_ssl == NULL) { 
    1282         PJ_LOG(1,(ssock->pool->obj_name, "Error creating SSL instance")); 
    1283         status = PJ_STATUS_FROM_OSSL(ERR_get_error()); 
     1302        GET_SSL_STATUS(status); 
    12841303        goto on_return; 
    12851304    } 
     
    17231742        } else { 
    17241743            /* Some problem occured */ 
    1725             status = PJ_STATUS_FROM_OSSL(err); 
     1744            GET_SSL_STATUS(status); 
    17261745        } 
    17271746    } else { 
     
    20182037    ret = SSL_renegotiate(ssock->ossl_ssl); 
    20192038    if (ret <= 0) { 
    2020         status = PJ_STATUS_FROM_OSSL(SSL_get_error(ssock->ossl_ssl, ret)); 
     2039        GET_SSL_STATUS(status); 
    20212040    } else { 
    20222041        status = do_handshake(ssock); 
  • pjproject/trunk/pjlib/src/pjlib-test/ssl_sock.c

    r2981 r2986  
    151151    } 
    152152 
     153    /* Start reading data */ 
     154    read_buf[0] = st->read_buf; 
     155    status = pj_ssl_sock_start_read2(ssock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0); 
     156    if (status != PJ_SUCCESS) { 
     157        app_perror("...ERROR pj_ssl_sock_start_read2()", status); 
     158        goto on_return; 
     159    } 
     160 
    153161    /* Start sending data */ 
    154162    while (st->sent < st->send_str_len) { 
     
    169177    } 
    170178 
    171     /* Start reading data */ 
    172     read_buf[0] = st->read_buf; 
    173     status = pj_ssl_sock_start_read2(ssock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0); 
    174     if (status != PJ_SUCCESS  && status != PJ_EPENDING) { 
    175         app_perror("...ERROR pj_ssl_sock_start_read2()", status); 
    176         goto on_return; 
    177     } 
    178  
    179179on_return: 
    180180    st->err = status; 
     
    196196{ 
    197197    struct test_state *parent_st = (struct test_state*)  
    198                             pj_ssl_sock_get_user_data(ssock); 
     198                                   pj_ssl_sock_get_user_data(ssock); 
    199199    struct test_state *st; 
    200200    void *read_buf[1]; 
     
    237237            dump_cert_info(".......", &info.remote_cert_info); 
    238238        } 
     239    } 
     240 
     241    /* Start reading data */ 
     242    read_buf[0] = st->read_buf; 
     243    status = pj_ssl_sock_start_read2(newsock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0); 
     244    if (status != PJ_SUCCESS) { 
     245        app_perror("...ERROR pj_ssl_sock_start_read2()", status); 
     246        goto on_return; 
    239247    } 
    240248 
     
    255263        else 
    256264            break; 
    257     } 
    258  
    259     /* Start reading data */ 
    260     read_buf[0] = st->read_buf; 
    261     status = pj_ssl_sock_start_read2(newsock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0); 
    262     if (status != PJ_SUCCESS  && status != PJ_EPENDING) { 
    263         app_perror("...ERROR pj_ssl_sock_start_read2()", status); 
    264         goto on_return; 
    265265    } 
    266266 
     
    422422#define HTTP_SERVER_PORT        443 
    423423 
    424 static int https_client_test(void) 
     424static int https_client_test(unsigned ms_timeout) 
    425425{ 
    426426    pj_pool_t *pool = NULL; 
    427427    pj_ioqueue_t *ioqueue = NULL; 
     428    pj_timer_heap_t *timer = NULL; 
    428429    pj_ssl_sock_t *ssock = NULL; 
    429430    pj_ssl_sock_param param; 
     
    436437 
    437438    status = pj_ioqueue_create(pool, 4, &ioqueue); 
     439    if (status != PJ_SUCCESS) { 
     440        goto on_return; 
     441    } 
     442 
     443    status = pj_timer_heap_create(pool, 4, &timer); 
    438444    if (status != PJ_SUCCESS) { 
    439445        goto on_return; 
     
    452458    param.user_data = &state; 
    453459    param.server_name = pj_str((char*)HTTP_SERVER_ADDR); 
     460    param.timer_heap = timer; 
     461    param.timeout.sec = 0; 
     462    param.timeout.msec = ms_timeout; 
     463    pj_time_val_normalize(&param.timeout); 
    454464 
    455465    status = pj_ssl_sock_create(pool, &param, &ssock); 
     
    476486        pj_time_val delay = {0, 100}; 
    477487        pj_ioqueue_poll(ioqueue, &delay); 
     488        pj_timer_heap_poll(timer, &delay); 
    478489#endif 
    479490    } 
     
    492503    if (ioqueue) 
    493504        pj_ioqueue_destroy(ioqueue); 
     505    if (timer) 
     506        pj_timer_heap_destroy(timer); 
    494507    if (pool) 
    495508        pj_pool_release(pool); 
     
    633646    } 
    634647 
     648    /* Clean up sockets */ 
     649    { 
     650        pj_time_val delay = {0, 100}; 
     651        while (pj_ioqueue_poll(ioqueue, &delay) > 0); 
     652    } 
     653 
    635654    if (state_serv.err || state_cli.err) { 
    636655        if (state_serv.err != PJ_SUCCESS) 
     
    683702    st->err = status; 
    684703 
     704    if (st->err != PJ_SUCCESS || st->done) { 
     705        pj_activesock_close(asock); 
     706        if (!st->is_server) 
     707            clients_num--; 
     708        return PJ_FALSE; 
     709    } 
     710 
    685711    return PJ_TRUE; 
    686712} 
     
    694720 
    695721    if (status == PJ_SUCCESS) { 
    696         status = pj_activesock_start_read(asock, st->pool, 1, 0); 
     722        void *read_buf[1]; 
     723 
     724        /* Start reading data */ 
     725        read_buf[0] = st->read_buf; 
     726        status = pj_activesock_start_read2(asock, st->pool, sizeof(st->read_buf), (void**)read_buf, 0); 
     727        if (status != PJ_SUCCESS) { 
     728            app_perror("...ERROR pj_ssl_sock_start_read2()", status); 
     729        } 
    697730    } 
    698731 
    699732    st->err = status; 
     733 
     734    if (st->err != PJ_SUCCESS) { 
     735        pj_activesock_close(asock); 
     736        if (!st->is_server) 
     737            clients_num--; 
     738        return PJ_FALSE; 
     739    } 
    700740 
    701741    return PJ_TRUE; 
     
    846886    if (ssock_serv) 
    847887        pj_ssl_sock_close(ssock_serv); 
    848     if (asock_cli) 
     888    if (asock_cli && !state_cli.err && !state_cli.done) 
    849889        pj_activesock_close(asock_cli); 
    850890    if (timer) 
     
    859899 
    860900 
     901/* Test will perform multiple clients trying to connect to single server. 
     902 * Once SSL connection established, echo test will be performed. 
     903 */ 
    861904static int perf_test(unsigned clients, unsigned ms_handshake_timeout) 
    862905{ 
     
    10231066    } 
    10241067 
     1068    /* Clean up sockets */ 
     1069    { 
     1070        pj_time_val delay = {0, 500}; 
     1071        while (pj_ioqueue_poll(ioqueue, &delay) > 0); 
     1072    } 
     1073 
    10251074    if (state_serv.err != PJ_SUCCESS) { 
    10261075        status = state_serv.err; 
     
    10781127        return ret; 
    10791128 
    1080     // Disable this test as requiring internet connection. 
    1081 #if 0 
    10821129    PJ_LOG(3,("", "..https client test")); 
    1083     ret = https_client_test(); 
    1084     if (ret != 0) 
    1085         return ret; 
    1086 #endif 
     1130    ret = https_client_test(30000); 
     1131    // Ignore test result as internet connection may not be available. 
     1132    //if (ret != 0) 
     1133        //return ret; 
     1134 
     1135#ifndef PJ_SYMBIAN 
    10871136 
    10881137    PJ_LOG(3,("", "..echo test w/ TLSv1 and TLS_RSA_WITH_DES_CBC_SHA cipher")); 
     
    11101159        return PJ_EBUG; 
    11111160 
    1112     PJ_LOG(3,("", "..client non-SSL timeout in 5 secs")); 
     1161    PJ_LOG(3,("", "..client non-SSL (handshake timeout 5 secs)")); 
    11131162    ret = client_non_ssl(5000); 
    11141163    if (ret != 0) 
     
    11191168    if (ret != 0) 
    11201169        return ret; 
     1170 
     1171#endif 
    11211172 
    11221173    return 0; 
Note: See TracChangeset for help on using the changeset viewer.