view src/g23m-fad/tcpip/rnet/rnet_rt/rnet_rt_api_new.c @ 10:a8f9cc376e98

components: pruned import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 21:19:43 +0000
parents d393cd9bb723
children
line wrap: on
line source

/**
 * @file    rnet_rt_api_new.c
 *
 * RNET_RT API
 *
 * @author  Regis Feneon
 * @version 0.1
 */

/*
 * $Id: rnet_rt_api_new.c,v 1.4 2002/10/30 15:23:34 rf Exp $
 * $Name: ti_20021030 $
 *
 * History:
 *
 *  Date        Author        Modification
 *  --------------------------------------------------
 *  3/22/2002   Regis Feneon  Create
 *  6/24/2002   Regis Feneon  RNET_SEND_CFM renamed RNET_SEND_RDY
 *                            send this message when a connection
 *                            is accepted
 * (C) Copyright 2002 by TI, All Rights Reserved
 *
 */

#include "rnet_cfg.h"
#ifdef RNET_CFG_REAL_TRANSPORT

#include "rnet_rt_i.h"
#include "rnet_rt_env.h"
#include "rnet_message.h"


/*
 * Send a message back to the user using socket's return path
 */
static int socket_send_msg( NGsock *so, T_RV_HDR *msg)
{
  if( ((T_RNET_RT_SOCK *) so)->return_path.callback_func != NULL) {
    /* Send the message using callback function. */
    ((T_RNET_RT_SOCK *) so)->return_path.callback_func( msg);
    return( RV_OK);
  }
  else {
    /* Send the message using mailbox. */
    return( rvf_send_msg( ((T_RNET_RT_SOCK *) so)->return_path.addr_id, msg));
  }
}

NGsock *cach_so = NULL ; 

//pinghua add two function to avoid abormal sock close. OMAPS00173156 patch fix 05122008
void cach_sock_message(NGsock *so)
{

     cach_so = so ;
     return ; 	 

}

void Send_cach_message(void )
{

  union {
    T_RNET_ERROR_IND eind;
    T_RNET_CONNECT_IND cind;
    T_RNET_CONNECT_CFM ccfm;
    T_RNET_SEND_RDY srdy;
    T_RNET_RECV_IND rind;
  } *msg;

   if(cach_so==NULL)
   	return ; 
   if(cach_so->so_rcv_cc!=0)
   	return ; 
  
      RNET_RT_SEND_TRACE("RNET_RT: Send_cach_message close! ",RV_TRACE_LEVEL_ERROR);	
        if( rvf_get_msg_buf( rnet_rt_env_ctrl_blk_p->mb_id, sizeof(T_RNET_ERROR_IND),
           RNET_ERROR_IND, (T_RV_HDR **) &msg) == RVF_RED) {
          return ;
        }
        msg->eind.desc = (T_RNET_DESC *) cach_so;
        msg->eind.error = RNET_CONN_CLOSED;
        socket_send_msg( cach_so, (T_RV_HDR *) msg);
        ((T_RNET_RT_SOCK *) cach_so)->flags &= ~RNET_RT_SOCKF_NOTIFY_CLOSED;  

	cach_so= NULL; 	

}
// end 
/*
 * Socket callback function.
 * The socket events are translated to RNET messages and sent the application.
 *
 */
