linux rpc

44
Linux RPC Comer Chapter 21 (RPCgen Concept) RFC 1057 – RPC Spec. UNIX Network Programming - Stevens 1

Upload: dean-holt

Post on 31-Dec-2015

28 views

Category:

Documents


0 download

DESCRIPTION

Linux RPC. Comer Chapter 21 (RPCgen Concept) RFC 1057 – RPC Spec. UNIX Network Programming - Stevens. Sockets API Limitations. Must explicitly account for differences in systems Byte order (big-endian / little-endian) Limited to sending characters (without tricking the system) - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Linux RPC

Linux RPC

Comer Chapter 21(RPCgen Concept)

RFC 1057 – RPC Spec.UNIX Network Programming - Stevens

1

Page 2: Linux RPC

Sockets API Limitations

• Must explicitly account for differences in systems– Byte order (big-endian / little-endian)

• Limited to sending characters (without tricking the system)– requires source and destination to implicitly

understand the data transformation.

2

Page 3: Linux RPC

Client / Server Between SystemsOne Solution:

• eXternal Data Representation (XDR)

• Developed by Sun Microsystems

• A standard for representing data over the network.

• Includes a set of library routines for converting data between local format and XDR format (either direction).

3

Page 4: Linux RPC

XDR Data Types• int 32 bits• unsigned int 32 bits• bool 32 bits• enum arbitrary• hyper 64 bits• unsigned hyper 64 bits• float 32 bits• double 64 bits• opaque arbitrary

• String arbitrary• fixed array arbitrary• counted array arbitrary• structure arbitrary• discriminated union arbitrary.• void 0• symbolic constant arbitrary• optional data arbitrary

4

Page 5: Linux RPC

XDR Data Conversion

• Objective:– Gather all parameter data into a buffer in XDR

format

• Procedure:– Create a buffer (xdrmem_create)

5

Page 6: Linux RPC

XDR Data Conversion

• Objective:– Gather all parameter data into a buffer in XDR

format

• Procedure:– Create a buffer (xdrmem_create)

6

#include <rpc/xdr.h>#define BUFSIZE 4000

...XDR * xdrs;char buf[BUFSIZE];xdrmen_create(xdrs, buf, BUFSIZE, XDR_ENCODE);

Page 7: Linux RPC

XDR Data Conversion Routines

xdr_bool (xdrs, ptrBool);

xdr_bytes (xdrs,str,strSize,maxsize);

xdr_char (xdrs, ptrChar);

xdr_double(xdrs, prtDouble);

xdr_enum(xdrs, ptrInt);

xdr_float(xdrs, ptrFloat);

xdr_int (xdrs, ptrInt);

xdr_long (xdrs, ptrLong);

xdr_opaque (xdrs, ptrChar, count);

xdr_pointer (xdrs, ptrObj, pbjSize, xdrObj);

xdrs_short (xdrs, ptrShort);

xdrs_u_char (xdrs, ptrUchar);

xdrs_u_int (xdrs, ptrUint);

xdrs_u_long (xdrs, ptrUlong);

xdrs_u_short (xdrs, ptrUshort);

xdr_union (xdrs, ptrDiscrim, ptrUnion, choiceFcn, default);

xdr_vector (xdrs, ptrArray, size, elemSize, elemProc);

xdr_void ( );

7

Page 8: Linux RPC

XDR Data Conversion

– Add data items in order to the buffer (after converting to XDR format)

8

int myInt;...myInt = 260;xdr_int(xdrs, &myInt);

Page 9: Linux RPC

RPC Programming MechanismsONC (Open Network Computing)

• XDR library routines for data conversion• XDR library routines for complex data

structures• RPC run-time library routines• Program generator tool

9

Page 10: Linux RPC

RPC Programming Process

• Dividing the program into local and remote procedures.

10

Proc A

Client Stub

Server Stub

Proc B

RPC

Page 11: Linux RPC

RPC Dispatching(Procedure Location)

11

Proc A1

Client Stub

Server Stub

Proc B1

Proc A2

Client StubProc B2

Server Stub

Dispatcher

RPC

RPC

Page 12: Linux RPC

RPC Interface Specification

12

Proc A

Client comm

Server Iface

Proc B

Server Comm

Client Iface

RPC

Page 13: Linux RPC

RPCgen Input and Output

• Input– Q.x Interface specification file

• Output– Q.h Declarations header file– Q_xdr.cpp XDR procedure calls used to

marshal arguments– Q_clnt.cpp Client-side communications stub– Q_svc.cpp Server-side communications stub

13

Page 14: Linux RPC

RPC Process Flow

14

Q.x rpcgen

Q_clnt.cpp

Q.h

Q_xdr.cpp

Q_svc.cpp

Clientapplication

Clientinterface

Serverinterface

Remoteprocedures

Server

Clientcompile

