Index: trunk/kernel/kern/ksocket.c
===================================================================
--- trunk/kernel/kern/ksocket.c	(revision 669)
+++ trunk/kernel/kern/ksocket.c	(revision 683)
@@ -1,6 +1,6 @@
 /*
- * ksocket.c - kernel socket API implementation.
+ * ksocket.c - kernel socket implementation.
  *
- * Authors  Alain Greiner   (2016,2017,2018,2019,2020)
+ * Authors  Alain Greiner        (2016,2017,2018,2019,2020)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -117,5 +117,5 @@
     switch( sts )
     {
-        case CMD_STS_SUCCESS  : return "TX_CONNECT";
+        case CMD_STS_SUCCESS  : return "SUCCESS";
         case CMD_STS_EOF      : return "EOF";
         case CMD_STS_RST      : return "RST";
@@ -135,11 +135,21 @@
 // and request the NIC_TX server thread to re-send the unacknowledged segment. 
 ///////////////////////////////////////////////////////////////////////////////////////////
-// @ args_xp    : extended pointer on the involved socket.
+// @ sock_xp    : extended pointer on the involved socket.
 ///////////////////////////////////////////////////////////////////////////////////////////
-static void __attribute__((noinline)) socket_alarm_handler( xptr_t args_xp )
+static void __attribute__((noinline)) socket_alarm_handler( xptr_t sock_xp )
 {
     // get cluster and local pointer on socket descriptor
-    socket_t * sock_ptr = GET_PTR( args_xp );
-    cxy_t      sock_cxy = GET_CXY( args_xp );
+    socket_t * sock_ptr = GET_PTR( sock_xp );
+    cxy_t      sock_cxy = GET_CXY( sock_xp );
+
+#if DEBUG_SOCKET_ALARM
+uint32_t cycle = (uint32_t)hal_get_cycles();
+#endif
+
+   // build extended pointer on lock protecting socket
+    xptr_t socket_lock_xp = XPTR( sock_cxy , &sock_ptr->lock );
+
+    // take the socket lock
+    remote_queuelock_acquire( socket_lock_xp );
 
     // get relevant infos from socket descriptor
@@ -151,6 +161,5 @@
 "illegal tx_client field for a retransmission timeout" );
 
-    // get TX client thread cluster and local pointer
-    thread_t * thread_ptr = GET_PTR( thread_xp );
+    // get TX client thread cluster 
     cxy_t      thread_cxy = GET_CXY( thread_xp );
 
@@ -168,5 +177,5 @@
 
     // update the date in alarm
-    alarm_update( thread_ptr , hal_get_cycles() + TCP_RETRANSMISSION_TIMEOUT );
+    alarm_update( thread_xp , hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT );
     
     //////////////////////////////
@@ -175,6 +184,6 @@
 
 #if DEBUG_SOCKET_ALARM
-uint32_t cycle = (uint32_t)hal_get_cycles();
-printk("\n[%s] rings for TX_CONNECT : request a new SYN segment / cycle %d\n",
+if( DEBUG_SOCKET_ALARM < cycle )
+printk("\n[%s] rings for CONNECT : request a new SYN segment / cycle %d\n",
 __FUNCTION__ , cycle );
 #endif
@@ -193,6 +202,6 @@
 
 #if DEBUG_SOCKET_ALARM
-uint32_t cycle = (uint32_t)hal_get_cycles();
-printk("\n[%s] rings for TX_ACCEPT : request a new SYN-ACK segment / cycle %d\n",
+if( DEBUG_SOCKET_ALARM < cycle )
+printk("\n[%s] rings for ACCEPT : request a new SYN-ACK segment / cycle %d\n",
 __FUNCTION__ , cycle );
 #endif
@@ -211,6 +220,6 @@
 
 #if DEBUG_SOCKET_ALARM
-uint32_t cycle = (uint32_t)hal_get_cycles();
-printk("\n[%s] rings for TX_CLOSE : request a new FIN-ACK segment / cycle %d\n",
+if( DEBUG_SOCKET_ALARM < cycle )
+printk("\n[%s] rings for CLOSE : request a new FIN-ACK segment / cycle %d\n",
 __FUNCTION__ , cycle );
 #endif
@@ -227,44 +236,27 @@
     if( tx_cmd == CMD_TX_SEND )
     {
-        // TODO build a new TX_SEND command
-    }
+        // get get relevant infos from socket pointer
+        uint32_t  tx_una = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_una ));
+        uint32_t  tx_ack = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_ack ));
+        uint32_t  tx_len = hal_remote_l32( XPTR( sock_cxy , &sock_ptr->tx_len ));
+
+#if DEBUG_SOCKET_ALARM       
+if( DEBUG_SOCKET_ALARM < cycle )
+printk("\n[%s] rings for SEND : request %d bytes / cycle %d\n",
+__FUNCTION__ , tx_len , cycle );
+#endif
+        // update command fields in socket
+        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_nxt    ) , tx_una );
+        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_todo   ) , tx_len - tx_ack );
+        hal_remote_s32( XPTR( sock_cxy , &sock_ptr->tx_valid  ) , true );
+
+        // unblock the NIC_TX server thread 
+        thread_unblock( tx_server_xp , THREAD_BLOCKED_CLIENT );
+    }
+
+    // release the socket lock
+    remote_queuelock_release( socket_lock_xp );
+
 }   // end socket_alarm_handler()
-
-///////////////////////////////////////////////////////////////////////////////////////////
-// This static function activates the alarm embedded in the calling thread descriptor,
-// using the <date> argument.
-///////////////////////////////////////////////////////////////////////////////////////////
-// @ delay   : number of cycles (from the current absolute date).
-///////////////////////////////////////////////////////////////////////////////////////////
-static void socket_alarm_start( xptr_t   socket_xp,
-                                uint32_t delay )
-{
-    // compute absolute date
-    cycle_t date = hal_get_cycles() + delay; 
-
-    // get pointer on calling threadf
-    thread_t * this = CURRENT_THREAD;
-
-    // start the alarm
-    alarm_start( date,
-                 &socket_alarm_handler,   // func_ptr
-                 socket_xp,               // args_xp
-                 this );
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////
-// This static function activates the alarm embedded in the calling thread descriptor,
-// using the <date> argument.
-///////////////////////////////////////////////////////////////////////////////////////////
-// @ date   : absolute date for this alarm.
-///////////////////////////////////////////////////////////////////////////////////////////
-static void socket_alarm_stop( void )
-{
-    // get pointer on calling threadf
-    thread_t * this = CURRENT_THREAD;
-
-    // stop the alarm
-    alarm_stop( this );
-}
 
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -470,5 +462,5 @@
 // associated to a socket: file descriptor, socket descriptor, RX buffer, R2T queue,
 // and CRQ queue. It allocates an fdid, and register it in the process fd_array.
-// It initialise the  the socket desccriptor static fields, other than local_addr, 
+// It initialise the socket desccriptor static fields, other than local_addr, 
 // local_port, remote_addr, remote_port), and set the socket state to UNBOUND.
 // It returns the local pointer on socket descriptor and the fdid value in buffers
@@ -489,15 +481,19 @@
 {
     uint32_t       fdid;
-    kmem_req_t     req;
     socket_t     * socket;
     vfs_file_t   * file;
     uint32_t       state;
+    void         * tx_buf;
     error_t        error;
+
 
     thread_t  * this    = CURRENT_THREAD;
     process_t * process = this->process;
 
+#if DEBUG_SOCKET_CREATE || DEBUG_SOCKET_ERROR
+uint32_t cycle = (uint32_t)hal_get_cycles();
+#endif
+
 #if DEBUG_SOCKET_CREATE
-uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_CREATE < cycle )
 printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
@@ -506,65 +502,82 @@
    
     // 1. allocate memory for socket descriptor 
-    req.type   = KMEM_KCM;
-    req.order  = bits_log2( sizeof(socket_t) );
-    req.flags  = AF_ZERO;
-    socket     = kmem_remote_alloc( cxy , &req );
+    socket = kmem_remote_alloc( cxy , bits_log2(sizeof(socket_t)) , AF_ZERO );
 
     if( socket == NULL )
     {
-        printk("\n[ERROR] in %s : cannot allocate socket descriptor / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, this->trdid );
-        return -1;
-    }
-
-    // 2. allocate memory for rx_buf buffer
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : cannot allocate socket descriptor / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, cycle );
+#endif
+        return -1;
+    }
+
+    // 2. allocate memory for rx_buf data buffer
     error = remote_buf_init( XPTR( cxy , &socket->rx_buf ),
-                             bits_log2( CONFIG_SOCK_RX_BUF_SIZE ) );
+                             CONFIG_SOCK_RX_BUF_ORDER );
 
     if( error )
     {
-        printk("\n[ERROR] in %s : cannot allocate rx_buf / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, this->trdid );
-        req.type = KMEM_KCM;
-        req.ptr  = socket;
-        kmem_remote_free( cxy , &req );
-        return -1;
-    }
-
-    // 3. allocate memory for r2tq queue 
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : no memory for rx_buf / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, cycle );
+#endif
+        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1
+        return -1;
+    }
+
+    // 3. allocate memory for tx_buf 
+    tx_buf = kmem_remote_alloc( cxy , CONFIG_SOCK_TX_BUF_ORDER , AF_NONE );
+
+    if( tx_buf == NULL )
+    {
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : no memory for tx_buf / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, cycle );
+#endif
+        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );        // 2
+        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1 
+        return -1;
+    }
+
+    // 4. allocate memory for r2tq queue 
     error = remote_buf_init( XPTR( cxy , &socket->r2tq ),
                              bits_log2( CONFIG_SOCK_R2T_BUF_SIZE ) );
     if( error )
     {
-        printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, this->trdid );
-        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );
-        req.type = KMEM_KCM;
-        req.ptr  = socket;
-        kmem_remote_free( cxy , &req );
-        return -1;
-    }
-
-    // don't allocate memory for crqq queue, as it is done by the socket_listen function
-
-    //  4. allocate memory for file descriptor
-	req.type  = KMEM_KCM;
-	req.order = bits_log2( sizeof(vfs_file_t) );
-    req.flags = AF_ZERO;
-	file      = kmem_remote_alloc( cxy , &req );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : cannot allocate R2T queue / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, cycle );
+#endif
+        kmem_remote_free( cxy , tx_buf , CONFIG_SOCK_TX_BUF_ORDER );     // 3
+        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );        // 2
+        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1 
+        return -1;
+    }
+
+    // don't allocate memory for CRQ queue / done by the socket_listen function
+
+    // 5. allocate memory for file descriptor
+	file = kmem_remote_alloc( cxy , bits_log2(sizeof(vfs_file_t)) , AF_ZERO );
 
     if( file == NULL ) 
     {
-        printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, this->trdid );
-        remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );
-        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );
-        req.type = KMEM_KCM;
-        req.ptr  = socket;
-        kmem_remote_free( cxy , &req );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : cannot allocate file descriptor / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, cycle );
+#endif
+        remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );          // 4 
+        kmem_remote_free( cxy , tx_buf , CONFIG_SOCK_TX_BUF_ORDER );     // 3
+        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );        // 2
+        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1 
         return -1;
     }
     
-    // 5. get an fdid value, and register file descriptor in fd_array[]
+    // 6. get an fdid value, and register file descriptor in fd_array[]
     error = process_fd_register( process->ref_xp,
                                  XPTR( cxy , file ),
@@ -572,13 +585,15 @@
     if ( error ) 
     {
-        printk("\n[ERROR] in %s : cannot register file descriptor / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, this->trdid );
-        req.type = KMEM_KCM;
-        req.ptr  = file;
-        kmem_free( &req );
-        remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );
-        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );
-        req.ptr  = socket;
-        kmem_free( &req );
+
+#if DEBUG_SOCKET_ERROR
+if( DEBUG_SOCKET_ERROR < cycle )
+printk("\n[ERROR] in %s : cannot register file descriptor / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, cycle );
+#endif
+        kmem_remote_free( cxy , file , bits_log2(sizeof(vfs_file_t)) );  // 5
+        remote_buf_release_data( XPTR( cxy , &socket->r2tq ) );          // 4 
+        kmem_remote_free( cxy , tx_buf , CONFIG_SOCK_TX_BUF_ORDER );     // 3
+        remote_buf_release_data( XPTR( cxy , &socket->rx_buf ) );        // 2
+        kmem_remote_free( cxy , socket , bits_log2(sizeof(socket_t)) );  // 1 
         return -1;
     }
@@ -597,4 +612,5 @@
     hal_remote_s32( XPTR( cxy , &socket->rx_valid    ) , false );
     hal_remote_s32( XPTR( cxy , &socket->nic_channel ) , 0 );
+    hal_remote_spt( XPTR( cxy , &socket->tx_buf      ) , tx_buf );
 
     // initialize file descriptor 
@@ -606,4 +622,5 @@
 
 #if DEBUG_SOCKET_CREATE
+cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_CREATE < cycle )
 printk("\n[%s] thread[%x,%x] exit / socket[%x,%d] / xptr[%x,%x] / cycle %d\n",
@@ -631,6 +648,4 @@
 static void socket_destroy( xptr_t file_xp )
 {
-    kmem_req_t          req;
-
     thread_t  * this    = CURRENT_THREAD;
     process_t * process = this->process;
@@ -677,7 +692,5 @@
 
     // release memory allocated for file descriptor
-    req.type = KMEM_KCM;
-    req.ptr  = file_ptr;
-    kmem_remote_free( file_cxy , &req );
+    kmem_remote_free( file_cxy , file_ptr , bits_log2(sizeof(vfs_file_t)) );
 
     // release memory allocated for buffers attached to socket descriptor
@@ -687,7 +700,5 @@
 
     // release memory allocated for socket descriptor
-    req.type = KMEM_KCM;
-    req.ptr  = socket_ptr;
-    kmem_remote_free( file_cxy , &req );
+    kmem_remote_free( file_cxy , socket_ptr , bits_log2(sizeof(socket_t)) );
 
 #if DEBUG_SOCKET_DESTROY
@@ -702,5 +713,5 @@
 ////////////////////////////////////////////////
 void socket_put_r2t_request( xptr_t    queue_xp,
-                             uint32_t  flags,
+                             uint8_t   flags,
                              uint32_t  channel )
 {
@@ -715,5 +726,5 @@
         // try to register R2T request
         error_t error = remote_buf_put_from_kernel( queue_xp,
-                                                    (uint8_t *)(&flags),
+                                                    &flags,
                                                     1 );
         if( error )
@@ -740,4 +751,14 @@
     }
 }  // end socket_put_r2t_request()
+
+///////////////////////////////////////////////////
+error_t socket_get_r2t_request( xptr_t    queue_xp,
+                                uint8_t * flags )
+{
+    // get one request from R2T queue
+    return remote_buf_get_to_kernel( queue_xp,
+                                     flags,
+                                     1 );
+}  // end socket_get_r2T_request()
   
 ///////////////////////////////////////////////////
@@ -843,6 +864,9 @@
     process_t * process = this->process;
 
+#if DEBUG_SOCKET_BIND || DEBUG_SOCKET_ERROR
+uint32_t cycle = (uint32_t)hal_get_cycles();
+#endif
+
 #if DEBUG_SOCKET_BIND
-uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_BIND < cycle )
 printk("\n[%s] thread[%x,%x] enter / socket[%x,%d] / addr %x / port %x / cycle %d\n",
@@ -858,6 +882,9 @@
     if( file_xp == XPTR_NULL )
     {
-        printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x]\n",
-        __FUNCTION__, fdid, process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, fdid, process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -869,6 +896,9 @@
     if( file_type != FILE_TYPE_SOCK )
     {
-        printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]",
-        __FUNCTION__, vfs_inode_type_str( file_type ), process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d",
+__FUNCTION__, vfs_inode_type_str( file_type ), process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -918,6 +948,9 @@
     process_t * process = this->process;
 
+#if DEBUG_SOCKET_LISTEN || DEBUG_SOCKET_ERROR
+uint32_t cycle = (uint32_t)hal_get_cycles();
+#endif
+
 #if DEBUG_SOCKET_LISTEN
-uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_LISTEN < cycle )
 printk("\n[%s] thread[%x,%x] enter / socket[%x,%d] / crq_depth %x / cycle %d\n",
@@ -933,6 +966,9 @@
     if( file_xp == XPTR_NULL )
     {
-        printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x]\n",
-        __FUNCTION__, fdid, process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, fdid, process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -944,6 +980,9 @@
     if( file_type != FILE_TYPE_SOCK )
     {
-        printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n",
-        __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -958,6 +997,9 @@
     if( socket_type != SOCK_STREAM )
     {
-        printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x]\n",
-        __FUNCTION__, socket_type_str(socket_type), process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, socket_type_str(socket_type), process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -966,6 +1008,9 @@
     if( socket_state != TCP_STATE_BOUND )
     {
-        printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x]\n",
-        __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -980,6 +1025,9 @@
     if( error )
     {
-        printk("\n[ERROR] in %s : cannot allocate CRQ queue / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : cannot allocate CRQ queue / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -1011,5 +1059,5 @@
     vfs_file_t        * file_ptr;
     cxy_t               file_cxy;
-    vfs_file_type_t    file_type;           // file descriptor type
+    vfs_file_type_t     file_type;           // file descriptor type
     socket_t          * socket_ptr;          // local pointer on remote waiting socket
     uint32_t            socket_type;         // listening socket type    
@@ -1045,6 +1093,9 @@
     process_t * process   = this->process;
 
-#if DEBUG_SOCKET_ACCEPT
+#if DEBUG_SOCKET_ACCEPT || DEBUG_SOCKET_ERROR
 uint32_t cycle = (uint32_t)hal_get_cycles();
+#endif
+
+#if DEBUG_SOCKET_ACCEPT 
 if( DEBUG_SOCKET_ACCEPT < cycle )
 printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / cycle %d\n",
@@ -1060,6 +1111,9 @@
     if( file_xp == XPTR_NULL )
     {
-        printk("\n[ERROR] in %s : undefined fdid %d",
-        __FUNCTION__, fdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : undefined fdid %d / thead[%x,%x] / cycle %d",
+__FUNCTION__, fdid, process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -1071,6 +1125,9 @@
     if( file_type != FILE_TYPE_SOCK )
     {
-        printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x]\n",
-        __FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, vfs_inode_type_str(file_type), process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -1097,9 +1154,10 @@
     if( socket_type != SOCK_STREAM )
     {
-        // release listening socket lock
+                    
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, socket_type_str(socket_type), process->pid , this->trdid, cycle );
+#endif
         remote_queuelock_release( socket_lock_xp );
-                    
-        printk("\n[ERROR] in %s : illegal socket type %s / thread[%x,%x]\n",
-        __FUNCTION__, socket_type_str(socket_type), process->pid , this->trdid );
         return -1;
     }
@@ -1108,9 +1166,10 @@
     if( socket_state != TCP_STATE_LISTEN ) 
     {
-        // release listening socket lock
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid, cycle );
+#endif
         remote_queuelock_release( socket_lock_xp );
-                    
-        printk("\n[ERROR] in %s : illegal socket state %s / thread[%x,%x]\n",
-        __FUNCTION__, socket_state_str(socket_state), process->pid, this->trdid );
         return -1;
     }
@@ -1119,9 +1178,10 @@
     if( (socket_rx_valid == true) || (socket_rx_client != XPTR_NULL) )
     { 
-        // release listening socket lock
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : previous RX cmd on socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
+#endif
         remote_queuelock_release( socket_lock_xp );
-                    
-        printk("\n[ERROR] in %s : previous RX cmd on socket[%x,%d] / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
         return -1;
     }
@@ -1130,13 +1190,14 @@
     if( (socket_tx_valid == true) || (socket_tx_client != XPTR_NULL) )
     { 
-        // release socket lock
+                    
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
+#endif
         remote_queuelock_release( socket_lock_xp );
-                    
-        printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
-        return -1;
-    }
-
-    // 2) build extended pointer on listening socket.crq
+        return -1;
+    }
+
+    // 2) check the listenig socket CRQ
     crq_xp  = XPTR( file_cxy , &socket_ptr->crqq );
 
@@ -1144,8 +1205,8 @@
     crq_status = remote_buf_status( crq_xp );
 
-    // block & deschedule when CRQ empty
+    // block & deschedule to wait a client request when CRQ empty
     if( crq_status == 0 )
     {
-        // register command arguments in listening socket
+        // register command arguments for NIC_RX server in listening socket
         hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_cmd    ), CMD_RX_ACCEPT );
         hal_remote_s64( XPTR( file_cxy , &socket_ptr->rx_client ), client_xp );
@@ -1179,5 +1240,6 @@
         crq_status   = remote_buf_status( crq_xp );
 
-assert( __FUNCTION__, (((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)),
+assert( __FUNCTION__,
+(((crq_status > 0) || (cmd_status!= CMD_STS_SUCCESS)) && (cmd_valid == false)),
 "illegal socket state when client thread resumes after RX_ACCEPT" );
 
@@ -1187,38 +1249,32 @@
         if( cmd_status != CMD_STS_SUCCESS )
         {
-            // release socket lock
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : reported for RX / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
+#endif
             remote_queuelock_release( socket_lock_xp );
-
-            printk("\n[ERROR] in %s for RX_ACCEPT command / socket[%x,%d] / thread[%x,%x]\n",
-            __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
             return -1;
         }
-
-        // extract first request from the listening socket CRQ
-        error = socket_get_crq_request( crq_xp,
+    }  // end blocking on CRQ empty 
+
+    // from this point, we can extract a request from listening socket CRQ
+    error = socket_get_crq_request( crq_xp,
                                     &new_remote_addr,
                                     &new_remote_port,
                                     &new_remote_iss,
                                     &new_remote_window );
-
 assert( __FUNCTION__, (error == 0),
 "cannot get a connection request from a non-empty CRQ" ); 
 
-        // reset listening socket rx_client
-        hal_remote_s32( XPTR( file_cxy , &socket_ptr->rx_client ) , XPTR_NULL );
-
-        // release socket lock
-        remote_queuelock_release( socket_lock_xp );
-
-    }  // end blocking on CRQ status 
-
-    // from this point, we can create a new socket 
-    // and ask the NIC_TX to send a SYN-ACK segment
+    // release listening socket lock
+    remote_queuelock_release( socket_lock_xp );
 
 #if DEBUG_SOCKET_ACCEPT
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_ACCEPT < cycle )
-printk("\n[%s] thread[%x,%x] socket[%x,%d] / got a CRQ request / cycle %d\n",
-__FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
+printk("\n[%s] thread[%x,%x] socket[%x,%d] / CRQ request [addr %x / port %x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, process->pid, fdid,
+new_remote_addr, new_remote_port, cycle );
 #endif
 
@@ -1234,6 +1290,9 @@
     if( error )
     {
-        printk("\n[ERROR] in %s : cannot allocate new socket / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : cannot create new socket / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -1287,10 +1346,13 @@
   
     // start retransmission timer
-    socket_alarm_start( new_socket_xp , TCP_RETRANSMISSION_TIMEOUT );
+    alarm_start( client_xp,
+                 hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT,
+                 &socket_alarm_handler,
+                 new_socket_xp );
 
 #if DEBUG_SOCKET_ACCEPT
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_ACCEPT < cycle )
-printk("\n[%s] thread[%x,%x] new_socket[%x,%d] blocks on <IO> waiting ESTAB / cycle %d\n",
+printk("\n[%s] thread[%x,%x] for socket[%x,%d] request SYN-ACK & blocks on <IO> / cycle %d\n",
 __FUNCTION__, process->pid, this->trdid, process->pid, new_fdid, cycle );
 #endif
@@ -1307,6 +1369,6 @@
 #endif
 
-    // stop retransmission timer
-    socket_alarm_stop();
+    // stop retransmission timer in thread descriptor
+    alarm_stop( client_xp );
 
     // get new socket state, tx_valid and tx_sts
@@ -1315,6 +1377,6 @@
     cmd_status = hal_remote_l32( XPTR( new_socket_cxy , &new_socket_ptr->tx_sts ));
 
-assert( __FUNCTION__, (((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS))
-        && (cmd_valid == false)), 
+assert( __FUNCTION__,
+(((new_state == TCP_STATE_ESTAB) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)), 
 "illegal socket state when client thread resumes after TX_ACCEPT" ); 
 
@@ -1324,6 +1386,9 @@
     if( cmd_status != CMD_STS_SUCCESS ) 
     {
-        printk("\n[ERROR] in %s for TX_ACCEPT command / socket[%x,%d] / thread[%x,%x]\n",
-        __FUNCTION__, process->pid, new_fdid, process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s reported for TX / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, new_fdid, process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -1370,4 +1435,8 @@
     trdid_t     trdid     = this->trdid;
 
+#if DEBUG_SOCKET_CONNECT || DEBUG_SOCKET_ERROR
+uint32_t cycle = (uint32_t)hal_get_cycles();
+#endif
+
     // get pointers on file descriptor
     xptr_t       file_xp  = process_fd_get_xptr_from_local( this->process , fdid );
@@ -1378,6 +1447,9 @@
     if( file_xp == XPTR_NULL )
     {
-        printk("\n[ERROR] in %s : undefined fdid %d",
-        __FUNCTION__, fdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : undefined fdid %d / thread[%x,%x] / cycle %d",
+__FUNCTION__, fdid, pid, trdid, cycle );
+#endif
         return -1;
     }
@@ -1388,7 +1460,6 @@
 
 #if DEBUG_SOCKET_CONNECT
-uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_CONNECT < cycle )
-printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / addr %x / port %d / cycle %d\n",
+printk("\n[%s] thread[%x,%x] enter for socket[%x,%d] / addr %x / port %x / cycle %d\n",
 __FUNCTION__,  pid, trdid, pid, fdid, remote_addr, remote_port, cycle );
 #endif
@@ -1397,6 +1468,9 @@
     if( file_type != FILE_TYPE_SOCK )
     {
-        printk("\n[ERROR] in %s : illegal file type %s",
-        __FUNCTION__, vfs_inode_type_str( file_type ) );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal file type %s / thread[%x,%x] / cycle %d",
+__FUNCTION__, vfs_inode_type_str( file_type ), pid, trdid, cycle );
+#endif
         return -1;
     }
@@ -1412,6 +1486,9 @@
         if( socket_state != UDP_STATE_BOUND )
         {
-            printk("\n[ERROR] in %s : illegal socket state %s for type %s",
-            __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type) );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal socket state %s for type %s / thread[%x,%x] / cycle %d",
+__FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type), pid, trdid, cycle );
+#endif
             return -1;
         }
@@ -1421,6 +1498,9 @@
         if( socket_state != TCP_STATE_BOUND )
         {
-            printk("\n[ERROR] in %s : illegal socket state %s for type %s",
-            __FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type) );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal socket state %s for type %s / thread[%x,%x] / cycle %d",
+__FUNCTION__, socket_state_str(socket_state), socket_type_str(socket_type), pid, trdid, cycle );
+#endif
             return -1;
         }
@@ -1428,6 +1508,9 @@
     else
     {
-        printk("\n[ERROR] in %s : illegal socket type %s",
-        __FUNCTION__,  socket_type_str(socket_type) );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal socket type / thread[%x,%x] / cycle %d",
+__FUNCTION__, pid, trdid, cycle );
+#endif
         return -1;
     }
@@ -1475,5 +1558,8 @@
  
         // start retransmission timer
-        socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT );
+        alarm_start( client_xp,
+                     hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT,
+                     &socket_alarm_handler,
+                     socket_xp );
 
 #if DEBUG_SOCKET_CONNECT
@@ -1494,6 +1580,6 @@
 #endif
 
-        // stop retransmission timer
-        socket_alarm_stop();
+        // stop retransmission timer in thread descriptor
+        alarm_stop( client_xp );
 
         // get socket state, tx_valid and tx_sts
@@ -1507,10 +1593,13 @@
 
         // reset socket.tx_client
-        hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );
+        hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );
 
         if( cmd_status != CMD_STS_SUCCESS )
         {
-            printk("\n[ERROR] in %s : for command TX_CONNECT / socket[%x,%d] / thread[%x,%x]\n",
-            __FUNCTION__, pid, fdid, pid, trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s reported by server / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, pid, fdid, pid, trdid, cycle );
+#endif
             return -1;
         }
@@ -1548,4 +1637,8 @@
     trdid_t      trdid     = this->trdid;
 
+#if DEBUG_SOCKET_CLOSE || DEBUG_SOCKET_ERROR
+uint32_t cycle = (uint32_t)hal_get_cycles();
+#endif
+
     // get pointers on socket descriptor
     cxy_t        file_cxy   = GET_CXY( file_xp );
@@ -1558,5 +1651,4 @@
 
 #if DEBUG_SOCKET_CLOSE
-uint32_t cycle = (uint32_t)hal_get_cycles();
 if (DEBUG_SOCKET_CLOSE < cycle )
 printk("\n[%s] thread[%x,%x] enters for socket[%x,%d] / cycle %d\n",
@@ -1574,9 +1666,10 @@
         (hal_remote_l64( XPTR( file_cxy , &socket_ptr->tx_client)) != XPTR_NULL) )
     { 
-        // release socket lock
+                    
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, pid, fdid, pid, trdid, cycle );
+#endif
         remote_queuelock_release( socket_lock_xp );
-                    
-        printk("\n[ERROR] in %s : previous TX cmd on socket[%x,%d] / thread[%x,%x]\n",
-        __FUNCTION__, pid, fdid, pid, trdid );
         return -1;
     }
@@ -1645,5 +1738,8 @@
 
         // start retransmission timer
-        socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT );
+        alarm_start( client_xp,
+                     hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT,
+                     &socket_alarm_handler,
+                     socket_xp );
 
 #if DEBUG_SOCKET_CLOSE
@@ -1663,6 +1759,6 @@
 __FUNCTION__, pid, trdid, pid, fdid, cycle );
 #endif
-        // stop retransmission timer
-        socket_alarm_stop();
+        // stop retransmission timer in thread descriptor
+        alarm_stop( client_xp );
 
         // take socket lock
@@ -1674,17 +1770,19 @@
         cmd_valid    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid ) );
 
-assert( __FUNCTION__, (((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS))
-         && (cmd_valid == false)),
-"illegal socket state when client thread resumes after TX_CLOSE\n"
-" socket_state = %s / cmd_status = %d / cmd_valid = %d\n",
+assert( __FUNCTION__,
+(((socket_state == TCP_STATE_CLOSED) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
+" socket_state = %s / cmd_status = %d / cmd_valid = %d",
 socket_state_str(socket_state), cmd_status, cmd_valid );
 
         // reset socket.tx_client
-        hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );
+        hal_remote_s64( XPTR( file_cxy , &socket_ptr->tx_client ) , XPTR_NULL );
 
         if( cmd_status != CMD_STS_SUCCESS )  // error reported
         {
-            printk("\n[ERROR] in %s for command TX_CLOSE / socket[%x,%d] / thread[%x,%x]\n",
-            __FUNCTION__, pid, fdid, pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s for command TX_CLOSE / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, pid, fdid, pid, this->trdid, cycle );
+#endif
             return -1;
         }
@@ -1708,10 +1806,10 @@
 ////////////////////////////////////////////////////////////////////////////////////////
 // This static function is called by the two functions socket_send() & socket_recv().
-// It can be used for both UDP and TCP sockets.
+// It is used for both UDP and TCP sockets.
 ////////////////////////////////////////////////////////////////////////////////////////
 // @ is_send   : send when true / receive when false.
 // @ fdid      : socket identifier.
 // @ u_buf     : pointer on user buffer in user space.
-// @ length    : number of bytes.
+// @ length    : number of bytes in buffer.
 ////////////////////////////////////////////////////////////////////////////////////////
 // Implementation note : The behavior is different for SEND & RECV
@@ -1749,16 +1847,29 @@
     chdev_t           * chdev_ptr;
     cxy_t               chdev_cxy;
-    uint32_t            buf_status;      // number of bytes in rx_buf
     int32_t             moved_bytes;     // total number of moved bytes (fot return)
-    xptr_t              server_xp;       // extended pointer on NIC_TX / NIC_RX server thread
-    thread_t          * server_ptr;      // local pointer on NIC_TX / NIC_RX server thread
-    kmem_req_t          req;             // KCM request for TX kernel buffer
-    uint8_t           * tx_buf;          // kernel buffer for TX transfer
-    bool_t              cmd_valid;       // from socket descriptor
-    uint32_t            cmd_status;      // from socket descriptor
-    uint32_t            tx_todo;         // from socket descriptor
+    xptr_t              server_xp;       // ext pointer on NIC_TX / NIC_RX thread
+    thread_t          * server_ptr;      // local pointer on NIC_TX / NIC_RX thread
+    uint8_t           * tx_buf;          // pointer on kernel buffer for TX transfer
+    bool_t              cmd_valid;       // RX or TX command from socket descriptor
+    uint32_t            cmd_sts;         // RX or TX command from socket descriptor
+    uint32_t            tx_todo;         // number of bytes still to send
+    xptr_t              rx_buf_xp;       // extended pointer on socket rx_buf
+    uint32_t            rx_buf_sts;      // current status of socket rx_buf
 
     thread_t  * this    = CURRENT_THREAD;
     process_t * process = this->process;
+
+#if DEBUG_SOCKET_SEND || DEBUG_SOCKET_RECV || DEBUG_SOCKET_ERROR
+uint32_t cycle = (uint32_t)hal_get_cycles();
+#endif
+
+#if DEBUG_SOCKET_SEND || DEBUG_SOCKET_RECV 
+if( is_send )
+printk("\n[%s] thread[%x,%x] socket[%x,%d] enter : SEND / buf %x / length %d / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, process->pid, fdid, u_buf, length, cycle );
+else
+printk("\n[%s] thread[%x,%x] socket[%x,%d] enter : RECV / buf %x / length %d / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, process->pid, fdid, u_buf, length, cycle );
+#endif
 
     // build extended pointer on client thread
@@ -1772,6 +1883,9 @@
     if( file_xp == XPTR_NULL )
     {
-        printk("\n[ERROR] in %s : undefined fdid %d / thread%x,%x]\n",
-        __FUNCTION__, fdid , process->pid, this->trdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : undefined fdid %d / thread%x,%x] / cycle %d\n",
+__FUNCTION__, fdid , process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -1787,6 +1901,9 @@
     if( file_type != FILE_TYPE_SOCK )
     {
-        printk("\n[ERROR] in %s : illegal file type %s / socket[%x,%d]\n",
-        __FUNCTION__, vfs_inode_type_str(file_type), process->pid, fdid );
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : illegal file type thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, this->trdid, cycle );
+#endif
         return -1;
     }
@@ -1803,46 +1920,40 @@
     nic_channel  = hal_remote_l32( XPTR( file_cxy , &socket_ptr->nic_channel ));
 
-    /////////////
+    //////////////////////////////////////////////////////
     if( is_send )                       // SEND command
     {
 
 #if DEBUG_SOCKET_SEND
-uint32_t    cycle = (uint32_t)hal_get_cycles();
+cycle = (uint32_t)hal_get_cycles();
 if (DEBUG_SOCKET_SEND < cycle )
-printk("\n[%s] thread[%x,%x] received SEND command for socket[%x,%d] / length %d / cycle %d\n",
+printk("\n[%s] thread[%x,%x] / socket[%x,%d] get SEND / length %d / cycle %d\n",
 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle );
 #endif
+
         // check no previous TX command
-        if( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )) == true) || 
-            (hal_remote_l64( XPTR( file_cxy , &socket_ptr->tx_client)) != XPTR_NULL) )
+        if( hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid )) == true ) 
         { 
-            // release socket lock
+                    
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : previous TX command / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
+#endif
             remote_queuelock_release( socket_lock_xp );
-                    
-            printk("\n[ERROR] in %s : previous TX command / socket[%x,%d] / thread[%x,%x]\n",
-            __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
             return -1;
         }
 
-        // allocate a temporary kernel buffer
-        req.type  = KMEM_KCM;
-        req.order = bits_log2( length );
-        req.flags = AF_NONE;
-        tx_buf    = kmem_alloc( &req );  
-
-        if( tx_buf == NULL )
-        {
-            // release socket lock
-            remote_queuelock_release( socket_lock_xp );
-                    
-            printk("\n[ERROR] in %s : no memory for tx_buf / socket[%x,%d] / thread[%x,%x]\n",
-            __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
-            return -1;
-        }
-
-        // copy data from user u_buf to kernel tx_buf   
-        hal_copy_from_uspace( XPTR( local_cxy , tx_buf ),
+        // get tx_buf pointer from socket pointer
+        tx_buf = (uint8_t*)hal_remote_lpt( XPTR( file_cxy , &socket_ptr->tx_buf ));
+
+        // copy data from user u_buf to kernel socket tx_buf   
+        hal_copy_from_uspace( XPTR( file_cxy , tx_buf ),
                               u_buf,
                               length );
+#if DEBUG_SOCKET_SEND
+if (DEBUG_SOCKET_SEND < cycle )
+printk("\n[%s] thread[%x,%x] / socket[%x,%d] copied %d bytes to tx_buf (%x,%x)\n",
+__FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, file_cxy, tx_buf );
+putb("tx_buf : 16 first data bytes" , tx_buf , 16 ); 
+#endif
 
         // register command in socket descriptor
@@ -1852,4 +1963,5 @@
         hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_len    ) , length );
         hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_todo   ) , length );
+        hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_ack    ) , 0 );
         hal_remote_s32( XPTR( file_cxy , &socket_ptr->tx_valid  ) , true );
 
@@ -1869,12 +1981,17 @@
         thread_unblock( server_xp , THREAD_BLOCKED_CLIENT );
 
-        // start retransmission timer
-        socket_alarm_start( socket_xp , TCP_RETRANSMISSION_TIMEOUT );
+        // start retransmission timer for TCP socket
+        if( socket_type == SOCK_STREAM )  
+        {
+            alarm_start( client_xp,
+                         hal_get_cycles() + CONFIG_SOCK_RETRY_TIMEOUT,
+                         &socket_alarm_handler,
+                         socket_xp );
+        }
 
 #if DEBUG_SOCKET_SEND   
-cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_SEND < cycle )
-printk("\n[%s] thread[%x,%x] socket[%x,%d] register SEND => blocks on <IO> / cycle %d\n",
-__FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
+printk("\n[%s] thread[%x,%x] / socket[%x,%d] registers SEND => blocks on <IO>\n",
+__FUNCTION__, process->pid, this->trdid, process->pid, fdid );
 #endif
         // client thread blocks itself and deschedules
@@ -1885,11 +2002,14 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_SEND < cycle )
-printk("\n[%s] thread[%x,%x] socket[%x,%d] for SEND resumes / cycle %d\n",
+printk("\n[%s] thread[%x,%x] / socket[%x,%d] resumes for SEND / cycle %d\n",
 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
 #endif
-        // stop retransmission timer
-        socket_alarm_stop();
-
-        // take socket lock
+        // stop retransmission timer for TCP socket
+        if( socket_type == SOCK_STREAM )
+        {
+            alarm_stop( client_xp );
+        }
+
+        // take socket lock 
         remote_queuelock_acquire( socket_lock_xp );
       
@@ -1897,5 +2017,5 @@
         tx_todo    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_todo ));
         cmd_valid  = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_valid ));
-        cmd_status = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_sts ));
+        cmd_sts    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->tx_sts ));
 
         // reset tx_client in socket descriptor
@@ -1906,21 +2026,15 @@
       
 // check SEND command completed when TX client thread resumes
-assert( __FUNCTION__, (((tx_todo == 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
-"illegal socket state when client thread resumes after TX_SEND\n"
-" tx_todo = %d / tx_status = %d / tx_valid = %d\n",
-tx_todo, cmd_status, cmd_valid );
-
-        // release the tx_buf
-        req.ptr = tx_buf;
-        kmem_free( &req );
-
-        if( cmd_status != CMD_STS_SUCCESS )
+assert( __FUNCTION__, 
+(((tx_todo == 0) || (cmd_sts != CMD_STS_SUCCESS)) && (cmd_valid == false)),
+"client thread resumes from SEND / bad state : tx_todo %d / tx_sts %d / tx_valid %d",
+tx_todo, cmd_sts, cmd_valid );
+
+        if( cmd_sts != CMD_STS_SUCCESS )
         {
 
-#if DEBUG_SOCKET_SEND
-cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_SOCKET_RECV < cycle )
-printk("\n[%s] error %s for TX_SEND / socket[%x,%d] / thread[%x,%x]\n",
-__FUNCTION__, socket_cmd_sts_str(cmd_status), process->pid, fdid, process->pid, this->trdid );
+#if DEBUG_SOCKET_ERROR    
+printk("\n[ERROR] in %s : reported for SEND / socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
 #endif
             return -1;
@@ -1932,5 +2046,5 @@
 cycle = (uint32_t)hal_get_cycles();
 if (DEBUG_SOCKET_SEND < cycle )
-printk("\n[%s] thread[%x,%x] success for SEND / socket[%x,%d] / length %d / cycle %d\n",
+printk("\n[%s] thread[%x,%x] SEND success / socket[%x,%d] / bytes %d / cycle %d\n",
 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle );
 #endif
@@ -1940,23 +2054,22 @@
     }  // end SEND command
 
-    ////
-    else                                 // RECV command
+    /////////////////////////////////////////////////////////////
+    else                                       // RECV command
     {
 
 #if DEBUG_SOCKET_RECV
-uint32_t    cycle = (uint32_t)hal_get_cycles();
-if (DEBUG_SOCKET_SEND < cycle )
-printk("\n[%s] thread[%x,%x] received RECV command for socket[%x,%d] / length %d / cycle %d\n",
+if (DEBUG_SOCKET_RECV < cycle )
+printk("\n[%s] thread[%x,%x] / socket[%x,%d] get RECV / length %d / cycle %d\n",
 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, length, cycle );
 #endif
         // check no previous RX command
-        if( (hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )) == true) || 
-            (hal_remote_l64( XPTR( file_cxy , &socket_ptr->rx_client)) != XPTR_NULL) )
+        if( hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid )) == true )
         {
-            // release socket lock
+                    
+#if DEBUG_SOCKET_ERROR    
+printk("\n[ERROR] in %s : previous RX command on socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
+#endif
             remote_queuelock_release( socket_lock_xp );
-                    
-            printk("\n[ERROR] in %s : previous RX command on socket[%x,%d] / thread[%x,%x]\n",
-            __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
             return -1;
         }
@@ -1969,18 +2082,20 @@
                     
 #if DEBUG_SOCKET_RECV  
-uint32_t cycle = (uint32_t)hal_get_cycles();
+cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_RECV < cycle )
-printk("\n[%s] thread[%x,%x] socket[%x,%d] TCP connection closed / cycle %d\n",
+printk("\n[%s] thread[%x,%x] / socket[%x,%d] TCP connection closed / cycle %d\n",
 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
 #endif
             return 0;
         }
-        // build extended pointer on socket.rx_buf
-        xptr_t rx_buf_xp   = XPTR( file_cxy , &socket_ptr->rx_buf );
-
-        // get rx_buf status
-        buf_status = remote_buf_status( rx_buf_xp );
-
-        if( buf_status == 0 )
+
+        // build extended pointer on socket rx_buf
+        rx_buf_xp = XPTR( file_cxy , &socket_ptr->rx_buf );
+
+        // get socket rx_buf status
+        rx_buf_sts = remote_buf_status( rx_buf_xp );
+
+        // register RECV command and deschedule when rx_buf empty
+        if( rx_buf_sts == 0 )
         {
             // registers RX_RECV command in socket descriptor
@@ -1993,8 +2108,7 @@
 
 #if DEBUG_SOCKET_RECV  
-uint32_t cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_RECV < cycle )
-printk("\n[%s] thread[%x,%x] socket[%x,%d] rx_buf empty => blocks on <IO> / cycle %d\n",
-__FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
+printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV : rx_buf empty => blocks on <IO>\n",
+__FUNCTION__, process->pid, this->trdid, process->pid, fdid );
 #endif
             // client thread blocks itself and deschedules
@@ -2005,5 +2119,5 @@
 cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_RECV < cycle )
-printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV resumes / cycle %d\n",
+printk("\n[%s] thread[%x,%x] socket[%x,%d] for RECV : resumes / cycle %d\n",
 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, cycle );
 #endif
@@ -2011,50 +2125,53 @@
             remote_queuelock_acquire( socket_lock_xp );
 
-            // get rx_sts and rx_buf status
+            // get command status, command valid, and rx_buf status
             cmd_valid  = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_valid ));
-            cmd_status = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_sts ));
-            buf_status = remote_buf_status( rx_buf_xp );
+            cmd_sts    = hal_remote_l32( XPTR( file_cxy , &socket_ptr->rx_sts ));
+            rx_buf_sts = remote_buf_status( rx_buf_xp );
         
-assert( __FUNCTION__, (((buf_status != 0) || (cmd_status != CMD_STS_SUCCESS)) && (cmd_valid == false)),
-"illegal socket state when client thread resumes after RX_RECV\n"
-" buf_status = %d / rx_sts = %d / rx_valid = %d\n",
-buf_status , cmd_status , cmd_valid );
-
-            // reset rx_client in socket descriptor
-            hal_remote_s64( XPTR( file_cxy , &socket_ptr->rx_client  ) , XPTR_NULL );
-
-            // reset rx_buf for an UDP socket
-            if( socket_type == SOCK_DGRAM ) remote_buf_reset( rx_buf_xp );
-
-            // release socket lock
-            remote_queuelock_release( socket_lock_xp );
-
-            if( cmd_status == CMD_STS_EOF )           // EOF (remote close) reported
+assert( __FUNCTION__, (cmd_valid == false),
+"client thread resumes from RECV but rx_valid is true" );
+
+            if( cmd_sts == CMD_STS_EOF )           // EOF reported by RX server
             {
 
 #if DEBUG_SOCKET_RECV
-cycle = (uint32_t)hal_get_cycles();
 if( DEBUG_SOCKET_RECV < cycle )
-printk("\n[%s] EOF for RX_RECV / socket[%x,%d] / thread[%x,%x]\n",
+printk("\n[%s] EOF received for socket[%x,%d] / thread[%x,%x]\n",
 __FUNCTION__, process->pid, fdid, process->pid, this->trdid );
 #endif
+                // release socket lock
+                remote_queuelock_release( socket_lock_xp );
+
                 return 0;
             }
-            else if( cmd_status != CMD_STS_SUCCESS )   // other error reported
+            else if( cmd_sts != CMD_STS_SUCCESS )   // error reported by RX server
             {
 
-#if DEBUG_SOCKET_RECV
-cycle = (uint32_t)hal_get_cycles();
-if( DEBUG_SOCKET_RECV < cycle )
-printk("\n[%s] error %s for RX_RECV / socket[%x,%d] / thread[%x,%x]\n",
-__FUNCTION__, socket_cmd_sts_str(cmd_status), process->pid, fdid, process->pid, this->trdid );
-#endif
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : rx_server for socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
+#endif
+                // release socket lock
+                remote_queuelock_release( socket_lock_xp );
+
                 return -1;
             }
-
+            else if( rx_buf_sts == 0 )              // annormally empty rx_buf
+            {
+
+#if DEBUG_SOCKET_ERROR
+printk("\n[ERROR] in %s : rx_buf empty for socket[%x,%d] / thread[%x,%x] / cycle %d\n",
+__FUNCTION__, process->pid, fdid, process->pid, this->trdid, cycle );
+#endif
+                // release socket lock
+                remote_queuelock_release( socket_lock_xp );
+
+                return -1;
+            }
         }
 
         // number of bytes extracted from rx_buf cannot be larger than u_buf size
-        moved_bytes = ( length < buf_status ) ? length : buf_status;
+        moved_bytes = ( length < rx_buf_sts ) ? length : rx_buf_sts;
 
         // move data from kernel rx_buf to user u_buf
@@ -2062,10 +2179,13 @@
                                 u_buf,
                                 moved_bytes );
-#if DEBUG_SOCKET_SEND
-cycle = (uint32_t)hal_get_cycles();
-if (DEBUG_SOCKET_SEND < cycle )
-printk("\n[%s] thread[%x,%x] success for RECV / socket[%x,%d] / length %d / cycle %d\n",
+#if DEBUG_SOCKET_RECV
+cycle = (uint32_t)hal_get_cycles();
+if (DEBUG_SOCKET_RECV < cycle )
+printk("\n[%s] thread[%x,%x] : RECV success / socket[%x,%d] / bytes %d / cycle %d\n",
 __FUNCTION__, process->pid, this->trdid, process->pid, fdid, moved_bytes, cycle );
 #endif
+        // release socket lock
+        remote_queuelock_release( socket_lock_xp );
+
         return moved_bytes;
 
@@ -2095,8 +2215,37 @@
 } // end socket_recv()
 
+////////////////////////////////////
+int socket_sendto( uint32_t    fdid,
+                   uint8_t   * u_buf,
+                   uint32_t    length,
+                   uint32_t    remote_ip,
+                   uint16_t    remote_port )
+{
+    printk("\n[ERROR] in %s : this function is not implemented yet\n",
+    __FUNCTION__, fdid, u_buf, length, remote_ip, remote_port );
+    return -1;
+
+}  // end socket_sendto()
+
+//////////////////////////////////////
+int socket_recvfrom( uint32_t    fdid,
+                     uint8_t   * u_buf,
+                     uint32_t    length,
+                     uint32_t    remote_ip,
+                     uint16_t    remote_port )
+{
+    printk("\n[ERROR] in %s : this function is not implemented yet\n", 
+    __FUNCTION__, fdid, u_buf, length, remote_ip, remote_port );
+    return -1;
+
+} // end socket_recvfrom()
+
 ////////////////////////////////////////////
 void socket_display( xptr_t       socket_xp,
-                     const char * func_str )
-{
+                     const char * func_str,
+                     const char * string )
+{
+    uint32_t   cycle = (uint32_t)hal_get_cycles();
+
     socket_t * socket = GET_PTR( socket_xp );
     cxy_t      cxy    = GET_CXY( socket_xp );
@@ -2111,4 +2260,5 @@
     uint32_t   remote_port = hal_remote_l32( XPTR( cxy , &socket->remote_port ));
     uint32_t   tx_valid    = hal_remote_l32( XPTR( cxy , &socket->tx_valid ));
+    xptr_t     tx_client   = hal_remote_l64( XPTR( cxy , &socket->tx_client ));
     uint32_t   tx_cmd      = hal_remote_l32( XPTR( cxy , &socket->tx_cmd ));
     uint32_t   tx_sts      = hal_remote_l32( XPTR( cxy , &socket->tx_sts ));
@@ -2118,35 +2268,45 @@
     uint32_t   tx_nxt      = hal_remote_l32( XPTR( cxy , &socket->tx_nxt ));          
     uint32_t   tx_wnd      = hal_remote_l32( XPTR( cxy , &socket->tx_wnd ));          
+    uint32_t   tx_ack      = hal_remote_l32( XPTR( cxy , &socket->tx_ack ));          
     uint32_t   rx_valid    = hal_remote_l32( XPTR( cxy , &socket->rx_valid ));
+    xptr_t     rx_client   = hal_remote_l64( XPTR( cxy , &socket->rx_client ));
     uint32_t   rx_cmd      = hal_remote_l32( XPTR( cxy , &socket->rx_cmd ));
     uint32_t   rx_sts      = hal_remote_l32( XPTR( cxy , &socket->rx_sts ));
     uint32_t   rx_nxt      = hal_remote_l32( XPTR( cxy , &socket->rx_nxt ));          
     uint32_t   rx_wnd      = hal_remote_l32( XPTR( cxy , &socket->rx_wnd ));          
-    uint32_t   rx_irs      = hal_remote_l32( XPTR( cxy , &socket->rx_irs ));          
-
-    if( func_str == NULL )
-    {
-        printk("\n****** socket[%x,%d] / xptr[%x,%x]*****\n",
-        pid, fdid, cxy, socket );
+    uint32_t   rx_irs      = hal_remote_l32( XPTR( cxy , &socket->rx_irs ));  
+
+    remote_queuelock_t * lock_ptr = &socket->lock;  
+    uint32_t   taken       = hal_remote_l32( XPTR( cxy , &lock_ptr->taken ));
+
+    thread_t * tx_ptr = GET_PTR( tx_client );
+    cxy_t      tx_cxy = GET_CXY( tx_client );
+    trdid_t    tx_tid = hal_remote_l32( XPTR( tx_cxy , &tx_ptr->trdid ));
+
+    thread_t * rx_ptr = GET_PTR( rx_client );
+    cxy_t      rx_cxy = GET_CXY( rx_client );
+    trdid_t    rx_tid = hal_remote_l32( XPTR( rx_cxy , &rx_ptr->trdid ));
+
+    if( string == NULL )
+    {
+        printk("\n****** socket[%x,%d] / lock %d / in %s / cycle %d *****\n",
+        pid, fdid, taken, func_str, cycle );
     }
     else
     {
-        printk("\n***** socket[%x,%d] / xptr[%x,%x] / from %s *****\n",
-        pid, fdid, cxy, socket, func_str );
-    }
-    printk(" - state %s / channel %d\n"
-           " - local_addr %x / local_port %x\n"
-           " - remote_addr %x / remote_port %x\n"
-           " - tx_valid %d (%s) / tx_sts %d / tx_len %x / tx_todo %x\n"
-           " - tx_una %x / tx_nxt %x / tx_wnd %x\n"
-           " - rx_valid %d (%s) / rx_sts %d\n"
-           " - rx_nxt %x / rx_wnd %x / rx_irs %x\n",
-           socket_state_str(state), channel ,
-           local_addr, local_port,
-           remote_addr, remote_port,
-           tx_valid, socket_cmd_type_str(tx_cmd), tx_sts, tx_len, tx_todo,
-           tx_una, tx_nxt, tx_wnd,
-           rx_valid, socket_cmd_type_str(rx_cmd), rx_sts,
-           rx_nxt, rx_wnd, rx_irs );
+        printk("\n***** socket[%x,%d] / lock %d / in %s %s / cycle %d *****\n",
+        pid, fdid, taken, func_str, string, cycle );
+    }
+    printk(" - state %s / channel %d / local [%x,%x] / remote[%x,%x]\n"
+           " - tx : valid %d / client [%x,%x] / cmd %s \n"
+           "        sts %d / len %x / todo %x / ack %x / una %x / nxt %x / wnd %x\n"
+           " - rx : valid %d / client [%x,%x] / cmd %s\n"
+           "        sts %d / nxt %x / wnd %x / irs %x\n",
+           socket_state_str(state), channel, 
+           local_addr, local_port, remote_addr, remote_port,
+           tx_valid, pid, tx_tid, socket_cmd_type_str(tx_cmd),
+           tx_sts, tx_len, tx_todo, tx_ack, tx_una, tx_nxt, tx_wnd,
+           rx_valid, pid, rx_tid, socket_cmd_type_str(rx_cmd),
+           rx_sts, rx_nxt, rx_wnd, rx_irs );
 
 }  // end socket_display()
