Navigation


Changeset 1186:56c36d1007b4 in freeDiameter for libfdcore


Ignore:
Timestamp:
Jun 7, 2013, 7:48:34 PM (11 years ago)
Author:
Sebastien Decugis <sdecugis@freediameter.net>
Branch:
default
Phase:
public
Message:

Further preparation of the DTLS integration. Some cleanups in the GNUTLS handling.

Location:
libfdcore
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • libfdcore/cnxctx.c

    r1181 r1186  
    3939#include <net/if.h>
    4040#include <ifaddrs.h> /* for getifaddrs */
     41#include <sys/uio.h> /* writev */
    4142
    4243/* The maximum size of Diameter message we accept to receive (<= 2^24) to avoid too big mallocs in case of trashed headers */
     
    479480}
    480481
     482/* Mark the connection to tell if OOO delivery is permitted (only for SCTP) */
     483int fd_cnx_unordered_delivery(struct cnxctx * conn, int is_allowed)
     484{
     485        CHECK_PARAMS( conn );
     486        conn->cc_sctp_para.unordered = is_allowed;
     487        return 0;
     488}
     489
    481490/* Return true if the connection supports unordered delivery of messages */
    482 int fd_cnx_isMultichan(struct cnxctx * conn)
     491int fd_cnx_is_unordered_delivery_supported(struct cnxctx * conn)
    483492{
    484493        CHECK_PARAMS_DO( conn, return 0 );
    485494        #ifndef DISABLE_SCTP
    486495        if (conn->cc_proto == IPPROTO_SCTP)
    487                 return (conn->cc_sctp_para.str_in > 1) || (conn->cc_sctp_para.str_out > 1);
     496                return (conn->cc_sctp_para.str_out > 1);
    488497        #endif /* DISABLE_SCTP */
    489498        return 0;
     
    531540}
    532541
     542static int fd_cnx_may_dtls(struct cnxctx * conn);
     543
     544/* Get a short string representing the connection */
     545int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len)
     546{
     547        CHECK_PARAMS( conn );
     548       
     549        if (fd_cnx_teststate(conn, CC_STATUS_TLS)) {
     550                snprintf(buf, len, "%s,%s,soc#%d", IPPROTO_NAME(conn->cc_proto), fd_cnx_may_dtls(conn) ? "DTLS" : "TLS", conn->cc_socket);
     551        } else {
     552                snprintf(buf, len, "%s,soc#%d", IPPROTO_NAME(conn->cc_proto), conn->cc_socket);
     553        }
     554       
     555        return 0;
     556}
     557
    533558/* Retrieve a list of all IP addresses of the local system from the kernel, using getifaddrs */
    534559int fd_cnx_get_local_eps(struct fd_list * list)
     
    600625        CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), /* Also timeout for sending, to avoid waiting forever */ );
    601626}
     627
     628
     629#ifdef GNUTLS_VERSION_300
     630/* The pull_timeout function for gnutls */
     631static int fd_cnx_s_select (struct cnxctx * conn, unsigned int ms)
     632{
     633        fd_set rfds;
     634        struct timeval tv;
     635       
     636        FD_ZERO (&rfds);
     637        FD_SET (conn->cc_socket, &rfds);
     638       
     639        tv.tv_sec = ms / 1000;
     640        tv.tv_usec = (ms * 1000) % 1000000;
     641       
     642        return select (conn->cc_socket + 1, &rfds, NULL, NULL, &tv);
     643}               
     644#endif /* GNUTLS_VERSION_300 */
    602645
    603646/* 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 */
     
    628671}
    629672
    630 /* Send */
    631 static ssize_t fd_cnx_s_send(struct cnxctx * conn, void *buffer, size_t length)
     673/* Send, for older GNUTLS */
     674#ifndef GNUTLS_VERSION_212
     675static ssize_t fd_cnx_s_send(struct cnxctx * conn, const void *buffer, size_t length)
    632676{
    633677        ssize_t ret = 0;
     
    635679again:
    636680        ret = send(conn->cc_socket, buffer, length, 0);
     681        /* Handle special case of timeout */
     682        if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
     683                pthread_testcancel();
     684                if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING ))
     685                        goto again; /* don't care, just ignore */
     686                if (!timedout) {
     687                        timedout ++; /* allow for one timeout while closing */
     688                        goto again;
     689                }
     690                CHECK_SYS_DO(ret, /* continue */);
     691        }
     692       
     693        /* Mark the error */
     694        if (ret <= 0)
     695                fd_cnx_markerror(conn);
     696       
     697        return ret;
     698}
     699#endif /* GNUTLS_VERSION_212 */
     700
     701/* Send */
     702static ssize_t fd_cnx_s_sendv(struct cnxctx * conn, const struct iovec * iov, int iovcnt)
     703{
     704        ssize_t ret = 0;
     705        int timedout = 0;
     706again:
     707        ret = writev(conn->cc_socket, iov, iovcnt);
    637708        /* Handle special case of timeout */
    638709        if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) {
     
    16051676                /* Set the push and pull callbacks */
    16061677                if (!dtls) {
     1678                        #ifdef GNUTLS_VERSION_300
     1679                        GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( conn->cc_tls_para.session, (void *)fd_cnx_s_select ) );
     1680                        #endif /* GNUTLS_VERSION_300 */
    16071681                        GNUTLS_TRACE( gnutls_transport_set_pull_function(conn->cc_tls_para.session, (void *)fd_cnx_s_recv) );
     1682                        #ifndef GNUTLS_VERSION_212
    16081683                        GNUTLS_TRACE( gnutls_transport_set_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_send) );
     1684                        #else /* GNUTLS_VERSION_212 */
     1685                        GNUTLS_TRACE( gnutls_transport_set_vec_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_sendv) );
     1686                        #endif /* GNUTLS_VERSION_212 */
    16091687                } else {
    16101688                        TODO("DTLS push/pull functions");
     
    17841862                        CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_tls_para.session, buf + sent, len - sent),  );
    17851863                } else {
    1786                         /* Maybe better to replace this call with sendmsg for atomic sending? */
    1787                         CHECK_SYS_DO( ret = fd_cnx_s_send(conn, buf + sent, len - sent), );
     1864                        struct iovec iov;
     1865                        iov.iov_base = buf + sent;
     1866                        iov.iov_len  = len - sent;
     1867                        CHECK_SYS_DO( ret = fd_cnx_s_sendv(conn, &iov, 1), );
    17881868                }
    17891869                if (ret <= 0)
     
    17961876
    17971877/* Send a message -- this is synchronous -- and we assume it's never called by several threads at the same time (on the same conn), so we don't protect. */
    1798 int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len, uint32_t flags)
    1799 {
    1800         TRACE_ENTRY("%p %p %zd %x", conn, buf, len, flags);
     1878int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len)
     1879{
     1880        TRACE_ENTRY("%p %p %zd", conn, buf, len);
    18011881       
    18021882        CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! fd_cnx_teststate(conn, CC_STATUS_ERROR)) && buf && len);
     
    18121892                case IPPROTO_SCTP: {
    18131893                        int dtls = fd_cnx_uses_dtls(conn);
    1814 
    18151894                        if (!dtls) {
    1816                                 if (flags & FD_CNX_ORDERED) {
    1817                                         /* We send over stream #0 */
     1895                                int stream = 0;
     1896                                if (conn->cc_sctp_para.unordered) {
     1897                                        int limit;
     1898                                        if (fd_cnx_teststate(conn, CC_STATUS_TLS))
     1899                                                limit = conn->cc_sctp_para.pairs;
     1900                                        else
     1901                                                limit = conn->cc_sctp_para.str_out;
     1902                                       
     1903                                        if (limit > 1) {
     1904                                                conn->cc_sctp_para.next += 1;
     1905                                                conn->cc_sctp_para.next %= limit;
     1906                                                stream = conn->cc_sctp_para.next;
     1907                                        }
     1908                                }
     1909                               
     1910                                if (stream == 0) {
     1911                                        /* We can use default function, it sends over stream #0 */
    18181912                                        CHECK_FCT( send_simple(conn, buf, len) );
    18191913                                } else {
    1820                                         /* Default case : no flag specified */
    1821                        
    1822                                         int another_str = 0; /* do we send over stream #0 ? */
    1823 
    1824                                         if ((conn->cc_sctp_para.str_out > 1) && ((!fd_cnx_teststate(conn, CC_STATUS_TLS)) || (conn->cc_sctp_para.pairs > 1)))  {
    1825                                                 /* Update the id of the stream we will send this message over */
    1826                                                 conn->cc_sctp_para.next += 1;
    1827                                                 conn->cc_sctp_para.next %= (fd_cnx_teststate(conn, CC_STATUS_TLS) ? conn->cc_sctp_para.pairs : conn->cc_sctp_para.str_out);
    1828                                                 another_str = (conn->cc_sctp_para.next ? 1 : 0);
    1829                                         }
    1830 
    1831                                         if ( ! another_str ) {
    1832                                                 CHECK_FCT( send_simple(conn, buf, len) );
     1914                                        if (!fd_cnx_teststate(conn, CC_STATUS_TLS)) {
     1915                                                struct iovec iov;
     1916                                                iov.iov_base = buf;
     1917                                                iov.iov_len  = len;
     1918                                               
     1919                                                CHECK_SYS_DO( fd_sctp_sendstrv(conn, stream, &iov, 1), { fd_cnx_markerror(conn); return ENOTCONN; } );
    18331920                                        } else {
    1834                                                 if (!fd_cnx_teststate(conn, CC_STATUS_TLS)) {
    1835                                                         CHECK_FCT_DO( fd_sctp_sendstr(conn, conn->cc_sctp_para.next, buf, len), { fd_cnx_markerror(conn); return ENOTCONN; } );
    1836                                                 } else {
    1837                                                         /* push the record to the appropriate session */
    1838                                                         ssize_t ret;
    1839                                                         size_t sent = 0;
    1840                                                         ASSERT(conn->cc_sctp3436_data.array != NULL);
    1841                                                         do {
    1842                                                                 CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_sctp3436_data.array[conn->cc_sctp_para.next].session, buf + sent, len - sent), );
    1843                                                                 if (ret <= 0)
    1844                                                                         return ENOTCONN;
    1845 
    1846                                                                 sent += ret;
    1847                                                         } while ( sent < len );
    1848                                                 }
     1921                                                /* push the data to the appropriate session */
     1922                                                ssize_t ret;
     1923                                                size_t sent = 0;
     1924                                                ASSERT(conn->cc_sctp3436_data.array != NULL);
     1925                                                do {
     1926                                                        CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_sctp3436_data.array[stream].session, buf + sent, len - sent), );
     1927                                                        if (ret <= 0)
     1928                                                                return ENOTCONN;
     1929
     1930                                                        sent += ret;
     1931                                                } while ( sent < len );
    18491932                                        }
    18501933                                }
    18511934                        } else {
    18521935                                /* DTLS */
    1853                                 /* We signal the push function directly to tell if using stream 0 or round-robin */
    1854                                 TODO("DTLS send");
    1855                                 return ENOTSUP;
     1936                                /* Multistream is handled at lower layer in the push/pull function */
     1937                                CHECK_FCT( send_simple(conn, buf, len) );
    18561938                        }
    18571939                }
  • libfdcore/cnxctx.h

    r1181 r1186  
    7575                uint16_t pairs;         /* max number of pairs ( = min(in, out)) */
    7676                uint16_t next;          /* # of stream the next message will be sent to */
     77                int      unordered;     /* boolean telling if use of streams > 0 is permitted */
    7778        }               cc_sctp_para;
    7879
     
    118119int fd_sctp_get_remote_ep(int sock, struct fd_list * list);
    119120int fd_sctp_get_str_info( int sock, uint16_t *in, uint16_t *out, sSS *primary );
    120 int fd_sctp_sendstr(struct cnxctx * conn, uint16_t strid, uint8_t * buf, size_t len);
     121ssize_t fd_sctp_sendstrv(struct cnxctx * conn, uint16_t strid, const struct iovec *iov, int iovcnt);
    121122int fd_sctp_recvmeta(struct cnxctx * conn, uint16_t * strid, uint8_t ** buf, size_t * len, int *event);
    122123
  • libfdcore/fdcore-internal.h

    r1181 r1186  
    296296
    297297/* Peer out */
    298 int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer, uint32_t flags);
     298int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer);
    299299int fd_out_start(struct fd_peer * peer);
    300300int fd_out_stop(struct fd_peer * peer);
     
    342342int             fd_cnx_start_clear(struct cnxctx * conn, int loop);
    343343void            fd_cnx_sethostname(struct cnxctx * conn, DiamId_t hn);
     344int             fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len);
    344345#define ALGO_HANDSHAKE_DEFAULT  0 /* TLS for TCP, DTLS for SCTP */
    345346#define ALGO_HANDSHAKE_3436     1 /* For TLS for SCTP also */
     
    348349int             fd_cnx_getproto(struct cnxctx * conn);
    349350int             fd_cnx_getTLS(struct cnxctx * conn);
    350 int             fd_cnx_isMultichan(struct cnxctx * conn);
     351int             fd_cnx_is_unordered_delivery_supported(struct cnxctx * conn);
     352int             fd_cnx_unordered_delivery(struct cnxctx * conn, int is_allowed);
    351353int             fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsigned int *cert_list_size);
    352354int             fd_cnx_get_local_eps(struct fd_list * list);
     
    355357int             fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len);
    356358int             fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo); /* send FDEVP_CNX_MSG_RECV event to the fifo list */
    357 int             fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len, uint32_t flags);
     359int             fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len);
    358360void            fd_cnx_destroy(struct cnxctx * conn);
    359361#ifdef GNUTLS_VERSION_300
    360362int             fd_tls_verify_credentials_2(gnutls_session_t session);
    361363#endif /* GNUTLS_VERSION_300 */
    362 
    363 /* Flags for the fd_cnx_send function : */
    364 #define FD_CNX_ORDERED          (1 << 0)        /* All messages sent with this flag set will be delivered in the same order. No guarantee on other messages */
    365364
    366365/* Internal calls of the hook mechanism */
  • libfdcore/hooks.c

    r1168 r1186  
    420420                                }
    421421                                CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break);
    422                                 LOG_N("Connected to '%s', remote capabilities: ", peer ? peer->p_hdr.info.pi_diamid : "<unknown>");
     422                                char protobuf[40];
     423                                if (peer) {
     424                                        CHECK_FCT_DO(fd_peer_cnx_proto_info(&peer->p_hdr, protobuf, sizeof(protobuf)), break );
     425                                } else {
     426                                        protobuf[0] = '-';
     427                                        protobuf[1] = '\0';
     428                                }
     429                                LOG_N("Connected to '%s' (%s), remote capabilities: ", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", protobuf);
    423430                                LOG_SPLIT(FD_LOG_NOTICE, "   ", buf?:"<error dumping message>", NULL);
    424431                                break;
  • libfdcore/p_ce.c

    r1181 r1186  
    633633        CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, cer, MSGFL_ANSW_ERROR ), goto destroy );
    634634        CHECK_FCT_DO( fd_msg_rescode_set(*cer, error->pei_errcode, error->pei_message, error->pei_avp, 1 ), goto destroy );
    635         CHECK_FCT_DO( fd_out_send(cer, *recv_cnx, NULL, FD_CNX_ORDERED), goto destroy );
     635        CHECK_FCT_DO( fd_out_send(cer, *recv_cnx, NULL), goto destroy );
    636636       
    637637        /* And now destroy this connection */
     
    653653        /* Send CER on the new connection */
    654654        CHECK_FCT( create_CER(peer, initiator, &cer) );
    655         CHECK_FCT( fd_out_send(&cer, initiator, peer, FD_CNX_ORDERED) );
     655        CHECK_FCT( fd_out_send(&cer, initiator, peer) );
    656656       
    657657        /* Are we doing an election ? */
     
    708708
    709709                /* msg now contains an answer message to send back */
    710                 CHECK_FCT_DO( fd_out_send(msg, NULL, peer, FD_CNX_ORDERED), /* In case of error the message has already been dumped */ );
     710                CHECK_FCT_DO( fd_out_send(msg, NULL, peer), /* In case of error the message has already been dumped */ );
    711711        }
    712712       
     
    950950        fd_hook_call(HOOK_PEER_CONNECT_SUCCESS, msg, peer, NULL, NULL);
    951951       
    952         CHECK_FCT( fd_out_send(&msg, peer->p_cnxctx, peer, FD_CNX_ORDERED ) );
     952        CHECK_FCT( fd_out_send(&msg, peer->p_cnxctx, peer ) );
    953953       
    954954        /* Handshake if needed */
     
    994994                CHECK_FCT( fd_p_dw_reopen(peer) );
    995995        } else {
    996                 if ((!tls_sync) && (fd_cnx_isMultichan(peer->p_cnxctx))) {
     996                if ((!tls_sync) && (fd_cnx_is_unordered_delivery_supported(peer->p_cnxctx))) {
    997997                        fd_psm_change_state(peer, STATE_OPEN_NEW );
    998998                        /* send DWR */
  • libfdcore/p_cnx.c

    r1181 r1186  
    346346        }
    347347}
     348
  • libfdcore/p_dp.c

    r1127 r1186  
    118118               
    119119                        /* Now send the DPA */
    120                         CHECK_FCT( fd_out_send( msg, NULL, peer, FD_CNX_ORDERED) );
     120                        CHECK_FCT( fd_out_send( msg, NULL, peer) );
    121121                       
    122122                        /* and move to CLOSED */
     
    132132                       
    133133                        /* Now send the DPA */
    134                         CHECK_FCT( fd_out_send( msg, NULL, peer, FD_CNX_ORDERED) );
     134                        CHECK_FCT( fd_out_send( msg, NULL, peer) );
    135135                }
    136136        } else {
     
    202202       
    203203        /* Now send the DPR message */
    204         CHECK_FCT_DO( fd_out_send(&msg, NULL, peer, FD_CNX_ORDERED), /* ignore since we are on timeout anyway */ );
     204        CHECK_FCT_DO( fd_out_send(&msg, NULL, peer), /* ignore since we are on timeout anyway */ );
    205205       
    206206        return 0;
  • libfdcore/p_dw.c

    r1127 r1186  
    8383       
    8484        /* Now send this message */
    85         CHECK_FCT( fd_out_send(&msg, NULL, peer, FD_CNX_ORDERED) );
     85        CHECK_FCT( fd_out_send(&msg, NULL, peer) );
    8686       
    8787        /* And mark the pending DW */
     
    106106                CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) );
    107107                CHECK_FCT( fd_msg_add_origin ( *msg, 1 ) );
    108                 CHECK_FCT( fd_out_send( msg, peer->p_cnxctx, peer, FD_CNX_ORDERED) );
     108                CHECK_FCT( fd_out_send( msg, peer->p_cnxctx, peer) );
    109109               
    110110        } else {
  • libfdcore/p_out.c

    r1119 r1186  
    3737
    3838/* Alloc a new hbh for requests, bufferize the message and send on the connection, save in sentreq if provided */
    39 static int do_send(struct msg ** msg, uint32_t flags, struct cnxctx * cnx, uint32_t * hbh, struct fd_peer * peer)
     39static int do_send(struct msg ** msg, struct cnxctx * cnx, uint32_t * hbh, struct fd_peer * peer)
    4040{
    4141        struct msg_hdr * hdr;
     
    4747        struct msg *cpy_for_logs_only;
    4848       
    49         TRACE_ENTRY("%p %x %p %p %p", msg, flags, cnx, hbh, peer);
     49        TRACE_ENTRY("%p %p %p %p", msg, cnx, hbh, peer);
    5050       
    5151        /* Retrieve the message header */
     
    7676       
    7777        /* Send the message */
    78         CHECK_FCT_DO( ret = fd_cnx_send(cnx, buf, sz, flags), );
     78        CHECK_FCT_DO( ret = fd_cnx_send(cnx, buf, sz), );
    7979out:
    8080        ;       
     
    128128               
    129129                /* Send the message, log any error */
    130                 CHECK_FCT_DO( ret = do_send(&msg, 0, peer->p_cnxctx, &peer->p_hbh, peer),
     130                CHECK_FCT_DO( ret = do_send(&msg, peer->p_cnxctx, &peer->p_hbh, peer),
    131131                        {
    132132                                if (msg) {
     
    149149
    150150/* Wrapper to sending a message either by out thread (peer in OPEN state) or directly; cnx or peer must be provided. Flags are valid only for direct sending, not through thread (unused) */
    151 int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer, uint32_t flags)
     151int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer)
    152152{
    153153        struct msg_hdr * hdr;
    154154       
    155         TRACE_ENTRY("%p %p %p %x", msg, cnx, peer, flags);
     155        TRACE_ENTRY("%p %p %p", msg, cnx, peer);
    156156        CHECK_PARAMS( msg && *msg && (cnx || (peer && peer->p_cnxctx)));
    157157       
     
    182182
    183183                /* Do send the message */
    184                 CHECK_FCT_DO( ret = do_send(msg, flags, cnx, hbh, peer),
     184                CHECK_FCT_DO( ret = do_send(msg, cnx, hbh, peer),
    185185                        {
    186186                                if (msg) {
     
    205205        CHECK_POSIX( pthread_create(&peer->p_outthr, NULL, out_thr, peer) );
    206206       
     207        CHECK_FCT( fd_cnx_unordered_delivery(peer->p_cnxctx, 1) );
     208       
    207209        return 0;
    208210}
     
    214216        CHECK_PARAMS( CHECK_PEER(peer) );
    215217       
     218        CHECK_FCT( fd_cnx_unordered_delivery(peer->p_cnxctx, 0) );
     219       
    216220        CHECK_FCT( fd_thr_term(&peer->p_outthr) );
    217221       
  • libfdcore/p_psm.c

    r1181 r1186  
    7272Note about (5) and (6): if the Diameter Identity received in CER or CEA
    7373does not match the credentials from the certificate presented during
    74 DTLS handshake, we may need to specify a path of clean disconnection
     74TLS handshake, we may need to specify a path of clean disconnection
    7575(not blocking the remote peer waiting for something).
    7676
     
    601601                                if (msg == NULL) {
    602602                                        /* Send the error back to the peer */
    603                                         CHECK_FCT_DO( ret = fd_out_send(&error, NULL, peer, FD_CNX_ORDERED),  );
     603                                        CHECK_FCT_DO( ret = fd_out_send(&error, NULL, peer),  );
    604604                                        if (error) {
    605605                                                char buf[256];
     
    655655
    656656                                                /* Send the answer */
    657                                                 CHECK_FCT_DO( fd_out_send(&msg, peer->p_cnxctx, peer, FD_CNX_ORDERED), break );
     657                                                CHECK_FCT_DO( fd_out_send(&msg, peer->p_cnxctx, peer), break );
    658658                                        } while (0);
    659659                                } else {
  • libfdcore/peers.c

    r1185 r1186  
    258258}
    259259
     260/* Describe the current connection */
     261int fd_peer_cnx_proto_info(struct peer_hdr *peer, char * buf, size_t len)
     262{
     263        struct fd_peer * p = (struct fd_peer *)peer;
     264        TRACE_ENTRY("%p %p %zd", peer, buf, len);
     265        CHECK_PARAMS(CHECK_PEER(peer) && buf && len);
     266       
     267        if (p->p_cnxctx) {
     268                CHECK_FCT(fd_cnx_proto_info(p->p_cnxctx, buf, len));
     269        } else if (p->p_receiver) {
     270                CHECK_FCT(fd_cnx_proto_info(p->p_receiver, buf, len));
     271        } else {
     272                snprintf(buf, len, "Not Connected");
     273        }
     274       
     275        return 0;
     276}
     277
    260278/* Return the value of srlist->cnt */
    261279int fd_peer_get_load_pending(struct peer_hdr *peer, long * to_receive, long * to_send)
     
    512530                fd_hook_call(HOOK_PEER_CONNECT_FAILED, *cer, NULL, "Received CER with invalid Origin-Host AVP", NULL);
    513531               
    514                 CHECK_FCT( fd_out_send(cer, *cnx, NULL, FD_CNX_ORDERED) );
     532                CHECK_FCT( fd_out_send(cer, *cnx, NULL) );
    515533                return EINVAL;
    516534        }
  • libfdcore/routing_dispatch.c

    r1154 r1186  
    413413                CHECK_FCT( fd_fifo_post(fd_g_incoming, pmsg) );
    414414        } else {
    415                 CHECK_FCT( fd_out_send(pmsg, NULL, peer, 0) );
     415                CHECK_FCT( fd_out_send(pmsg, NULL, peer) );
    416416        }
    417417       
     
    887887
    888888                /* Push the message into this peer */
    889                 CHECK_FCT( fd_out_send(&msgptr, NULL, peer, 0) );
     889                CHECK_FCT( fd_out_send(&msgptr, NULL, peer) );
    890890
    891891                /* We're done with this answer */
     
    10041004                if (fd_peer_getstate(peer) == STATE_OPEN) {
    10051005                        /* Send to this one */
    1006                         CHECK_FCT_DO( fd_out_send(&msgptr, NULL, peer, 0), continue );
     1006                        CHECK_FCT_DO( fd_out_send(&msgptr, NULL, peer), continue );
    10071007                       
    10081008                        /* If the sending was successful */
  • libfdcore/sctp.c

    r1175 r1186  
    10801080}
    10811081
    1082 /* Send a buffer over a specified stream */
    1083 int fd_sctp_sendstr(struct cnxctx * conn, uint16_t strid, uint8_t * buf, size_t len)
     1082/* Send a vector over a specified stream */
     1083ssize_t fd_sctp_sendstrv(struct cnxctx * conn, uint16_t strid, const struct iovec *iov, int iovcnt)
    10841084{
    10851085        struct msghdr mhdr;
    1086         struct iovec  iov;
    10871086        struct cmsghdr          *hdr;
    10881087#ifdef OLD_SCTP_SOCKET_API
     
    10961095        int timedout = 0;
    10971096       
    1098         TRACE_ENTRY("%p %hu %p %zd", conn, strid, buf, len);
    1099         CHECK_PARAMS(conn && buf && len);
     1097        TRACE_ENTRY("%p %hu %p %d", conn, strid, iov, iovcnt);
     1098        CHECK_PARAMS_DO(conn && iov && iovcnt, { errno = EINVAL; return -1; } );
    11001099       
    11011100        memset(&mhdr, 0, sizeof(mhdr));
    1102         memset(&iov,  0, sizeof(iov));
    11031101        memset(&anci, 0, sizeof(anci));
    1104        
    1105         /* IO Vector: message data */
    1106         iov.iov_base = buf;
    1107         iov.iov_len  = len;
    11081102       
    11091103        /* Anciliary data: specify SCTP stream */
     
    11241118        /* We don't use mhdr.msg_name here; it could be used to specify an address different from the primary */
    11251119       
    1126         mhdr.msg_iov    = &iov;
    1127         mhdr.msg_iovlen = 1;
     1120        mhdr.msg_iov    = (struct iovec *)iov;
     1121        mhdr.msg_iovlen = iovcnt;
    11281122       
    11291123        mhdr.msg_control    = anci;
    11301124        mhdr.msg_controllen = sizeof(anci);
    11311125       
    1132         TRACE_DEBUG(FULL, "Sending %zdb data on stream %hu of socket %d", len, strid, conn->cc_socket);
     1126        TRACE_DEBUG(FULL, "Sending %d chunks of data (first:%zdb) on stream %hu of socket %d", iovcnt, iov[0].iov_len, strid, conn->cc_socket);
    11331127again: 
    11341128        ret = sendmsg(conn->cc_socket, &mhdr, 0);
     
    11441138        }
    11451139       
    1146         CHECK_SYS( ret );
    1147         ASSERT( ret == len ); /* There should not be partial delivery with sendmsg... */
    1148        
    1149         return 0;
     1140        CHECK_SYS_DO( ret, ); /* for tracing error only */
     1141       
     1142        return ret;
    11501143}
    11511144
  • libfdcore/sctp3436.c

    r1181 r1186  
    5252 We also have a demux thread that reads the socket and store received data in the appropriate fifo
    5353 
    54  We have one gnutls_session per stream pair, and as many streams that read the gnutls records and save incoming data to the target queue.
     54 We have one gnutls_session per stream pair, and as many threads that read the gnutls records and save incoming data to the target queue.
    5555 
    5656This complexity is required because we cannot read a socket for a given stream only; we can only get the next message and find its stream.
    5757*/
    5858
    59 /* TODO: change this whole wrapper to DTLS which should not require many different threads */
     59/* Note that this mechanism is replaced by DTLS in RFC6733 */
    6060
    6161/*************************************************************/
     
    164164/*************************************************************/
    165165
     166#ifdef GNUTLS_VERSION_300
     167/* Check if data is available for gnutls on a given context */
     168static int sctp3436_pull_timeout(gnutls_transport_ptr_t tr, unsigned int ms)
     169{
     170        struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
     171        struct timespec tsstore, *ts = NULL;
     172        int ret;
     173       
     174        TRACE_ENTRY("%p %d", tr, ms);
     175       
     176        if (ctx->partial.buf)
     177                return 1; /* data is already available for pull */
     178       
     179        if (ms) {
     180                CHECK_SYS_DO(  clock_gettime(CLOCK_REALTIME, &tsstore),  return -1  );
     181                tsstore.tv_nsec += (long)ms * 1000000;
     182                tsstore.tv_sec += tsstore.tv_nsec / 1000000000L;
     183                tsstore.tv_nsec %= 1000000000L;
     184                ts = &tsstore;
     185        }
     186       
     187        ret = fd_fifo_select ( ctx->raw_recv, ts );
     188        if (ret < 0) {
     189                errno = -ret;
     190                ret = -1;
     191        }
     192               
     193        return ret;
     194}
     195#endif /* GNUTLS_VERSION_300 */
     196
    166197/* Send data over the connection, called by gnutls */
     198#ifndef GNUTLS_VERSION_212
    167199static ssize_t sctp3436_push(gnutls_transport_ptr_t tr, const void * data, size_t len)
    168200{
    169201        struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
     202        struct iovec iov;
    170203       
    171204        TRACE_ENTRY("%p %p %zd", tr, data, len);
    172205        CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } );
    173206       
    174         CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent, ctx->strid, (uint8_t *)data, len), return -1 );
    175        
    176         return len;
    177 }
     207        iov.iov_base = (void *)data;
     208        iov.iov_len  = len;
     209       
     210        return fd_sctp_sendstrv(ctx->parent, ctx->strid, &iov, 1);
     211}
     212#else /*  GNUTLS_VERSION_212 */
     213static ssize_t sctp3436_pushv(gnutls_transport_ptr_t tr, const giovec_t * iov, int iovcnt)
     214{
     215        struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr;
     216       
     217        TRACE_ENTRY("%p %p %d", tr, iov, iovcnt);
     218        CHECK_PARAMS_DO( tr && iov, { errno = EINVAL; return -1; } );
     219       
     220        return fd_sctp_sendstrv(ctx->parent, ctx->strid, (const struct iovec *)iov, iovcnt);
     221}
     222#endif /*  GNUTLS_VERSION_212 */
    178223
    179224/* Retrieve data received on a stream and already demultiplexed */
     
    238283        /* starting version 2.12, this call is not needed */
    239284        GNUTLS_TRACE( gnutls_transport_set_lowat( session, 0 ) );
     285#else  /* GNUTLS_VERSION_300 */
     286        /* but in 3.0 we have to provide the pull_timeout callback */
     287        GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( session, sctp3436_pull_timeout ) );
    240288#endif /* GNUTLS_VERSION_300 */
    241289       
    242290        /* Set the push and pull callbacks */
    243291        GNUTLS_TRACE( gnutls_transport_set_pull_function(session, sctp3436_pull) );
     292#ifndef GNUTLS_VERSION_212
    244293        GNUTLS_TRACE( gnutls_transport_set_push_function(session, sctp3436_push) );
     294#else /* GNUTLS_VERSION_212 */
     295        GNUTLS_TRACE( gnutls_transport_set_vec_push_function(session, sctp3436_pushv) );
     296#endif /* GNUTLS_VERSION_212 */
    245297
    246298        return;
Note: See TracChangeset for help on using the changeset viewer.