static void socket_callback( NGsock *so, void *data, int flags)
{
  NGsock *nso;
  NGsockaddr addr;
  NGbuf *bufp;
  char tmp[25]; 
  union {
    T_RNET_ERROR_IND eind;
    T_RNET_CONNECT_IND cind;
    T_RNET_CONNECT_CFM ccfm;
    T_RNET_SEND_RDY srdy;
    T_RNET_RECV_IND rind;
  } *msg;


   sprintf(tmp,"recv data len %d", so->so_rcv_cc);
   RNET_RT_SEND_TRACE(tmp,RV_TRACE_LEVEL_ERROR);

  msg = NULL;
  if( so->so_error != 0) {
    /* send RNET_ERROR_IND msg */
    RNET_RT_SEND_TRACE("RNET_RT: RNET_ERROR_IND ",RV_TRACE_LEVEL_ERROR);	
    if( rvf_get_msg_buf( rnet_rt_env_ctrl_blk_p->mb_id, sizeof(T_RNET_ERROR_IND),
       RNET_ERROR_IND, (T_RV_HDR **) &msg) == RVF_RED) {
      goto getbuf_error;
    }
    msg->eind.desc = (T_RNET_DESC *) so;
    msg->eind.error = rnet_rt_ngip_error( so->so_error);
    socket_send_msg( so, (T_RV_HDR *) msg);
    so->so_error = 0;
    return;
  }

  if( flags & NG_SAIO_READ) {
    if( so->so_state & NG_SS_CANTRCVMORE) {
      /* connection has been closed/aborted */
//pinghua add one condiction to avoid close abnormal 20080505
	  
      if( ((T_RNET_RT_SOCK *) so)->flags & RNET_RT_SOCKF_NOTIFY_CLOSED && ( so->so_rcv_cc==0 )  ) {
        /* connection is closed */
        /* send RNET_ERROR_IND/RNET_CONN_CLOSED msg */
        if( rvf_get_msg_buf( rnet_rt_env_ctrl_blk_p->mb_id, sizeof(T_RNET_ERROR_IND),
           RNET_ERROR_IND, (T_RV_HDR **) &msg) == RVF_RED) {
          goto getbuf_error;
        }
        msg->eind.desc = (T_RNET_DESC *) so;
        msg->eind.error = RNET_CONN_CLOSED;
        socket_send_msg( so, (T_RV_HDR *) msg);
        ((T_RNET_RT_SOCK *) so)->flags &= ~RNET_RT_SOCKF_NOTIFY_CLOSED;
      }
      else {              //buffer this close FIN messgae 

           cach_sock_message(so);

      	}

	  
    }
    else if( so->so_options & NG_SO_ACCEPTCONN) {
        

      /* accept a new connection */
      if( ngSAIOAccept( so, &addr, 0, &nso) == NG_EOK) {
        /* initialise rnet part of socket */
        ((T_RNET_RT_SOCK *) nso)->return_path = ((T_RNET_RT_SOCK *) so)->return_path;
        ((T_RNET_RT_SOCK *) nso)->flags =
          RNET_RT_SOCKF_NOTIFY_RECV|RNET_RT_SOCKF_NOTIFY_CLOSED;
        ((T_RNET_RT_SOCK *) nso)->user_data = NULL;
        /* install callback */
        ngSAIOSetCallback( nso, socket_callback, NULL);
        /* send RNET_CONNECT_IND msg */
        if( rvf_get_msg_buf( rnet_rt_env_ctrl_blk_p->mb_id, sizeof(T_RNET_CONNECT_IND),
           RNET_CONNECT_IND, (T_RV_HDR **) &msg) == RVF_RED) {
          ngSAIOClose( nso, 0);
          goto getbuf_error;
        }
        msg->cind.new_desc = (T_RNET_DESC *) nso;
        msg->cind.listen_desc = (T_RNET_DESC *) so;
        msg->cind.peer_addr = ngNTOHL( addr.sin_addr);
        msg->cind.peer_port = ngNTOHS( addr.sin_port);
        socket_send_msg( so, (T_RV_HDR *) msg);
        /* send first RNET_SEND_RDY message */
        if( rvf_get_msg_buf( rnet_rt_env_ctrl_blk_p->mb_id, sizeof(T_RNET_SEND_RDY),
           RNET_SEND_RDY, (T_RV_HDR **) &msg) == RVF_RED) {
          goto getbuf_error;
        }
        msg->srdy.desc = (T_RNET_DESC *) nso;
        socket_send_msg( so, (T_RV_HDR *) msg);
      }
      return;
    }
    else {
      if( ((T_RNET_RT_SOCK *) so)->flags & RNET_RT_SOCKF_NOTIFY_CONNECT) {
        /* active connection is done */
        /* send RNET_CONNECT_CFM msg */
        if( rvf_get_msg_buf( rnet_rt_env_ctrl_blk_p->mb_id, sizeof(T_RNET_CONNECT_CFM),
           RNET_CONNECT_CFM, (T_RV_HDR **) &msg) == RVF_RED) {
          goto getbuf_error;
        }
        msg->ccfm.desc = (T_RNET_DESC *) so;
        socket_send_msg( so, (T_RV_HDR *) msg);
        ((T_RNET_RT_SOCK *) so)->flags &= ~RNET_RT_SOCKF_NOTIFY_CONNECT;
        ((T_RNET_RT_SOCK *) so)->flags |= RNET_RT_SOCKF_NOTIFY_CLOSED;
        ((T_RNET_RT_SOCK *) so)->flags |= RNET_RT_SOCKF_NOTIFY_RECV ;
      }
      if( (((T_RNET_RT_SOCK *) so)->flags & RNET_RT_SOCKF_NOTIFY_RECV) &&
          (so->so_rcv_cc >= so->so_rcv_lowat)) {
        /* data has been received */
        /* send RNET_RECV_IND msg */
        if( rvf_get_msg_buf( rnet_rt_env_ctrl_blk_p->mb_id, sizeof(T_RNET_RECV_IND),
           RNET_RECV_IND, (T_RV_HDR **) &msg) == RVF_RED) {
          goto getbuf_error;
        }
        msg->rind.desc = (T_RNET_DESC *) so;
        /* fillin sender's address */
        if( so->so_state & NG_SS_ISCONNECTED) {
          /* socket is connected, get peer address in socket control block */
          msg->rind.peer_addr = ngNTOHL( so->so_faddr);
          msg->rind.peer_port = ngNTOHS( so->so_fport);
        }
        else if( (so->so_proto->pr_flags & NG_PR_ADDR) &&
                 ((bufp = (NGbuf *) so->so_rcv_q.qu_tail) != NULL)) {
          /* get address from last queued buffer */
          ngMemCpy( &addr, bufp->buf_iov, sizeof( NGsockaddr));
          msg->rind.peer_addr = ngNTOHL( addr.sin_addr);
          msg->rind.peer_port = ngNTOHS( addr.sin_port);
        }
        else {
          /* cannot get address, this should not happen... */
          msg->rind.peer_addr = 0;
          msg->rind.peer_port = 0;
        }
        socket_send_msg( so, (T_RV_HDR *) msg);
        ((T_RNET_RT_SOCK *) so)->flags &= ~RNET_RT_SOCKF_NOTIFY_RECV;
      }
    }
  }


  if( flags & NG_SAIO_WRITE) {
    if( !(so->so_state & NG_SS_CANTSENDMORE) &&
        (((T_RNET_RT_SOCK *) so)->flags & RNET_RT_SOCKF_NOTIFY_SEND) &&
        ((so->so_snd_hiwat - so->so_snd_cc) >= so->so_snd_lowat)) {
      /* send data has been acknowledged by peer */
      /* send RNET_SEND_RDY msg */
      if( rvf_get_msg_buf( rnet_rt_env_ctrl_blk_p->mb_id, sizeof(T_RNET_SEND_RDY),
         RNET_SEND_RDY, (T_RV_HDR **) &msg) == RVF_RED) {
        goto getbuf_error;
      }
      msg->srdy.desc = (T_RNET_DESC *) so;
      socket_send_msg( so, (T_RV_HDR *) msg);
      ((T_RNET_RT_SOCK *) so)->flags &= ~RNET_RT_SOCKF_NOTIFY_SEND;
    }
  }
  return;

getbuf_error:
  RNET_RT_SEND_TRACE("RNET_RT: cannot allocate MSG ",RV_TRACE_LEVEL_ERROR);
  return;
}

