home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / comm / amitcp-3.0ß2.lha / AmiTCP / src / rpclib / clnt_tcp.c < prev    next >
C/C++ Source or Header  |  1994-03-09  |  13KB  |  507 lines

  1. /*
  2.  * $Id: clnt_tcp.c,v 1.2 1993/11/10 01:46:31 jraja Exp $
  3.  *
  4.  * $Log: clnt_tcp.c,v $
  5.  * Revision 1.2  1993/11/10  01:46:31  jraja
  6.  * Fixed includes, added ANSI prototypes.
  7.  * Fixed various types.
  8.  * Added AMIGA specific includes.
  9.  * Changed close() to CloseSocket() for the AMITCP.
  10.  * Changed read() to recv() and write() to send() for portability.
  11.  * Removed EINTR handling for the AMITCP (lets CTRL-C come through).
  12.  *
  13.  */
  14. /* @(#)clnt_tcp.c    2.2 88/08/01 4.0 RPCSRC */
  15. /*
  16.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  17.  * unrestricted use provided that this legend is included on all tape
  18.  * media and as a part of the software program in whole or part.  Users
  19.  * may copy or modify Sun RPC without charge, but are not authorized
  20.  * to license or distribute it to anyone else except as part of a product or
  21.  * program developed by the user.
  22.  * 
  23.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  24.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  25.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  26.  * 
  27.  * Sun RPC is provided with no support and without any obligation on the
  28.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  29.  * modification or enhancement.
  30.  * 
  31.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  32.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  33.  * OR ANY PART THEREOF.
  34.  * 
  35.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  36.  * or profits or other special, indirect and consequential damages, even if
  37.  * Sun has been advised of the possibility of such damages.
  38.  * 
  39.  * Sun Microsystems, Inc.
  40.  * 2550 Garcia Avenue
  41.  * Mountain View, California  94043
  42.  */
  43. #if !defined(lint) && defined(SCCSIDS)
  44. static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
  45. #endif
  46.  
  47. /*
  48.  * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
  49.  *
  50.  * Copyright (C) 1984, Sun Microsystems, Inc.
  51.  *
  52.  * TCP based RPC supports 'batched calls'.
  53.  * A sequence of calls may be batched-up in a send buffer.  The rpc call
  54.  * return immediately to the client even though the call was not necessarily
  55.  * sent.  The batching occurs if the results' xdr routine is NULL (0) AND
  56.  * the rpc timeout value is zero (see clnt.h, rpc).
  57.  *
  58.  * Clients should NOT casually batch calls that in fact return results; that is,
  59.  * the server side should be aware that a call is batched and not produce any
  60.  * return message.  Batched calls that produce many result messages can
  61.  * deadlock (netlock) the client and the server....
  62.  *
  63.  * Now go hang yourself.
  64.  */
  65.  
  66. #include <sys/param.h>
  67. #include <rpc/rpc.h>
  68. #include <sys/socket.h>
  69. #include <netdb.h>
  70. #include <errno.h>
  71. #include <rpc/pmap_clnt.h>
  72. #include <stdio.h>
  73.  
  74. #ifdef AMIGA
  75. #include <proto/exec.h>
  76. #endif
  77.  
  78. #define MCALL_MSG_SIZE 24
  79.  
  80. static int    readtcp(struct ct_data * ct, caddr_t buf, int len);
  81. static int    writetcp(struct ct_data * ct, caddr_t buf, int len);
  82.  
  83. static enum clnt_stat    clnttcp_call(CLIENT * h, u_long proc,
  84.                      xdrproc_t xdr_args, caddr_t args_ptr,
  85.                      xdrproc_t xdr_results,
  86.                      caddr_t results_ptr,
  87.                      struct timeval timeout);
  88. static void        clnttcp_abort(CLIENT * h);
  89. static void        clnttcp_geterr(CLIENT * h, struct rpc_err * errp);
  90. static bool_t        clnttcp_freeres(CLIENT * cl, 
  91.                     xdrproc_t xdr_res, caddr_t res_ptr);
  92. static bool_t           clnttcp_control(CLIENT * cl,
  93.                     u_int request, caddr_t info);
  94. static void        clnttcp_destroy(CLIENT * h);
  95.  
  96. static struct clnt_ops tcp_ops = {
  97.     clnttcp_call,
  98.     clnttcp_abort,
  99.     clnttcp_geterr,
  100.     clnttcp_freeres,
  101.     clnttcp_destroy,
  102.     clnttcp_control
  103. };
  104.  
  105. struct ct_data {
  106.     int        ct_sock;
  107.     bool_t        ct_closeit;
  108.     struct timeval    ct_wait;
  109.     bool_t          ct_waitset;       /* wait set by clnt_control? */
  110.     struct sockaddr_in ct_addr; 
  111.     struct rpc_err    ct_error;
  112.     char        ct_mcall[MCALL_MSG_SIZE];    /* marshalled callmsg */
  113.     u_int        ct_mpos;            /* pos after marshal */
  114.     XDR        ct_xdrs;
  115. };
  116.  
  117. /*
  118.  * Create a client handle for a tcp/ip connection.
  119.  * If *sockp<0, *sockp is set to a newly created TCP socket and it is
  120.  * connected to raddr.  If *sockp non-negative then
  121.  * raddr is ignored.  The rpc/tcp package does buffering
  122.  * similar to stdio, so the client must pick send and receive buffer sizes,];
  123.  * 0 => use the default.
  124.  * If raddr->sin_port is 0, then a binder on the remote machine is
  125.  * consulted for the right port number.
  126.  * NB: *sockp is copied into a private area.
  127.  * NB: It is the clients responsibility to close *sockp.
  128.  * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
  129.  * something more useful.
  130.  */
  131. CLIENT *
  132. clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
  133.     struct sockaddr_in *raddr;
  134.     u_long prog;
  135.     u_long vers;
  136.     register int *sockp;
  137.     u_int sendsz;
  138.     u_int recvsz;
  139. {
  140.     CLIENT *h;
  141.     register struct ct_data *ct = NULL;
  142.     struct timeval now;
  143.     struct rpc_msg call_msg;
  144.  
  145.     h  = (CLIENT *)mem_alloc(sizeof(*h));
  146.     if (h == NULL) {
  147.         (void)fprintf(stderr, "clnttcp_create: out of memory\n");
  148.         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  149.         rpc_createerr.cf_error.re_errno = errno;
  150.         goto fooy;
  151.     }
  152.     ct = (struct ct_data *)mem_alloc(sizeof(*ct));
  153.     if (ct == NULL) {
  154.         (void)fprintf(stderr, "clnttcp_create: out of memory\n");
  155.         rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  156.         rpc_createerr.cf_error.re_errno = errno;
  157.         goto fooy;
  158.     }
  159.  
  160.     /*
  161.      * If no port number given ask the pmap for one
  162.      */
  163.     if (raddr->sin_port == 0) {
  164.         u_short port;
  165.         if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
  166.              goto fooy;
  167.         }
  168.         raddr->sin_port = htons(port);
  169.     }
  170.  
  171.     /*
  172.      * If no socket given, open one
  173.      */
  174.     if (*sockp < 0) {
  175.         *sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  176.         (void)bindresvport(*sockp, (struct sockaddr_in *)0);
  177.         if ((*sockp < 0)
  178.             || (connect(*sockp, (struct sockaddr *)raddr,
  179.             sizeof(*raddr)) < 0)) {
  180.             rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  181.             rpc_createerr.cf_error.re_errno = errno;
  182. #ifdef AMITCP
  183.             (void)CloseSocket(*sockp);
  184. #else
  185.             (void)close(*sockp);
  186. #endif
  187.             goto fooy;
  188.         }
  189.         ct->ct_closeit = TRUE;
  190.     } else {
  191.         ct->ct_closeit = FALSE;
  192.     }
  193.  
  194.     /*
  195.      * Set up private data struct
  196.      */
  197.     ct->ct_sock = *sockp;
  198.     ct->ct_wait.tv_usec = 0;
  199.     ct->ct_waitset = FALSE;
  200.     ct->ct_addr = *raddr;
  201.  
  202.     /*
  203.      * Initialize call message
  204.      */
  205.     (void)gettimeofday(&now, NULL);
  206. #ifdef AMIGA
  207.     call_msg.rm_xid = (u_long)FindTask(NULL) ^ now.tv_sec ^ now.tv_usec;
  208. #else
  209.     call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
  210. #endif
  211.     call_msg.rm_direction = CALL;
  212.     call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  213.     call_msg.rm_call.cb_prog = prog;
  214.     call_msg.rm_call.cb_vers = vers;
  215.  
  216.     /*
  217.      * pre-serialize the static part of the call msg and stash it away
  218.      */
  219.     xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
  220.         XDR_ENCODE);
  221.     if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
  222.         if (ct->ct_closeit) {
  223. #ifdef AMITCP
  224.             (void)CloseSocket(*sockp);
  225. #else
  226.             (void)close(*sockp);
  227. #endif
  228.         }
  229.         goto fooy;
  230.     }
  231.     ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
  232.     XDR_DESTROY(&(ct->ct_xdrs));
  233.  
  234.     /*
  235.      * Create a client handle which uses xdrrec for serialization
  236.      * and authnone for authentication.
  237.      */
  238.     xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
  239.         ct, readtcp, writetcp);
  240.     h->cl_ops = &tcp_ops;
  241.     h->cl_private = (caddr_t) ct;
  242.     h->cl_auth = authnone_create();
  243.     return (h);
  244.  
  245. fooy:
  246.     /*
  247.      * Something goofed, free stuff and barf
  248.      */
  249.     if (ct) 
  250.       mem_free((caddr_t)ct, sizeof(struct ct_data));
  251.     if (h)
  252.       mem_free((caddr_t)h, sizeof(CLIENT));
  253.     return ((CLIENT *)NULL);
  254. }
  255.  
  256. static enum clnt_stat
  257. clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
  258.     register CLIENT *h;
  259.     u_long proc;
  260.     xdrproc_t xdr_args;
  261.     caddr_t args_ptr;
  262.     xdrproc_t xdr_results;
  263.     caddr_t results_ptr;
  264.     struct timeval timeout;
  265. {
  266.     register struct ct_data *ct = (struct ct_data *) h->cl_private;
  267.     register XDR *xdrs = &(ct->ct_xdrs);
  268.     struct rpc_msg reply_msg;
  269.     u_long x_id;
  270.     u_long *msg_x_id = (u_long *)(ct->ct_mcall);    /* yuk */
  271.     register bool_t shipnow;
  272.     int refreshes = 2;
  273.  
  274.     if (!ct->ct_waitset) {
  275.         ct->ct_wait = timeout;
  276.     }
  277.  
  278.     shipnow =
  279.         (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
  280.         && timeout.tv_usec == 0) ? FALSE : TRUE;
  281.  
  282. call_again:
  283.     xdrs->x_op = XDR_ENCODE;
  284.     ct->ct_error.