compile

Page 15: Linux RPC

RPC General Build Procedure

15

Develop Interface

Develop Client Develop Server

Page 16: Linux RPC

Developing the Interface

16

MyApp.x

RPCgen

MyApp_clnt.cClient Stub

MyApp_svc.cServer Stub

MyApp.h

MyApp_xdr.c

Page 17: Linux RPC

Developing the Server

17

MyApp.x

RPCgen

MyApp_svc.cServer Stub

MyApp.hMySrvr.c MyApp_xdr.c

C Compiler

Linker

MySrvr.exe

Page 18: Linux RPC

Developing the Client

18

MyApp.x

RPCgen

MyApp_clnt.cClient Stub

MyApp.hMyClnt.c

C Compiler

Linker

MyClnt.exe

MyApp_xdr.c

Page 19: Linux RPC

How the Server Prepares for a Connection

• (Be certain that Portmap is running)• Create UDP service• Register UDP service with Portmap• Create TCP service• Register TCP service with Portmap• Run service...– Uses select( ) to monitor ports.

19

Page 20: Linux RPC

Start Portmap

Portmap is included in all Linux distributions as a standard server.

Under Red Hat / Fedora Open services applet , select portmap and startFrom command line (as root)

/sbin/service portmap start

Other distributions should be similar

20

Page 21: Linux RPC

Server concurrency mode

RPC servers can be created in either single threaded or multi-threaded mode.

Servers automatically create and (when done) destroy a thread for each incoming connection.

21

Page 22: Linux RPC

Register the Server Program

