/* * clnt_udp.c, Implements a UDP/IP based, client side RPC. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include /* program is the identifier of the service on the server */ /* A service can be implemented in different successive versions, version specifies which one you want to call */ struct cu_data * ClntUdp_create(hostname, program, version) char *hostname; u_long program; u_long version; { register int sockp; register struct cu_data *cu; struct rpc_msg call_msg; struct hostent *h; struct protoent *p; struct sockaddr_in sin; /* cu is the structure that stores all data related to the RPC */ /* allocation of a buffer for sending and receiving data */ sendsz = ((UDPMSGSIZE + 3) / 4) * 4; recvsz = ((UDPMSGSIZE + 3) / 4) * 4; cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz); cu->cu_outbuf = &cu->cu_inbuf[recvsz]; cu->cu_sendsz = sendsz; cu->cu_recvsz = recvsz; /* retrieve the IP address of the server, from its name */ h = gethostbyname(hostname); sin.sin_family = h->h_addrtype; sin.sin_port = 0; bzero(sin.sin_zero, sizeof(sin.sin_zero)); bcopy(h->h_addr, (char*)&sin.sin_addr, h->h_length); cu->cu_raddr = sin; cu->cu_rlen = sizeof (cu->cu_raddr); /* binding (client/server) id */ call_msg.rm_xid = getpid(); /* Constant header that is prepend to the procedure signature */ call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; call_msg.rm_call.cb_prog = program; call_msg.rm_call.cb_vers = version; /* init of the structure cu_outxdrs which control encoding (decoding) */ /* Encoding (Marshalling) result will be stored in the */ /* output buffer (cu->cu_outbuf) */ Xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE); /* Encoding of the constant header */ /* This is done once, then the result is reused for each subsequent rpc */ Xdr_callhdr(&(cu->cu_outxdrs), &call_msg); cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs)); /* socket initialization and server binding */ sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); (void)bindresvport(*sockp, (struct sockaddr_in *)0); cu->cu_sock = sockp; return cu; }