Navigation


Changeset 1102:1d7b3ebda27f in freeDiameter


Ignore:
Timestamp:
May 9, 2013, 5:40:02 PM (11 years ago)
Author:
Sebastien Decugis <sdecugis@freediameter.net>
Branch:
default
Children:
1103:d8591b1c56cd, 1105:6b4a417d2845
Phase:
public
Message:

Implemented the calls to HOOK_DATA_RECEIVED hook

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • include/freeDiameter/libfdcore.h

    r1101 r1102  
    916916                 - {msg} is NULL.
    917917                 - {peer} is NULL.
    918                  - {other} is a pointer to a structure { size_t len; uint8_t * buf; } containing the received buffer.
     918                 - {other} is a pointer to a struct fd_cnx_rcvdata containing the received buffer.
    919919                 - {permsgdata} points to either a new empty structure allocated for this message (cf. fd_hook_data_hdl), or NULL if no hdl is registered.
    920920                 */
     
    10251025struct fd_hook_data_hdl;
    10261026
     1027/* The following structure is what is passed to the HOOK_DATA_RECEIVED hook */
     1028struct fd_cnx_rcvdata {
     1029        size_t  length;
     1030        uint8_t * buffer; /* internal note: the buffer is padded with a struct fd_msg_pmdl, not accounted for in length */
     1031};
     1032
    10271033/* Function to register a new fd_hook_data_hdl. Should be called by your extension init function.
    10281034 * The arguments are the functions called to initialize a new fd_hook_permsgdata and to free this structure when the corresponding message is being freed.
  • include/freeDiameter/libfdproto.h

    r1101 r1102  
    25532553        pthread_mutex_t lock;
    25542554};
    2555 #define FD_MSG_PMDL_INITIALIZER(pmdl_ptr)        { FD_LIST_INITIALIZER(  (pmdl_ptr)->sentinel       ), PTHREAD_MUTEX_INITIALIZER }
    25562555struct fd_msg_pmdl * fd_msg_pmdl_get(struct msg * msg);
     2556
    25572557
    25582558/***************************************/
  • libfdcore/cnxctx.c

    r1101 r1102  
    673673}
    674674
     675#define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0)  /* Could use __alignof__(t) on some systems but this is more portable probably */
     676#define PMDL_PADDED(len) ( ((len) + ALIGNOF(struct fd_msg_pmdl) - 1) & ~(ALIGNOF(struct fd_msg_pmdl) - 1) )
     677
     678size_t fd_msg_pmdl_sizewithoverhead(size_t datalen)
     679{
     680        return PMDL_PADDED(datalen);
     681}
     682
     683struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen)
     684{
     685        return (struct fd_msg_pmdl *)(buf + PMDL_PADDED(datalen));
     686}
     687
     688static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl)
     689{
     690        *pmdl = fd_msg_pmdl_get_inbuf(buffer, expected_len);
     691        fd_list_init(&(*pmdl)->sentinel, NULL);
     692        CHECK_POSIX(pthread_mutex_init(&(*pmdl)->lock, NULL) );
     693        return 0;
     694}
     695
     696static uint8_t * fd_cnx_alloc_msg_buffer(size_t expected_len, struct fd_msg_pmdl ** pmdl)
     697{
     698        uint8_t * ret = NULL;
     699       
     700        CHECK_MALLOC_DO(  ret = malloc( PMDL_PADDED(expected_len) ), return NULL );
     701        CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
     702        return ret;
     703}
     704
     705static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl)
     706{
     707        uint8_t * ret = NULL;
     708       
     709        CHECK_MALLOC_DO(  ret = realloc( buffer, PMDL_PADDED(expected_len) ), return NULL );
     710        CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
     711        return ret;
     712}
     713
     714static void free_rcvdata(void * arg)
     715{
     716        struct fd_cnx_rcvdata * data = arg;
     717        struct fd_msg_pmdl * pmdl = fd_msg_pmdl_get_inbuf(data->buffer, data->length);
     718        (void) pthread_mutex_destroy(&pmdl->lock);
     719        free(data->buffer);
     720}
     721
    675722/* Receiver thread (TCP & noTLS) : incoming message is directly saved into the target queue */
    676723static void * rcvthr_notls_tcp(void * arg)
     
    695742        do {
    696743                uint8_t header[4];
    697                 uint8_t * newmsg;
    698                 size_t  length;
     744                struct fd_cnx_rcvdata rcv_data;
     745                struct fd_msg_pmdl *pmdl=NULL;
    699746                ssize_t ret = 0;
    700747                size_t  received = 0;
     
    709756                } while (received < sizeof(header));
    710757
    711                 length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
     758                rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
    712759
    713760                /* Check the received word is a valid begining of a Diameter message */
    714761                if ((header[0] != DIAMETER_VERSION)     /* defined in <libfdproto.h> */
    715                    || (length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
     762                   || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
    716763                        /* The message is suspect */
    717                         TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], length);
     764                        LOG_E( "Received suspect header [ver: %d, size: %zd], assuming disconnection", (int)header[0], rcv_data.length);
    718765                        fd_cnx_markerror(conn);
    719766                        goto out; /* Stop the thread, the recipient of the event will cleanup */
     
    721768
    722769                /* Ok, now we can really receive the data */
    723                 CHECK_MALLOC_DO(  newmsg = malloc( length + sizeof(struct timespec) ), goto fatal );
    724                 memcpy(newmsg, header, sizeof(header));
    725 
    726                 while (received < length) {
    727                         pthread_cleanup_push(free, newmsg); /* In case we are canceled, clean the partialy built buffer */
    728                         ret = fd_cnx_s_recv(conn, newmsg + received, length - received);
     770                CHECK_MALLOC_DO(  rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ), goto fatal );
     771                memcpy(rcv_data.buffer, header, sizeof(header));
     772
     773                while (received < rcv_data.length) {
     774                        pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */
     775                        ret = fd_cnx_s_recv(conn, rcv_data.buffer + received, rcv_data.length - received);
    729776                        pthread_cleanup_pop(0);
    730777
    731778                        if (ret <= 0) {
    732                                 free(newmsg);
     779                                free_rcvdata(&rcv_data);
    733780                                goto out;
    734781                        }
     
    736783                }
    737784               
    738                 // fd_msg_log(....)
     785                fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
    739786               
    740787                /* We have received a complete message, pass it to the daemon */
    741                 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg), /* continue or destroy everything? */);
     788                CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer),
     789                        {
     790                                free_rcvdata(&rcv_data);
     791                                CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
     792                                return NULL;
     793                        } );
    742794               
    743795        } while (conn->cc_loop);
     
    758810{
    759811        struct cnxctx * conn = arg;
    760         uint8_t * buf;
    761         size_t    bufsz;
     812        struct fd_cnx_rcvdata rcv_data;
    762813        int       event;
    763814       
     
    777828       
    778829        do {
    779                 CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &buf, &bufsz, &event), goto fatal );
     830                struct fd_msg_pmdl *pmdl=NULL;
     831                CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &rcv_data.buffer, &rcv_data.length, &event), goto fatal );
    780832                if (event == FDEVP_CNX_ERROR) {
    781833                        fd_cnx_markerror(conn);
     
    787839                        continue;
    788840                }
    789                 /* Note: the real size of buf is bufsz + struct timespec */
    790                 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, bufsz, buf), goto fatal );
     841
     842                if (event == FDEVP_CNX_MSG_RECV) {
     843                        CHECK_MALLOC_DO( rcv_data.buffer = fd_cnx_realloc_msg_buffer(rcv_data.buffer, rcv_data.length, &pmdl), goto fatal );
     844                        fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
     845                }
     846                CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, rcv_data.length, rcv_data.buffer), goto fatal );
    791847               
    792848        } while (conn->cc_loop || (event != FDEVP_CNX_MSG_RECV));
     
    928984        do {
    929985                uint8_t header[4];
    930                 uint8_t * newmsg;
    931                 size_t  length;
     986                struct fd_cnx_rcvdata rcv_data;
     987                struct fd_msg_pmdl *pmdl=NULL;
    932988                ssize_t ret = 0;
    933989                size_t  received = 0;
     
    942998                } while (received < sizeof(header));
    943999
    944                 length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
     1000                rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];
    9451001
    9461002                /* Check the received word is a valid beginning of a Diameter message */
    9471003                if ((header[0] != DIAMETER_VERSION)     /* defined in <libfreeDiameter.h> */
    948                    || (length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
     1004                   || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
    9491005                        /* The message is suspect */
    950                         TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], length);
     1006                        LOG_E( "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], rcv_data.length);
    9511007                        fd_cnx_markerror(conn);
    9521008                        goto out;
     
    9541010
    9551011                /* Ok, now we can really receive the data */
    956                 CHECK_MALLOC(  newmsg = malloc( length + sizeof(struct timespec)) );
    957                 memcpy(newmsg, header, sizeof(header));
    958 
    959                 while (received < length) {
    960                         pthread_cleanup_push(free, newmsg); /* In case we are canceled, clean the partialy built buffer */
    961                         ret = fd_tls_recv_handle_error(conn, session, newmsg + received, length - received);
     1012                CHECK_MALLOC(  rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ) );
     1013                memcpy(rcv_data.buffer, header, sizeof(header));
     1014
     1015                while (received < rcv_data.length) {
     1016                        pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */
     1017                        ret = fd_tls_recv_handle_error(conn, session, rcv_data.buffer + received, rcv_data.length - received);
    9621018                        pthread_cleanup_pop(0);
    9631019
    9641020                        if (ret <= 0) {
    965                                 free(newmsg);
     1021                                free_rcvdata(&rcv_data);
    9661022                                goto out;
    9671023                        }
     
    9691025                }
    9701026               
     1027                fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl);
     1028               
    9711029                /* We have received a complete message, pass it to the daemon */
    972                 CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg),
     1030                CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer),
    9731031                        {
    974                                 free(newmsg);
     1032                                free_rcvdata(&rcv_data);
    9751033                                CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
    9761034                                return ret;
  • libfdcore/cnxctx.h

    r894 r1102  
    6666                int                              mode;          /* GNUTLS_CLIENT / GNUTLS_SERVER */
    6767                gnutls_session_t                 session;       /* Session object (stream #0 in case of SCTP) */
    68                 struct timespec                  recvon;        /* Timestamp of the last chunk of data received on this session -- before uncipher */
    6968        }               cc_tls_para;
    7069
     
    131130                size_t   offset;
    132131        }                partial;       /* If the pull function did not read the full content of first message in raw, it stores it here for next read call. */
    133         struct timespec  recvon;        /* Timestamp of the last chunk of data received on this stream -- before uncipher */
    134132        pthread_t        thr;           /* Thread to decrypt raw data in this pair of streams */
    135133        gnutls_session_t session;       /* TLS context using this pair of streams -- except if strid == 0, in that case session is outside the array */
  • libfdcore/fdcore-internal.h

    r1098 r1102  
    219219        FDEVP_TERMINATE = 1500
    220220       
    221         /* A connection object has received a message. (data contains the buffer + struct timespec piggytailed -- unaligned) */
     221        /* A connection object has received a message. (data contains the buffer + padding + struct fd_msg_pmdl) */
    222222        ,FDEVP_CNX_MSG_RECV
    223223                         
     
    271271        int               validate;     /* The peer is new, it must be validated (by an extension) or error CEA to be sent */
    272272};
    273 
    274273
    275274/* Functions */
     
    367366void   fd_hook_associate(struct msg * msg, struct fd_msg_pmdl * pmdl);
    368367int    fd_hooks_init(void);
     368size_t fd_msg_pmdl_sizewithoverhead(size_t datalen);
     369struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen);
     370
    369371#endif /* _FDCORE_INTERNAL_H */
  • libfdcore/sctp.c

    r1078 r1102  
    10861086        /* We will loop while all data is not received. */
    10871087incomplete:
    1088         while (datasize + sizeof(struct timespec) >= bufsz ) {
     1088        while (datasize >= bufsz ) {
    10891089                /* The buffer is full, enlarge it */
    10901090                bufsz += mempagesz;
     
    10941094        memset(&iov,  0, sizeof(iov));
    10951095        iov.iov_base = data + datasize ;
    1096         iov.iov_len  = bufsz - sizeof(struct timespec) - datasize;
     1096        iov.iov_len  = bufsz - datasize;
    10971097
    10981098        /* Receive data from the socket */
  • libfdcore/sctps.c

    r1034 r1102  
    9292                                /* 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                                         /* Note, here the timespec is piggytailed to buf */
    9594                                        CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto fatal );
    9695                                } else {
     
    196195                        return -1;
    197196                }
    198                 if (ev == FDEVP_CNX_MSG_RECV) {
    199                         memcpy(&ctx->recvon, ctx->partial.buf + ctx->partial.bufsz, sizeof(struct timespec)); /* retrieve piggy-tailed ts */
    200                 }
    201197        }
    202198               
Note: See TracChangeset for help on using the changeset viewer.