FreeCalypso > hg > fc-selenite
view src/g23m-fad/tcpip/tcpip_api_layer.c @ 192:4f40ae165be4
abb.c & init.c: sync with Magnetite for Luna additions
These Luna target-specific additions are conditionalized on CONFIG_TARGET_LUNA,
a C preprocessor symbol that will never be defined in Selenite, hence this
change has exactly zero impact on FC Selenite. However, they are being pulled
in as a sync in order to keep the diff between Magnetite and Selenite to a
minimum; keeping this diff to a minimum increases our opportunities for
possible evolution of future FC firmwares.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 23 May 2020 07:03:46 +0000 |
parents | d393cd9bb723 |
children |
line wrap: on
line source
/* +------------------------------------------------------------------------------ | File: tcpip_api_layer.c +------------------------------------------------------------------------------ | Copyright 2003 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : GPF-based TCP/IP's glue layer towards the socket API. +----------------------------------------------------------------------------- */ #define TCPIP_API_LAYER_C #define ENTITY_TCPIP /*==== INCLUDES =============================================================*/ #include <string.h> /* String functions, e. g. strncpy(). */ #include "typedefs.h" /* to get Condat data types */ #include "vsi.h" /* to get a lot of macros */ #include "custom.h" #include "gsm.h" /* to get a lot of macros */ #include "prim.h" /* to get the definitions of used SAP and directions */ #include "pei.h" /* to get PEI interface */ #include "tools.h" /* to get common tools */ #include "dti.h" /* For DTI library definitions. */ #include "glob_defs.h" #include "tcpip.h" /* to get the global entity definitions */ #include "tcpip_int.h" /* RNET includes */ #include "rv_general.h" #include "rnet_api.h" #include "rnet_rt_env.h" #include "rnet_message.h" #include "rnet_rt_i.h" /* NexGenIP includes */ #include <ngip/if.h> #ifdef _SIMULATION_ #include "tcpip_sim_utils.h" /* Utilities for use in the simulation. */ #endif /* _SIMULATION_ */ /*==== Local prototypes =====================================================*/ /*==== Macros ===============================================================*/ /* Two macros to go from socket descriptor to sock_table[] index and vice * versa. */ #define SOCK_S_INDEX(desc) (SOCKPAR_GET(desc)->s_index) #define SOCK_RT_DESC(s_index) (sock_table[s_index]->rtdesc) /* Retrieve the parameter block associated with a socket descriptor (as * user_data). */ #define SOCKPAR_GET(socket) ((T_sockpar *) rnet_get_user_data(socket)) /* Check if there is a valid socket for the specified socket index. */ #define INVALID_S_INDEX(socket) \ ((socket) >= RNET_RT_SOCK_MAX OR sock_table[socket] EQ NULL) /* We don't have a fixed value for the application handle (there will be more * than one). TCPIP wants to send a message to itself, so it is not convenient * to redirect all primitives, so we use the MMI handle for the application * for testing. This will then be redirected to the TAP. */ #ifdef _SIMULATION_ #define APP_HANDLE hCommMMI #else /* _SIMULATION_ */ #define APP_HANDLE app_handle #endif /* _SIMULATION_ */ /*==== Types ================================================================*/ /* This struct is to be associated to a socket descriptor as user_data in * order to provide context for the event handler functions. The struct is * zero-initialized, so all default values must be zero. * * Pointers to these structures are kept in sock_table[]. */ typedef struct sock_params { int s_index ; /* Index in socket table. */ T_RNET_DESC *rtdesc ; /* The RNET_RT socket descriptor. */ T_HANDLE app_handle ; /* Communication handle of application * entity. */ U8 ipproto ; /* IP protocol number of socket. */ U32 request_id ; /* Request identification (if present). */ U32 expected_event ; /* The event we are waiting for on this * connection. This is necessary * for error handling, because the * RNET_ERROR_IND function gets no information * *which* request caused the error. */ BOOL is_connected ; /* Connected UDP or TCP socket. (NexGenIP does * not give us an error code when we try to * send on a non-connected socket, so we have * to maintain this status by ourselves in * order to report the error to the * application. */ BOOL recv_waiting ; /* TRUE iff incoming data is (or might be) * available. */ BOOL appl_xoff ; /* TRUE iff flow control to the application is * in "xoff" status. */ struct { U16 total_length ; /* Total length of buffer, zero if no data is * waiting. */ U16 offset ; /* Offset of first byte not yet sent. */ U8 *buffer ; /* Pointer to data buffer waiting to be * sent. */ } send ; } T_sockpar ; /*==== Local data ===========================================================*/ /* Table of active socket descriptors; provides the mapping between the small * integers used in the primitives and the actual RNET socket descriptors. */ static T_sockpar *sock_table[RNET_RT_SOCK_MAX] ; /*==== Primitive sender functions ===========================================*/ /** Confirm the result of a TCPIP_INITIALIZE_REQ. * * @param result Result of the initialization. */ static void tcpip_initialize_cnf(U8 result) { TRACE_FUNCTION("tcpip_initialize_cnf()") ; { PALLOC(prim, TCPIP_INITIALIZE_CNF) ; prim->result = result ; PSENDX(MMI, prim) ; } } /** Confirm the result of a TCPIP_SHUTDOWN_REQ * * @param result Result of the shutdown. */ static void tcpip_shutdown_cnf(U8 result) { TRACE_FUNCTION("tcpip_shutdown_cnf()") ; { PALLOC(prim, TCPIP_SHUTDOWN_CNF) ; prim->result = result ; PSENDX(MMI, prim) ; } } /** Confirm the result of a TCPIP_IFCONFIG_REQ * * @param result Result of the configuration. */ static void tcpip_ifconfig_cnf(U8 result) { TRACE_FUNCTION("tcpip_ifconfig_cnf()") ; { PALLOC(prim, TCPIP_IFCONFIG_CNF) ; prim->result = result ; PSENDX(MMI, prim) ; } } /** Confirm the result of a TCPIP_DTI_REQ. This function is called * from tcpip_dti.c, so it must not be static. * * @param dti_conn Indicates whether the DTI link is to be established or * disconnected * @param link_id DTI link identifier */ void tcpip_dti_cnf(U8 dti_conn, U32 link_id) { TRACE_FUNCTION("tcpip_dti_cnf()") ; { PALLOC(prim, TCPIP_DTI_CNF) ; prim->dti_conn = dti_conn ; prim->link_id = link_id ; PSENDX(MMI, prim) ; } } /** Confirm the result of a TCPIP_CREATE_REQ. * * @param app_handle Communication handle of requesting task. * @param result Result of the operation. * @param socket Index of newly created socket (if OK). * @param request_id Request ID as passed in TCPIP_CREATE_REQ. */ static void tcpip_create_cnf(T_HANDLE app_handle, U8 result, int socket, U32 request_id) { TRACE_FUNCTION("tcpip_create_cnf()") ; TRACE_EVENT_P1("app_handle %d",APP_HANDLE); { PALLOC(prim, TCPIP_CREATE_CNF) ; prim->event_type = TCPIP_EVT_CREATE_CNF ; prim->result = result ; prim->socket = socket ; prim->request_id = request_id ; PSEND(APP_HANDLE, prim) ; } } /** Confirm the result of a TCPIP_CLOSE_REQ. * * @param app_handle Communication handle of requesting task. * @param result Result of the operation. * @param socket Index of (no longer valid) socket. */ static void tcpip_close_cnf(T_HANDLE app_handle, U8 result, int socket) { TRACE_FUNCTION("tcpip_close_cnf()") ; { PALLOC(prim, TCPIP_CLOSE_CNF) ; prim->event_type = TCPIP_EVT_CLOSE_CNF ; prim->result = result ; prim->socket = socket ; PSEND(APP_HANDLE, prim) ; } } /** Confirm the result of a TCPIP_BIND_REQ. * * @param app_handle Communication handle of requesting task. * @param result Result of the operation. * @param socket Index of the socket. */ static void tcpip_bind_cnf(T_HANDLE app_handle, U8 result, int socket) { TRACE_FUNCTION("tcpip_bind_cnf()") ; { PALLOC(prim, TCPIP_BIND_CNF) ; prim->event_type = TCPIP_EVT_BIND_CNF ; prim->result = result ; prim->socket = socket ; PSEND(APP_HANDLE, prim) ; } } /** Confirm the result of a TCPIP_LISTEN_REQ. * * @param app_handle Communication handle of requesting task. * @param result Result of the operation. * @param socket Index of the socket. */ static void tcpip_listen_cnf(T_HANDLE app_handle, U8 result, int socket) { TRACE_FUNCTION("tcpip_listen_cnf()") ; { PALLOC(prim, TCPIP_LISTEN_CNF) ; prim->event_type = TCPIP_EVT_LISTEN_CNF ; prim->result = result ; prim->socket = socket ; PSEND(APP_HANDLE, prim) ; } } /** Confirm the result of a TCPIP_CONNECT_REQ. * * @param app_handle Communication handle of requesting task. * @param result Result of the operation. * @param socket Index of the socket. */ static void tcpip_connect_cnf(T_HANDLE app_handle, U8 result, int socket) { TRACE_FUNCTION("tcpip_connect_cnf()") ; { PALLOC(prim, TCPIP_CONNECT_CNF) ; prim->event_type = TCPIP_EVT_CONNECT_CNF ; prim->result = result ; prim->socket = socket ; PSEND(APP_HANDLE, prim) ; } } /** Confirm the result of a TCPIP_DATA_REQ. * * @param app_handle Communication handle of requesting task. * @param result Result of the operation. * @param socket Index of the socket. * @param window Window size for sender. */ static void tcpip_data_cnf(T_HANDLE app_handle, U8 result, int socket, U16 window) { TRACE_FUNCTION("tcpip_data_cnf()") ; { PALLOC(prim, TCPIP_DATA_CNF) ; prim->event_type = TCPIP_EVT_FLOW_READY_IND ; prim->result = result ; prim->socket = socket ; prim->window = window ; PSEND(APP_HANDLE, prim) ; } } /** Indicate incoming data. * * @param app_handle Communication handle of requesting task. * @param result Result of the operation. * @param socket Index of the socket. * @param ipaddr Source IP address. * @param port Source port number. * @param buflen Length of payload data. * @param data Adress of payload data buffer. */ static void tcpip_data_ind(T_HANDLE app_handle, U8 result, int socket, U32 ipaddr, U16 port, U16 buflen, U8 *data) { TRACE_FUNCTION("tcpip_data_ind()") ; { PALLOC(prim, TCPIP_DATA_IND) ; prim->event_type = TCPIP_EVT_RECV_IND ; /* Unfortunately not _DATA_IND */ prim->result = result ; prim->socket = socket ; prim->ipaddr = ipaddr ; prim->port = port ; prim->buflen = buflen ; prim->data = (U32) data ; PSEND(APP_HANDLE, prim) ; } } /** Confirm the result of a TCPIP_SOCKNAME_REQ. * * @param app_handle Communication handle of the requesting task. * @param result Result of the operation. * @param socket Index of the socket. * @param ipaddr IP address of the socket. * @param port Port number of the socket. */ static void tcpip_sockname_cnf(T_HANDLE app_handle, U8 result, int socket, U32 ipaddr, U16 port) { TRACE_FUNCTION("tcpip_sockname_cnf()") ; { PALLOC(prim, TCPIP_SOCKNAME_CNF) ; prim->event_type = TCPIP_EVT_SOCKNAME_CNF ; prim->result = result ; prim->socket = socket ; prim->ipaddr = ipaddr ; prim->port = port ; PSEND(APP_HANDLE, prim) ; } } /** Confirm the result of a TCPIP_PEERNAME_REQ. * * @param app_handle Communication handle of the requesting task. * @param result Result of the operation. * @param socket Index of the socket. * @param ipaddr IP address of the remote peer. * @param port Remore port number of the socket. */ static void tcpip_peername_cnf(T_HANDLE app_handle, U8 result, int socket, U32 ipaddr, U16 port) { TRACE_FUNCTION("tcpip_peername_cnf()") ; { PALLOC(prim, TCPIP_PEERNAME_CNF) ; prim->event_type = TCPIP_EVT_PEERNAME_CNF ; prim->result = result ; prim->socket = socket ; prim->ipaddr = ipaddr ; prim->port = port ; PSEND(APP_HANDLE, prim) ; } } /** Confirm the result of a TCPIP_HOSTINFO_REQ. * * @param app_handle Communication handle of the requesting task. * @param result Result of the operation. * @param request_id Request ID as passed in TCPIP_CREATE_REQ. * @param hostname Full-qualified domain name of the host, may be NULL. * @param ipaddr IP address of the host. */ static void tcpip_hostinfo_cnf(T_HANDLE app_handle, U8 result, U32 request_id, char *hostname, U32 ipaddr) { TRACE_FUNCTION("tcpip_hostinfo_cnf()") ; { PALLOC(prim, TCPIP_HOSTINFO_CNF) ; prim->event_type = TCPIP_EVT_HOSTINFO_CNF ; prim->result = result ; prim->request_id = request_id ; if (hostname NEQ NULL) { strncpy((char *) prim->hostname, hostname, TCPIP_HNAMELEN) ; prim->hostname[TCPIP_HNAMELEN-1] = '\0' ; } else { prim->hostname[0] = '\0' ; } prim->ipaddr = ipaddr ; PSEND(APP_HANDLE, prim) ; } } /** Confirm the result of a TCPIP_MTU_SIZE_REQ. * * @param app_handle Communication handle of the requesting task. * @param result Result of the operation. * @param socket Index of the socket. * @param mtu_size Size of the MTU. */ static void tcpip_mtu_size_cnf(T_HANDLE app_handle, U8 result, int socket, U16 mtu_size) { TRACE_FUNCTION("tcpip_mtu_size_cnf()") ; { PALLOC(prim, TCPIP_MTU_SIZE_CNF) ; prim->event_type = TCPIP_EVT_MTU_SIZE_CNF ; prim->result = result ; prim->socket = socket ; prim->mtu_size = mtu_size ; PSEND(APP_HANDLE, prim) ; } } /** Indicate an incoming TCP connection. * * @param app_handle Communication handle of the task. * @param socket Index of the listening socket. * @param new_socket New socket for this connection. * @param ipaddr IP address of the remote peer. * @param port Remore port number of the socket. */ static void tcpip_connect_ind(T_HANDLE app_handle, int socket, int new_socket, U32 ipaddr, U16 port) { TRACE_FUNCTION("tcpip_connect_ind()") ; { PALLOC(prim, TCPIP_CONNECT_IND) ; prim->event_type = TCPIP_EVT_CONNECT_IND ; prim->result = TCPIP_RESULT_OK ; prim->socket = socket ; prim->new_socket = new_socket ; prim->ipaddr = ngHTONL(ipaddr) ; prim->port = ngHTONS(port) ; PSEND(APP_HANDLE, prim) ; } } /** Indicate that a connection has been closed. * * @param app_handle Communication handle of the task. * @param socket Index of the socket. */ static void tcpip_conn_closed_ind(T_HANDLE app_handle, int socket) { TRACE_FUNCTION("tcpip_conn_closed_ind()") ; { PALLOC(prim, TCPIP_CONN_CLOSED_IND) ; prim->event_type = TCPIP_EVT_CONN_CLOSED_IND ; prim->result = TCPIP_RESULT_OK ; prim->socket = socket ; PSEND(APP_HANDLE, prim) ; } } /** Indicate an asynchronous error on a socket. * * @param app_handle Communication handle of the task. * @param result Result code of the error. * @param socket Index of the socket. */ static void tcpip_error_ind(T_HANDLE app_handle, U8 result, int socket) { TRACE_FUNCTION("tcpip_error_ind()") ; { PALLOC(prim, TCPIP_ERROR_IND) ; prim->event_type = TCPIP_EVT_ERROR_IND ; prim->result = result ; prim->socket = socket ; PSEND(APP_HANDLE, prim) ; } } /** Send a message to self. * * @param msg_p pointer to message * @param msg_id message identification */ void tcpip_send_internal_ind(U32 msg_p, U32 msg_id) { TRACE_FUNCTION("tcpip_send_internal_ind()") ; { PALLOC(prim, TCPIP_INTERNAL_IND) ; prim->msg_p = msg_p ; prim->msg_id = msg_id ; PSEND(hCommTCPIP, prim) ; } } /*==== Local utility functions ==============================================*/ /** Allocate a new socket parameter block, initialize it with the given * parameters, and put it into the list. Allocate a slot in the sock_table[] * and fill it. If we cannot allocate a slot, return NULL. This is considered * an internal error, because we *have* a slot free for each possible socket. * * @param socket The socket descriptor (if applicable). * @param app_handle Communication handle of application task. * @param request_id Request identification (if applicable). * @return a pointer to the sock_params struct or NULL on error. */ static T_sockpar *sockpar_new(T_RNET_DESC *socket, T_HANDLE app_handle, U8 ipproto, U32 request_id) { T_sockpar *sp ; /* Pointer to new struct. */ int sti ; /* Socket table index. */ TRACE_FUNCTION("sockpar_new()") ; /* Allocate and enqueue. */ MALLOC(sp, sizeof(T_sockpar)) ; /* TRACE_EVENT_P1("MALLOC gives us %08x", sp) ; */ memset(sp, 0, sizeof(T_sockpar)) ; sp->rtdesc = socket ; sp->app_handle = app_handle ; sp->ipproto = ipproto ; sp->request_id = request_id ; for (sti = 0; sti < RNET_RT_SOCK_MAX; sti++) { if (sock_table[sti] EQ NULL) { sock_table[sti] = sp ; sp->s_index = sti ; return sp ; } } /* No free slot in table found -- this must be an error, because we have a * slot for each possible socket. */ TRACE_ERROR("No free slot in sock_table[] found") ; /* TRACE_EVENT_P1("We MFREE %08x", sp) ; */ MFREE(sp) ; return NULL ; } /** Dequeue and deallocate a socket parameter block. Free the slot in * sock_table[]. * * @param sp Pointer to sock_params struct. */ static void sockpar_delete(T_sockpar *sp) { TRACE_FUNCTION("sockpar_delete()") ; sock_table[sp->s_index] = 0 ; /* TRACE_EVENT_P1("We MFREE %08x", sp) ; */ MFREE(sp) ; } /** Clear the send buffer of a socket parameter block and free the associated * data. * * @param sockpar The socket parameter block. */ static void tcpip_clear_send_buffer(T_sockpar *sockpar) { sockpar->send.total_length = 0 ; sockpar->send.offset = 0 ; #ifndef _SIMULATION_ /* The simulation would crash in the MFREE(), as the send.buffer is not a * frame-allocated piece of memory. */ /* TRACE_EVENT_P1("MFREE sockpar->send.buffer %x", sockpar->send.buffer) ; */ MFREE(sockpar->send.buffer) ; #endif /* _SIMULATION_ */ sockpar->send.buffer = NULL ; } /** Convert an RNET error code to the appropriate TCPIP result code. * * @param rnet_ret The RNET error code. * @return The TCPIP result code. */ static U8 rnet_error_to_tcpip_result(T_RNET_RET rnet_ret) { switch (rnet_ret) { case RNET_OK: TRACE_EVENT("RNET_OK -> TCPIP_RESULT_OK") ; return TCPIP_RESULT_OK ; case RNET_MEMORY_ERR: TRACE_EVENT("RNET_MEMORY_ERR -> TCPIP_RESULT_OUT_OF_MEMORY") ; return TCPIP_RESULT_OUT_OF_MEMORY ; case RNET_INVALID_PARAMETER: TRACE_EVENT("RNET_INVALID_PARAMETER -> TCPIP_RESULT_INVALID_PARAMETER") ; return TCPIP_RESULT_INVALID_PARAMETER ; case RNET_NOT_SUPPORTED: TRACE_EVENT("RNET_NOT_SUPPORTED -> TCPIP_RESULT_NOT_SUPPORTED") ; return TCPIP_RESULT_NOT_SUPPORTED ; case RNET_NOT_READY: TRACE_EVENT("RNET_NOT_READY -> TCPIP_RESULT_NOT_READY") ; return TCPIP_RESULT_NOT_READY ; case RNET_INTERNAL_ERR: TRACE_EVENT("RNET_INTERNAL_ERR -> TCPIP_RESULT_INTERNAL_ERROR") ; return TCPIP_RESULT_INTERNAL_ERROR ; case RNET_IN_USE: TRACE_EVENT("RNET_IN_USE -> TCPIP_RESULT_ADDR_IN_USE") ; return TCPIP_RESULT_ADDR_IN_USE ; case RNET_NOT_INITIALIZED: TRACE_EVENT("RNET_NOT_INITIALIZED -> TCPIP_RESULT_NOT_READY") ; return TCPIP_RESULT_NOT_READY ; case RNET_NET_UNREACHABLE: TRACE_EVENT("RNET_NET_UNREACHABLE -> TCPIP_RESULT_UNREACHABLE") ; return TCPIP_RESULT_UNREACHABLE ; case RNET_TIMEOUT: TRACE_EVENT("RNET_TIMEOUT -> TCPIP_RESULT_TIMEOUT") ; return TCPIP_RESULT_TIMEOUT ; case RNET_CONN_REFUSED: TRACE_EVENT("RNET_CONN_REFUSED -> TCPIP_RESULT_CONN_REFUSED") ; return TCPIP_RESULT_CONN_REFUSED ; case RNET_CONN_RESET: TRACE_EVENT("RNET_CONN_RESET -> TCPIP_RESULT_CONN_RESET") ; return TCPIP_RESULT_CONN_RESET ; case RNET_CONN_ABORTED: TRACE_EVENT("RNET_CONN_ABORTED -> TCPIP_RESULT_CONN_ABORTED") ; return TCPIP_RESULT_CONN_ABORTED ; case RNET_MSG_SIZE: TRACE_EVENT("RNET_MSG_SIZE -> TCPIP_RESULT_MSG_TOO_BIG") ; return TCPIP_RESULT_MSG_TOO_BIG ; case RNET_HOST_NOT_FOUND: TRACE_EVENT("RNET_HOST_NOT_FOUND -> TCPIP_RESULT_HOST_NOT_FOUND") ; return TCPIP_RESULT_HOST_NOT_FOUND ; /* The following should not be delivered as a result code: */ case RNET_CONN_CLOSED: TRACE_EVENT("RNET_CONN_CLOSED -> TCPIP_RESULT_INTERNAL_ERROR") ; return TCPIP_RESULT_INTERNAL_ERROR ; case RNET_PARTIAL_SENT: TRACE_EVENT("RNET_PARTIAL_SENT -> TCPIP_RESULT_INTERNAL_ERROR") ; return TCPIP_RESULT_INTERNAL_ERROR ; default: TRACE_EVENT_P1("unknown (%d) ->TCPIP_RESULT_INTERNAL_ERROR", rnet_ret) ; return TCPIP_RESULT_INTERNAL_ERROR ; } } /** Read incoming data (from TCP/IP to the application). This function is * called only when the flow control status towards the application is in xon * state. * * @param sockpar Socket parameter block. */ static void tcpip_read_incoming_to_app(T_sockpar *sockpar) { U8 *buffer ; /* Payload data buffer. */ U16 length ; /* Payload data length. */ T_RNET_RET retval ; /* Return value of rnet_recv(). */ T_RNET_IP_ADDR ipaddr ; /* IP address of sender. */ T_RNET_PORT port ; /* Port numer at remote end. */ TRACE_FUNCTION("tcpip_read_incoming_to_app()") ; /* If flow control status is off, we must not send incoming data. */ if (sockpar->appl_xoff) { TRACE_EVENT("tcpip_read_incoming_to_app() called in xoff state") ; return ; } /* We don't expect to read packets larger than this. To be precise, we * aren't able to. */ MALLOC(buffer, TCPIP_DEFAULT_MTU_SIZE) ; /* TRACE_EVENT_P1("MALLOC gives us %08x", buffer) ; */ length = TCPIP_DEFAULT_MTU_SIZE ; /* Should be unspecified for TCP; will be set by rnet_recv_from() for * UDP. */ ipaddr = TCPIP_UNSPECIFIED_IPADDR ; port = TCPIP_UNSPECIFIED_PORT ; switch (sockpar->ipproto) { case TCPIP_IPPROTO_TCP: TRACE_EVENT_P2("Calling rnet_recv() for socket %d length %d", sockpar->s_index, length) ; retval = rnet_recv(sockpar->rtdesc, buffer, &length) ; TRACE_EVENT_P2("rnet_recv() returns %d length %d", retval, length) ; break ; case TCPIP_IPPROTO_UDP: /* Need to read sender address with UDP. */ TRACE_EVENT_P4("Calling rnet_recv_from() for socket %d length %d " "ipaddr %x port %d", sockpar->s_index, length, ipaddr, port) ; retval = rnet_recv_from(sockpar->rtdesc, buffer, &length, &ipaddr, &port) ; TRACE_EVENT_P4("rnet_recv_from() returns %d length %d ipaddr %x port %d", retval, length, ipaddr, port) ; break ; default: retval = RNET_INVALID_PARAMETER ; TRACE_ERROR("tcpip_read_incoming_to_app: unknown IP protocol") ; break ; } if (retval EQ RNET_OK) { /* Only if the length is zero, there is no more data waiting. */ if (length EQ 0) { sockpar->recv_waiting = FALSE ; /* TRACE_EVENT_P1("We MFREE %08x", buffer) ; */ MFREE(buffer) ; } else { /* We use an effective window size of zero, so flow control status is * xoff after sending a primitive. */ tcpip_data_ind(sockpar->app_handle, TCPIP_RESULT_OK, sockpar->s_index, ipaddr, port, length, buffer) ; TRACE_EVENT("switch flow control towards application to xoff") ; dti_stop(tcpip_data->dti_handle, 0, TCPIP_DTI_TO_LOWER_LAYER, 0) ; // Add one flow control to not allow SNDCP send next data package. OMAPS00172999 05132008 sockpar->appl_xoff = TRUE ; #ifdef _SIMULATION_ /* In the simulation, free the buffer -- it is meaningless for the TAP * and will not be freed at any other place. */ MFREE(buffer) ; #endif /* _SIMULATION_ */ } } else /* retval != RNET_OK */ { /* TRACE_EVENT_P1("We MFREE %08x", buffer) ; */ MFREE(buffer) ; tcpip_error_ind(sockpar->app_handle, rnet_error_to_tcpip_result(retval), sockpar->s_index) ; } } /** Try to send data over RNET. To be called after the application has sent * data, and if we have waiting data and RNET has signalled that we may send * again. * * @param sockpar Socket parameter block. */ static void tcpip_try_send_data(T_sockpar *sockpar) { U16 length ; /* Length of data to send or sent. */ T_RNET_RET retval ; /* Return value of rnet_send(). */ TRACE_FUNCTION("tcpip_try_send_data()") ; if (sockpar->send.total_length EQ 0) { TRACE_ERROR("tcpip_try_send_data: called although no data present") ; } else { length = sockpar->send.total_length - sockpar->send.offset ; TRACE_EVENT_P2("Calling rnet_send() socket %d length %d", sockpar->s_index, length) ; retval = rnet_send(sockpar->rtdesc, sockpar->send.buffer, &length) ; TRACE_EVENT_P2("rnet_send() returns %d length %d", retval, length) ; switch (retval) { case RNET_OK: /* We could send all data, so clear send * buffer and send a confirmation to the * application. */ tcpip_clear_send_buffer(sockpar) ; tcpip_data_cnf(sockpar->app_handle, TCPIP_RESULT_OK, sockpar->s_index, TCPIP_DEFAULT_WINDOW) ; break ; case RNET_PARTIAL_SENT: /* Not all of the data could be sent. We * update the send buffer offset and wait for * an RNET_SEND_RDY event to continue. */ sockpar->send.offset += length ; break ; default: /* Every other return value indicates an * error. We translate the return value to our * result codes and send an error indication * to the application. The data will no longer * be needed and is freed. */ tcpip_clear_send_buffer(sockpar) ; tcpip_data_cnf(sockpar->app_handle, rnet_error_to_tcpip_result(retval), sockpar->s_index, TCPIP_DEFAULT_WINDOW) ; break ; } } } /** Initialize RNET and the data of the TCPIP entity. * * This in a separate function to make control flow more elegant -- this way * we can jump out of the initialization sequence without having to use a * goto. * * @return a result code with the usual semantics */ static U8 tcpip_do_initialization(void) { static T_RVF_MB_ID entity_bk_id_table[8]; static T_RV_RETURN_PATH entity_return_pathes[8]; T_RNET_RET retval ; /* Return value of RNET initialisation. */ TRACE_FUNCTION("tcpip_do_initialization()") ; if (tcpip_data->is_initialized) { TRACE_ERROR("initialization called although tcpip_data->is_initialized") ; return TCPIP_RESULT_INTERNAL_ERROR ; } memset(sock_table,0,sizeof(sock_table)); /* quite ad-hoc: both arrays "entity_return_pathes", "entity_bk_id_table" are uninitialized and arbitrarily set to length 8. last param, call_back_error_ft function, undefined. */ rnet_rt_set_info((T_RVF_ADDR_ID) tcpip_handle, entity_return_pathes, entity_bk_id_table, 0); retval = (T_RNET_RET)rnet_rt_init() ; if (retval NEQ RNET_OK ) { TRACE_ERROR("rnet_rt_init() != RV_OK") ; return rnet_error_to_tcpip_result(retval) ; } retval = (T_RNET_RET)rnet_rt_start() ; if (retval NEQ RNET_OK ) { TRACE_ERROR("rnet_rt_start() != RV_OK") ; rnet_rt_kill() ; return rnet_error_to_tcpip_result(retval) ; } #ifdef _SIMULATION_ tcpip_if_properties(&rnet_rt_env_ctrl_blk_p->ifnet_lo) ; #endif /* _SIMULATION_ */ tcpip_data->is_initialized = TRUE ; return TCPIP_RESULT_OK ; } /** Mark an event as expected for the specified socket. * * @param sock_desc The Socket descriptor. * @param expected_event The event type. */ static void socket_expect_event(T_RNET_DESC* sock_desc, U32 expected_event) { #ifdef TRACING char *event_name ; switch (expected_event) { case TCPIP_EVT_CONNECT_CNF: event_name = "CONNECT_CNF" ; break ; case TCPIP_EVT_RECV_IND: event_name = "RECV_IND" ; break ; case TCPIP_EVT_CONNECT_IND: event_name = "CONNECT_IND" ; break ; default: event_name = "<none>" ; break ; } TRACE_EVENT_P1("ready for TCPIP_EVT_%s for %d", event_name, SOCK_S_INDEX(sock_desc)) ; #endif /* TRACING */ SOCKPAR_GET(sock_desc)->expected_event = expected_event ; } /*==== Specific event handler functions =====================================*/ /** Handle an RNET_CONNECT_IND event; pass it through to the application. * * @param connect_ind Pointer to the event message. */ static void tcpip_handle_rnet_connect_ind(T_RNET_CONNECT_IND *connect_ind) { T_sockpar *sockpar, *sp_new ; TRACE_FUNCTION("tcpip_handle_rnet_connect_ind()") ; sockpar = SOCKPAR_GET(connect_ind->listen_desc) ; sp_new = sockpar_new(connect_ind->new_desc, sockpar->app_handle, sockpar->ipproto, 0) ; if (sp_new EQ NULL) { tcpip_error_ind(sockpar->app_handle, TCPIP_RESULT_INTERNAL_ERROR, sockpar->s_index) ; } else { sp_new->is_connected = TRUE ; rnet_set_user_data(connect_ind->new_desc, (void *) sp_new) ; tcpip_connect_ind(sockpar->app_handle, sockpar->s_index, sp_new->s_index, connect_ind->peer_addr, connect_ind->peer_port) ; socket_expect_event(connect_ind->new_desc, TCPIP_EVT_RECV_IND) ; } rvf_free_buf(connect_ind) ; } /** Handle an RNET_CONNECT_CFM event; pass it through to the application. * * @param connect_cfm Pointer to the event message. */ static void tcpip_handle_rnet_connect_cfm(T_RNET_CONNECT_CFM *connect_cfm) { T_sockpar *sockpar ; TRACE_FUNCTION("tcpip_handle_rnet_connect_cfm()") ; sockpar = SOCKPAR_GET(connect_cfm->desc) ; sockpar->is_connected = TRUE ; tcpip_connect_cnf(sockpar->app_handle, TCPIP_RESULT_OK, SOCK_S_INDEX(connect_cfm->desc)) ; socket_expect_event(connect_cfm->desc, TCPIP_EVT_RECV_IND) ; rvf_free_buf(connect_cfm) ; } /** Handle an RNET_SEND_RDY event; try to send more data if anything is left. * * @param send_rdy Pointer to the event message. */ static void tcpip_handle_rnet_send_rdy(T_RNET_SEND_RDY *send_rdy) { T_sockpar *sockpar ; TRACE_FUNCTION("tcpip_handle_rnet_send_rdy()") ; sockpar = SOCKPAR_GET(send_rdy->desc) ; if( sockpar ) { if (sockpar->send.total_length) { tcpip_try_send_data(sockpar) ; } else { TRACE_EVENT("received RNET_SEND_RDY; no data waiting") ; } }else TRACE_ERROR("tcpip_handle_rnet_send_rdy(): WARNING: sockpar=0"); rvf_free_buf(send_rdy) ; } /** Handle an RNET_RECV_IND event; read incoming data. * * @param recv_ind Pointer to the event message. */ static void tcpip_handle_rnet_recv_ind(T_RNET_RECV_IND *recv_ind) { T_sockpar *sockpar ; /* Socket parameters. */ TRACE_FUNCTION("tcpip_handle_rnet_recv_ind()") ; sockpar = SOCKPAR_GET(recv_ind->desc) ; sockpar->recv_waiting = TRUE ; tcpip_read_incoming_to_app(sockpar) ; rvf_free_buf(recv_ind) ; } /** Handle an RNET_ERROR_IND event; * * @param error_ind Pointer to the event message. */ static void tcpip_handle_rnet_error_ind(T_RNET_ERROR_IND *error_ind) { T_sockpar *sockpar ; TRACE_FUNCTION("tcpip_handle_rnet_error_ind()") ; TRACE_EVENT_P1("RNET_ERROR_IND for socket %08x", error_ind->desc) ; sockpar = SOCKPAR_GET(error_ind->desc) ; if (error_ind->error EQ RNET_CONN_CLOSED) { TRACE_EVENT("RNET_CONN_CLOSED") ; tcpip_conn_closed_ind(sockpar->app_handle, sockpar->s_index) ; } else { /* TODO: this switch looks bogus -- we are only interested in * TCPIP_EVT_CONNECT_CNF, right? Everything else is handled the same * anyway. */ switch (sockpar->expected_event) { case TCPIP_EVT_CONNECT_CNF: TRACE_EVENT("error received when expecting TCPIP_EVT_CONNECT_CNF") ; tcpip_connect_cnf(sockpar->app_handle, rnet_error_to_tcpip_result(error_ind->error), sockpar->s_index) ; break ; case TCPIP_EVT_RECV_IND: TRACE_EVENT("error received when expecting TCPIP_EVT_RECV_IND") ; tcpip_error_ind(sockpar->app_handle, rnet_error_to_tcpip_result(error_ind->error), sockpar->s_index) ; break ; case TCPIP_EVT_CONNECT_IND: TRACE_EVENT("error received when expecting TCPIP_EVT_CONNECT_IND") ; tcpip_error_ind(sockpar->app_handle, rnet_error_to_tcpip_result(error_ind->error), sockpar->s_index) ; break ; default: TRACE_EVENT_P1("error received when expecting unknown event (%d)?", sockpar->expected_event) ; TRACE_ERROR("Unexpected sockpar->expected_event in " "tcpip_handle_rnet_error_ind()") ; tcpip_error_ind(sockpar->app_handle, rnet_error_to_tcpip_result(error_ind->error), sockpar->s_index) ; break ; } } rvf_free_buf(error_ind) ; } /*==== Callback functions ===================================================*/ /** Callback for rnet_get_host_info(). * * @param * @return */ void tcpip_hostinfo_callback(void *msg) { T_RNET_HOST_INFO *hinfo ; T_TCPIP_HOSTINFO_REQ *request ; TRACE_FUNCTION("tcpip_hostinfo_callback()") ; hinfo = msg ; request = hinfo->user_data ; switch (hinfo->error) { case RNET_OK: tcpip_hostinfo_cnf(request->app_handle, TCPIP_RESULT_OK, request->request_id, hinfo->host_name, ngHTONL(hinfo->host_addr)) ; break ; default: tcpip_hostinfo_cnf(request->app_handle, rnet_error_to_tcpip_result(hinfo->error), request->request_id, NULL, 0) ; break ; } PFREE(request) ; //PatternVibrator("o20f10", 1); //rvf_free_buf(msg) ; //PatternVibrator("o20f10", 1); } /** Callback for RNET events. * * @param rv_msg Pointer to Riviera message. */ static void tcpip_rnet_callback(void *rv_msg) { T_RV_HDR *rv_hdr ; /* Header of Riviera message. */ rv_hdr = (T_RV_HDR *) rv_msg ; TRACE_FUNCTION("tcpip_rnet_callback()") ; TRACE_EVENT_P1("rv_hdr->msg_id = %d",rv_hdr->msg_id); switch (rv_hdr->msg_id) { case RNET_CONNECT_IND: TRACE_EVENT("tcpip_rnet_callback() called with RNET_CONNECT_IND") ; tcpip_handle_rnet_connect_ind((T_RNET_CONNECT_IND *) rv_hdr) ; break ; case RNET_CONNECT_CFM: TRACE_EVENT("tcpip_rnet_callback() called with RNET_CONNECT_CFM") ; tcpip_handle_rnet_connect_cfm((T_RNET_CONNECT_CFM *) rv_hdr) ; break ; case RNET_SEND_RDY: TRACE_EVENT("tcpip_rnet_callback() called with RNET_SEND_RDY") ; tcpip_handle_rnet_send_rdy((T_RNET_SEND_RDY *) rv_hdr) ; break ; case RNET_RECV_IND: TRACE_EVENT("tcpip_rnet_callback() called with RNET_RECV_IND") ; tcpip_handle_rnet_recv_ind((T_RNET_RECV_IND *) rv_hdr) ; break ; case RNET_ERROR_IND: TRACE_EVENT("tcpip_rnet_callback() called with RNET_ERROR_IND") ; tcpip_handle_rnet_error_ind((T_RNET_ERROR_IND *) rv_hdr) ; break ; default: TRACE_ERROR("Default: unknown RNET event:") ; TRACE_EVENT_P1("[ERROR] event 0x%08x from RNET\n", rv_hdr->msg_id) ; break ; } } /*==== Other public functions ===============================================*/ /** Shut down RNET and deallocate data. This defined as a separate function * because it will also be called by pei_exit(). * */ void tcpip_do_shutdown(void) { int s_index ; /* Socket index in sock_table[]. */ TRACE_FUNCTION("tcpip_do_shutdown()") ; if (tcpip_data->is_initialized) { /* The error code conversion is done only for the trace in * rnet_error_to_tcpip_result(). It doesn't hurt anyway. */ rnet_error_to_tcpip_result((T_RNET_RET)rnet_rt_stop()) ; rnet_error_to_tcpip_result((T_RNET_RET)rnet_rt_kill()) ; for (s_index = 0; s_index < RNET_RT_SOCK_MAX; s_index++) { T_sockpar *sp ; /* Pointer to socket parameter struct. */ sp = sock_table[s_index] ; if (sp) { tcpip_error_ind(sp->app_handle, TCPIP_RESULT_NETWORK_LOST, sp->s_index) ; sockpar_delete(sp) ; } } tcpip_data->is_initialized = FALSE ; } } /*==== Primitive handler functions ==========================================*/ /** Handle a TCPIP_INITIALIZE_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_initialize_req(void *primdata) { U8 result ; /* Result code of initialization. */ TRACE_FUNCTION("tcpip_initialize_req()") ; /* The variable should be optimized away by the compiler, but it looks * clearer with the initialization call on a separate line. */ result = tcpip_do_initialization() ; tcpip_initialize_cnf(result) ; PFREE(primdata) ; } /** Handle a TCPIP_SHUTDOWN_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_shutdown_req(void *primdata) { TRACE_FUNCTION("tcpip_shutdown_req()") ; tcpip_do_shutdown() ; tcpip_shutdown_cnf(TCPIP_RESULT_OK) ; PFREE(primdata) ; } /** Handle a TCPIP_IFCONFIG_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_ifconfig_req(void *primdata) { T_TCPIP_IFCONFIG_REQ *prim ; NGifnet *netp ; /* Pointer to network interface struct. */ NGuint local_addr ; /* Local address of interface (host byte * order). */ NGuint dest_addr ; /* Destination address (always zero in our * case). */ NGuint netmask ; U8 result = TCPIP_RESULT_INTERNAL_ERROR ; /* Result code of operation. */ /* We don't jump through all the hoops of constructing a message in a * message and sending it to the network interface control function, but * rather twiddle the necessary bits by ourselves. This saves quite some * code and is lots easier to read. */ TRACE_FUNCTION("tcpip_ifconfig_req()") ; prim = (T_TCPIP_IFCONFIG_REQ *) primdata ; /* First, find the network interface. This turned out to be surprisingly * easy. :-) */ netp = &rnet_rt_env_ctrl_blk_p->ifnet_dti.dti_ifnet ; switch (prim->if_up) { case TCPIP_IFCONFIG_DOWN: TRACE_EVENT("ifconfig down") ; netp->if_flags &= ~NG_IFF_UP ; /* Lint loves the void: */ (void) ngProto_IP.pr_cntl_f(NG_CNTL_SET, NG_IPO_NETDOWN, netp) ; result = TCPIP_RESULT_OK ; break ; case TCPIP_IFCONFIG_UP: netp->if_flags |= NG_IFF_UP ; netp->if_mtu = prim->mtu_size ; local_addr = prim->ipaddr ; dest_addr = TCPIP_UNSPECIFIED_IPADDR ; netmask = 0xffffffff ; if (tcpip_data->config_dns_address) { TRACE_EVENT("override dnsaddr1 by address from config primitive") ; prim->dnsaddr1 = tcpip_data->config_dns_address ; } TRACE_EVENT_P3("ifconfig %08x dns %08x, %08x up", ngNTOHL(local_addr), ngNTOHL(prim->dnsaddr1), ngNTOHL(prim->dnsaddr2)) ; ngIfGenCntl(netp, NG_CNTL_SET, NG_IFO_ADDR, &local_addr) ; ngIfGenCntl(netp, NG_CNTL_SET, NG_IFO_DSTADDR, &dest_addr) ; ngIfGenCntl(netp, NG_CNTL_GET, NG_IFO_NETMASK, &netmask) ; (void) ngProto_IP.pr_cntl_f(NG_CNTL_SET, NG_IPO_ROUTE_DEFAULT, &local_addr); (void) ngProto_RESOLV.pr_cntl_f(NG_CNTL_SET, NG_RSLVO_SERV1_IPADDR, &prim->dnsaddr1) ; (void) ngProto_RESOLV.pr_cntl_f(NG_CNTL_SET, NG_RSLVO_SERV2_IPADDR, &prim->dnsaddr2) ; result = TCPIP_RESULT_OK ; break ; default: TRACE_ERROR("ifconfig: bogus prim->if_up value") ; result = TCPIP_RESULT_INVALID_PARAMETER ; break ; } #ifdef _SIMULATION_ tcpip_if_properties(netp) ; #endif /* _SIMULATION_ */ tcpip_ifconfig_cnf(result) ; PFREE(primdata) ; } /** Handle a TCPIP_DTI_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_dti_req(void *primdata) { T_TCPIP_DTI_REQ *prim ; TRACE_FUNCTION("tcpip_dti_req()") ; prim = (T_TCPIP_DTI_REQ *) primdata ; if (prim->dti_direction EQ TCPIP_DTI_TO_LOWER_LAYER) { tcpip_data->ll[0].link_id = prim->link_id ; if(prim->dti_conn == TCPIP_CONNECT_DTI) { if(dti_open(tcpip_data->dti_handle, 0, /* instance */ prim->dti_direction, 0, /* channel */ TCPIP_DTI_QUEUE_SIZE, prim->dti_direction, DTI_QUEUE_WATERMARK, DTI_VERSION_10, #ifdef _SIMULATION_ "SND", #else (U8 *) prim->entity_name, #endif prim->link_id) != TRUE) { TRACE_ERROR("dti_open returns with error") ; } } else { dti_close(tcpip_data->dti_handle,0,prim->dti_direction,0,FALSE); // TCPIP_DISCONNECT_CNF is sent here, because the DTI callback is not called // after DTI2_DISCONNECT_REQ was sent (no CNF-primitive) tcpip_dti_cnf(TCPIP_DISCONNECT_DTI,prim->link_id); } } else { TRACE_ERROR("DTI link to other than upper layer not (yet) supported!") ; } /* The result will be signalled by DTI. */ PFREE(primdata) ; } /** Handle a TCPIP_CREATE_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_create_req(void *primdata) { T_TCPIP_CREATE_REQ *prim = primdata ; T_RNET_RET retval ; T_RNET_DESC *sdesc ; /* The socket descriptor. */ T_RV_RETURN_PATH retpath = { 0, tcpip_rnet_callback } ; T_sockpar *sockpar ; /* Pointer to socket parameter struct ; */ TRACE_FUNCTION("tcpip_create_req()") ; TRACE_EVENT_P1("Calling rnet_new() for ipproto %d", prim->ipproto) ; retval = rnet_new((T_RNET_IPPROTO) prim->ipproto, &sdesc, retpath) ; TRACE_EVENT_P1("rnet_new() returns %d", retval) ; if (retval EQ RNET_OK) { sockpar = sockpar_new(sdesc, prim->app_handle, prim->ipproto, 0) ; TRACE_EVENT_P1("New socket is %d", sockpar->s_index) ; if (sockpar EQ NULL) { tcpip_create_cnf(prim->app_handle, TCPIP_RESULT_INTERNAL_ERROR, 0, prim->request_id) ; rnet_close(sdesc) ; } else { rnet_set_user_data(sdesc, (void *) sockpar) ; tcpip_create_cnf(prim->app_handle, TCPIP_RESULT_OK, sockpar->s_index, prim->request_id) ; } } else { tcpip_create_cnf(prim->app_handle, rnet_error_to_tcpip_result(retval), 0, prim->request_id) ; } PFREE(primdata) ; } /** Handle a TCPIP_CLOSE_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_close_req(void *primdata) { T_TCPIP_CLOSE_REQ *prim = primdata ; T_RNET_RET retval ; /* Return value of rnet_close(). */ T_sockpar *sockpar ; /* Socket parameter block. */ T_RNET_DESC *sdesc ; /* Socket descriptor. */ TRACE_FUNCTION("tcpip_close_req()") ; if (INVALID_S_INDEX(prim->socket)) { TRACE_ERROR("Invalid socket index in tcpip_close_req()") ; tcpip_close_cnf(prim->app_handle, TCPIP_RESULT_INVALID_PARAMETER, prim->socket) ; } else { sdesc = SOCK_RT_DESC(prim->socket) ; sockpar = SOCKPAR_GET(sdesc) ; TRACE_EVENT_P1("Calling rnet_close() for socket %d", sockpar->s_index) ; retval = rnet_close(sdesc) ; TRACE_EVENT_P1("rnet_close() returns %d", retval) ; tcpip_close_cnf(prim->app_handle, (U8) ((retval EQ RNET_OK) ? TCPIP_RESULT_OK : rnet_error_to_tcpip_result(retval)), prim->socket) ; sockpar_delete(sockpar) ; } PFREE(primdata) ; } /** Handle a TCPIP_BIND_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_bind_req(void *primdata) { T_TCPIP_BIND_REQ *prim = primdata ; T_RNET_RET retval ; /* Return value of rnet_bind(). */ T_RNET_DESC *sdesc ; /* Socket descriptor. */ TRACE_FUNCTION("tcpip_bind_req()") ; if (INVALID_S_INDEX(prim->socket)) { TRACE_ERROR("Invalid socket index in tcpip_bind_req()") ; tcpip_bind_cnf(prim->app_handle, TCPIP_RESULT_INVALID_PARAMETER, prim->socket) ; } else { sdesc = SOCK_RT_DESC(prim->socket) ; TRACE_EVENT_P2("Calling rnet_bind() for socket %d port %d", prim->socket, prim->port) ; retval = rnet_bind(sdesc, TCPIP_UNSPECIFIED_IPADDR, (U16) ngNTOHS(prim->port)) ; TRACE_EVENT_P1("rnet_bind() returns %d", retval) ; tcpip_bind_cnf(prim->app_handle, (U8) ((retval EQ RNET_OK) ? TCPIP_RESULT_OK : rnet_error_to_tcpip_result(retval)), prim->socket) ; } PFREE(primdata) ; } /** Handle a TCPIP_LISTEN_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_listen_req(void *primdata) { T_TCPIP_LISTEN_REQ *prim = primdata ; T_RNET_RET retval ; /* Return value of rnet_listen(). */ T_RNET_DESC *sdesc ; /* Socket descriptor. */ TRACE_FUNCTION("tcpip_listen_req()") ; if (INVALID_S_INDEX(prim->socket)) { TRACE_ERROR("Invalid socket index in tcpip_listen_req()") ; tcpip_listen_cnf(prim->app_handle, TCPIP_RESULT_INVALID_PARAMETER, prim->socket) ; } else { sdesc = SOCK_RT_DESC(prim->socket) ; TRACE_EVENT_P1("Calling rnet_listen() for socket %d", prim->socket) ; retval = rnet_listen(sdesc) ; TRACE_EVENT_P1("rnet_listen() returns %d", retval) ; switch (retval) { case RNET_OK: socket_expect_event(sdesc, TCPIP_EVT_CONNECT_IND) ; tcpip_listen_cnf(prim->app_handle, TCPIP_RESULT_OK, prim->socket) ; break ; default: tcpip_listen_cnf(prim->app_handle, rnet_error_to_tcpip_result(retval), prim->socket) ; break ; } } PFREE(primdata) ; } /** Handle a TCPIP_CONNECT_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_connect_req(void *primdata) { T_TCPIP_CONNECT_REQ *prim = primdata ; T_RNET_RET retval ; /* Return value of rnet_connect(). */ T_RNET_DESC *sdesc ; /* Socket descriptor. */ T_sockpar *sockpar ; /* Socket parameter block. */ TRACE_FUNCTION("tcpip_connect_req()") ; if (INVALID_S_INDEX(prim->socket)) { TRACE_ERROR("Invalid socket index in tcpip_connect_req()") ; tcpip_connect_cnf(prim->app_handle, TCPIP_RESULT_INVALID_PARAMETER, prim->socket) ; } else { sdesc = SOCK_RT_DESC(prim->socket) ; socket_expect_event(sdesc, TCPIP_EVT_CONNECT_CNF) ; TRACE_EVENT_P3("Calling rnet_connect() for socket %d ipaddr %x port %d", prim->socket, ngNTOHL(prim->ipaddr), ngNTOHS(prim->port)) ; retval = rnet_connect(sdesc, ngNTOHL(prim->ipaddr), (U16) ngNTOHS(prim->port)) ; TRACE_EVENT_P1("rnet_connect() returns %d", retval) ; sockpar = SOCKPAR_GET(sdesc) ; switch (sockpar->ipproto) { case TCPIP_IPPROTO_TCP: if (retval EQ RNET_OK) { TRACE_EVENT("wait... TCPIP_CONNECT_CNF"); /* Wait for the result of the connect; we will send a * TCPIP_CONNECT_CNF then. */ } else { tcpip_connect_cnf(prim->app_handle, rnet_error_to_tcpip_result(retval), prim->socket) ; socket_expect_event(sdesc, 0) ; } break ; case TCPIP_IPPROTO_UDP: sockpar->is_connected = TRUE ; tcpip_connect_cnf(prim->app_handle, rnet_error_to_tcpip_result(retval), prim->socket) ; socket_expect_event(sdesc, 0) ; break ; default: TRACE_ERROR("unknown protocol in tcpip_connect_req()!?") ; break ; } } PFREE(primdata) ; } /** Handle a TCPIP_DATA_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_data_req(void *primdata) { T_TCPIP_DATA_REQ *prim = primdata ; T_sockpar *sockpar ; T_RNET_DESC *sdesc ; /* Socket descriptor. */ TRACE_FUNCTION("tcpip_data_req()") ; if (INVALID_S_INDEX(prim->socket)) { tcpip_data_cnf(prim->app_handle, TCPIP_RESULT_INVALID_PARAMETER, prim->socket, 0) ; TRACE_ERROR("Invalid socket index in tcpip_data_req()") ; } else { sdesc = SOCK_RT_DESC(prim->socket) ; sockpar = SOCKPAR_GET(sdesc) ; if (sockpar->send.total_length) { /* We haven't sent the previous block completely, but the API already * sends more data. That must be an error -- either an error of the * socket API or we have sent out a TCPIP_DATA_CNF too early. */ TRACE_ERROR("tcpip_data_req: new data although old data is still left") ; tcpip_data_cnf(prim->app_handle, TCPIP_RESULT_INTERNAL_ERROR, prim->socket, 0) ; } else if (!sockpar->is_connected AND (sockpar->ipproto EQ TCPIP_IPPROTO_TCP OR prim->ipaddr EQ 0 OR prim->port EQ 0)) { /* Application tried to send on a non-connected TCP socket or a * non-connected UDP socket without specifying IP address and port * number. RNET or, respectively, NexGenIP does for some reason not * catch this error, so we do it here. */ tcpip_data_cnf(prim->app_handle, TCPIP_RESULT_NOT_CONNECTED, prim->socket, 1) ; } else /* Finally ok. */ { sockpar->send.total_length = prim->buflen ; sockpar->send.offset = 0 ; #ifdef _SIMULATION_ prim->data = tcpip_sim_fake_data(prim->socket, prim->buflen) ; #endif /* _SIMULATION_ */ sockpar->send.buffer = (U8 *) prim->data ; tcpip_try_send_data(sockpar) ; } } PFREE(primdata) ; } /** Handle a TCPIP_DATA_RES primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_data_res(void *primdata) { T_TCPIP_DATA_RES *prim = primdata ; T_sockpar *sockpar ; TRACE_FUNCTION("tcpip_data_res()") ; if (INVALID_S_INDEX(prim->socket)) { /* Do nothing -- what *could* we do in response to a response? */ TRACE_ERROR("Invalid socket index in tcpip_data_res()") ; } else { TRACE_EVENT("switch flow control towards application to xon") ; sockpar = sock_table[prim->socket] ; sockpar->appl_xoff = FALSE ; dti_start(tcpip_data->dti_handle, 0, TCPIP_DTI_TO_LOWER_LAYER, 0) ; // when receive the application data confrim then allow SNDCP send next data package 05132008 // OMAPS00172999 fix if (sockpar->recv_waiting) { tcpip_read_incoming_to_app(sockpar) ; } } PFREE(primdata) ; } /** Handle a TCPIP_SOCKNAME_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_sockname_req(void *primdata) { T_TCPIP_SOCKNAME_REQ *prim = primdata ; T_RNET_RET retval ; T_RNET_IP_ADDR ipaddr ; T_RNET_PORT port ; T_RNET_DESC *sdesc ; /* The socket descriptor. */ TRACE_FUNCTION("tcpip_sockname_req()") ; if (INVALID_S_INDEX(prim->socket)) { TRACE_ERROR("Invalid socket index in tcpip_sockname_req()") ; tcpip_sockname_cnf(prim->app_handle, TCPIP_RESULT_INVALID_PARAMETER, prim->socket, TCPIP_UNSPECIFIED_IPADDR, TCPIP_UNSPECIFIED_PORT) ; } else { sdesc = SOCK_RT_DESC(prim->socket) ; TRACE_EVENT_P1("Calling rnet_get_local_addr_port() for socket %d", prim->socket) ; retval = rnet_get_local_addr_port(sdesc, &ipaddr, &port) ; TRACE_EVENT_P3("rnet_get_local_addr_port() returns %d, " "ipaddr %d port %d", retval, ipaddr, port) ; switch (retval) { case RNET_OK: tcpip_sockname_cnf(prim->app_handle, TCPIP_RESULT_OK, prim->socket, ngHTONL(ipaddr), (U16) ngHTONS(port)) ; break ; default: tcpip_sockname_cnf(prim->app_handle, rnet_error_to_tcpip_result(retval), prim->socket, TCPIP_UNSPECIFIED_IPADDR, TCPIP_UNSPECIFIED_PORT) ; break ; } } PFREE(primdata) ; } /** Handle a TCPIP_PEERNAME_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_peername_req(void *primdata) { T_TCPIP_PEERNAME_REQ *prim = primdata ; T_RNET_RET retval ; T_RNET_DESC *sdesc ; /* The socket descriptor. */ NGsockaddr addr ; /* Socket address struct. */ int optlen ; /* Length of option (address struct). */ TRACE_FUNCTION("tcpip_peername_req()") ; if (INVALID_S_INDEX(prim->socket)) { TRACE_ERROR("Invalid socket index in tcpip_peername_req()") ; tcpip_peername_cnf(prim->app_handle, TCPIP_RESULT_INVALID_PARAMETER, prim->socket, TCPIP_UNSPECIFIED_IPADDR, TCPIP_UNSPECIFIED_PORT) ; } else { sdesc = SOCK_RT_DESC(prim->socket) ; optlen = sizeof(addr) ; TRACE_EVENT_P1("Calling ngSAIOGetOption() for peername socket %d", prim->socket) ; retval = (T_RNET_RET) ngSAIOGetOption((NGsock *) sdesc, NG_IOCTL_SOCKET, NG_SO_PEERNAME, &addr, &optlen) ; TRACE_EVENT_P3("ngSAIOGetOption() returns %d ipaddr %x port %d (net order)", retval, addr.sin_addr, addr.sin_port) ; switch (rnet_rt_ngip_error(retval)) { case RNET_OK: tcpip_peername_cnf(prim->app_handle, TCPIP_RESULT_OK, prim->socket, addr.sin_addr, addr.sin_port) ; break ; default: tcpip_peername_cnf(prim->app_handle, rnet_error_to_tcpip_result(retval), prim->socket, TCPIP_UNSPECIFIED_IPADDR, TCPIP_UNSPECIFIED_PORT) ; break ; } } PFREE(primdata) ; } /** Handle a TCPIP_HOSTINFO_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_hostinfo_req(void *primdata) { T_TCPIP_HOSTINFO_REQ *prim = primdata ; T_RV_RETURN_PATH retpath = { 0, tcpip_hostinfo_callback } ; /* Trick: We use the primitive itself as user data for the RNET call. This * way we do not have to allocate extra memory to save the request_id and * the app_handle. */ TRACE_FUNCTION("tcpip_hostinfo_req()") ; switch (rnet_get_host_info((char *) prim->hostname, ngNTOHL(prim->ipaddr), retpath, primdata)) { case RNET_OK: /* We now wait for the hostinfo callback being called. */ break ; case RNET_MEMORY_ERR: tcpip_hostinfo_cnf(prim->app_handle, TCPIP_RESULT_OUT_OF_MEMORY, prim->request_id, NULL, TCPIP_UNSPECIFIED_IPADDR) ; PFREE(prim) ; break ; default: /* Unexpected error code. */ tcpip_hostinfo_cnf(prim->app_handle, TCPIP_RESULT_INTERNAL_ERROR, prim->request_id, NULL, TCPIP_UNSPECIFIED_IPADDR) ; PFREE(prim) ; break ; } /* Do *not* PFREE(primdata) -- the primitive is used as userdata for the * RNET call. */ } /** Handle a TCPIP_MTU_SIZE_REQ primitive from the Socket API. * * @param primdata Data part of the primitive. */ void tcpip_mtu_size_req(void *primdata) { T_TCPIP_MTU_SIZE_REQ *prim = primdata ; TRACE_FUNCTION("tcpip_mtu_size_req()") ; if (INVALID_S_INDEX(prim->socket)) { TRACE_ERROR("Invalid socket index in tcpip_mtu_size_req()") ; tcpip_mtu_size_cnf(prim->app_handle, TCPIP_RESULT_INVALID_PARAMETER, prim->socket, TCPIP_DEFAULT_MTU_SIZE) ; } else { /* The MTU size is usually not negotiated between the network and the * mobile station. It is guaranteed, though, that it is not less than 1500 * bytes, and that is what we report here. This might be changed to some * "real" value queried from the interface when the need comes up. */ tcpip_mtu_size_cnf(prim->app_handle, TCPIP_RESULT_OK, prim->socket, TCPIP_DEFAULT_MTU_SIZE) ; } PFREE(primdata) ; } /** Handle a TCPIP_INTERNAL_IND primitive sent by TCPIP itself. * * @param primdata Data part of the primitive. * @return */ void tcpip_internal_ind(void *primdata) { T_TCPIP_INTERNAL_IND *prim = primdata ; T_RVM_RETURN retval ; TRACE_FUNCTION("tcpip_internal_ind()") ; TRACE_EVENT_P1("received TCPIP_INTERNAL_IND id %d", prim->msg_id) ; retval = rnet_rt_handle_message((T_RV_HDR *) prim->msg_p) ; if (retval != RV_OK) { TRACE_EVENT_P1("rnet_rt_handle_message() returned %d", retval) ; } PFREE(primdata) ; } /* EOF */