# HG changeset patch # User Sebastien Decugis # Date 1370602114 -28800 # Node ID 56c36d1007b4eb1108b7a3702589c9cbb2aeeb1f # Parent 23695957bfc017e41210a97c0d30e6abfb51a4f0 Further preparation of the DTLS integration. Some cleanups in the GNUTLS handling. diff -r 23695957bfc0 -r 56c36d1007b4 cmake/Modules/FindGnuTLS.cmake --- a/cmake/Modules/FindGnuTLS.cmake Thu Jun 06 19:06:00 2013 +0800 +++ b/cmake/Modules/FindGnuTLS.cmake Fri Jun 07 18:48:34 2013 +0800 @@ -5,6 +5,7 @@ # GNUTLS_INCLUDE_DIR - where to find gnutls.h, etc. # GNUTLS_LIBRARIES - List of libraries when using gnutls. # GNUTLS_VERSION_210 - true if GnuTLS version is >= 2.10.0 (does not require additional separate gcrypt initialization) +# GNUTLS_VERSION_212 - true if GnuTLS version is >= 2.12.0 (supports gnutls_transport_set_vec_push_function) # GNUTLS_VERSION_300 - true if GnuTLS version is >= 3.00.0 (x509 verification functions changed) # GNUTLS_VERSION_310 - true if GnuTLS version is >= 3.01.0 (stabilization branch with new APIs) @@ -47,12 +48,15 @@ MESSAGE(STATUS "Checking GNUTLS version") UNSET(GNUTLS_VERSION_210) UNSET(GNUTLS_VERSION_210 CACHE) + UNSET(GNUTLS_VERSION_212) + UNSET(GNUTLS_VERSION_212 CACHE) UNSET(GNUTLS_VERSION_300) UNSET(GNUTLS_VERSION_300 CACHE) UNSET(GNUTLS_VERSION_310) UNSET(GNUTLS_VERSION_310 CACHE) GET_FILENAME_COMPONENT(GNUTLS_PATH ${GNUTLS_LIBRARY} PATH) CHECK_LIBRARY_EXISTS(gnutls gnutls_hash ${GNUTLS_PATH} GNUTLS_VERSION_210) + CHECK_LIBRARY_EXISTS(gnutls gnutls_transport_set_vec_push_function ${GNUTLS_PATH} GNUTLS_VERSION_212) CHECK_LIBRARY_EXISTS(gnutls gnutls_x509_trust_list_verify_crt ${GNUTLS_PATH} GNUTLS_VERSION_300) CHECK_LIBRARY_EXISTS(gnutls gnutls_handshake_set_timeout ${GNUTLS_PATH} GNUTLS_VERSION_310) SET( GNUTLS_VERSION_TEST_FOR ${GNUTLS_LIBRARY} CACHE INTERNAL "Version the test was made against" ) diff -r 23695957bfc0 -r 56c36d1007b4 include/freeDiameter/freeDiameter-host.h.in --- a/include/freeDiameter/freeDiameter-host.h.in Thu Jun 06 19:06:00 2013 +0800 +++ b/include/freeDiameter/freeDiameter-host.h.in Fri Jun 07 18:48:34 2013 +0800 @@ -61,6 +61,7 @@ #cmakedefine DISABLE_PEER_EXPIRY #cmakedefine WORKAROUND_ACCEPT_INVALID_VSAI #cmakedefine GNUTLS_VERSION_210 +#cmakedefine GNUTLS_VERSION_212 #cmakedefine GNUTLS_VERSION_300 #cmakedefine GNUTLS_VERSION_310 diff -r 23695957bfc0 -r 56c36d1007b4 include/freeDiameter/libfdcore.h --- a/include/freeDiameter/libfdcore.h Thu Jun 06 19:06:00 2013 +0800 +++ b/include/freeDiameter/libfdcore.h Fri Jun 07 18:48:34 2013 +0800 @@ -398,6 +398,23 @@ int fd_peer_get_state(struct peer_hdr *peer); /* + * FUNCTION: fd_peer_cnx_proto_info + * + * PARAMETERS: + * peer : The peer which information to be read + * buf : Where to store the protocol information + * len : available space in bug + * + * DESCRIPTION: + * Creates a string describing the current connection to this peer, e.g.: "TCP,TLS,soc#3". + * + * RETURN VALUE: + * 0 : buffer was written + * >=0 : error code. + */ +int fd_peer_cnx_proto_info(struct peer_hdr *peer, char * buf, size_t len); + +/* * FUNCTION: fd_peer_get_load_pending * * PARAMETERS: diff -r 23695957bfc0 -r 56c36d1007b4 include/freeDiameter/libfdproto.h --- a/include/freeDiameter/libfdproto.h Thu Jun 06 19:06:00 2013 +0800 +++ b/include/freeDiameter/libfdproto.h Fri Jun 07 18:48:34 2013 +0800 @@ -3183,6 +3183,28 @@ #define fd_fifo_timedget(queue, item, abstime) \ fd_fifo_timedget_int((queue), (void *)(item), (abstime)) + +/* + * FUNCTION: fd_fifo_select + * + * PARAMETERS: + * queue : The queue to test. + * abstime : the absolute time until which we can block waiting for an item. If NULL, the function returns immediatly. + * + * DESCRIPTION: + * This function is similar to select(), it waits for data to be available in the queue + * until the abstime is expired. + * Upon function entry, even if abstime is already expired the data availability is tested. + * + * RETURN VALUE: + * 0 : timeout expired without available data. + * <0 : An error occurred (e.g., -EINVAL...) + * >0 : data is available. The next call to fd_fifo_get will not block. + */ +int fd_fifo_select ( struct fifo * queue, const struct timespec *abstime ); + + + /* Dump a fifo list and optionally its inner elements -- beware of deadlocks! */ typedef DECLARE_FD_DUMP_PROTOTYPE((*fd_fifo_dump_item_cb), void * item); /* This function should be 1 line if possible, or use indent level. Ends with '\n' */ DECLARE_FD_DUMP_PROTOTYPE(fd_fifo_dump, char * name, struct fifo * queue, fd_fifo_dump_item_cb dump_item); diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/cnxctx.c --- a/libfdcore/cnxctx.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/cnxctx.c Fri Jun 07 18:48:34 2013 +0800 @@ -38,6 +38,7 @@ #include #include /* for getifaddrs */ +#include /* writev */ /* The maximum size of Diameter message we accept to receive (<= 2^24) to avoid too big mallocs in case of trashed headers */ #ifndef DIAMETER_MSG_SIZE_MAX @@ -478,13 +479,21 @@ return fd_cnx_teststate(conn, CC_STATUS_TLS); } +/* Mark the connection to tell if OOO delivery is permitted (only for SCTP) */ +int fd_cnx_unordered_delivery(struct cnxctx * conn, int is_allowed) +{ + CHECK_PARAMS( conn ); + conn->cc_sctp_para.unordered = is_allowed; + return 0; +} + /* Return true if the connection supports unordered delivery of messages */ -int fd_cnx_isMultichan(struct cnxctx * conn) +int fd_cnx_is_unordered_delivery_supported(struct cnxctx * conn) { CHECK_PARAMS_DO( conn, return 0 ); #ifndef DISABLE_SCTP if (conn->cc_proto == IPPROTO_SCTP) - return (conn->cc_sctp_para.str_in > 1) || (conn->cc_sctp_para.str_out > 1); + return (conn->cc_sctp_para.str_out > 1); #endif /* DISABLE_SCTP */ return 0; } @@ -530,6 +539,22 @@ return conn->cc_remid; } +static int fd_cnx_may_dtls(struct cnxctx * conn); + +/* Get a short string representing the connection */ +int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len) +{ + CHECK_PARAMS( conn ); + + if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { + snprintf(buf, len, "%s,%s,soc#%d", IPPROTO_NAME(conn->cc_proto), fd_cnx_may_dtls(conn) ? "DTLS" : "TLS", conn->cc_socket); + } else { + snprintf(buf, len, "%s,soc#%d", IPPROTO_NAME(conn->cc_proto), conn->cc_socket); + } + + return 0; +} + /* Retrieve a list of all IP addresses of the local system from the kernel, using getifaddrs */ int fd_cnx_get_local_eps(struct fd_list * list) { @@ -600,6 +625,24 @@ CHECK_SYS_DO( setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), /* Also timeout for sending, to avoid waiting forever */ ); } + +#ifdef GNUTLS_VERSION_300 +/* The pull_timeout function for gnutls */ +static int fd_cnx_s_select (struct cnxctx * conn, unsigned int ms) +{ + fd_set rfds; + struct timeval tv; + + FD_ZERO (&rfds); + FD_SET (conn->cc_socket, &rfds); + + tv.tv_sec = ms / 1000; + tv.tv_usec = (ms * 1000) % 1000000; + + return select (conn->cc_socket + 1, &rfds, NULL, NULL, &tv); +} +#endif /* GNUTLS_VERSION_300 */ + /* 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 */ ssize_t fd_cnx_s_recv(struct cnxctx * conn, void *buffer, size_t length) { @@ -627,8 +670,9 @@ return ret; } -/* Send */ -static ssize_t fd_cnx_s_send(struct cnxctx * conn, void *buffer, size_t length) +/* Send, for older GNUTLS */ +#ifndef GNUTLS_VERSION_212 +static ssize_t fd_cnx_s_send(struct cnxctx * conn, const void *buffer, size_t length) { ssize_t ret = 0; int timedout = 0; @@ -652,6 +696,33 @@ return ret; } +#endif /* GNUTLS_VERSION_212 */ + +/* Send */ +static ssize_t fd_cnx_s_sendv(struct cnxctx * conn, const struct iovec * iov, int iovcnt) +{ + ssize_t ret = 0; + int timedout = 0; +again: + ret = writev(conn->cc_socket, iov, iovcnt); + /* Handle special case of timeout */ + if ((ret < 0) && ((errno == EAGAIN) || (errno == EINTR))) { + pthread_testcancel(); + if (! fd_cnx_teststate(conn, CC_STATUS_CLOSING )) + goto again; /* don't care, just ignore */ + if (!timedout) { + timedout ++; /* allow for one timeout while closing */ + goto again; + } + CHECK_SYS_DO(ret, /* continue */); + } + + /* Mark the error */ + if (ret <= 0) + fd_cnx_markerror(conn); + + return ret; +} #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 */ #define PMDL_PADDED(len) ( ((len) + ALIGNOF(struct fd_msg_pmdl) - 1) & ~(ALIGNOF(struct fd_msg_pmdl) - 1) ) @@ -1604,8 +1675,15 @@ /* Set the push and pull callbacks */ if (!dtls) { + #ifdef GNUTLS_VERSION_300 + GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( conn->cc_tls_para.session, (void *)fd_cnx_s_select ) ); + #endif /* GNUTLS_VERSION_300 */ GNUTLS_TRACE( gnutls_transport_set_pull_function(conn->cc_tls_para.session, (void *)fd_cnx_s_recv) ); + #ifndef GNUTLS_VERSION_212 GNUTLS_TRACE( gnutls_transport_set_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_send) ); + #else /* GNUTLS_VERSION_212 */ + GNUTLS_TRACE( gnutls_transport_set_vec_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_sendv) ); + #endif /* GNUTLS_VERSION_212 */ } else { TODO("DTLS push/pull functions"); return ENOTSUP; @@ -1783,8 +1861,10 @@ if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_tls_para.session, buf + sent, len - sent), ); } else { - /* Maybe better to replace this call with sendmsg for atomic sending? */ - CHECK_SYS_DO( ret = fd_cnx_s_send(conn, buf + sent, len - sent), ); + struct iovec iov; + iov.iov_base = buf + sent; + iov.iov_len = len - sent; + CHECK_SYS_DO( ret = fd_cnx_s_sendv(conn, &iov, 1), ); } if (ret <= 0) return ENOTCONN; @@ -1795,9 +1875,9 @@ } /* 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. */ -int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len, uint32_t flags) +int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len) { - TRACE_ENTRY("%p %p %zd %x", conn, buf, len, flags); + TRACE_ENTRY("%p %p %zd", conn, buf, len); CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! fd_cnx_teststate(conn, CC_STATUS_ERROR)) && buf && len); @@ -1811,48 +1891,50 @@ #ifndef DISABLE_SCTP case IPPROTO_SCTP: { int dtls = fd_cnx_uses_dtls(conn); - if (!dtls) { - if (flags & FD_CNX_ORDERED) { - /* We send over stream #0 */ + int stream = 0; + if (conn->cc_sctp_para.unordered) { + int limit; + if (fd_cnx_teststate(conn, CC_STATUS_TLS)) + limit = conn->cc_sctp_para.pairs; + else + limit = conn->cc_sctp_para.str_out; + + if (limit > 1) { + conn->cc_sctp_para.next += 1; + conn->cc_sctp_para.next %= limit; + stream = conn->cc_sctp_para.next; + } + } + + if (stream == 0) { + /* We can use default function, it sends over stream #0 */ CHECK_FCT( send_simple(conn, buf, len) ); } else { - /* Default case : no flag specified */ - - int another_str = 0; /* do we send over stream #0 ? */ - - if ((conn->cc_sctp_para.str_out > 1) && ((!fd_cnx_teststate(conn, CC_STATUS_TLS)) || (conn->cc_sctp_para.pairs > 1))) { - /* Update the id of the stream we will send this message over */ - conn->cc_sctp_para.next += 1; - conn->cc_sctp_para.next %= (fd_cnx_teststate(conn, CC_STATUS_TLS) ? conn->cc_sctp_para.pairs : conn->cc_sctp_para.str_out); - another_str = (conn->cc_sctp_para.next ? 1 : 0); - } - - if ( ! another_str ) { - CHECK_FCT( send_simple(conn, buf, len) ); + if (!fd_cnx_teststate(conn, CC_STATUS_TLS)) { + struct iovec iov; + iov.iov_base = buf; + iov.iov_len = len; + + CHECK_SYS_DO( fd_sctp_sendstrv(conn, stream, &iov, 1), { fd_cnx_markerror(conn); return ENOTCONN; } ); } else { - if (!fd_cnx_teststate(conn, CC_STATUS_TLS)) { - CHECK_FCT_DO( fd_sctp_sendstr(conn, conn->cc_sctp_para.next, buf, len), { fd_cnx_markerror(conn); return ENOTCONN; } ); - } else { - /* push the record to the appropriate session */ - ssize_t ret; - size_t sent = 0; - ASSERT(conn->cc_sctp3436_data.array != NULL); - do { - 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), ); - if (ret <= 0) - return ENOTCONN; + /* push the data to the appropriate session */ + ssize_t ret; + size_t sent = 0; + ASSERT(conn->cc_sctp3436_data.array != NULL); + do { + CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_sctp3436_data.array[stream].session, buf + sent, len - sent), ); + if (ret <= 0) + return ENOTCONN; - sent += ret; - } while ( sent < len ); - } + sent += ret; + } while ( sent < len ); } } } else { /* DTLS */ - /* We signal the push function directly to tell if using stream 0 or round-robin */ - TODO("DTLS send"); - return ENOTSUP; + /* Multistream is handled at lower layer in the push/pull function */ + CHECK_FCT( send_simple(conn, buf, len) ); } } break; diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/cnxctx.h --- a/libfdcore/cnxctx.h Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/cnxctx.h Fri Jun 07 18:48:34 2013 +0800 @@ -74,6 +74,7 @@ uint16_t str_in; /* In streams */ uint16_t pairs; /* max number of pairs ( = min(in, out)) */ uint16_t next; /* # of stream the next message will be sent to */ + int unordered; /* boolean telling if use of streams > 0 is permitted */ } cc_sctp_para; /* If both conditions */ @@ -117,7 +118,7 @@ int fd_sctp_get_local_ep(int sock, struct fd_list * list); int fd_sctp_get_remote_ep(int sock, struct fd_list * list); int fd_sctp_get_str_info( int sock, uint16_t *in, uint16_t *out, sSS *primary ); -int fd_sctp_sendstr(struct cnxctx * conn, uint16_t strid, uint8_t * buf, size_t len); +ssize_t fd_sctp_sendstrv(struct cnxctx * conn, uint16_t strid, const struct iovec *iov, int iovcnt); int fd_sctp_recvmeta(struct cnxctx * conn, uint16_t * strid, uint8_t ** buf, size_t * len, int *event); /* TLS over SCTP (multi-stream) */ diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/fdcore-internal.h --- a/libfdcore/fdcore-internal.h Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/fdcore-internal.h Fri Jun 07 18:48:34 2013 +0800 @@ -295,7 +295,7 @@ void fd_psm_cleanup(struct fd_peer * peer, int terminate); /* Peer out */ -int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer, uint32_t flags); +int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer); int fd_out_start(struct fd_peer * peer); int fd_out_stop(struct fd_peer * peer); @@ -341,28 +341,27 @@ struct cnxctx * fd_cnx_cli_connect_sctp(int no_ip6, uint16_t port, struct fd_list * list); int fd_cnx_start_clear(struct cnxctx * conn, int loop); void fd_cnx_sethostname(struct cnxctx * conn, DiamId_t hn); +int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len); #define ALGO_HANDSHAKE_DEFAULT 0 /* TLS for TCP, DTLS for SCTP */ #define ALGO_HANDSHAKE_3436 1 /* For TLS for SCTP also */ int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority, void * alt_creds); char * fd_cnx_getid(struct cnxctx * conn); int fd_cnx_getproto(struct cnxctx * conn); int fd_cnx_getTLS(struct cnxctx * conn); -int fd_cnx_isMultichan(struct cnxctx * conn); +int fd_cnx_is_unordered_delivery_supported(struct cnxctx * conn); +int fd_cnx_unordered_delivery(struct cnxctx * conn, int is_allowed); int fd_cnx_getcred(struct cnxctx * conn, const gnutls_datum_t **cert_list, unsigned int *cert_list_size); int fd_cnx_get_local_eps(struct fd_list * list); int fd_cnx_getremoteeps(struct cnxctx * conn, struct fd_list * eps); char * fd_cnx_getremoteid(struct cnxctx * conn); int fd_cnx_receive(struct cnxctx * conn, struct timespec * timeout, unsigned char **buf, size_t * len); int fd_cnx_recv_setaltfifo(struct cnxctx * conn, struct fifo * alt_fifo); /* send FDEVP_CNX_MSG_RECV event to the fifo list */ -int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len, uint32_t flags); +int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len); void fd_cnx_destroy(struct cnxctx * conn); #ifdef GNUTLS_VERSION_300 int fd_tls_verify_credentials_2(gnutls_session_t session); #endif /* GNUTLS_VERSION_300 */ -/* Flags for the fd_cnx_send function : */ -#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 */ - /* Internal calls of the hook mechanism */ void fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl); void fd_hook_associate(struct msg * msg, struct fd_msg_pmdl * pmdl); diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/hooks.c --- a/libfdcore/hooks.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/hooks.c Fri Jun 07 18:48:34 2013 +0800 @@ -419,7 +419,14 @@ fd_msg_answ_getq(msg, &msg); /* We dump the CER in that case */ } CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); - LOG_N("Connected to '%s', remote capabilities: ", peer ? peer->p_hdr.info.pi_diamid : ""); + char protobuf[40]; + if (peer) { + CHECK_FCT_DO(fd_peer_cnx_proto_info(&peer->p_hdr, protobuf, sizeof(protobuf)), break ); + } else { + protobuf[0] = '-'; + protobuf[1] = '\0'; + } + LOG_N("Connected to '%s' (%s), remote capabilities: ", peer ? peer->p_hdr.info.pi_diamid : "", protobuf); LOG_SPLIT(FD_LOG_NOTICE, " ", buf?:"", NULL); break; } diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/p_ce.c --- a/libfdcore/p_ce.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/p_ce.c Fri Jun 07 18:48:34 2013 +0800 @@ -632,7 +632,7 @@ /* Create and send the CEA with appropriate error code */ CHECK_FCT_DO( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, cer, MSGFL_ANSW_ERROR ), goto destroy ); CHECK_FCT_DO( fd_msg_rescode_set(*cer, error->pei_errcode, error->pei_message, error->pei_avp, 1 ), goto destroy ); - CHECK_FCT_DO( fd_out_send(cer, *recv_cnx, NULL, FD_CNX_ORDERED), goto destroy ); + CHECK_FCT_DO( fd_out_send(cer, *recv_cnx, NULL), goto destroy ); /* And now destroy this connection */ destroy: @@ -652,7 +652,7 @@ /* Send CER on the new connection */ CHECK_FCT( create_CER(peer, initiator, &cer) ); - CHECK_FCT( fd_out_send(&cer, initiator, peer, FD_CNX_ORDERED) ); + CHECK_FCT( fd_out_send(&cer, initiator, peer) ); /* Are we doing an election ? */ if (fd_peer_getstate(peer) == STATE_WAITCNXACK_ELEC) { @@ -707,7 +707,7 @@ CHECK_FCT( fd_msg_rescode_set(*msg, "DIAMETER_UNABLE_TO_COMPLY", "No CER allowed in current state", NULL, 1 ) ); /* msg now contains an answer message to send back */ - CHECK_FCT_DO( fd_out_send(msg, NULL, peer, FD_CNX_ORDERED), /* In case of error the message has already been dumped */ ); + CHECK_FCT_DO( fd_out_send(msg, NULL, peer), /* In case of error the message has already been dumped */ ); } /* If the state is not WAITCEA, just discard the message */ @@ -949,7 +949,7 @@ /* The connection is complete, but we may still need TLS handshake */ fd_hook_call(HOOK_PEER_CONNECT_SUCCESS, msg, peer, NULL, NULL); - CHECK_FCT( fd_out_send(&msg, peer->p_cnxctx, peer, FD_CNX_ORDERED ) ); + CHECK_FCT( fd_out_send(&msg, peer->p_cnxctx, peer ) ); /* Handshake if needed */ if (isi & PI_SEC_TLS_OLD) { @@ -993,7 +993,7 @@ fd_psm_change_state(peer, STATE_REOPEN ); CHECK_FCT( fd_p_dw_reopen(peer) ); } else { - if ((!tls_sync) && (fd_cnx_isMultichan(peer->p_cnxctx))) { + if ((!tls_sync) && (fd_cnx_is_unordered_delivery_supported(peer->p_cnxctx))) { fd_psm_change_state(peer, STATE_OPEN_NEW ); /* send DWR */ CHECK_FCT( fd_p_dw_timeout(peer) ); diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/p_cnx.c --- a/libfdcore/p_cnx.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/p_cnx.c Fri Jun 07 18:48:34 2013 +0800 @@ -345,3 +345,4 @@ empty_connection_list(peer); } } + diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/p_dp.c --- a/libfdcore/p_dp.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/p_dp.c Fri Jun 07 18:48:34 2013 +0800 @@ -117,7 +117,7 @@ CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING) ); /* Now send the DPA */ - CHECK_FCT( fd_out_send( msg, NULL, peer, FD_CNX_ORDERED) ); + CHECK_FCT( fd_out_send( msg, NULL, peer) ); /* and move to CLOSED */ fd_psm_cleanup(peer, 0); @@ -131,7 +131,7 @@ fd_psm_next_timeout(peer, 0, GRACE_TIMEOUT); /* Now send the DPA */ - CHECK_FCT( fd_out_send( msg, NULL, peer, FD_CNX_ORDERED) ); + CHECK_FCT( fd_out_send( msg, NULL, peer) ); } } else { /* We received a DPA */ @@ -201,7 +201,7 @@ fd_psm_next_timeout(peer, 0, DPR_TIMEOUT); /* Now send the DPR message */ - CHECK_FCT_DO( fd_out_send(&msg, NULL, peer, FD_CNX_ORDERED), /* ignore since we are on timeout anyway */ ); + CHECK_FCT_DO( fd_out_send(&msg, NULL, peer), /* ignore since we are on timeout anyway */ ); return 0; } diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/p_dw.c --- a/libfdcore/p_dw.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/p_dw.c Fri Jun 07 18:48:34 2013 +0800 @@ -82,7 +82,7 @@ CHECK_FCT( fd_msg_add_origin ( msg, 1 ) ); /* Now send this message */ - CHECK_FCT( fd_out_send(&msg, NULL, peer, FD_CNX_ORDERED) ); + CHECK_FCT( fd_out_send(&msg, NULL, peer) ); /* And mark the pending DW */ peer->p_flags.pf_dw_pending = 1; @@ -105,7 +105,7 @@ CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) ); CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) ); CHECK_FCT( fd_msg_add_origin ( *msg, 1 ) ); - CHECK_FCT( fd_out_send( msg, peer->p_cnxctx, peer, FD_CNX_ORDERED) ); + CHECK_FCT( fd_out_send( msg, peer->p_cnxctx, peer) ); } else { /* Discard the DWA */ diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/p_out.c --- a/libfdcore/p_out.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/p_out.c Fri Jun 07 18:48:34 2013 +0800 @@ -36,7 +36,7 @@ #include "fdcore-internal.h" /* Alloc a new hbh for requests, bufferize the message and send on the connection, save in sentreq if provided */ -static int do_send(struct msg ** msg, uint32_t flags, struct cnxctx * cnx, uint32_t * hbh, struct fd_peer * peer) +static int do_send(struct msg ** msg, struct cnxctx * cnx, uint32_t * hbh, struct fd_peer * peer) { struct msg_hdr * hdr; int msg_is_a_req; @@ -46,7 +46,7 @@ uint32_t bkp_hbh = 0; struct msg *cpy_for_logs_only; - TRACE_ENTRY("%p %x %p %p %p", msg, flags, cnx, hbh, peer); + TRACE_ENTRY("%p %p %p %p", msg, cnx, hbh, peer); /* Retrieve the message header */ CHECK_FCT( fd_msg_hdr(*msg, &hdr) ); @@ -75,7 +75,7 @@ fd_hook_call(HOOK_MESSAGE_SENT, cpy_for_logs_only, peer, NULL, fd_msg_pmdl_get(cpy_for_logs_only)); /* Send the message */ - CHECK_FCT_DO( ret = fd_cnx_send(cnx, buf, sz, flags), ); + CHECK_FCT_DO( ret = fd_cnx_send(cnx, buf, sz), ); out: ; pthread_cleanup_pop(1); @@ -127,7 +127,7 @@ pthread_cleanup_push(cleanup_requeue, msg); /* Send the message, log any error */ - CHECK_FCT_DO( ret = do_send(&msg, 0, peer->p_cnxctx, &peer->p_hbh, peer), + CHECK_FCT_DO( ret = do_send(&msg, peer->p_cnxctx, &peer->p_hbh, peer), { if (msg) { char buf[256]; @@ -148,11 +148,11 @@ } /* 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) */ -int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer, uint32_t flags) +int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer) { struct msg_hdr * hdr; - TRACE_ENTRY("%p %p %p %x", msg, cnx, peer, flags); + TRACE_ENTRY("%p %p %p", msg, cnx, peer); CHECK_PARAMS( msg && *msg && (cnx || (peer && peer->p_cnxctx))); if (peer) { @@ -181,7 +181,7 @@ cnx = peer->p_cnxctx; /* Do send the message */ - CHECK_FCT_DO( ret = do_send(msg, flags, cnx, hbh, peer), + CHECK_FCT_DO( ret = do_send(msg, cnx, hbh, peer), { if (msg) { char buf[256]; @@ -204,6 +204,8 @@ CHECK_POSIX( pthread_create(&peer->p_outthr, NULL, out_thr, peer) ); + CHECK_FCT( fd_cnx_unordered_delivery(peer->p_cnxctx, 1) ); + return 0; } @@ -213,6 +215,8 @@ TRACE_ENTRY("%p", peer); CHECK_PARAMS( CHECK_PEER(peer) ); + CHECK_FCT( fd_cnx_unordered_delivery(peer->p_cnxctx, 0) ); + CHECK_FCT( fd_thr_term(&peer->p_outthr) ); return 0; diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/p_psm.c --- a/libfdcore/p_psm.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/p_psm.c Fri Jun 07 18:48:34 2013 +0800 @@ -71,7 +71,7 @@ Note about (5) and (6): if the Diameter Identity received in CER or CEA does not match the credentials from the certificate presented during -DTLS handshake, we may need to specify a path of clean disconnection +TLS handshake, we may need to specify a path of clean disconnection (not blocking the remote peer waiting for something). This proposed mechanism removes the problem of application messages @@ -600,7 +600,7 @@ } else { if (msg == NULL) { /* Send the error back to the peer */ - CHECK_FCT_DO( ret = fd_out_send(&error, NULL, peer, FD_CNX_ORDERED), ); + CHECK_FCT_DO( ret = fd_out_send(&error, NULL, peer), ); if (error) { char buf[256]; /* Only if an error occurred & the message was not saved / dumped */ @@ -654,7 +654,7 @@ CHECK_FCT_DO( fd_msg_rescode_set(msg, "DIAMETER_COMMAND_UNSUPPORTED", "Or maybe the P-bit or application Id are erroneous.", NULL, 1 ), break ); /* Send the answer */ - CHECK_FCT_DO( fd_out_send(&msg, peer->p_cnxctx, peer, FD_CNX_ORDERED), break ); + CHECK_FCT_DO( fd_out_send(&msg, peer->p_cnxctx, peer), break ); } while (0); } else { /* We did ASK for it ??? */ diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/peers.c --- a/libfdcore/peers.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/peers.c Fri Jun 07 18:48:34 2013 +0800 @@ -257,6 +257,24 @@ return; } +/* Describe the current connection */ +int fd_peer_cnx_proto_info(struct peer_hdr *peer, char * buf, size_t len) +{ + struct fd_peer * p = (struct fd_peer *)peer; + TRACE_ENTRY("%p %p %zd", peer, buf, len); + CHECK_PARAMS(CHECK_PEER(peer) && buf && len); + + if (p->p_cnxctx) { + CHECK_FCT(fd_cnx_proto_info(p->p_cnxctx, buf, len)); + } else if (p->p_receiver) { + CHECK_FCT(fd_cnx_proto_info(p->p_receiver, buf, len)); + } else { + snprintf(buf, len, "Not Connected"); + } + + return 0; +} + /* Return the value of srlist->cnt */ int fd_peer_get_load_pending(struct peer_hdr *peer, long * to_receive, long * to_send) { @@ -511,7 +529,7 @@ fd_hook_call(HOOK_PEER_CONNECT_FAILED, *cer, NULL, "Received CER with invalid Origin-Host AVP", NULL); - CHECK_FCT( fd_out_send(cer, *cnx, NULL, FD_CNX_ORDERED) ); + CHECK_FCT( fd_out_send(cer, *cnx, NULL) ); return EINVAL; } diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/routing_dispatch.c --- a/libfdcore/routing_dispatch.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/routing_dispatch.c Fri Jun 07 18:48:34 2013 +0800 @@ -412,7 +412,7 @@ if (is_loc) { CHECK_FCT( fd_fifo_post(fd_g_incoming, pmsg) ); } else { - CHECK_FCT( fd_out_send(pmsg, NULL, peer, 0) ); + CHECK_FCT( fd_out_send(pmsg, NULL, peer) ); } /* Done */ @@ -886,7 +886,7 @@ hdr->msg_hbhid = qry_hdr->msg_hbhid; /* Push the message into this peer */ - CHECK_FCT( fd_out_send(&msgptr, NULL, peer, 0) ); + CHECK_FCT( fd_out_send(&msgptr, NULL, peer) ); /* We're done with this answer */ return 0; @@ -1003,7 +1003,7 @@ if (fd_peer_getstate(peer) == STATE_OPEN) { /* Send to this one */ - CHECK_FCT_DO( fd_out_send(&msgptr, NULL, peer, 0), continue ); + CHECK_FCT_DO( fd_out_send(&msgptr, NULL, peer), continue ); /* If the sending was successful */ break; diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/sctp.c --- a/libfdcore/sctp.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/sctp.c Fri Jun 07 18:48:34 2013 +0800 @@ -1079,11 +1079,10 @@ return 0; } -/* Send a buffer over a specified stream */ -int fd_sctp_sendstr(struct cnxctx * conn, uint16_t strid, uint8_t * buf, size_t len) +/* Send a vector over a specified stream */ +ssize_t fd_sctp_sendstrv(struct cnxctx * conn, uint16_t strid, const struct iovec *iov, int iovcnt) { struct msghdr mhdr; - struct iovec iov; struct cmsghdr *hdr; #ifdef OLD_SCTP_SOCKET_API struct sctp_sndrcvinfo *sndrcv; @@ -1095,17 +1094,12 @@ ssize_t ret; int timedout = 0; - TRACE_ENTRY("%p %hu %p %zd", conn, strid, buf, len); - CHECK_PARAMS(conn && buf && len); + TRACE_ENTRY("%p %hu %p %d", conn, strid, iov, iovcnt); + CHECK_PARAMS_DO(conn && iov && iovcnt, { errno = EINVAL; return -1; } ); memset(&mhdr, 0, sizeof(mhdr)); - memset(&iov, 0, sizeof(iov)); memset(&anci, 0, sizeof(anci)); - /* IO Vector: message data */ - iov.iov_base = buf; - iov.iov_len = len; - /* Anciliary data: specify SCTP stream */ hdr = (struct cmsghdr *)anci; hdr->cmsg_len = sizeof(anci); @@ -1123,13 +1117,13 @@ /* We don't use mhdr.msg_name here; it could be used to specify an address different from the primary */ - mhdr.msg_iov = &iov; - mhdr.msg_iovlen = 1; + mhdr.msg_iov = (struct iovec *)iov; + mhdr.msg_iovlen = iovcnt; mhdr.msg_control = anci; mhdr.msg_controllen = sizeof(anci); - TRACE_DEBUG(FULL, "Sending %zdb data on stream %hu of socket %d", len, strid, conn->cc_socket); + 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); again: ret = sendmsg(conn->cc_socket, &mhdr, 0); /* Handle special case of timeout */ @@ -1143,10 +1137,9 @@ } } - CHECK_SYS( ret ); - ASSERT( ret == len ); /* There should not be partial delivery with sendmsg... */ + CHECK_SYS_DO( ret, ); /* for tracing error only */ - return 0; + return ret; } /* Receive the next data from the socket, or next notification */ diff -r 23695957bfc0 -r 56c36d1007b4 libfdcore/sctp3436.c --- a/libfdcore/sctp3436.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdcore/sctp3436.c Fri Jun 07 18:48:34 2013 +0800 @@ -51,12 +51,12 @@ - the push function sends the data on a certain stream. We also have a demux thread that reads the socket and store received data in the appropriate fifo - 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. + 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. This 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. */ -/* TODO: change this whole wrapper to DTLS which should not require many different threads */ +/* Note that this mechanism is replaced by DTLS in RFC6733 */ /*************************************************************/ /* threads */ @@ -163,18 +163,63 @@ /* push / pull */ /*************************************************************/ +#ifdef GNUTLS_VERSION_300 +/* Check if data is available for gnutls on a given context */ +static int sctp3436_pull_timeout(gnutls_transport_ptr_t tr, unsigned int ms) +{ + struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; + struct timespec tsstore, *ts = NULL; + int ret; + + TRACE_ENTRY("%p %d", tr, ms); + + if (ctx->partial.buf) + return 1; /* data is already available for pull */ + + if (ms) { + CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &tsstore), return -1 ); + tsstore.tv_nsec += (long)ms * 1000000; + tsstore.tv_sec += tsstore.tv_nsec / 1000000000L; + tsstore.tv_nsec %= 1000000000L; + ts = &tsstore; + } + + ret = fd_fifo_select ( ctx->raw_recv, ts ); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; +} +#endif /* GNUTLS_VERSION_300 */ + /* Send data over the connection, called by gnutls */ +#ifndef GNUTLS_VERSION_212 static ssize_t sctp3436_push(gnutls_transport_ptr_t tr, const void * data, size_t len) { struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; + struct iovec iov; TRACE_ENTRY("%p %p %zd", tr, data, len); CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } ); - CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent, ctx->strid, (uint8_t *)data, len), return -1 ); + iov.iov_base = (void *)data; + iov.iov_len = len; - return len; + return fd_sctp_sendstrv(ctx->parent, ctx->strid, &iov, 1); } +#else /* GNUTLS_VERSION_212 */ +static ssize_t sctp3436_pushv(gnutls_transport_ptr_t tr, const giovec_t * iov, int iovcnt) +{ + struct sctp3436_ctx * ctx = (struct sctp3436_ctx *) tr; + + TRACE_ENTRY("%p %p %d", tr, iov, iovcnt); + CHECK_PARAMS_DO( tr && iov, { errno = EINVAL; return -1; } ); + + return fd_sctp_sendstrv(ctx->parent, ctx->strid, (const struct iovec *)iov, iovcnt); +} +#endif /* GNUTLS_VERSION_212 */ /* Retrieve data received on a stream and already demultiplexed */ static ssize_t sctp3436_pull(gnutls_transport_ptr_t tr, void * buf, size_t len) @@ -237,11 +282,18 @@ #ifndef GNUTLS_VERSION_300 /* starting version 2.12, this call is not needed */ GNUTLS_TRACE( gnutls_transport_set_lowat( session, 0 ) ); +#else /* GNUTLS_VERSION_300 */ + /* but in 3.0 we have to provide the pull_timeout callback */ + GNUTLS_TRACE( gnutls_transport_set_pull_timeout_function( session, sctp3436_pull_timeout ) ); #endif /* GNUTLS_VERSION_300 */ /* Set the push and pull callbacks */ GNUTLS_TRACE( gnutls_transport_set_pull_function(session, sctp3436_pull) ); +#ifndef GNUTLS_VERSION_212 GNUTLS_TRACE( gnutls_transport_set_push_function(session, sctp3436_push) ); +#else /* GNUTLS_VERSION_212 */ + GNUTLS_TRACE( gnutls_transport_set_vec_push_function(session, sctp3436_pushv) ); +#endif /* GNUTLS_VERSION_212 */ return; } diff -r 23695957bfc0 -r 56c36d1007b4 libfdproto/fifo.c --- a/libfdproto/fifo.c Thu Jun 06 19:06:00 2013 +0800 +++ b/libfdproto/fifo.c Fri Jun 07 18:48:34 2013 +0800 @@ -645,3 +645,37 @@ return fifo_tget(queue, item, 1, abstime); } +/* Test if data is available in the queue, without pulling it */ +int fd_fifo_select ( struct fifo * queue, const struct timespec *abstime ) +{ + int ret = 0; + TRACE_ENTRY( "%p %p", queue, abstime ); + + CHECK_PARAMS_DO( CHECK_FIFO( queue ), return -EINVAL ); + + /* lock the queue */ + CHECK_POSIX_DO( pthread_mutex_lock( &queue->mtx ), return -__ret__ ); + +awaken: + ret = (queue->count > 0 ) ? queue->count : 0; + if ((ret == 0) && (abstime != NULL)) { + /* We have to wait for a new item */ + queue->thrs++ ; + pthread_cleanup_push( fifo_cleanup, queue); + ret = pthread_cond_timedwait( &queue->cond_pull, &queue->mtx, abstime ); + pthread_cleanup_pop(0); + queue->thrs-- ; + if (ret == 0) + goto awaken; /* test for spurious wake-ups */ + + if (ret == ETIMEDOUT) + ret = 0; + else + ret = -ret; + } + + /* Unlock */ + CHECK_POSIX_DO( pthread_mutex_unlock( &queue->mtx ), return -__ret__ ); + + return ret; +} diff -r 23695957bfc0 -r 56c36d1007b4 tests/testcnx.c --- a/tests/testcnx.c Thu Jun 06 19:06:00 2013 +0800 +++ b/tests/testcnx.c Fri Jun 07 18:48:34 2013 +0800 @@ -743,14 +743,14 @@ CHECK( 0, fd_cnx_start_clear(client_side, 0) ); /* Send a message and receive it */ - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); /* Do it in the other direction */ - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -783,7 +783,7 @@ CHECK( 0, fd_cnx_start_clear(server_side, 1) ); /* Send a message and receive it */ - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( EINVAL, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( 0, fd_cnx_start_clear(client_side, 0) ); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); @@ -792,14 +792,14 @@ free(rcv_buf); /* Do it in the other direction */ - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); /* Do it one more time to use another stream */ - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -849,14 +849,14 @@ CHECK( 0, fd_cnx_start_clear(client_side, 0) ); /* Send a message and receive it */ - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); /* And the supposed reply */ - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -870,13 +870,13 @@ /* Send a few TLS protected message, and replies */ for (i = 0; i < 2 * NB_STREAMS; i++) { - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -935,14 +935,14 @@ CHECK( 0, fd_cnx_start_clear(client_side, 0) ); /* Send a message and receive it */ - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); /* And the supposed reply */ - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -956,13 +956,13 @@ /* Send a few TLS protected message, and replies */ for (i = 0; i < 2 * NB_STREAMS; i++) { - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -1022,13 +1022,13 @@ /* Send a few TLS protected message, and replies */ for (i = 0; i < 2 * NB_STREAMS; i++) { - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -1091,13 +1091,13 @@ /* Send a few TLS protected messages, and replies */ for (i = 0; i < 2 * NB_STREAMS; i++) { - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -1157,13 +1157,13 @@ /* Send a few TLS protected messages, and replies */ for (i = 0; i < 2 * NB_STREAMS; i++) { - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -1228,13 +1228,13 @@ /* Send a few TLS protected message, and replies */ for (i = 0; i < 4 * NB_STREAMS; i++) { - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -1267,13 +1267,13 @@ /* Send a few TLS protected message, and replies */ for (i = 0; i < 2 * NB_STREAMS; i++) { - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -1334,13 +1334,13 @@ /* Send a few TLS protected message, and replies */ for (i = 0; i < 4 * NB_STREAMS; i++) { - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -1373,13 +1373,13 @@ /* Send a few TLS protected message, and replies */ for (i = 0; i < 2 * NB_STREAMS; i++) { - CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); free(rcv_buf); - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); CHECK( cer_sz, rcv_sz ); CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); @@ -1753,7 +1753,7 @@ CHECK( 1, (str[0] != '\0') ? 1 : 0 ); /* fd_cnx_recv_setaltfifo */ - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_fifo_new(&myfifo, 0) ); CHECK( 0, fd_cnx_recv_setaltfifo(server_side, myfifo) ); CHECK( 0, clock_gettime(CLOCK_REALTIME, &now) ); @@ -1848,7 +1848,7 @@ CHECK( 1, (str[0] != '\0') ? 1 : 0 ); /* fd_cnx_recv_setaltfifo */ - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_fifo_new(&myfifo, 0) ); CHECK( 0, fd_cnx_recv_setaltfifo(server_side, myfifo) ); CHECK( 0, clock_gettime(CLOCK_REALTIME, &now) ); @@ -1941,7 +1941,7 @@ CHECK( 1, (str[0] != '\0') ? 1 : 0 ); /* fd_cnx_recv_setaltfifo */ - CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz)); CHECK( 0, fd_fifo_new(&myfifo, 0) ); CHECK( 0, fd_cnx_recv_setaltfifo(server_side, myfifo) ); CHECK( 0, clock_gettime(CLOCK_REALTIME, &now) ); diff -r 23695957bfc0 -r 56c36d1007b4 tests/testsctp.c --- a/tests/testsctp.c Thu Jun 06 19:06:00 2013 +0800 +++ b/tests/testsctp.c Fri Jun 07 18:48:34 2013 +0800 @@ -60,6 +60,7 @@ char buf1[]="abcdef"; char *buf2; size_t sz; + struct iovec iov; struct fd_list eps = FD_LIST_INITIALIZER(eps); uint16_t str; int ev; @@ -103,7 +104,9 @@ srv.cc_socket = accept(sock, NULL, NULL); /* Send a first message */ - CHECK( 0, fd_sctp_sendstr(&srv, 1, (uint8_t *)buf1, sizeof(buf1) ) ); + iov.iov_base = buf1; + iov.iov_len = sizeof(buf1); + CHECK( sizeof(buf1), fd_sctp_sendstrv(&srv, 1, &iov, 1 ) ); CHECK( 0, srv.cc_state); /* Receive this message */ @@ -119,7 +122,7 @@ free(buf2); buf2 = NULL; /* Send in the other direction */ - CHECK( 0, fd_sctp_sendstr(&cli, 2, (uint8_t *)buf1, sizeof(buf1)) ); + CHECK( sizeof(buf1), fd_sctp_sendstrv(&cli, 2, &iov, 1) ); CHECK( 0, cli.cc_state); /* Receive this message */