Changeset 1102:1d7b3ebda27f in freeDiameter
- Timestamp:
- May 9, 2013, 5:40:02 PM (11 years ago)
- Branch:
- default
- Children:
- 1103:d8591b1c56cd, 1105:6b4a417d2845
- Phase:
- public
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
include/freeDiameter/libfdcore.h
r1101 r1102 916 916 - {msg} is NULL. 917 917 - {peer} is NULL. 918 - {other} is a pointer to a struct ure { size_t len; uint8_t * buf; }containing the received buffer.918 - {other} is a pointer to a struct fd_cnx_rcvdata containing the received buffer. 919 919 - {permsgdata} points to either a new empty structure allocated for this message (cf. fd_hook_data_hdl), or NULL if no hdl is registered. 920 920 */ … … 1025 1025 struct fd_hook_data_hdl; 1026 1026 1027 /* The following structure is what is passed to the HOOK_DATA_RECEIVED hook */ 1028 struct fd_cnx_rcvdata { 1029 size_t length; 1030 uint8_t * buffer; /* internal note: the buffer is padded with a struct fd_msg_pmdl, not accounted for in length */ 1031 }; 1032 1027 1033 /* Function to register a new fd_hook_data_hdl. Should be called by your extension init function. 1028 1034 * The arguments are the functions called to initialize a new fd_hook_permsgdata and to free this structure when the corresponding message is being freed. -
include/freeDiameter/libfdproto.h
r1101 r1102 2553 2553 pthread_mutex_t lock; 2554 2554 }; 2555 #define FD_MSG_PMDL_INITIALIZER(pmdl_ptr) { FD_LIST_INITIALIZER( (pmdl_ptr)->sentinel ), PTHREAD_MUTEX_INITIALIZER }2556 2555 struct fd_msg_pmdl * fd_msg_pmdl_get(struct msg * msg); 2556 2557 2557 2558 2558 /***************************************/ -
libfdcore/cnxctx.c
r1101 r1102 673 673 } 674 674 675 #define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0) /* Could use __alignof__(t) on some systems but this is more portable probably */ 676 #define PMDL_PADDED(len) ( ((len) + ALIGNOF(struct fd_msg_pmdl) - 1) & ~(ALIGNOF(struct fd_msg_pmdl) - 1) ) 677 678 size_t fd_msg_pmdl_sizewithoverhead(size_t datalen) 679 { 680 return PMDL_PADDED(datalen); 681 } 682 683 struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen) 684 { 685 return (struct fd_msg_pmdl *)(buf + PMDL_PADDED(datalen)); 686 } 687 688 static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) 689 { 690 *pmdl = fd_msg_pmdl_get_inbuf(buffer, expected_len); 691 fd_list_init(&(*pmdl)->sentinel, NULL); 692 CHECK_POSIX(pthread_mutex_init(&(*pmdl)->lock, NULL) ); 693 return 0; 694 } 695 696 static uint8_t * fd_cnx_alloc_msg_buffer(size_t expected_len, struct fd_msg_pmdl ** pmdl) 697 { 698 uint8_t * ret = NULL; 699 700 CHECK_MALLOC_DO( ret = malloc( PMDL_PADDED(expected_len) ), return NULL ); 701 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); 702 return ret; 703 } 704 705 static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) 706 { 707 uint8_t * ret = NULL; 708 709 CHECK_MALLOC_DO( ret = realloc( buffer, PMDL_PADDED(expected_len) ), return NULL ); 710 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); 711 return ret; 712 } 713 714 static void free_rcvdata(void * arg) 715 { 716 struct fd_cnx_rcvdata * data = arg; 717 struct fd_msg_pmdl * pmdl = fd_msg_pmdl_get_inbuf(data->buffer, data->length); 718 (void) pthread_mutex_destroy(&pmdl->lock); 719 free(data->buffer); 720 } 721 675 722 /* Receiver thread (TCP & noTLS) : incoming message is directly saved into the target queue */ 676 723 static void * rcvthr_notls_tcp(void * arg) … … 695 742 do { 696 743 uint8_t header[4]; 697 uint8_t * newmsg;698 s ize_t length;744 struct fd_cnx_rcvdata rcv_data; 745 struct fd_msg_pmdl *pmdl=NULL; 699 746 ssize_t ret = 0; 700 747 size_t received = 0; … … 709 756 } while (received < sizeof(header)); 710 757 711 length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];758 rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3]; 712 759 713 760 /* Check the received word is a valid begining of a Diameter message */ 714 761 if ((header[0] != DIAMETER_VERSION) /* defined in <libfdproto.h> */ 715 || ( length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */762 || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */ 716 763 /* The message is suspect */ 717 TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0],length);764 LOG_E( "Received suspect header [ver: %d, size: %zd], assuming disconnection", (int)header[0], rcv_data.length); 718 765 fd_cnx_markerror(conn); 719 766 goto out; /* Stop the thread, the recipient of the event will cleanup */ … … 721 768 722 769 /* Ok, now we can really receive the data */ 723 CHECK_MALLOC_DO( newmsg = malloc( length + sizeof(struct timespec)), goto fatal );724 memcpy( newmsg, header, sizeof(header));725 726 while (received < length) {727 pthread_cleanup_push(free , newmsg); /* In case we are canceled, clean the partialy built buffer */728 ret = fd_cnx_s_recv(conn, newmsg + received,length - received);770 CHECK_MALLOC_DO( rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ), goto fatal ); 771 memcpy(rcv_data.buffer, header, sizeof(header)); 772 773 while (received < rcv_data.length) { 774 pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */ 775 ret = fd_cnx_s_recv(conn, rcv_data.buffer + received, rcv_data.length - received); 729 776 pthread_cleanup_pop(0); 730 777 731 778 if (ret <= 0) { 732 free (newmsg);779 free_rcvdata(&rcv_data); 733 780 goto out; 734 781 } … … 736 783 } 737 784 738 // fd_msg_log(....)785 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); 739 786 740 787 /* We have received a complete message, pass it to the daemon */ 741 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg), /* continue or destroy everything? */); 788 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 789 { 790 free_rcvdata(&rcv_data); 791 CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), ); 792 return NULL; 793 } ); 742 794 743 795 } while (conn->cc_loop); … … 758 810 { 759 811 struct cnxctx * conn = arg; 760 uint8_t * buf; 761 size_t bufsz; 812 struct fd_cnx_rcvdata rcv_data; 762 813 int event; 763 814 … … 777 828 778 829 do { 779 CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &buf, &bufsz, &event), goto fatal ); 830 struct fd_msg_pmdl *pmdl=NULL; 831 CHECK_FCT_DO( fd_sctp_recvmeta(conn, NULL, &rcv_data.buffer, &rcv_data.length, &event), goto fatal ); 780 832 if (event == FDEVP_CNX_ERROR) { 781 833 fd_cnx_markerror(conn); … … 787 839 continue; 788 840 } 789 /* Note: the real size of buf is bufsz + struct timespec */ 790 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, bufsz, buf), goto fatal ); 841 842 if (event == FDEVP_CNX_MSG_RECV) { 843 CHECK_MALLOC_DO( rcv_data.buffer = fd_cnx_realloc_msg_buffer(rcv_data.buffer, rcv_data.length, &pmdl), goto fatal ); 844 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); 845 } 846 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, rcv_data.length, rcv_data.buffer), goto fatal ); 791 847 792 848 } while (conn->cc_loop || (event != FDEVP_CNX_MSG_RECV)); … … 928 984 do { 929 985 uint8_t header[4]; 930 uint8_t * newmsg;931 s ize_t length;986 struct fd_cnx_rcvdata rcv_data; 987 struct fd_msg_pmdl *pmdl=NULL; 932 988 ssize_t ret = 0; 933 989 size_t received = 0; … … 942 998 } while (received < sizeof(header)); 943 999 944 length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3];1000 rcv_data.length = ((size_t)header[1] << 16) + ((size_t)header[2] << 8) + (size_t)header[3]; 945 1001 946 1002 /* Check the received word is a valid beginning of a Diameter message */ 947 1003 if ((header[0] != DIAMETER_VERSION) /* defined in <libfreeDiameter.h> */ 948 || ( length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */1004 || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */ 949 1005 /* The message is suspect */ 950 TRACE_DEBUG(INFO, "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0],length);1006 LOG_E( "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], rcv_data.length); 951 1007 fd_cnx_markerror(conn); 952 1008 goto out; … … 954 1010 955 1011 /* Ok, now we can really receive the data */ 956 CHECK_MALLOC( newmsg = malloc( length + sizeof(struct timespec)) );957 memcpy( newmsg, header, sizeof(header));958 959 while (received < length) {960 pthread_cleanup_push(free , newmsg); /* In case we are canceled, clean the partialy built buffer */961 ret = fd_tls_recv_handle_error(conn, session, newmsg + received,length - received);1012 CHECK_MALLOC( rcv_data.buffer = fd_cnx_alloc_msg_buffer( rcv_data.length, &pmdl ) ); 1013 memcpy(rcv_data.buffer, header, sizeof(header)); 1014 1015 while (received < rcv_data.length) { 1016 pthread_cleanup_push(free_rcvdata, &rcv_data); /* In case we are canceled, clean the partialy built buffer */ 1017 ret = fd_tls_recv_handle_error(conn, session, rcv_data.buffer + received, rcv_data.length - received); 962 1018 pthread_cleanup_pop(0); 963 1019 964 1020 if (ret <= 0) { 965 free (newmsg);1021 free_rcvdata(&rcv_data); 966 1022 goto out; 967 1023 } … … 969 1025 } 970 1026 1027 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); 1028 971 1029 /* We have received a complete message, pass it to the daemon */ 972 CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, length, newmsg),1030 CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 973 1031 { 974 free (newmsg);1032 free_rcvdata(&rcv_data); 975 1033 CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), ); 976 1034 return ret; -
libfdcore/cnxctx.h
r894 r1102 66 66 int mode; /* GNUTLS_CLIENT / GNUTLS_SERVER */ 67 67 gnutls_session_t session; /* Session object (stream #0 in case of SCTP) */ 68 struct timespec recvon; /* Timestamp of the last chunk of data received on this session -- before uncipher */69 68 } cc_tls_para; 70 69 … … 131 130 size_t offset; 132 131 } partial; /* If the pull function did not read the full content of first message in raw, it stores it here for next read call. */ 133 struct timespec recvon; /* Timestamp of the last chunk of data received on this stream -- before uncipher */134 132 pthread_t thr; /* Thread to decrypt raw data in this pair of streams */ 135 133 gnutls_session_t session; /* TLS context using this pair of streams -- except if strid == 0, in that case session is outside the array */ -
libfdcore/fdcore-internal.h
r1098 r1102 219 219 FDEVP_TERMINATE = 1500 220 220 221 /* A connection object has received a message. (data contains the buffer + struct timespec piggytailed -- unaligned) */221 /* A connection object has received a message. (data contains the buffer + padding + struct fd_msg_pmdl) */ 222 222 ,FDEVP_CNX_MSG_RECV 223 223 … … 271 271 int validate; /* The peer is new, it must be validated (by an extension) or error CEA to be sent */ 272 272 }; 273 274 273 275 274 /* Functions */ … … 367 366 void fd_hook_associate(struct msg * msg, struct fd_msg_pmdl * pmdl); 368 367 int fd_hooks_init(void); 368 size_t fd_msg_pmdl_sizewithoverhead(size_t datalen); 369 struct fd_msg_pmdl * fd_msg_pmdl_get_inbuf(uint8_t * buf, size_t datalen); 370 369 371 #endif /* _FDCORE_INTERNAL_H */ -
libfdcore/sctp.c
r1078 r1102 1086 1086 /* We will loop while all data is not received. */ 1087 1087 incomplete: 1088 while (datasize + sizeof(struct timespec)>= bufsz ) {1088 while (datasize >= bufsz ) { 1089 1089 /* The buffer is full, enlarge it */ 1090 1090 bufsz += mempagesz; … … 1094 1094 memset(&iov, 0, sizeof(iov)); 1095 1095 iov.iov_base = data + datasize ; 1096 iov.iov_len = bufsz - sizeof(struct timespec) -datasize;1096 iov.iov_len = bufsz - datasize; 1097 1097 1098 1098 /* Receive data from the socket */ -
libfdcore/sctps.c
r1034 r1102 92 92 /* Demux this message to the appropriate fifo, another thread will pull, gnutls process, and send to target queue */ 93 93 if (strid < conn->cc_sctp_para.pairs) { 94 /* Note, here the timespec is piggytailed to buf */95 94 CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto fatal ); 96 95 } else { … … 196 195 return -1; 197 196 } 198 if (ev == FDEVP_CNX_MSG_RECV) {199 memcpy(&ctx->recvon, ctx->partial.buf + ctx->partial.bufsz, sizeof(struct timespec)); /* retrieve piggy-tailed ts */200 }201 197 } 202 198
Note: See TracChangeset
for help on using the changeset viewer.