svc_register(port#, SERV#, VER#, serv_func, proto#);

port#: port on which the service is activeSERV#: unique number for the serviceVER#: version for this particular serviceserv_func: name by which this function is calledproto#: IPPROTO_UDP or IPPROTO_TCP

22

Page 23: Linux RPC

How the Client Establishes a Connection

• Make a Remote Procedure Call• Find the Server Host Computer• Find Server Process Port # (through Portmap)• Create a (connection) to the Server Process

23

Page 24: Linux RPC

How the Client Establishes a Connection

clnt_create(server, SERV#, VER#, proto#);

remote procedure call...

Clnt_destroy(CLIENT);

24

Page 25: Linux RPC

Example #1

• Temperature Server (Fahrenheit to Centigrade)– Parameters passed as integers– TCP / IP port connection

• Source files:– temp.x– Tclient.c– tempServer.c

25

Page 26: Linux RPC

temp.x

program TEMPSERV {version TEMPVERS {

int TempConv(int) = 1; //procedure number} = 1; //version number

} = 77; //program number

26

Page 27: Linux RPC

TClient.c#include <stdio.h>, <stdlib.h>, <string.h>#include <rpc/rpc.h>#include "temp.h"#define YES 0#define NO 1

void main (int argc, char *argv[]){

int tempconvert(int temp, char *srvr);int temperature, nuTemp;int loopFlag;char srvr[25];CLIENT * cl;

27

Page 28: Linux RPC

TClient.c (cont)

strcpy (srvr, argv[1]);cl = clnt_create(srvr, TEMPSERV, TEMPVERS, "tcp");loopFlag = YES;

while(loopFlag == YES){

printf("Enter temperature in Faherenheit (-999 to quit)");

scanf ("%d", &temperature);ans = tempconv_1(&temperature, cl);

28

Page 29: Linux RPC

TClient.c (cont)

if (ans != NULL)nuTemp = * ans;

if (temperature == -999 || temperature == -9999)

{loopFlag = NO;printf ("Goodbye...\n");continue;

}printf("That’s %2d in centigrade\n", nuTemp);

}clnt_destroy(cl);return 0;

}

29

Page 30: Linux RPC

tempServer.c

#include <stdlib.h>, <unistd.h>, <stdio.h>#include <rpc/rpc.h>, "temp.h"

static int count;static int nuTemp;

int *tempconv_1_svc (int *val, struct svc_req * rqst)

{int oldTemp;oldTemp = *val;

30

Page 31: Linux RPC

tempServer.c

if (oldTemp == -9999){

printf("We're shutting down...\n");exit (0);

}printf("We got a temperature of %d, ", oldTemp);count++;nuTemp = (int)((5*(oldTemp -32)) / 9.0);printf("and we returned a value of %d\n", nuTemp);sleep(1);return (&nuTemp);

}

31

Page 32: Linux RPC

Files created with rpcgen

• Input:– temp.x

• Output– temp.h– temp_xdr.c (NULL file)– temp_clnt.c– temp_svc.c

32

Page 33: Linux RPC

temp.h#include <rpc/rpc.h>

#ifdef __cplusplus

extern "C" {

#endif

#define TEMPSERV 77

#define TEMPVERS 1

#if defined(__STDC__) || defined(__cplusplus)

#define TempConv 1

extern int * tempconv_1(int *, CLIENT *);

extern int * tempconv_1_svc(int *, struct svc_req *);

extern int tempserv_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);

#ifdef __cplusplus}

#endif

#endif /* !_TEMP_H_RPCGEN */

33

Page 34: Linux RPC

temp_xdr.c

#include <rpc/rpc.h>

#include "temp.h"

34

Page 35: Linux RPC

temp_clnt.c#include <memory.h> /* for memset */#include "temp.h“/* Default timeout can be changed using

clnt_control() */

static struct timeval TIMEOUT = { 25, 0 };

int *tempconv_1(int *argp, CLIENT *clnt){static int clnt_res;memset((char *)&clnt_res, 0, sizeof(clnt_res));

35

Page 36: Linux RPC

temp_clnt.c (cont)

if (clnt_call (clnt, TempConv,(xdrproc_t) xdr_int, (caddr_t)

argp, (xdrproc_t) xdr_int, (caddr_t) &clnt_res,TIMEOUT) != RPC_SUCCESS)

{return (NULL);

}return (&clnt_res);}

36

Page 37: Linux RPC

temp_svc.c

#include "temp.h“#include <stdio.h>#include <stdlib.h>#include <rpc/pmap_clnt.h>#include <string.h>#include <memory.h>#include <sys/socket.h>#include <netinet/in.h>

#ifndef SIG_PF#define SIG_PF void(*)(int)#endif

37

Page 38: Linux RPC

temp_svc.c (cont)static void tempserv_1(struct svc_req *rqstp, register SVCXPRT *transp){

union {

int tempconv_1_arg;

} argument;

char *result;

xdrproc_t _xdr_argument, _xdr_result;

char *(*local)(char *, struct svc_req *);

switch (rqstp->rq_proc) {

case NULLPROC:

(void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL);return;

case TempConv:

_xdr_argument = (xdrproc_t) xdr_int;

_xdr_result = (xdrproc_t) xdr_int;

local = (char *(*)(char *, struct svc_req *)) tempconv_1_svc;break;

default:

svcerr_noproc (transp);

return; } 38

Page 39: Linux RPC

temp_svc.c (cont)memset ((char *)&argument, 0, sizeof (argument));if (!svc_getargs (transp, (xdrproc_t) _xdr_argument,

(caddr_t) &argument)) {svcerr_decode (transp);return;

}result = (*local)((char *)&argument, rqstp);if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {

svcerr_systemerr (transp);}if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {

fprintf (stderr, "%s", "unable to free arguments");exit (1);

}return;

}

39

Page 40: Linux RPC

temp_svc.c (cont)int main (int argc, char **argv){

register SVCXPRT *transp;pmap_unset (TEMPSERV, TEMPVERS);transp = svcudp_create(RPC_ANYSOCK);if (transp == NULL) {

fprintf (stderr, "%s", "can’t create udp service."); exit(1);}if (!svc_register(transp, TEMPSERV, TEMPVERS,

tempserv_1, IPPROTO_UDP)) {fprintf (stderr, "%s", "unable to register

(TEMPSERV, TEMPVERS, udp).");exit(1);

}

40

Page 41: Linux RPC

temp_svc.c (cont)transp = svctcp_create(RPC_ANYSOCK, 0, 0);

if (transp == NULL) {fprintf (stderr, "%s", "cannot create

tcp service.");

exit(1);}if (!svc_register(transp, TEMPSERV, TEMPVERS,

tempserv_1, IPPROTO_TCP)) {fprintf (stderr, "%s", "unable to

register (TEMPSERV, TEMPVERS, tcp).");

exit(1);}svc_run ();fprintf (stderr, "%s", "svc_run returned");exit (1); /* NOTREACHED */}

41

Page 42: Linux RPC

Sample Client Output

D:\data\RPC\onrpc_temp\client\Debug>client localhost

Enter the temperature in Faherenheit (-999 to quit)32

That would be 0 in centigrade

Enter the temperature in Faherenheit (-999 to quit)100

That would be 37 in centigrade

Enter the temperature in Faherenheit (-999 to quit)212

That would be 100 in centigrade

Enter the temperature in Faherenheit (-999 to quit)-9999

Goodbye...

D:\data\RPC\onrpc_temp\client\Debug>

42

Page 43: Linux RPC

Sample Server Output

D:\data\RPC\examples\onrpc_temp\server\Debug>server

We got a temperature of 32, and we returned a value of 0

We got a temperature of 100, and we returned a value of 37

We got a temperature of 212, and we returned a value of 100

We're shutting down...

D:\data\RPC\examples\onrpc_temp\server\Debug>

43

Page 44: Linux RPC

Summary

• Linux RPC Implementation models SUN ONCRPC functionality

• RPC specific programming limited to linking original applications code with rpcgen interface code.

44