コード例 #1
0
/**
*  callback associated with the socket controller for receiving a
   RPC message on a AF_UNIX socket operating of datagram mode

  @param socket_pointer: pointer to the socket context
  @param socketId: reference of the socket--> not used

*/
uint32_t af_unix_recv_rpc_stream_generic_cbk(void * socket_pointer,int socketId)
{

  af_unix_ctx_generic_t  *sock_p = (af_unix_ctx_generic_t*)socket_pointer;
  com_recv_template_t    *recv_p;
  uint16_t               recv_credit;
  void                  *buf_recv_p = NULL;
  int                    full_msg_len;
  uint32_t               payloadLen;
  uint8_t               *payload_p;
  uint32_t               status;
  uint32_t              *record_len_p;
  int                    len_read;
  void *bufref = NULL;
  com_rpc_recv_template_t  *rpc;
  /*
  ** set the credit, notice that the credit is decremented upon reception
  ** of a full message
  */
  recv_p = &sock_p->recv;
  recv_credit = recv_p->recv_credit_conf;
  rpc = &recv_p->rpc;

  while(recv_credit != 0)
  {
    switch (recv_p->state)
    {
      /*
      ** There is no recepition in progress
      */
      case RECV_IDLE:
        rpc->last_record   = 0;
        rpc->record_len    = 0;     
        rpc->in_tot_len    = 0;
        rpc->in_wr_offset  = 0; 
     
        recv_p->nbread = 0;
        recv_p->nb2read = recv_p->headerSize;
        recv_p->bufRefCurrent = NULL;
        recv_p->state = RECV_WAIT_HDR;
        break;
      /*
      **_________________________________________________________________
      ** Waiting for the header before allocating the receive buffer
      **_________________________________________________________________
      */
      case RECV_WAIT_HDR:
        /*
        ** attempt to receive the full header to figure out what kind of receive buffer
        ** Must be allocated
        */
        status = af_unix_recv_stream_sock_recv(sock_p,recv_p->buffer_header+recv_p->nbread,
                                               recv_p->nb2read- recv_p->nbread ,0,&len_read);
        switch(status)
        {
          case RUC_OK:
           /*
           ** that's fine : go to the next step to figure out what kind of buffer can be allocated
           */
           sock_p->stats.totalRecvBytes += len_read;
           if (recv_p->bufRefCurrent == NULL)
           {
             /*
             ** buffer has not be yet allocated
             */
             recv_p->state = RECV_ALLOC_BUF;
           }
           else
           {
             /*
             ** Buffer has already been alllocated, so it is not the fisrt received record
             ** get the header of the RPC record in order to extract the length and the type
             ** of the rpc message.
             ** The current length of the rpc record is added with the total length.
             ** Since it is not the first record, the system does not store in the receive 
             ** buffer the first 4 bytes of the rpc record. This is done for the first
             ** record only.
             */
             record_len_p = (uint32_t *)recv_p->buffer_header;    
             rpc->record_len = ntohl(*record_len_p);
             if (rpc->record_len & (~0x7fffffff)) {
	       rpc->last_record = 1;
	     }
             rpc->record_len  &= 0x7fffffff;
             rpc->in_tot_len  += rpc->record_len;           
             if ((rpc->in_tot_len+recv_p->headerSize) > rpc->max_receive_sz)
             {
                /*
                ** release the buffer
                */
                bufref = recv_p->bufRefCurrent;
                recv_p->bufRefCurrent = NULL;
                ruc_buf_freeBuffer(bufref);
                /*
                ** general disconnection
                */
                af_unix_sock_stream_disconnect_internal(sock_p);
                recv_p->state = RECV_DEAD;
                sock_p->stats.totalRecvBadHeader++;
                /*
                ** the length is wrong, we have no choice we need to close the connection
                */
                (sock_p->userDiscCallBack)(sock_p->userRef,sock_p->index,NULL,errno);


                return TRUE;
             }
             /*
             ** set the number of bytes to read and already read
             */
             recv_p->nbread = 0;
             recv_p->nb2read = rpc->record_len;    
             /*
             ** now read the payload of the record
             */
             recv_p->state = RECV_PAYLOAD;
       
           }
           break;

          case RUC_WOULDBLOCK:
           /*
           ** we don't get the full header so no change, wait for the next receiver event
           */
	   sock_p->stats.emptyRecv++;
           return TRUE;

          case RUC_PARTIAL:
          /*
          ** update the count and re-attempt until getting a EAGAIN or a full header
          */
	  sock_p->stats.partialRecv++;
          sock_p->stats.totalRecvBytes += len_read;
          recv_p->nbread += len_read;
          break;

          default:
          case RUC_DISC:
         /*
          ** general disconnection
          */
          af_unix_sock_stream_disconnect_internal(sock_p);
          /*
          ** socket is dead call the user callback
          */
          recv_p->state = RECV_DEAD;
//          warning("af_unix_recv_stream_generic_cbk:%s",strerror(errno));
          (sock_p->userDiscCallBack)(sock_p->userRef,sock_p->index,NULL,errno);
 
          return TRUE;
        }
      break;

      /*
      **_________________________________________________________________
      ** allocate a receive buffer according to the length of the message
      **_________________________________________________________________
      */
      case RECV_ALLOC_BUF:      
        /*
        ** store the total length of the message
        */
        record_len_p = (uint32_t *)recv_p->buffer_header;    
        rpc->record_len = ntohl(*record_len_p);
        if (rpc->record_len & (~0x7fffffff)) rpc->last_record = 1;
        rpc->record_len  &= 0x7fffffff;
        /*
        ** check if the message does not exceed the max buffer size
        */
        if (rpc->last_record == 0)
        {
          /*
          ** assume max length
          */
          full_msg_len = rpc->max_receive_sz;        
        }
        else
        {
           full_msg_len = rpc->record_len + recv_p->headerSize;
        }
        if (full_msg_len > rpc->max_receive_sz)
        {
           /*
           ** general disconnection: purge the xmit side
           */
           af_unix_sock_stream_disconnect_internal(sock_p);
           recv_p->state = RECV_DEAD;
           sock_p->stats.totalRecvBadHeader++;           /*
           ** the length is wrong, we have no choice we need to close the connection
           */
           (sock_p->userDiscCallBack)(sock_p->userRef,sock_p->index,NULL,errno);


           return TRUE;
        }
        /*
        ** Ok now call the application for receive buffer allocation
        */
        if (sock_p->userRcvAllocBufCallBack != NULL)
        {
           buf_recv_p = (sock_p->userRcvAllocBufCallBack)(sock_p->userRef,sock_p->index,full_msg_len);
        }
        else
        {
           fatal("Alloc Buffer callback is mandatory for rpc service");
        }
        if (buf_recv_p == NULL)
        {
          /*
          ** the receiver is out of buffer-> leave the message in the receiver queue and exit
          */
          sock_p->stats.totalRecvOutoFBuf++;
          recv_p->state = RECV_ALLOC_BUF;
          return TRUE;
        }
        /*
        ** set the payload length in the buffer
        */
        rpc->in_tot_len  += rpc->record_len;
        payloadLen = rpc->record_len;       
        
        ruc_buf_setPayloadLen(buf_recv_p,(uint32_t)(payloadLen + recv_p->headerSize));
        /*
        ** Ok now start receiving the payload
        */
        recv_p->nbread = recv_p->headerSize;
        recv_p->nb2read = recv_p->headerSize+payloadLen;
        recv_p->bufRefCurrent = buf_recv_p;
        payload_p = (uint8_t*)ruc_buf_getPayload(recv_p->bufRefCurrent);
        /*
        ** copy the already received bytes in the allocated received buffer
        */
        memcpy(payload_p,recv_p->buffer_header,recv_p->headerSize);
        recv_p->state = RECV_PAYLOAD;
        break;


      /*
      **_________________________________________________________________
      ** reception of the payload of the message
      **_________________________________________________________________
      */
      case RECV_PAYLOAD:
        /*
        ** attempt to receive the full header to figure out what kind of receive buffer
        ** Must be allocated
        */
        payload_p = (uint8_t*)ruc_buf_getPayload(recv_p->bufRefCurrent);
        status = af_unix_recv_stream_sock_recv(sock_p,payload_p+rpc->in_wr_offset+recv_p->nbread,
                                               recv_p->nb2read- recv_p->nbread ,0,&len_read);
        switch(status)
        {
          case RUC_OK:
	   /*
	   ** update the speculative scheduler
	   */
	   ruc_sockCtrl_speculative_scheduler_decrement(sock_p->connectionId);
           /*
           ** that fine's call the application with that received message
           */
           sock_p->stats.totalRecvBytes += len_read;
           sock_p->stats.totalRecvSuccess++;
           recv_p->nbread += len_read;
	   
           /*
           ** Check if it is the last record: in such a case we deliver the rpc message 
           ** to the application
           */
           if (rpc->last_record)
           {
             /*
             ** clear the reference of the buffer to avoid a double release that may occur
             ** if the application delete the context
             ** Update the first length header of the rpc message with the total length of the
             ** RPC message
             */
             bufref = recv_p->bufRefCurrent;
             recv_p->bufRefCurrent = NULL;
             ruc_buf_setPayloadLen(bufref,(uint32_t)(rpc->in_tot_len + recv_p->headerSize));
             record_len_p = (uint32_t *)payload_p;  
             *record_len_p = htonl((rpc->in_tot_len) | 0x80000000);                          
             (sock_p->userRcvCallBack)(sock_p->userRef,sock_p->index,bufref);
             recv_p->state = RECV_IDLE;
             recv_credit--;
             break;
           }
           /*
           ** not the last record:
           ** udpate the in_wr_offset with the current record length and prepare to receive
           ** the next record
           */
           rpc->in_wr_offset+= recv_p->nbread; 
           recv_p->nbread = 0;
           recv_p->nb2read = recv_p->headerSize;	             
           recv_p->state = RECV_WAIT_HDR;
           break;

          case RUC_WOULDBLOCK:
           /*
           ** we don't get the full message so no change, wait for the next receiver event
           */
	   sock_p->stats.emptyRecv++;
           return TRUE;

          case RUC_PARTIAL:
          /*
          ** update the count and re-attempt until getting a EAGAIN or a full header
          */
	  sock_p->stats.partialRecv++;
          sock_p->stats.totalRecvBytes += len_read;
          recv_p->nbread += len_read;
          break;

          case RUC_DISC:
          default:
          /*
          ** socket is dead call the user callback
          */
          bufref = recv_p->bufRefCurrent;
          recv_p->bufRefCurrent = NULL;
          ruc_buf_freeBuffer(bufref);
           /*
          ** general disconnection
          */
          af_unix_sock_stream_disconnect_internal(sock_p);
          /*
          ** it is up to the application to release the buffer if the error is fatal
          ** but for the case of the receiver, no buffer reference is provided
          */
          recv_p->state = RECV_DEAD;
          (sock_p->userDiscCallBack)(sock_p->userRef,sock_p->index,NULL,errno);

          return TRUE;
        }
        break;
      /*
      **_________________________________________________________________
      ** Dead state of the receiver
      **_________________________________________________________________
      */
      case RECV_DEAD:
        return TRUE;
    }
  }
  return TRUE;
}
コード例 #2
0
 /*
**__________________________________________________________________________
*/
void af_unix_send_stream_fsm(af_unix_ctx_generic_t *socket_p,com_xmit_template_t *xmit_p)
{
  char *pbuf;
  int write_len;
  int ret;
  int inuse;

  while(1)
  {

    switch (xmit_p->state)
    {
      case XMIT_READY:
      /*
      ** the transmitter is ready to send however we need to double if there is a
      ** current buffer to send (because we just exit from congestion or if there
      ** some buffer in the xmit pending queue
      */
      /*
      ** Check if there is a current buffer to send
      */
      if (xmit_p->bufRefCurrent != NULL)
      {
         write_len  = (int)ruc_buf_getPayloadLen(xmit_p->bufRefCurrent);
         /*
         ** Get the reference of the destination socket (name) from the ruc_buffer)
         */
         xmit_p->nbWrite  = 0;
         xmit_p->nb2Write = write_len;
         xmit_p->state = XMIT_IN_PRG;
      }
      else
      {
        /*
        ** nothing to send !!
        */
        return;
      }
      break;

      case XMIT_IN_PRG:

        /*
        ** Check if there is a current buffer to send
        */
        socket_p->stats.totalXmitAttempts++;
        pbuf = (char *)ruc_buf_getPayload(xmit_p->bufRefCurrent);

        ret  = af_unix_send_stream_generic(socket_p->socketRef,pbuf+xmit_p->nbWrite,xmit_p->nb2Write - xmit_p->nbWrite, &write_len);

        switch (ret)
        {
          case RUC_OK:
          /*
          ** release the buffer that has been sent
          */
          xmit_p->xmit_credit++;
          inuse = ruc_buf_inuse_decrement(xmit_p->bufRefCurrent);
          if (inuse < 0)
          {
            /*
	    ** inuse MUST never be negative so EXIT !!!!!
	    */
            fatal("Inuse is negative %d",inuse);
          }
          if (socket_p->userXmitDoneCallBack != NULL)
          {
             /*
             ** caution: in that case it is up to the application that provides the callback to release
             ** the xmit buffer
             */
	         if (ruc_buf_get_opaque_ref(xmit_p->bufRefCurrent) == socket_p) 
             {
                   (socket_p->userXmitDoneCallBack)(socket_p->userRef,socket_p->index,xmit_p->bufRefCurrent);
	         }
	         else 
             {
                if (inuse == 1) 
                {
                  /*
                  ** need an obj remove since that buffer might still queue somewhere : typically
                  ** in the xmit list of a load balacner entry.
                  */
                  ruc_objRemove((ruc_obj_desc_t*)xmit_p->bufRefCurrent);
                  ruc_buf_freeBuffer(xmit_p->bufRefCurrent);	
                }        
	         }  
          }
          else
          {
            if (inuse == 1) 
            {
              ruc_objRemove((ruc_obj_desc_t*)xmit_p->bufRefCurrent);
              ruc_buf_freeBuffer(xmit_p->bufRefCurrent);
            }
          }
          xmit_p->bufRefCurrent = NULL;
          xmit_p->nbWrite  = 0;
          xmit_p->nb2Write = 0;
          socket_p->stats.totalXmitSuccess++;
          socket_p->stats.totalXmitBytes += write_len;
          xmit_p->state = XMIT_CHECK_XMITQ;
          break;

          case RUC_PARTIAL:
          /*
          ** need to re-attempt writing
          */
          xmit_p->nbWrite  += write_len;
          socket_p->stats.totalXmitBytes += write_len;
          break;

          case RUC_WOULDBLOCK:
          /*
          ** the socket is congested-> so exit
          */
          socket_p->stats.totalXmitCongested++;
          xmit_p->congested_flag = 1;
          xmit_p->eoc_flag       = 0;
          xmit_p->eoc_threshold  = AF_UNIX_CONGESTION_DEFAULT_THRESHOLD;
          xmit_p->state = XMIT_CONGESTED;
          return ;

          case RUC_DISC:
          /*
          ** something wrong on sending: if the user has a callback use it:
          ** the transmitter is no more the owner of the buffer
          */
          inuse = ruc_buf_inuse_decrement(xmit_p->bufRefCurrent);
          if (inuse < 0)
          {
            /*
	        * inuse MUST never be negative so EXIT !!!!!
	        */
            fatal("Inuse is negative %d",inuse);
          }
          socket_p->stats.totalXmitError++;
          if (socket_p->userDiscCallBack != NULL)
          {
            void *bufref = xmit_p->bufRefCurrent;
            xmit_p->bufRefCurrent = NULL;	     
            if (ruc_buf_get_opaque_ref(bufref) != socket_p) 
            {
              /*
              ** the buffer is affected to another socket, however it might possible
              ** that the real owner of the buffer has finished while the buffer is
              ** still used by that old connection. So it might be necessary to release
              ** the buffer.
              ** However in any case the application must not be inform that there was
              ** an issue while sendig that buffer since the connection is not considered
              ** anymore.
              */ 
              if (inuse == 1) 
              {
                ruc_objRemove((ruc_obj_desc_t*)bufref);
                ruc_buf_freeBuffer(bufref);
              }
              bufref = NULL;
            }
            /*
            ** it is up to the application to release the buffer if the error is fatal:
            ** caution the internal disconnection MUST be called before the application since
            ** the application might attempt to perform a direct re-connection
            */
            xmit_p->state = XMIT_DEAD;
            af_unix_sock_stream_disconnect_internal(socket_p);
            (socket_p->userDiscCallBack)(socket_p->userRef,socket_p->index,bufref,errno);
            return;
          }
          else
          {
              if (inuse == 1) 
              {
                ruc_objRemove((ruc_obj_desc_t*)xmit_p->bufRefCurrent);
                ruc_buf_freeBuffer(xmit_p->bufRefCurrent);
              }            
              xmit_p->bufRefCurrent = NULL;
          }
          /*
          ** general disconnection->need to clean the socket queue
          */
          xmit_p->state = XMIT_DEAD;
          af_unix_sock_stream_disconnect_internal(socket_p);
          return ;
          break;

        }
        break;

      case XMIT_CHECK_XMITQ:
        /*
        ** Check the xmit credit
        */
        if (xmit_p->xmit_credit >= xmit_p->xmit_credit_conf)
        {
          xmit_p->xmit_credit = 0;
          /*
          ** asser the flag to request a re-activation on the next run of the socket
          ** controller
          */
          xmit_p->xmit_req_flag = 1;
          return;
        }
        /*
        ** check if there is a pending buffer (case found if there was a previous congestion
        */
        if (xmit_p->bufRefCurrent != NULL)
        {
          /*
          * lest's go and send it
          */
          xmit_p->state =  XMIT_IN_PRG;
          break;
        }
        /*
        ** read the pending Xmit queue (only priority 0 is considered in the current implementation
        */
        xmit_p->bufRefCurrent = com_xmit_pendingQueue_get(xmit_p,0);
        if (xmit_p->bufRefCurrent == NULL)
        {
          /*
          ** queue is empty
          */
          xmit_p->xmit_credit = 0;
          xmit_p->state =  XMIT_READY;
          return;
        }
        /*
        ** OK, go back to send that new bufffer
        */
        ruc_buf_inuse_increment(xmit_p->bufRefCurrent);
        xmit_p->state =  XMIT_READY;
        break;


      case XMIT_CONGESTED:
        /*
        ** the transmitter is congested: check of the threshold has reached 0
        */
        xmit_p->eoc_threshold--;
        if (xmit_p->eoc_threshold == 0)
        {
           xmit_p->eoc_flag  = 1;
           xmit_p->congested_flag = 0;
           xmit_p->state = XMIT_IN_PRG;
           break;
        }
        return;

       case XMIT_DEAD:
        /*
        ** the transmitter is dead
        */
        return;

    }
  }
}
コード例 #3
0
/**
*  callback associated with the socket controller for receiving a
   message on a AF_UNIX socket operating of datagram mode

  @param socket_pointer: pointer to the socket context
  @param socketId: reference of the socket--> not used

*/
uint32_t af_unix_recv_stream_generic_cbk(void * socket_pointer,int socketId)
{

  af_unix_ctx_generic_t  *sock_p = (af_unix_ctx_generic_t*)socket_pointer;
  com_recv_template_t    *recv_p;
  uint16_t               recv_credit;
  void                  *buf_recv_p = NULL;
  int                    full_msg_len;
  uint32_t               payloadLen;
  uint8_t               *payload_p;
  uint32_t               status;
  int                    len_read;
  void *bufref = NULL;
  /*
  ** set the credit, notice that the credit is decremented upon reception
  ** of a full message
  */
  recv_p = &sock_p->recv;
  recv_credit = recv_p->recv_credit_conf;

  while(recv_credit != 0)
  {
    switch (recv_p->state)
    {
      /*
      ** There is no recepition in progress
      */
      case RECV_IDLE:
        recv_p->nbread = 0;
        recv_p->nb2read = recv_p->headerSize;
        recv_p->bufRefCurrent = NULL;
        recv_p->state = RECV_WAIT_HDR;
        break;
      /*
      **_________________________________________________________________
      ** Waiting for the header before allocating the receive buffer
      **_________________________________________________________________
      */
      case RECV_WAIT_HDR:
        /*
        ** attempt to receive the full header to figure out what kind of receive buffer
        ** Must be allocated
        */
        status = af_unix_recv_stream_sock_recv(sock_p,recv_p->buffer_header+recv_p->nbread,
                                               recv_p->nb2read- recv_p->nbread ,0,&len_read);
        switch(status)
        {
          case RUC_OK:
           /*
           ** that's fine : go to the next step to figure out what kind of buffer can be allocated
           */
           sock_p->stats.totalRecvBytes += len_read;
           recv_p->state = RECV_ALLOC_BUF;
           break;

          case RUC_WOULDBLOCK:
           /*
           ** we don't get the full header so no change, wait for the next receiver event
           */
	   sock_p->stats.emptyRecv++;
           return TRUE;

          case RUC_PARTIAL:
          /*
          ** update the count and re-attempt until getting a EAGAIN or a full header
          */
	  sock_p->stats.partialRecv++;
          sock_p->stats.totalRecvBytes += len_read;
          recv_p->nbread += len_read;
          break;

          default:
          case RUC_DISC:
          /*
          ** general disconnection
          */
          af_unix_sock_stream_disconnect_internal(sock_p);
          /*
          ** socket is dead call the user callback
          */
          recv_p->state = RECV_DEAD;
//          warning("af_unix_recv_stream_generic_cbk: %s",strerror(errno));
          (sock_p->userDiscCallBack)(sock_p->userRef,sock_p->index,NULL,errno);

          return TRUE;
        }
      break;

      /*
      **_________________________________________________________________
      ** allocate a receive buffer according to the length of the message
      **_________________________________________________________________
      */
      case RECV_ALLOC_BUF:
        if (sock_p->userHdrAnalyzerCallBack != NULL)
        {
           /*
           ** The applicaton has provide a callback for parsing its header and to extract the
           ** length of the payload-> Typically, it is mandatory for the case of the RPC since
           ** the field that contains the length has the bit 31 asserted
           */
           payloadLen = (sock_p->userHdrAnalyzerCallBack)((char*)recv_p->buffer_header);         

        }
        else
        {
          payloadLen = com_sock_extract_length_from_header_host_format((char*)recv_p->buffer_header,
                                                                       recv_p->msgLenOffset,
                                                                       recv_p->msgLenSize);
        }
        if (payloadLen == 0)
        {
           /*
           ** general disconnection
           */
           af_unix_sock_stream_disconnect_internal(sock_p);
           recv_p->state = RECV_DEAD;
           sock_p->stats.totalRecvBadHeader++;
           /*
           ** the length is wrong, we have no choice we need to close the connection
           */
           (sock_p->userDiscCallBack)(sock_p->userRef,sock_p->index,NULL,errno);


           return TRUE;
        }
        /*
        ** check if the message does not exceed the max buffer size
        */
        full_msg_len = payloadLen + recv_p->headerSize;
        if (full_msg_len > recv_p->bufSize)
        {
          /*
           ** general disconnection
           */
           af_unix_sock_stream_disconnect_internal(sock_p);
           recv_p->state = RECV_DEAD;
           sock_p->stats.totalRecvBadHeader++;           /*
           ** the length is wrong, we have no choice we need to close the connection
           */
           (sock_p->userDiscCallBack)(sock_p->userRef,sock_p->index,NULL,errno);
 
 
           return TRUE;
        }
        /*
        ** Ok now call the application for receive buffer allocation
        */
        if (sock_p->userRcvAllocBufCallBack != NULL)
        {
           buf_recv_p = (sock_p->userRcvAllocBufCallBack)(sock_p->userRef,sock_p->index,full_msg_len);
        }
        else
        {
          buf_recv_p = af_unix_alloc_recv_buf();
        }
        if (buf_recv_p == NULL)
        {
          /*
          ** the receiver is out of buffer-> leave the message in the receiver queue and exit
          */
          sock_p->stats.totalRecvOutoFBuf++;
          recv_p->state = RECV_ALLOC_BUF;
          return TRUE;
        }
        /*
        ** set the payload length in the buffer
        */
        ruc_buf_setPayloadLen(buf_recv_p,(uint32_t)(payloadLen + recv_p->headerSize));
        /*
        ** Ok now start receiving the payload
        */
        recv_p->nbread = recv_p->headerSize;
        recv_p->nb2read = recv_p->headerSize+payloadLen;
        recv_p->bufRefCurrent = buf_recv_p;
        payload_p = (uint8_t*)ruc_buf_getPayload(recv_p->bufRefCurrent);
        /*
        ** copy the already received bytes in the allocated received buffer
        */
        memcpy(payload_p,recv_p->buffer_header,recv_p->headerSize);
        recv_p->state = RECV_PAYLOAD;
        break;


      /*
      **_________________________________________________________________
      ** reception of the payload of the message
      **_________________________________________________________________
      */
      case RECV_PAYLOAD:
        /*
        ** attempt to receive the full header to figure out what kind of receive buffer
        ** Must be allocated
        */
        payload_p = (uint8_t*)ruc_buf_getPayload(recv_p->bufRefCurrent);
        status = af_unix_recv_stream_sock_recv(sock_p,payload_p+recv_p->nbread,
                                               recv_p->nb2read- recv_p->nbread ,0,&len_read);
        switch(status)
        {
          case RUC_OK:
	   /*
	   ** update the speculative scheduler
	   */
	   ruc_sockCtrl_speculative_scheduler_decrement(sock_p->connectionId);
           /*
           ** that fine's call the application with that received message
           */
           sock_p->stats.totalRecvBytes += len_read;
           sock_p->stats.totalRecvSuccess++;
           /*
           ** clear the reference of the buffer to avoid a double release that may occur
           ** if the application delete the context
           */
           bufref = recv_p->bufRefCurrent;
           recv_p->bufRefCurrent = NULL;
           (sock_p->userRcvCallBack)(sock_p->userRef,sock_p->index,bufref);
           recv_p->state = RECV_IDLE;
           recv_credit--;
           break;

          case RUC_WOULDBLOCK:
           /*
           ** we don't get the full message so no change, wait for the next receiver event
           */
	   sock_p->stats.emptyRecv++;
           return TRUE;

          case RUC_PARTIAL:
          /*
          ** update the count and re-attempt until getting a EAGAIN or a full header
          */
	  sock_p->stats.partialRecv++;
          sock_p->stats.totalRecvBytes += len_read;
          recv_p->nbread += len_read;
          break;

          case RUC_DISC:
          default:
          /*
          ** socket is dead call the user callback
          */
          bufref = recv_p->bufRefCurrent;
          recv_p->bufRefCurrent = NULL;
          ruc_buf_freeBuffer(bufref);
           /*
          ** general disconnection
          */
          af_unix_sock_stream_disconnect_internal(sock_p);

          /*
          ** it is up to the application to release the buffer if the error is fatal
          ** but for the case of the receiver, no buffer reference is provided
          */
          recv_p->state = RECV_DEAD;
          (sock_p->userDiscCallBack)(sock_p->userRef,sock_p->index,NULL,errno);

          return TRUE;
        }
        break;
      /*
      **_________________________________________________________________
      ** Dead state of the receiver
      **_________________________________________________________________
      */
      case RECV_DEAD:
        return TRUE;
    }
  }
  return TRUE;
}