/* TCP/IP based Transport Service for RPC ts_tcp.c ** ====================================== ** ** This module provides a transport service for the RPC system developed ** by CERN/DD Online group in 1986-90. ** ** This particular module uses the xistsing TCP/IP protocol. ** See the RPC User Manual for details of address syntax. ** ** See also the RPC internals manual, which describes how modules ** similar to this one work, also giving flow charts and message formats. ** ** History: ** 30 Apr 90 Code extracted from general ts.c module. ** ** Compilation switches: ** */ /* Module parameters: ** ----------------- ** ** These may be undefined and redefined by syspec.h */ # define WILDCARD '*' /* Wildcard used in addressing */ #include #include "syspec.h" #define TS /* Require visibility of TS data structures */ #include "rpcrts.h" /* Define all general RPC data structures */ #include "rpc_code.h" /* Coding convention macros */ #include "ts.h" /* protocol type structure */ /* ** Definitions for pointers */ #define NIL_MESSAGE (rpc_message *)0 extern char *malloc(); extern void free(); extern char *strncpy(); /* External Routines ** ----------------- */ extern void rpc_new(); /* Allocate rpc_message */ extern void rpc_dispose(); /* Deallocate rpc_message */ extern void rpc_get_string(); /* Get Pascal or C string parameter */ #ifdef AST /* Always used by CATS !!!!!! */ extern void sys_setast(); /* En/Disable ASTs */ rpc_status ts_when_receive(); /* forward (ASTs only) */ #endif /* Return RPC address of this socket tcp_my_address() ** --------------------------------- ** ** This routine returns a string indicating the RPC address of the socket. ** ** On entry, ** soc should be a valid socket pointer ** addrstr points to a buffer to contain a string. ** addrlen indicates the length of the string buffer ** ** On exit, ** *addrstr has the contact address for an external node wishing to contact ** this socket written into it, zero terminated, without the ** protocol on the end. */ #ifdef __STDC__ PRIVATE rpc_status tcp_my_address( socket_type soc, chr * addrstr, int addrlen) #else PRIVATE rpc_status tcp_my_address(soc, addrstr, addrlen) socket_type soc; char * addrstr; int addrlen; #endif { @@@ } /* Return RPC address of peer tcp_peer_address() ** -------------------------- ** ** On entry, ** soc should be a valid socket pointer ** address points to a buffer to contain an rpc_name. ** ** On exit, ** *address has the contact address for the peer node. ** blank filled. ** 26 useful characters in the address. */ #ifdef __STDC__ PRIVATE rpc_status tcp_peer_address( socket_type soc, char * addrstr, int addrlen) #else PRIVATE rpc_status tcp_peer_address(soc, addrstr, addrlen) socket_type soc; char * addrstr; int addrlen; #endif { @@@ } /* Send a message over the given socket tcp_write() ** ------------------------------------ ** ** On entry, ** pmessage points to a pointer to the message, with fields: ** m_next (undefined) ** m_socket valid ** m_index Length of message to be sent in bytes, ** exclusing any bytes needed for the protocol. ** m_status (undefined) ** ** On exit, ** ** The pointer to the message may have been changed. In this case, ** it will point to a message with the m_socket and m_status fields ** set, but without the data. This routine is therefore DESTRUCTIVE. ** ** returns: Status of operation. */ #ifdef __STDC__ PRIVATE rpc_status tcp_write(rpc_message_pointer *ppmessage) #else PRIVATE rpc_status tcp_write(ppmessage) rpc_message_pointer *ppmessage; #endif { rpc_status status; register rpc_message *mes = *ppmessage; register struct socket_struct *soc = mes->m_socket; status = check_socket(soc); if (BAD(status)) return status; if (rpc_trace) { UTRACE(tfp, "RPC/tcp: Sending message, "); hex_message(mes, mes->m_index); } @@@ return status; } /* Receive message tcp_read() ** --------------- ** ** This procedure waits for a message to arrive on a socket and returns the ** message. A suitable message buffer is passed to the routine, but a ** different one may be returned. If the socket passed is the master socket ** for mutiple connections, then the message recieved will carry the socket ** number of the slave socket on which the message actually arrived. ** ** On entry: ** ppmessage is pointer to pointer to buffer, fields: ** m_socket The socket to be used - possibly a master socket ** m_index don't care ** m_status don't care ** m_next don't care ** ** timeout -1 for infinite, 0 for poll, else in units of 10ms ** ** On exit, ** returns The status of the operation. ** *pmessage may have been modified to point to another message ** from the pool. Fields: ** m_socket The (possible slave) socket the msg came on. ** m_status The status of the operation (= return value). ** m_index The number of bytes recieved if good status ** m_next junk. ** */ #ifdef __STDC__ PRIVATE rpc_status tcp_read( rpc_message_pointer *ppmessage, int timeout) #else PRIVATE rpc_status tcp_read(ppmessage, timeout) rpc_message_pointer *ppmessage; int timeout; #endif { @@@ return status; } /* Asynchronous Receive ** -------------------- ** ** On entry, ** pmessage is the address of a suitable message buffer ** action is the address of the routine to be called ** user_1 is not used at the moment. ** ** On exit, ** the parameters are stored only. Exits immediately. ** ** On arrival of the next message: ** The routine *action() is called, and passed the message as a parameter. ** If the buffer *pmessage is not used, it will be reused elsewhere and ** a different buffer passed to *action(). */ #ifdef __STDC__ PRIVATE rpc_status tcp_aread( rpc_message_pointer pmessage, rpc_pointer action, rpc_integer user_1) #else PRIVATE rpc_status tcp_aread(pmessage, action, user_1) rpc_message_pointer pmessage; rpc_pointer action; rpc_integer user_1; #endif { return(RPC_S_NOT_IMPLEMENTED); } /* tcp_aread */ /* Open a transport connection tcp_open() ** --------------------------- ** ** On entry, ** soc points to a recently created socket, fields as follows: ** ** soc_last_call_sent NULL ** soc_last_reply_sent NULL ** soc_next-call_tid 0 ** soc_protocol valid pointer to protocol structure ** ** and otherwise uninitialised. ** ** tsap points to a zero-terminated string representing the address ** (with no .TCP on it) */ #ifdef __STDC__ PRIVATE rpc_status tcp_open(socket_type soc, char * tsap) #else PRIVATE rpc_status tcp_open(soc, tsap) socket_type soc; char *tsap; #endif { @@@ } /* Close a Transport Connection tcp_close() ** ---------------------------- ** ** On entry, ** soc Must be a socket opened by tcp_open(). ** ** On exit, ** returns a status of the close operation. */ #ifdef __STDC__ PRIVATE rpc_status tcp_close(socket_type soc) #else PRIVATE rpc_status tcp_close(soc) socket_type soc; #endif { @@@ } /* tcp_close */ /* Data structure defining this medium: ** ----------------------------------- */ PRIVATE rpc_protocol tcp_protocol = { 0, /* Link (not yet used) */ "tcp", /* Name of medium used in address strings */ 0, /* No, not reliable */ tcp_open, tcp_close, tcp_write, tcp_read, tcp_aread, tcp_my_address, tcp_peer_address, }; /* Register this protocol with the RPC system ** ------------------------------------------ */ #ifdef __STDC__ rpc_status use_tcp(void) #else rpc_status use_tcp() #endif { rpc_tcp_init(); /* Initialise any machine-dependent stuff */ rpc_use(tcp_protocol); }