/**
 * Creates a new connection identifier (T_RNET_DESC).
 *
 * The connection ID is not active until it has either been bound
 * to a local address or connected to a remote address.
 *
 * @param  proto  Protocol that should be used [IN].
 * @param  desc  Connection identifier created [OUT].
 * @param  return_path  Return path that should be used to send
 *          the messages like accept, connect, etc [IN].
 * @return  RNET_MEMORY_ERR      No available memory to create the new connection id.
 *      RNET_NOT_INITIALIZED  NET subsystem not initialized (internal error).
 *      RNET_INTERNAL_ERR    Network subsystem failed.
 *                or  No more socket descriptors available.
 *      RNET_NOT_READY      Still processing a callback function.
 *      RNET_NOT_SUPPORTED    Specified protocol not supported.
 *      RNET_OK          Connection ID successfully created.
 */

T_RNET_RET rnet_rt_new (T_RNET_IPPROTO proto,
           T_RNET_DESC ** desc,
           T_RV_RETURN_PATH return_path)
{
  NGsock *so;
  int type, err;

  /* check if SW entity has been initialised */
  if( rnet_rt_env_ctrl_blk_p == NULL) {
    return( RNET_NOT_INITIALIZED);
  }

  /* select type of socket, only TCP and UDP allowed */
  switch( proto) {
  case RNET_IPPROTO_TCP:
    type = NG_SOCK_STREAM;
    break;
  case RNET_IPPROTO_UDP:
    type = NG_SOCK_DGRAM;
    break;
  default:
    /* invalid protocol */
    /* could create raw IP socket... */
    return( RNET_NOT_SUPPORTED);
  }

  /* create ngip socket */
  
  rvf_lock_mutex( &rnet_rt_env_ctrl_blk_p->mutex);
  err = ngSAIOCreate( &so, NG_AF_INET, type, 0, NG_O_NONBLOCK);

  if( err == NG_EOK) {
    /* initialise rnet part of socket */
    ((T_RNET_RT_SOCK *) so)->return_path = return_path;
#if 0 /* RNET_RT bug!? [ni 2003-12-05 */
    ((T_RNET_RT_SOCK *) so)->flags = RNET_RT_SOCKF_NOTIFY_RECV |
                                           RNET_RT_SOCKF_NOTIFY_SEND;
#else
    if (proto == RNET_IPPROTO_UDP) {
      /* A UDP socket is ready for communication right after it has been
       * created, ... */
      ((T_RNET_RT_SOCK *) so)->flags =
        RNET_RT_SOCKF_NOTIFY_RECV | RNET_RT_SOCKF_NOTIFY_SEND;
    } else {
      /* ... whereas a TCP socket has to be connected first. */
      ((T_RNET_RT_SOCK *) so)->flags = 0 ;
    }
#endif /* 0 */
    ((T_RNET_RT_SOCK *) so)->user_data = NULL;

    
    /* install callback */
    ngSAIOSetCallback( so, socket_callback, NULL);


  }
  rvf_unlock_mutex( &rnet_rt_env_ctrl_blk_p->mutex);

  /* returns new socket */
  if( err == NG_EOK) {
    *desc = (T_RNET_DESC *) so;
    return( RNET_OK);
  }

  /* convert error code */
  return( rnet_rt_ngip_error( err));
}

#endif /* ifdef RNET_CFG_REAL_TRANSPORT */