Index: libfdcore/cnxctx.c
===================================================================
--- libfdcore/cnxctx.c	(revision 816)
+++ libfdcore/cnxctx.c	(revision 894)
@@ -641,4 +641,6 @@
 	}
 	
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &conn->cc_tls_para.recvon), /* continue */ );
+	
 	return ret;
 }
@@ -696,4 +698,5 @@
 		ssize_t ret = 0;
 		size_t	received = 0;
+		struct timespec recv_on;
 
 		do {
@@ -718,5 +721,5 @@
 
 		/* Ok, now we can really receive the data */
-		CHECK_MALLOC_DO(  newmsg = malloc( length ), goto fatal );
+		CHECK_MALLOC_DO(  newmsg = malloc( length + sizeof(struct timespec) ), goto fatal );
 		memcpy(newmsg, header, sizeof(header));
 
@@ -732,4 +735,8 @@
 			received += ret;
 		}
+		
+		/* Piggy-tail the timestamp of reception */
+		CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &recv_on), /* continue */ );
+		memcpy(newmsg + length, &recv_on, sizeof(struct timespec));
 		
 		/* We have received a complete message, pass it to the daemon */
@@ -782,5 +789,5 @@
 			continue;
 		}
-		
+		/* Note: the real size of buf is bufsz + struct timespec */
 		CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, bufsz, buf), goto fatal );
 		
@@ -920,4 +927,15 @@
 int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session)
 {
+	struct timespec * rcv_on;
+	
+	void * ptr = gnutls_transport_get_ptr(session);
+	if (ptr == conn) {
+		rcv_on = &conn->cc_tls_para.recvon;
+	} else {
+		struct sctps_ctx * ctx = (struct sctps_ctx *) ptr;
+		rcv_on = &ctx->recvon;
+	}
+	
+	
 	/* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP */
 	do {
@@ -927,4 +945,5 @@
 		ssize_t ret = 0;
 		size_t	received = 0;
+		struct timespec recv_on;
 
 		do {
@@ -949,5 +968,5 @@
 
 		/* Ok, now we can really receive the data */
-		CHECK_MALLOC(  newmsg = malloc( length ) );
+		CHECK_MALLOC(  newmsg = malloc( length + sizeof(struct timespec)) );
 		memcpy(newmsg, header, sizeof(header));
 
@@ -963,4 +982,7 @@
 			received += ret;
 		}
+		
+		/* The timestamp of the last TLS chunk received for this rebuilt message lives close to the session pointer, we piggyback it */
+		memcpy(newmsg + length, rcv_on, sizeof(struct timespec));
 		
 		/* We have received a complete message, pass it to the daemon */
Index: libfdcore/cnxctx.h
===================================================================
--- libfdcore/cnxctx.h	(revision 808)
+++ libfdcore/cnxctx.h	(revision 894)
@@ -66,4 +66,5 @@
 		int				 mode; 		/* GNUTLS_CLIENT / GNUTLS_SERVER */
 		gnutls_session_t 		 session;	/* Session object (stream #0 in case of SCTP) */
+		struct timespec  		 recvon;	/* Timestamp of the last chunk of data received on this session -- before uncipher */
 	}		cc_tls_para;
 
@@ -130,4 +131,5 @@
 		size_t   offset;
 	} 		 partial;	/* If the pull function did not read the full content of first message in raw, it stores it here for next read call. */
+	struct timespec  recvon;	/* Timestamp of the last chunk of data received on this stream -- before uncipher */
 	pthread_t	 thr;		/* Thread to decrypt raw data in this pair of streams */
 	gnutls_session_t session;	/* TLS context using this pair of streams -- except if strid == 0, in that case session is outside the array */
Index: libfdcore/fdcore-internal.h
===================================================================
--- libfdcore/fdcore-internal.h	(revision 815)
+++ libfdcore/fdcore-internal.h	(revision 894)
@@ -215,5 +215,5 @@
 	,FDEVP_TERMINATE
 	
-	/* A connection object has received a message. (data contains the buffer) */
+	/* A connection object has received a message. (data contains the buffer + struct timespec piggytailed -- unaligned) */
 	,FDEVP_CNX_MSG_RECV
 			 
Index: libfdcore/sctp.c
===================================================================
--- libfdcore/sctp.c	(revision 817)
+++ libfdcore/sctp.c	(revision 894)
@@ -1068,4 +1068,5 @@
 	size_t			 mempagesz = sysconf(_SC_PAGESIZE); /* We alloc buffer by memory pages for efficiency */
 	int 			 timedout = 0;
+	struct timespec 	 recv_on;
 	
 	TRACE_ENTRY("%p %p %p %p %p", conn, strid, buf, len, event);
@@ -1086,13 +1087,13 @@
 	/* We will loop while all data is not received. */
 incomplete:
-	if (datasize == bufsz) {
+	if (datasize == bufsz - sizeof(struct timespec)) {
 		/* The buffer is full, enlarge it */
 		bufsz += mempagesz;
-		CHECK_MALLOC( data = realloc(data, bufsz) );
+		CHECK_MALLOC( data = realloc(data, bufsz ) );
 	}
 	/* the new data will be received following the preceding */
 	memset(&iov,  0, sizeof(iov));
 	iov.iov_base = data + datasize ;
-	iov.iov_len  = bufsz - datasize;
+	iov.iov_len  = bufsz - sizeof(struct timespec) - datasize;
 
 	/* Receive data from the socket */
@@ -1188,4 +1189,8 @@
 	}
 	
+	/* Piggy-tail the timestamp of reception */
+	CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &recv_on), /* continue */ );
+	memcpy(data + datasize, &recv_on, sizeof(struct timespec));
+		
 	/* From this point, we have received a message */
 	*event = FDEVP_CNX_MSG_RECV;
Index: libfdcore/sctps.c
===================================================================
--- libfdcore/sctps.c	(revision 808)
+++ libfdcore/sctps.c	(revision 894)
@@ -92,4 +92,5 @@
 				/* Demux this message to the appropriate fifo, another thread will pull, gnutls process, and send to target queue */
 				if (strid < conn->cc_sctp_para.pairs) {
+					/* Note, here the timespec is piggytailed to buf */
 					CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto fatal );
 				} else {
@@ -195,4 +196,7 @@
 			return -1;
 		}
+		if (ev == FDEVP_CNX_MSG_RECV) {
+			memcpy(&ctx->recvon, ctx->partial.buf + ctx->partial.bufsz, sizeof(struct timespec)); /* retrieve piggy-tailed ts */
+		}
 	}
 		
