Navigation


Changeset 209:b9f48f2f2a22 in freeDiameter


Ignore:
Timestamp:
Feb 16, 2010, 3:29:55 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Some cleanups in the code

Location:
freeDiameter
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/cnxctx.c

    r208 r209  
    136136                if (rc)
    137137                        snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
    138                 snprintf(cnx->cc_id, sizeof(cnx->cc_id), "Srv TCP [%s]:%hu (%d)", addrbuf, port, cnx->cc_socket);
     138                snprintf(cnx->cc_id, sizeof(cnx->cc_id), "TCP srv [%s]:%hu (%d)", addrbuf, port, cnx->cc_socket);
    139139        }
    140140
     
    171171
    172172        /* Generate the name for the connection object */
    173         snprintf(cnx->cc_id, sizeof(cnx->cc_id), "Srv SCTP :%hu (%d)", port, cnx->cc_socket);
     173        snprintf(cnx->cc_id, sizeof(cnx->cc_id), "SCTP srv :%hu (%d)", port, cnx->cc_socket);
    174174
    175175        cnx->cc_proto = IPPROTO_SCTP;
     
    218218        CHECK_PARAMS_DO(serv, return NULL);
    219219       
    220         /* Accept the new connection -- this is blocking until new client enters or cancellation */
     220        /* Accept the new connection -- this is blocking until new client enters or until cancellation */
    221221        CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL );
    222222       
     
    247247                }
    248248               
    249                 snprintf(cli->cc_id, sizeof(cli->cc_id), "Incoming %s [%s]:%s (%d) @ serv (%d)",
    250                                 IPPROTO_NAME(cli->cc_proto),
    251                                 addrbuf, portbuf,
    252                                 cli->cc_socket, serv->cc_socket);
     249                snprintf(cli->cc_id, sizeof(cli->cc_id), "{%s} (%d) <- [%s]:%s (%d)",
     250                                IPPROTO_NAME(cli->cc_proto), serv->cc_socket,
     251                                addrbuf, portbuf, cli->cc_socket);
    253252               
    254253                /* Name for log messages */
     
    316315                }
    317316               
    318                 snprintf(cnx->cc_id, sizeof(cnx->cc_id), "Client of TCP server [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket);
     317                snprintf(cnx->cc_id, sizeof(cnx->cc_id), "{TCP} -> [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket);
    319318               
    320319                /* Name for log messages */
     
    379378                }
    380379               
    381                 snprintf(cnx->cc_id, sizeof(cnx->cc_id), "Client of SCTP server [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket);
     380                snprintf(cnx->cc_id, sizeof(cnx->cc_id), "{SCTP} -> [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket);
    382381               
    383382                /* Name for log messages */
     
    420419{
    421420        CHECK_PARAMS_DO( conn, return 0 );
    422         return conn->cc_tls;
     421        return conn->cc_status & CC_STATUS_TLS;
    423422}
    424423
     
    494493/**************************************/
    495494
     495/* An error occurred on the socket */
     496void fd_cnx_markerror(struct cnxctx * conn)
     497{
     498        TRACE_ENTRY("%p", conn);
     499        CHECK_PARAMS_DO( conn, goto fatal );
     500       
     501        /* Mark the error */
     502        conn->cc_status |= CC_STATUS_ERROR;
     503       
     504        /* Report the error if not reported yet, and not closing */
     505        if ((!(conn->cc_status & CC_STATUS_CLOSING )) && (!(conn->cc_status & CC_STATUS_SIGNALED )))  {
     506                CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), goto fatal);
     507                conn->cc_status |= CC_STATUS_SIGNALED;
     508        }
     509       
     510        return;
     511fatal:
     512        /* An unrecoverable error occurred, stop the daemon */
     513        CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );       
     514}
     515
    496516/* Set the timeout option on the socket */
    497517void fd_cnx_s_setto(int sock)
     
    504524        CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)), /* best effort only */ );
    505525        CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), /* Also timeout for sending, to avoid waiting forever */ );
    506 }       
    507 
    508 /* A recv-like function, taking a cnxctx object instead of socket as entry. Only used to filter timeouts error (GNUTLS does not like these...) */
     526}
     527
     528/* A recv-like function, taking a cnxctx object instead of socket as entry. We use it to quickly react to timeouts without traversing GNUTLS wrapper each time */
    509529ssize_t fd_cnx_s_recv(struct cnxctx * conn, void *buffer, size_t length)
    510530{
     
    515535        /* Handle special case of timeout */
    516536        if ((ret < 0) && (errno == EAGAIN)) {
    517                 if (!conn->cc_closing)
     537                if (! (conn->cc_status & CC_STATUS_CLOSING))
    518538                        goto again; /* don't care, just ignore */
    519539                if (!timedout) {
     
    521541                        goto again;
    522542                }
    523                 CHECK_SYS_DO(ret, /* continue */);
    524         }
     543        }
     544       
     545        CHECK_SYS_DO(ret, /* continue */);
    525546       
    526547        /* Mark the error */
    527548        if (ret <= 0)
    528                 conn->cc_goterror=1;
     549                fd_cnx_markerror(conn);
    529550       
    530551        return ret;
     
    540561        /* Handle special case of timeout */
    541562        if ((ret < 0) && (errno == EAGAIN)) {
    542                 if (!conn->cc_closing)
     563                if (! (conn->cc_status & CC_STATUS_CLOSING))
    543564                        goto again; /* don't care, just ignore */
    544565                if (!timedout) {
     
    551572        /* Mark the error */
    552573        if (ret <= 0)
    553                 conn->cc_goterror=1;
     574                fd_cnx_markerror(conn);
    554575       
    555576        return ret;
     
    572593       
    573594        ASSERT( conn->cc_proto == IPPROTO_TCP );
    574         ASSERT( conn->cc_tls == 0 );
     595        ASSERT( ! (conn->cc_status & CC_STATUS_TLS) );
    575596        ASSERT( Target_Queue(conn) );
    576597       
     
    586607                        ret = fd_cnx_s_recv(conn, &header[received], sizeof(header) - received);
    587608                        if (ret <= 0) {
    588                                 CHECK_SYS_DO(ret, /* continue */);
    589                                 goto error; /* Stop the thread, the recipient of the event will cleanup */
     609                                goto out; /* Stop the thread, the event was already sent */
    590610                        }
    591611
     
    600620                        /* The message is suspect */
    601621                        TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], length);
    602                         goto error; /* Stop the thread, the recipient of the event will cleanup */
     622                        fd_cnx_markerror(conn);
     623                        goto out; /* Stop the thread, the recipient of the event will cleanup */
    603624                }
    604625
    605626                /* Ok, now we can really receive the data */
    606                 CHECK_MALLOC_DO(  newmsg = malloc( length ), goto error );
     627                CHECK_MALLOC_DO(  newmsg = malloc( length ), goto fatal );
    607628                memcpy(newmsg, header, sizeof(header));
    608629
     
    613634
    614635                        if (ret <= 0) {
    615                                 CHECK_SYS_DO(ret, /* continue */);
    616636                                free(newmsg);
    617                                 goto error; /* Stop the thread, the recipient of the event will cleanup */
     637                                goto out;
    618638                        }
    619639                        received += ret;
    620640                }
    621641               
    622                 /* We have received a complete message, send it */
     642                /* We have received a complete message, pass it to the daemon */
    623643                CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg), /* continue or destroy everything? */);
    624644               
     
    628648        TRACE_DEBUG(FULL, "Thread terminated");
    629649        return NULL;
    630 error:
    631         if (!conn->cc_closing) {
    632                 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
    633         }
     650       
     651fatal:
     652        /* An unrecoverable error occurred, stop the daemon */
     653        CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
    634654        goto out;
    635655}
     
    645665       
    646666        TRACE_ENTRY("%p", arg);
    647         CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out);
     667        CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto fatal);
    648668       
    649669        /* Set the thread name */
     
    655675       
    656676        ASSERT( conn->cc_proto == IPPROTO_SCTP );
    657         ASSERT( conn->cc_tls == 0 );
     677        ASSERT( ! (conn->cc_status & CC_STATUS_TLS) );
    658678        ASSERT( Target_Queue(conn) );
    659679       
    660680        do {
    661                 CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, NULL, &buf, &bufsz, &event, &conn->cc_closing), goto error );
     681                CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, NULL, &buf, &bufsz, &event, &conn->cc_status), goto fatal );
    662682                if (event == FDEVP_CNX_ERROR) {
    663                         conn->cc_goterror = 1;
    664                         goto error;
    665                 }
    666                
    667                 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), event, bufsz, buf), goto error );
     683                        fd_cnx_markerror(conn);
     684                        goto out;
     685                }
     686               
     687                CHECK_FCT_DO( fd_event_send( Target_Queue(conn), event, bufsz, buf), goto fatal );
    668688               
    669689        } while (conn->cc_loop);
     
    672692        TRACE_DEBUG(FULL, "Thread terminated");
    673693        return NULL;
    674 error:
    675         if (!conn->cc_closing) {
    676                 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
    677         }
     694
     695fatal:
     696        /* An unrecoverable error occurred, stop the daemon */
     697        CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
    678698        goto out;
    679699}
    680700#endif /* DISABLE_SCTP */
    681 
    682 /* Returns 0 on error, received data size otherwise (always >= 0) */
    683 static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
    684 {
    685         ssize_t ret;
    686 again: 
    687         CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz),
    688                 {
    689                         switch (ret) {
    690                                 case GNUTLS_E_REHANDSHAKE:
    691                                         if (!conn->cc_closing)
    692                                                 CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
    693                                                         {
    694                                                                 if (TRACE_BOOL(INFO)) {
    695                                                                         fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
    696                                                                 }
    697                                                                 ret = 0;
    698                                                                 goto end;
    699                                                         } );
    700 
    701                                 case GNUTLS_E_AGAIN:
    702                                 case GNUTLS_E_INTERRUPTED:
    703                                         if (!conn->cc_closing)
    704                                                 goto again;
    705                                         TRACE_DEBUG(INFO, "Connection is closing, so abord gnutls_record_recv now.");
    706                                         ret = 0;
    707                                         break;
    708 
    709                                 default:
    710                                         TRACE_DEBUG(INFO, "This TLS error is not handled, assume unrecoverable error");
    711                                         ret = 0;
    712                         }
    713                 } );
    714 end:   
    715         if (ret <= 0)
    716                 conn->cc_goterror = 1;
    717         return ret;
    718 }
    719 
    720 /* Wrapper around gnutls_record_send to handle some error codes */
    721 static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
    722 {
    723         ssize_t ret;
    724 again: 
    725         CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz),
    726                 {
    727                         switch (ret) {
    728                                 case GNUTLS_E_REHANDSHAKE:
    729                                         if (!conn->cc_closing)
    730                                                 CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
    731                                                         {
    732                                                                 if (TRACE_BOOL(INFO)) {
    733                                                                         fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
    734                                                                 }
    735                                                                 goto end;
    736                                                         } );
    737 
    738                                 case GNUTLS_E_AGAIN:
    739                                 case GNUTLS_E_INTERRUPTED:
    740                                         if (!conn->cc_closing)
    741                                                 goto again;
    742                                         TRACE_DEBUG(INFO, "Connection is closing, so abord gnutls_record_send now.");
    743                                         break;
    744 
    745                                 default:
    746                                         TRACE_DEBUG(INFO, "This TLS error is not handled, assume unrecoverable error");
    747                         }
    748                 } );
    749 end:   
    750         if (ret <= 0)
    751                 conn->cc_goterror = 1;
    752         return ret;
    753 }
    754 
    755 
    756 /* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */
    757 int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
    758 {
    759         /* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP */
    760         do {
    761                 uint8_t header[4];
    762                 uint8_t * newmsg;
    763                 size_t  length;
    764                 ssize_t ret = 0;
    765                 size_t  received = 0;
    766 
    767                 do {
    768                         ret = fd_tls_recv_handle_error(conn, session, &header[received], sizeof(header) - received);
    769                         if (ret == 0) {
    770                                 /* The connection is closed */
    771                                 goto out;
    772                         }
    773                         received += ret;
    774                 } while (received < sizeof(header));
    775 
    776                 length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
    777 
    778                 /* Check the received word is a valid beginning of a Diameter message */
    779                 if ((header[0] != DIAMETER_VERSION)     /* defined in <libfreeDiameter.h> */
    780                    || (length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
    781                         /* The message is suspect */
    782                         TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], length);
    783                         goto out;
    784                 }
    785 
    786                 /* Ok, now we can really receive the data */
    787                 CHECK_MALLOC(  newmsg = malloc( length ) );
    788                 memcpy(newmsg, header, sizeof(header));
    789 
    790                 while (received < length) {
    791                         pthread_cleanup_push(free, newmsg); /* In case we are canceled, clean the partialy built buffer */
    792                         ret = fd_tls_recv_handle_error(conn, session, newmsg + received, length - received);
    793                         pthread_cleanup_pop(0);
    794 
    795                         if (ret == 0) {
    796                                 free(newmsg);
    797                                 goto out; /* Stop the thread, the recipient of the event will cleanup */
    798                         }
    799                         received += ret;
    800                 }
    801                
    802                 /* We have received a complete message, send it */
    803                 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg), /* continue or destroy everything? */);
    804                
    805         } while (1);
    806 out:
    807         return ENOTCONN;
    808 }
    809 
    810 /* Receiver thread (TLS & 1 stream SCTP or TCP) : gnutls directly handles the socket, save records into the target queue */
    811 static void * rcvthr_tls_single(void * arg)
    812 {
    813         struct cnxctx * conn = arg;
    814        
    815         TRACE_ENTRY("%p", arg);
    816         CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto error);
    817        
    818         /* Set the thread name */
    819         {
    820                 char buf[48];
    821                 snprintf(buf, sizeof(buf), "Receiver (%d) TLS/single stream", conn->cc_socket);
    822                 fd_log_threadname ( buf );
    823         }
    824        
    825         ASSERT( conn->cc_tls == 1 );
    826         ASSERT( Target_Queue(conn) );
    827        
    828         CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */);
    829 error:
    830         if (!conn->cc_closing) {
    831                 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
    832         }
    833         TRACE_DEBUG(FULL, "Thread terminated");
    834         return NULL;
    835 }
    836701
    837702/* Start receving messages in clear (no TLS) on the connection */
     
    840705        TRACE_ENTRY("%p %i", conn, loop);
    841706       
    842         CHECK_PARAMS( conn && Target_Queue(conn) && (!conn->cc_tls) && (!conn->cc_loop));
     707        CHECK_PARAMS( conn && Target_Queue(conn) && (!(conn->cc_status & CC_STATUS_TLS)) && (!conn->cc_loop));
    843708       
    844709        /* Release resources in case of a previous call was already made */
     
    861726                default:
    862727                        TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto);
     728                        ASSERT(0);
    863729                        return ENOTSUP;
    864730        }
     
    867733}
    868734
     735
     736
     737
     738/* Returns 0 on error, received data size otherwise (always >= 0) */
     739static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
     740{
     741        ssize_t ret;
     742again: 
     743        CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz),
     744                {
     745                        switch (ret) {
     746                                case GNUTLS_E_REHANDSHAKE:
     747                                        if (!(conn->cc_status & CC_STATUS_CLOSING))
     748                                                CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
     749                                                        {
     750                                                                if (TRACE_BOOL(INFO)) {
     751                                                                        fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
     752                                                                }
     753                                                                goto end;
     754                                                        } );
     755
     756                                case GNUTLS_E_AGAIN:
     757                                case GNUTLS_E_INTERRUPTED:
     758                                        if (!(conn->cc_status & CC_STATUS_CLOSING))
     759                                                goto again;
     760                                        TRACE_DEBUG(INFO, "Connection is closing, so abord gnutls_record_recv now.");
     761                                        break;
     762
     763                                default:
     764                                        TRACE_DEBUG(INFO, "This TLS error is not handled, assume unrecoverable error");
     765                        }
     766                } );
     767end:   
     768        if (ret <= 0)
     769                fd_cnx_markerror(conn);
     770        return ret;
     771}
     772
     773/* Wrapper around gnutls_record_send to handle some error codes */
     774static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
     775{
     776        ssize_t ret;
     777again: 
     778        CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz),
     779                {
     780                        switch (ret) {
     781                                case GNUTLS_E_REHANDSHAKE:
     782                                        if (!(conn->cc_status & CC_STATUS_CLOSING))
     783                                                CHECK_GNUTLS_DO( ret = gnutls_handshake(session),
     784                                                        {
     785                                                                if (TRACE_BOOL(INFO)) {
     786                                                                        fd_log_debug("TLS re-handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
     787                                                                }
     788                                                                goto end;
     789                                                        } );
     790
     791                                case GNUTLS_E_AGAIN:
     792                                case GNUTLS_E_INTERRUPTED:
     793                                        if (!(conn->cc_status & CC_STATUS_CLOSING))
     794                                                goto again;
     795                                        TRACE_DEBUG(INFO, "Connection is closing, so abord gnutls_record_send now.");
     796                                        break;
     797
     798                                default:
     799                                        TRACE_DEBUG(INFO, "This TLS error is not handled, assume unrecoverable error");
     800                        }
     801                } );
     802end:   
     803        if (ret <= 0)
     804                fd_cnx_markerror(conn);
     805               
     806        return ret;
     807}
     808
     809
     810/* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */
     811int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
     812{
     813        /* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP */
     814        do {
     815                uint8_t header[4];
     816                uint8_t * newmsg;
     817                size_t  length;
     818                ssize_t ret = 0;
     819                size_t  received = 0;
     820
     821                do {
     822                        ret = fd_tls_recv_handle_error(conn, session, &header[received], sizeof(header) - received);
     823                        if (ret <= 0) {
     824                                /* The connection is closed */
     825                                goto out;
     826                        }
     827                        received += ret;
     828                } while (received < sizeof(header));
     829
     830                length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
     831
     832                /* Check the received word is a valid beginning of a Diameter message */
     833                if ((header[0] != DIAMETER_VERSION)     /* defined in <libfreeDiameter.h> */
     834                   || (length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
     835                        /* The message is suspect */
     836                        TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], length);
     837                        fd_cnx_markerror(conn);
     838                        goto out;
     839                }
     840
     841                /* Ok, now we can really receive the data */
     842                CHECK_MALLOC(  newmsg = malloc( length ) );
     843                memcpy(newmsg, header, sizeof(header));
     844
     845                while (received < length) {
     846                        pthread_cleanup_push(free, newmsg); /* In case we are canceled, clean the partialy built buffer */
     847                        ret = fd_tls_recv_handle_error(conn, session, newmsg + received, length - received);
     848                        pthread_cleanup_pop(0);
     849
     850                        if (ret <= 0) {
     851                                free(newmsg);
     852                                goto out;
     853                        }
     854                        received += ret;
     855                }
     856               
     857                /* We have received a complete message, pass it to the daemon */
     858                CHECK_FCT_DO( ret = fd_event_send( Target_Queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg),
     859                        {
     860                                free(newmsg);
     861                                CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
     862                                return ret;
     863                        } );
     864               
     865        } while (1);
     866       
     867out:
     868        return ENOTCONN;
     869}
     870
     871/* Receiver thread (TLS & 1 stream SCTP or TCP)  */
     872static void * rcvthr_tls_single(void * arg)
     873{
     874        struct cnxctx * conn = arg;
     875       
     876        TRACE_ENTRY("%p", arg);
     877        CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), return NULL );
     878       
     879        /* Set the thread name */
     880        {
     881                char buf[48];
     882                snprintf(buf, sizeof(buf), "Receiver (%d) TLS/single stream", conn->cc_socket);
     883                fd_log_threadname ( buf );
     884        }
     885       
     886        ASSERT( conn->cc_status & CC_STATUS_TLS );
     887        ASSERT( Target_Queue(conn) );
     888
     889        /* The next function only returns when there is an error on the socket */       
     890        CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */);
     891
     892        TRACE_DEBUG(FULL, "Thread terminated");
     893        return NULL;
     894}
     895
    869896/* Prepare a gnutls session object for handshake */
    870897int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority, void * alt_creds)
    871898{
    872         /* Create the master session context */
     899        /* Create the session context */
    873900        CHECK_GNUTLS_DO( gnutls_init (session, mode), return ENOMEM );
    874901
     
    901928        gnutls_x509_crt_t cert;
    902929        time_t now;
     930       
     931        TRACE_ENTRY("%p %d", conn, verbose);
     932        CHECK_PARAMS(conn);
    903933       
    904934        /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */
     
    11071137int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority, void * alt_creds)
    11081138{
    1109         TRACE_ENTRY( "%p %d", conn, mode);
    1110         CHECK_PARAMS( conn && (!conn->cc_tls) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) );
     1139        TRACE_ENTRY( "%p %d %p %p", conn, mode, priority, alt_creds);
     1140        CHECK_PARAMS( conn && (!(conn->cc_status & CC_STATUS_TLS)) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) );
    11111141
    11121142        /* Save the mode */
     
    11401170        }
    11411171
     1172        /* Mark the connection as protected from here, so that the gnutls credentials will be freed */
     1173        conn->cc_status |= CC_STATUS_TLS;
     1174
    11421175        /* Handshake master session */
    11431176        {
     
    11481181                                        fd_log_debug("TLS Handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret));
    11491182                                }
    1150                                 conn->cc_goterror = 1;
     1183                                fd_cnx_markerror(conn);
    11511184                                return EINVAL;
    11521185                        } );
     
    11551188                CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1),
    11561189                        { 
    1157                                 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), /* Continue */ );
    1158                                 gnutls_deinit(conn->cc_tls_para.session);
     1190                                CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), );
     1191                                fd_cnx_markerror(conn);
    11591192                                return EINVAL;
    11601193                        });
    11611194        }
    1162 
    1163         /* Mark the connection as protected from here */
    1164         conn->cc_tls = 1;
    11651195
    11661196        /* Multi-stream TLS: handshake other streams as well */
     
    11851215{
    11861216        TRACE_ENTRY("%p %p %p", conn, cert_list, cert_list_size);
    1187         CHECK_PARAMS( conn && (conn->cc_tls) && cert_list && cert_list_size );
     1217        CHECK_PARAMS( conn && (conn->cc_status & CC_STATUS_TLS) && cert_list && cert_list_size );
    11881218       
    11891219        /* This function only works for X.509 certificates. */
     
    12021232
    12031233/* Receive next message. if timeout is not NULL, wait only until timeout. This function only pulls from a queue, mgr thread is filling that queue aynchrounously. */
     1234/* if the altfifo has been set on this conn object, this function must not be called */
    12041235int fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len)
    12051236{
     
    12641295        TRACE_ENTRY("%p %p %zd", conn, buf, len);
    12651296        do {
    1266                 if (conn->cc_tls) {
    1267                         CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_tls_para.session, buf + sent, len - sent), return ENOTCONN );
     1297                if (conn->cc_status & CC_STATUS_TLS) {
     1298                        CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_tls_para.session, buf + sent, len - sent), );
    12681299                } else {
    1269                         CHECK_SYS( ret = fd_cnx_s_send(conn, buf + sent, len - sent) ); /* better to replace with sendmsg for atomic sending? */
    1270                 }
     1300                        /* Maybe better to replace this call with sendmsg for atomic sending? */
     1301                        CHECK_SYS_DO( ret = fd_cnx_s_send(conn, buf + sent, len - sent), );
     1302                }
     1303                if (ret <= 0)
     1304                        return ENOTCONN;
     1305               
    12711306                sent += ret;
    12721307        } while ( sent < len );
     
    12791314        TRACE_ENTRY("%p %p %zd %i", conn, buf, len, ordered);
    12801315       
    1281         CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! conn->cc_goterror) && buf && len);
    1282 
    1283         TRACE_DEBUG(FULL, "Sending %zdb %sdata on connection %s", len, conn->cc_tls ? "TLS-protected ":"", conn->cc_id);
     1316        CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! (conn->cc_status & CC_STATUS_ERROR)) && buf && len);
     1317
     1318        TRACE_DEBUG(FULL, "Sending %zdb %sdata on connection %s", len, (conn->cc_status & CC_STATUS_TLS) ? "TLS-protected ":"", conn->cc_id);
    12841319       
    12851320        switch (conn->cc_proto) {
     
    12921327                        int multistr = 0;
    12931328                       
    1294                         if ((!ordered) && (conn->cc_sctp_para.str_out > 1) && ((! conn->cc_tls) || (conn->cc_sctp_para.pairs > 1)))  {
     1329                        if ((!ordered) && (conn->cc_sctp_para.str_out > 1) && ((! (conn->cc_status & CC_STATUS_TLS)) || (conn->cc_sctp_para.pairs > 1)))  {
    12951330                                /* Update the id of the stream we will send this message on */
    12961331                                conn->cc_sctp_para.next += 1;
    1297                                 conn->cc_sctp_para.next %= (conn->cc_tls ? conn->cc_sctp_para.pairs : conn->cc_sctp_para.str_out);
     1332                                conn->cc_sctp_para.next %= ((conn->cc_status & CC_STATUS_TLS) ? conn->cc_sctp_para.pairs : conn->cc_sctp_para.str_out);
    12981333                                multistr = 1;
    12991334                        }
     
    13021337                                CHECK_FCT( send_simple(conn, buf, len) );
    13031338                        } else {
    1304                                 if (!conn->cc_tls) {
    1305                                         CHECK_FCT_DO( fd_sctp_sendstr(conn->cc_socket, conn->cc_sctp_para.next, buf, len, &conn->cc_closing), { conn->cc_goterror = 1; return ENOTCONN; } );
     1339                                if (!(conn->cc_status & CC_STATUS_TLS)) {
     1340                                        CHECK_FCT_DO( fd_sctp_sendstr(conn->cc_socket, conn->cc_sctp_para.next, buf, len, &conn->cc_status), { fd_cnx_markerror(conn); return ENOTCONN; } );
    13061341                                } else {
    13071342                                        /* push the record to the appropriate session */
     
    13101345                                        ASSERT(conn->cc_sctps_data.array != NULL);
    13111346                                        do {
    1312                                                 CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_sctps_data.array[conn->cc_sctp_para.next].session, buf + sent, len - sent), return ENOTCONN );
     1347                                                CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_sctps_data.array[conn->cc_sctp_para.next].session, buf + sent, len - sent), );
     1348                                                if (ret <= 0)
     1349                                                        return ENOTCONN;
     1350                                               
    13131351                                                sent += ret;
    13141352                                        } while ( sent < len );
     
    13211359                default:
    13221360                        TRACE_DEBUG(INFO, "Unknwon protocol: %d", conn->cc_proto);
     1361                        ASSERT(0);
    13231362                        return ENOTSUP; /* or EINVAL... */
    13241363        }
     
    13391378        CHECK_PARAMS_DO(conn, return);
    13401379       
    1341         conn->cc_closing = 1;
     1380        conn->cc_status |= CC_STATUS_CLOSING;
    13421381       
    13431382        /* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */
    1344         if (conn->cc_tls) {
     1383        if (conn->cc_status & CC_STATUS_TLS) {
    13451384#ifndef DISABLE_SCTP
    13461385                if (conn->cc_sctp_para.pairs > 1) {
    1347                         if (! conn->cc_goterror ) {
     1386                        if (! (conn->cc_status & CC_STATUS_ERROR )) {
    13481387                                /* Bye on master session */
    1349                                 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), /* Continue */ );
    1350 
     1388                                CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) );
     1389                        }
     1390
     1391                        if (! (conn->cc_status & CC_STATUS_ERROR ) ) {
    13511392                                /* and other stream pairs */
    13521393                                fd_sctps_bye(conn);
    1353 
     1394                        }
     1395
     1396                        if (! (conn->cc_status & CC_STATUS_ERROR ) ) {
    13541397                                /* Now wait for all decipher threads to terminate */
    13551398                                fd_sctps_waitthreadsterm(conn);
     
    13611404                        /* Deinit gnutls resources */
    13621405                        fd_sctps_gnutls_deinit_others(conn);
    1363                         gnutls_deinit(conn->cc_tls_para.session);
     1406                        if (conn->cc_tls_para.session) {
     1407                                gnutls_deinit(conn->cc_tls_para.session);
     1408                                conn->cc_tls_para.session = NULL;
     1409                        }
    13641410                       
    13651411                        /* Destroy the wrapper (also stops the demux thread) */
     
    13691415#endif /* DISABLE_SCTP */
    13701416                /* We are not using the sctps wrapper layer */
    1371                         if (! conn->cc_goterror ) {
     1417                        if (! (conn->cc_status & CC_STATUS_ERROR ) ) {
    13721418                                /* Master session */
    1373                                 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), /* Continue */ );
    1374 
     1419                                CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) );
     1420                        }
     1421
     1422                        if (! (conn->cc_status & CC_STATUS_ERROR ) ) {
    13751423                                /* In this case, just wait for thread rcvthr_tls_single to terminate */
    13761424                                if (conn->cc_rcvthr != (pthread_t)NULL) {
     
    13841432                       
    13851433                        /* Free the resources of the TLS session */
    1386                         gnutls_deinit(conn->cc_tls_para.session);
     1434                        if (conn->cc_tls_para.session) {
     1435                                gnutls_deinit(conn->cc_tls_para.session);
     1436                                conn->cc_tls_para.session = NULL;
     1437                        }
    13871438               
    13881439#ifndef DISABLE_SCTP
  • freeDiameter/cnxctx.h

    r203 r209  
    4747
    4848        int             cc_proto;       /* IPPROTO_TCP or IPPROTO_SCTP */
    49         int             cc_tls;         /* Is TLS already started ? */
    50         int             cc_goterror;    /* True when an error occurred on the socket */
    51         int             cc_closing;     /* True if the object is being destroyed: we don't send events anymore */
     49        uint32_t        cc_status;      /* True if the object is being destroyed: we don't send events anymore */
     50        #define         CC_STATUS_CLOSING       1
     51        #define         CC_STATUS_ERROR         2
     52        #define         CC_STATUS_SIGNALED      4
     53        #define         CC_STATUS_TLS           8
    5254
    5355        pthread_t       cc_rcvthr;      /* thread for receiving messages on the connection */
     
    7981        }               cc_sctps_data;
    8082};
     83
     84void fd_cnx_markerror(struct cnxctx * conn);
    8185
    8286/* Socket */
  • freeDiameter/sctp.c

    r201 r209  
    10421042
    10431043/* Send a buffer over a specified stream */
    1044 int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len, int * cc_closing)
     1044int fd_sctp_sendstr(int sock, uint16_t strid, uint8_t * buf, size_t len, int * cc_status)
    10451045{
    10461046        struct msghdr mhdr;
     
    10531053        int timedout = 0;
    10541054       
    1055         TRACE_ENTRY("%d %hu %p %zd %p", sock, strid, buf, len, cc_closing);
    1056         CHECK_PARAMS(cc_closing);
     1055        TRACE_ENTRY("%d %hu %p %zd %p", sock, strid, buf, len, cc_status);
     1056        CHECK_PARAMS(cc_status);
    10571057       
    10581058        memset(&mhdr, 0, sizeof(mhdr));
     
    10841084        /* Handle special case of timeout */
    10851085        if ((ret < 0) && (errno == EAGAIN)) {
    1086                 if (!*cc_closing)
     1086                if (!(*cc_status & CC_STATUS_CLOSING))
    10871087                        goto again; /* don't care, just ignore */
    10881088                if (!timedout) {
     
    10991099
    11001100/* Receive the next data from the socket, or next notification */
    1101 int fd_sctp_recvmeta(int sock, uint16_t * strid, uint8_t ** buf, size_t * len, int *event, int * cc_closing)
     1101int fd_sctp_recvmeta(int sock, uint16_t * strid, uint8_t ** buf, size_t * len, int *event, int * cc_status)
    11021102{
    11031103        ssize_t                  ret = 0;
     
    11101110        int                      timedout = 0;
    11111111       
    1112         TRACE_ENTRY("%d %p %p %p %p %p", sock, strid, buf, len, event, cc_closing);
    1113         CHECK_PARAMS( (sock > 0) && buf && len && event && cc_closing );
     1112        TRACE_ENTRY("%d %p %p %p %p %p", sock, strid, buf, len, event, cc_status);
     1113        CHECK_PARAMS( (sock > 0) && buf && len && event && cc_status );
    11141114       
    11151115        /* Cleanup out parameters */
     
    11451145        /* First, handle timeouts (same as fd_cnx_s_recv) */
    11461146        if ((ret < 0) && (errno == EAGAIN)) {
    1147                 if (!*cc_closing)
     1147                if (!(*cc_status & CC_STATUS_CLOSING))
    11481148                        goto again; /* don't care, just ignore */
    11491149                if (!timedout) {
  • freeDiameter/sctps.c

    r207 r209  
    8787       
    8888        do {
    89                 CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, &strid, &buf, &bufsz, &event, &conn->cc_closing), goto error );
     89                CHECK_FCT_DO( fd_sctp_recvmeta(conn->cc_socket, &strid, &buf, &bufsz, &event, &conn->cc_status), goto fatal );
    9090                switch (event) {
    9191                        case FDEVP_CNX_MSG_RECV:
    92                                 /* Demux this message in the appropriate fifo, another thread will pull, gnutls process, and send in target queue */
     92                                /* Demux this message to the appropriate fifo, another thread will pull, gnutls process, and send to target queue */
    9393                                if (strid < conn->cc_sctp_para.pairs) {
    94                                         CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto error );
     94                                        CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto fatal );
    9595                                } else {
    9696                                        TRACE_DEBUG(INFO, "Received packet (%d bytes) on out-of-range stream #%s from %s, discarded.", bufsz, strid, conn->cc_remid);
     
    101101                        case FDEVP_CNX_EP_CHANGE:
    102102                                /* Send this event to the target queue */
    103                                 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), event, bufsz, buf), goto error );
     103                                CHECK_FCT_DO( fd_event_send( Target_Queue(conn), event, bufsz, buf), goto fatal );
    104104                                break;
    105105                       
    106106                        case FDEVP_CNX_ERROR:
     107                                fd_cnx_markerror(conn);
     108                                goto out;
     109                               
    107110                        default:
    108                                 goto error;
     111                                goto fatal;
    109112                }
    110113               
     
    114117        TRACE_DEBUG(FULL, "Thread terminated");
    115118        return NULL;
    116 error:
    117         if (!conn->cc_closing) {
    118                 CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
    119         }
    120        
     119       
     120fatal:
     121        /* An unrecoverable error occurred, stop the daemon */
     122        CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
    121123        goto out;
    122124}
     
    140142        }
    141143       
     144        /* The next function loops while there is no error */
    142145        CHECK_FCT_DO(fd_tls_rcvthr_core(cnx, ctx->strid ? ctx->session : cnx->cc_tls_para.session), /* continue */);
    143146error:
    144         if (!cnx->cc_closing) {
    145                 CHECK_FCT_DO( fd_event_send( Target_Queue(cnx), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
    146         }
     147        fd_cnx_markerror(cnx);
    147148        TRACE_DEBUG(FULL, "Thread terminated");
    148149        return NULL;
     
    161162        CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } );
    162163       
    163         CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent->cc_socket, ctx->strid, (uint8_t *)data, len, &ctx->parent->cc_closing), /* errno is already set */ return -1 );
     164        CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent->cc_socket, ctx->strid, (uint8_t *)data, len, &ctx->parent->cc_status), /* errno is already set */ return -1 );
    164165       
    165166        return len;
     
    176177        CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; return -1; } );
    177178       
    178         /* If we don't have data available now, pull new message from the fifo -- this is blocking */
     179        /* If we don't have data available now, pull new message from the fifo -- this is blocking (until the queue is destroyed) */
    179180        if (!ctx->partial.buf) {
    180181                int ev;
     
    231232        pthread_rwlock_t lock;
    232233        struct cnxctx   *parent;
    233         /* Add another list to chain in a global list to implement a garbage collector on sessions */
     234        /* Add another list to chain in a global list to implement a garbage collector on sessions -- TODO */
    234235};
    235236
     
    336337                /* Check the data is the same */
    337338                if ((data.size != sr->data.size) || memcmp(data.data, sr->data.data, data.size)) {
    338                         TRACE_DEBUG(SR_LEVEL, "GnuTLS tried to store a session with same key and different data!");
     339                        TRACE_DEBUG(INFO, "GnuTLS tried to store a session with same key and different data!");
    339340                        ret = -1;
    340341                } else {
     
    571572        }
    572573       
    573         return errors ? ENOTCONN : 0;
     574        if (errors) {
     575                TRACE_DEBUG(INFO, "Handshake failed on %d/%hd stream pairs", errors, conn->cc_sctp_para.pairs);
     576                fd_cnx_markerror(conn);
     577                return ENOTCONN;
     578        }
     579       
     580        return 0;
    574581}
    575582
     
    599606        /* End all TLS sessions, in series (not as efficient as paralel, but simpler) */
    600607        for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
    601                 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctps_data.array[i].session, GNUTLS_SHUT_WR), /* Continue */ );
     608                if (!conn->cc_status & CC_STATUS_ERROR) {
     609                        CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctps_data.array[i].session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) );
     610                }
    602611        }
    603612}
     
    629638       
    630639        for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
    631                 gnutls_deinit(conn->cc_sctps_data.array[i].session);
     640                if (conn->cc_sctps_data.array[i].session) {
     641                        gnutls_deinit(conn->cc_sctps_data.array[i].session);
     642                        conn->cc_sctps_data.array[i].session = NULL;
     643                }
    632644        }
    633645}
     
    666678                        fd_event_destroy( &conn->cc_sctps_data.array[i].raw_recv, free );
    667679                free(conn->cc_sctps_data.array[i].partial.buf);
    668                 /* gnutls_session was already deinit */
     680                if (conn->cc_sctps_data.array[i].session) {
     681                        gnutls_deinit(conn->cc_sctps_data.array[i].session);
     682                        conn->cc_sctps_data.array[i].session = NULL;
     683                }
    669684        }
    670685       
Note: See TracChangeset for help on using the changeset viewer.