comparison libfdcore/cnxctx.c @ 1217:1e8267ad057c

Implemented early version of sctp_dtls.c, for debug
author Sebastien Decugis <sdecugis@freediameter.net>
date Tue, 18 Jun 2013 12:46:01 +0800
parents 76ac4bb75f0e
children 33ad82ffbdde
comparison
equal deleted inserted replaced
1214:76ac4bb75f0e 1217:1e8267ad057c
86 86
87 TRACE_ENTRY("%d", full); 87 TRACE_ENTRY("%d", full);
88 88
89 CHECK_MALLOC_DO( conn = malloc(sizeof(struct cnxctx)), return NULL ); 89 CHECK_MALLOC_DO( conn = malloc(sizeof(struct cnxctx)), return NULL );
90 memset(conn, 0, sizeof(struct cnxctx)); 90 memset(conn, 0, sizeof(struct cnxctx));
91 fd_list_init(&conn->cc_sctp_dtls_data.chunks, NULL);
91 92
92 if (full) { 93 if (full) {
93 CHECK_FCT_DO( fd_fifo_new ( &conn->cc_incoming, 5 ), return NULL ); 94 CHECK_FCT_DO( fd_fifo_new ( &conn->cc_incoming, 5 ), return NULL );
94 } 95 }
95 96
944 945
945 946
946 947
947 948
948 /* Returns 0 on error, received data size otherwise (always >= 0). This is not used for DTLS-protected associations. */ 949 /* Returns 0 on error, received data size otherwise (always >= 0). This is not used for DTLS-protected associations. */
949 static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz) 950 ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
950 { 951 {
951 ssize_t ret; 952 ssize_t ret;
952 again: 953 again:
953 CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz), 954 CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz),
954 { 955 {
974 case GNUTLS_E_UNEXPECTED_PACKET_LENGTH: 975 case GNUTLS_E_UNEXPECTED_PACKET_LENGTH:
975 /* The connection is closed */ 976 /* The connection is closed */
976 TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed..."); 977 TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed...");
977 break; 978 break;
978 979
980 case GNUTLS_E_WARNING_ALERT_RECEIVED:
981 LOG_N("Received TLS WARNING ALERT: %s", gnutls_alert_get_name(gnutls_alert_get(session)) ?: "<unknown alert>");
982 goto again;
983
984 case GNUTLS_E_FATAL_ALERT_RECEIVED:
985 LOG_E("Received TLS FATAL ALERT: %s", gnutls_alert_get_name(gnutls_alert_get(session)) ?: "<unknown alert>");
986 break;
987
979 default: 988 default:
980 if (gnutls_error_is_fatal (ret) == 0) { 989 if (gnutls_error_is_fatal (ret) == 0) {
981 LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret)); 990 LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret));
982 goto again; 991 goto again;
983 } 992 }
993 fd_cnx_markerror(conn); 1002 fd_cnx_markerror(conn);
994 return ret; 1003 return ret;
995 } 1004 }
996 1005
997 /* Wrapper around gnutls_record_send to handle some error codes. This is also used for DTLS-protected associations */ 1006 /* Wrapper around gnutls_record_send to handle some error codes. This is also used for DTLS-protected associations */
998 static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz) 1007 ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz)
999 { 1008 {
1000 ssize_t ret; 1009 ssize_t ret;
1001 struct timespec ts, now; 1010 struct timespec ts, now;
1002 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 ); 1011 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 );
1003 again: 1012 again:
1041 return ret; 1050 return ret;
1042 } 1051 }
1043 1052
1044 1053
1045 /* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */ 1054 /* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */
1046 /* For the case of DTLS, since we are not using SCTP_UNORDERED, the messages over a single stream are ordered. 1055 int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session, int dtls)
1047 Furthermore, as long as messages are shorter than the MTU [2^14 = 16384 bytes], they are delivered in a single
1048 record, as far as I understand.
1049 For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved.
1050 As a result, we do not use the following function for DTLS reception, because we use the sequence number to rebuild the
1051 messages. */
1052 int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
1053 { 1056 {
1054 /* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP. */ 1057 /* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP. */
1055 do { 1058 do {
1056 uint8_t header[4]; 1059 uint8_t header[4];
1057 struct fd_cnx_rcvdata rcv_data; 1060 struct fd_cnx_rcvdata rcv_data;
1058 struct fd_msg_pmdl *pmdl=NULL; 1061 struct fd_msg_pmdl *pmdl=NULL;
1059 ssize_t ret = 0; 1062 ssize_t ret = 0;
1060 size_t received = 0; 1063 size_t received = 0;
1061 1064
1062 do { 1065 do {
1063 ret = fd_tls_recv_handle_error(conn, session, &header[received], sizeof(header) - received); 1066 if (!dtls)
1067 ret = fd_tls_recv_handle_error(conn, session, &header[received], sizeof(header) - received);
1068 else
1069 ret = fd_dtls_recv_handle_error(conn, session, &header[received], sizeof(header) - received);
1064 if (ret <= 0) { 1070 if (ret <= 0) {
1065 /* The connection is closed */ 1071 /* The connection is closed */
1066 goto out; 1072 goto out;
1067 } 1073 }
1068 received += ret; 1074 received += ret;
1083 CHECK_MALLOC( rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ) ); 1089 CHECK_MALLOC( rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ) );
1084 memcpy(rcv_data.buffer, header, sizeof(header)); 1090 memcpy(rcv_data.buffer, header, sizeof(header));
1085 1091
1086 while (received < rcv_data.length) { 1092 while (received < rcv_data.length) {
1087 pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */ 1093 pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */
1088 ret = fd_tls_recv_handle_error(conn, session, rcv_data.buffer + received, rcv_data.length - received); 1094 if (!dtls)
1095 ret = fd_tls_recv_handle_error(conn, session, rcv_data.buffer + received, rcv_data.length - received);
1096 else
1097 ret = fd_dtls_recv_handle_error(conn, session, rcv_data.buffer + received, rcv_data.length - received);
1089 pthread_cleanup_pop(0); 1098 pthread_cleanup_pop(0);
1090 1099
1091 if (ret <= 0) { 1100 if (ret <= 0) {
1092 free_rcvdata(&rcv_data); 1101 free_rcvdata(&rcv_data);
1093 goto out; 1102 goto out;
1128 1137
1129 ASSERT( fd_cnx_teststate(conn, CC_STATUS_TLS) ); 1138 ASSERT( fd_cnx_teststate(conn, CC_STATUS_TLS) );
1130 ASSERT( fd_cnx_target_queue(conn) ); 1139 ASSERT( fd_cnx_target_queue(conn) );
1131 1140
1132 /* The next function only returns when there is an error on the socket */ 1141 /* The next function only returns when there is an error on the socket */
1133 CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */); 1142 CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session, 0), /* continue */);
1134 1143
1135 TRACE_DEBUG(FULL, "Thread terminated"); 1144 TRACE_DEBUG(FULL, "Thread terminated");
1136 return NULL; 1145 return NULL;
1137 } 1146 }
1138 1147
1139 /* Prepare a gnutls session object for handshake */ 1148 /* Prepare a gnutls session object for handshake */
1933 } while ( sent < len ); 1942 } while ( sent < len );
1934 } 1943 }
1935 } 1944 }
1936 } else { 1945 } else {
1937 /* DTLS */ 1946 /* DTLS */
1938 /* Multistream is handled at lower layer in the push/pull function */ 1947 CHECK_FCT( fd_sctp_dtls_send(conn, buf, len) );
1939 CHECK_FCT( send_simple(conn, buf, len) );
1940 } 1948 }
1941 } 1949 }
1942 break; 1950 break;
1943 #endif /* DISABLE_SCTP */ 1951 #endif /* DISABLE_SCTP */
1944 1952
"Welcome to our mercurial repository"