Mercurial > hg > freeDiameter-dtls
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 |