🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.unix.programmer
Article #369

RPC: clnttcp_create doesn't work

#369
From: Wade Guthrie
Date: Fri, 07 Aug 1992 02:40
430 lines
11620 bytes
I am having problems making an RPC call from a client using 'clnttcp_create' 
(clnt_perrno says: "RPC: unable to send").  The same code seems to work, 
however, when I use 'clnt_create' (I know, "then use clnt_create" :-> -- I 
can't).  I am on a Sun Sparc IPX running SunOS 4.1.2.  

I boiled the RPC code down to the minimum set (I tried to make it COMPLETE,
however, so that it could be cut and compiled).  I started with the code 
that follows, below.  

In the code, note that 'server' needs to be called first.  Next, client
wants as a single argument either:

    1) when TCP_CLIENT is defined: the internet address followed by the port
    address in decimal (and separated by a '.') as in:

        prompt> client 129.172.208.239.10.70

    where 1070 is the decimal value of the port.  It's a bit ugly, but it
    was easy to kludge up.

    2) when TCP_CLIENT isn't defined: the name of the server, as in:

        prompt> client drexler


--- client.c -----------------------------

#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/time.h>

#include "awesome.h"
#define MAIN_ROUTINE    1
#include "rpc_stuff.h"

static CLIENT   *client = NULL;
void            back_prog_1();


main(argc, argv)
        int     argc;
        char    *argv[];
{
#       define  FUNCTION        "main: client"

        int             argument        = ~0;

        (void) gethostname (host, sizeof (host));
        fprintf (stderr, "%s:%s\n", host, FUNCTION);

#       ifdef  TCP_CLIENT
            client = setup_tcp_client (argv[1], THERE_PROG, THERE_VER);
#       else
            client = setup_as_client (argv[1], THERE_PROG, THERE_VER);
#       endif

        /* Make the actual function call */

        argument = 42;  /* well, it'll do for now */
        fprintf (stderr, "%s: calling call_server_1(%d)\n", FUNCTION, argument);
        call_server_1 (&argument, client);

        if (client != NULL)
                clnt_destroy (client);
}

--- server.c -----------------------------

#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

#define MAIN_ROUTINE    1
#include "awesome.h"
#include "rpc_stuff.h"

void there_prog_1();

main()
{
#   define  FUNCTION    "main: server"
    u_short         port;
    struct hostent  *hostent;

    fprintf (stderr, "--%s--\n", FUNCTION);

    (void) gethostname (host, sizeof(host));
    hostent = gethostbyname (host);
    printf("port addr = %d.%d.%d.%d\n", 
        (unsigned char) (*hostent->h_addr_list)[0],
        (unsigned char) (*hostent->h_addr_list)[1],
        (unsigned char) (*hostent->h_addr_list)[2],
        (unsigned char) (*hostent->h_addr_list)[3]);

    port = register_as_server (THERE_PROG, THERE_VER, there_prog_1);
    printf("port=%d (0x%04x)\n", port, port);

    svc_run ();         /* poll for RPC service requests */

    fprintf (stderr, "** svc_run returned (and shouldn't have)\n");
    exit(1);
}



void *
call_server_1 (arg)
    int *arg;
{
    long    *result;
    int     argument;

    printf ("--%s(%d)--\n", "call_server_1", *arg);
    fflush (stdout);
    return (NULL);
}

--- rpc_stuff.c --------------------------

#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

#include <errno.h>  /* for timer stuff */
#include <signal.h>
#include <sys/time.h>

#include "rpc_stuff.h"

CLIENT  *
setup_as_client (server, program, version)
    char    *server; u_long  program; u_long  version;
{
#   define  FUNCTION    "setup_as_client"

    enum ExitCodes  {BAD_LINK=1, NO_TIMEOUT };

    CLIENT      *client;
    int     argument;
    int     bad_link = NO;

    /* body of the function */

    fprintf (stderr, "%s:%s> Link w/server (%s)...", host, FUNCTION, server);
    while ( (client=clnt_create (server, program, version, "tcp")) == NULL)
    {
            clnt_pcreateerror (server);
            exit (BAD_LINK);
    }
    fprintf (stderr, "GOOD link\n");

    return client;
}


u_short
register_as_server (program, version, func)
    u_long  program; u_long  version; void    (*func)();
{
#   undef   FUNCTION
#   define  FUNCTION    "register_as_server"

    register SVCXPRT *transp;

    /* body of the function */

    fprintf (stderr, "%s:%s> Entering\n", host, FUNCTION);

    (void) pmap_unset (program, version);

    transp = svctcp_create(RPC_ANYSOCK, 0, 0);
    if (transp == NULL) {
        fprintf(stderr, "** %s:%s> Cannot create tcp service.",
            host, FUNCTION);
        exit(1);
    }
    if (!svc_register(transp, program, version, func, IPPROTO_TCP)) {
        fprintf(stderr, "** %s:%s> Unable to register (%s, %s, tcp).",
            host, FUNCTION, program, version);
        exit(1);
    }
    return transp->xp_port;
}

/*
 * this thing strips out the port-id from a 'port_id' structure and
 * returns a short (for use in a struct sockaddr_in)
 */

    static u_short
peel_portid (port)
    char *port;
{
    static union
    {
        u_short value;
        char    bytes[sizeof(u_short)];
    }un;
    int         i       = ~0;

    un.value = ((unsigned) port[4]*100) + (unsigned) port[5];
    printf ("port=%d, 0x%04x\n", (unsigned) un.value, (unsigned) un.value);

    return  un.value;
}


/*
 * this thing strips out the internet addres from a 'port_id' 
 * structure and returns a short (for use in a struct sockaddr_in)
 */

    static u_long
peel_addr (port)
    char *port;
{
    static union
    {
        u_long  value;
        char    bytes[sizeof(u_long)];
    }un;
    int         i       = ~0;

    for(i=0; i<sizeof(u_long); i++)
        un.bytes[i] = port[i];

    printf("inet address: 0x%08x\n", un.value);
    return  un.value;
}


CLIENT *clnttcp_create ();

    CLIENT  *
setup_tcp_client (port_char, program, version)
    char    *port_char; 
    u_long  program;
    u_long  version;
{
#   undef   FUNCTION
#   define  FUNCTION    "setup_tcp_client"

    enum ExitCodes  {BAD_LINK=1, NO_TIMEOUT };

    struct sockaddr_in  server_addr;
    struct hostent      *host_struct;
    CLIENT              *client         = NULL;

    int                 argument        = ~0,
                        bad_link        = NO,
                        port_id         = ~0,
                        i               = ~0;

    char                port_num[6];

    /* body of the function */

    /*
     * peel out the address and port based on the command line --
     * the port number is split with a '.' to make the parsing
     * just a little easier.
     */

    port_num[0] = atoi(strtok(port_char, "."));
    port_num[1] = atoi(strtok(NULL, "."));
    port_num[2] = atoi(strtok(NULL, "."));
    port_num[3] = atoi(strtok(NULL, "."));
    port_num[4] = atoi(strtok(NULL, "."));
    port_num[5] = atoi(strtok(NULL, "."));

    for (i=0; i<6; i++)
        printf("%u ", (unsigned char) port_num[i]);
    printf("\n");

    /* fill the server_address structure */

    host_struct = gethostbyaddr ((char *)port_num, 4, AF_INET);

    server_addr.sin_addr.s_addr = peel_addr(port_num);
    port_id                     = peel_portid(port_num);
    server_addr.sin_port        = port_id;
    server_addr.sin_family      = AF_INET;

    fprintf (stderr, "%s:%s> Server is %s = %s\n", 
                host, FUNCTION, 
                host_struct->h_name,                    /* server name */
                inet_ntoa(&server_addr.sin_addr.s_addr) /*server address*/);

    fprintf (stderr, "%s:%s> TCP Link w/server...", host, FUNCTION);

    /*
     * copy over the dummy arguments -- I'd expect a bus error if this 
     * is the prob
     */

    while ( (client = clnttcp_create (
        &server_addr, program, version, &port_id,
        (u_int) 0, (u_int) 0)) == NULL)
    {
            clnt_pcreateerror ("remote server");
            exit (BAD_LINK);
    }
    fprintf (stderr, "GOOD link\n");

    return client;
}

--- awesome.x ----------------------------

#if (BUILD_THERE == 1)

    program THERE_PROG
    {
        version THERE_VER
        {
            void CALL_SERVER (int)  = 1;
        } = 1;
    } = 0x31415926;
#endif

--- rpc_stuff.h --------------------------

#define YES 1
#define NO  0

void poll_for_RPC_requests (/*void*/);
CLIENT  * setup_as_client ();
u_short register_as_server ();
CLIENT  * setup_tcp_client ();

#ifdef MAIN_ROUTINE
    char        host[256];
#else
    extern char host[256];
#endif
#define START_DIALOG        "dia_go"

--- Makefile -----------------------------

CFLAGS = -g

all : rpc_stuff.o server client tags 

tags : 
    ctags *.c *.h

rpc_stuff.o : rpc_stuff.c

awesome.h : awesome.x
    rpcgen -h -o awesome.h -DBUILD_THERE=1 -DBUILD_BACK=1 awesome.x

there_clnt.c there_svc.c : awesome.x awesome.h
    rpcgen -l -o there_clnt.c -DBUILD_THERE=1 awesome.x
    rpcgen -c -o there_xdr.c -DBUILD_THERE=1 awesome.x
    rpcgen -m -o there_svc.c -DBUILD_THERE=1 awesome.x

# this is the call back from 'server' back to 'client' 

server : awesome.h there_svc.o server.o rpc_stuff.o
    $(CC) $(CFLAGS) -o server server.o there_svc.o rpc_stuff.o

client : awesome.h there_clnt.o client.o rpc_stuff.o 
    $(CC) $(CFLAGS) -o client there_clnt.o client.o rpc_stuff.o

clean : 
    rm *.o
    rm *_xdr.c
    rm *_svc.c
    rm *_clnt.c
    rm server
    rm client

------------------------------------------

When I don't define the macro TCP_CLIENT in 'client.c', my client and
server terminals look like the following (Note the "--call_server_1--"
on the server screen):

prompt> server
--main: server--
port addr = 129.172.208.239
drexler:register_as_server> Entering
port=1072 (0x0430)
--call_server_1(42)--

prompt> client drexler
ld.so: warning: /usr/lib/libc.so.1.6 has older revision than expected 7
kareem:main: client
kareem:setup_as_client> Link w/server (drexler)...GOOD link
main: client: calling call_server_1(42)


------------------------------------------

Then, when I define the macro TCP_CLIENT in 'client.c', my client and
server terminals look like the following (Note the ABSENSE of the
"--call_server_1--" on the server screen -- the server function never 
gets called as far as its concerned):


prompt> server
--main: server--
port addr = 129.172.208.239
drexler:register_as_server> Entering
port=1070 (0x042e)

prompt>client 129.172.208.239.10.70
ld.so: warning: /usr/lib/libc.so.1.6 has older revision than expected 7
kareem:main: client
129 172 208 239 10 70 
inet address: 0x81acd0ef
port=1070, 0x042e
kareem:setup_tcp_client> Server is drexler.nb.rockwell.com = 129.172.208.239
kareem:setup_tcp_client> TCP Link w/server...GOOD link
main: client: calling call_server_1(42)



------------------------------------------

Please help me Obi Wan -- you're my only hope. . .

Wade Guthrie
wade@nb.rockwell.com
Technical Details
Message-ID: <1992Aug7.024026.29608@nb.rockwell.com>
Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cs.utexas.edu!rice!nb.rockwell.com!wade

Show Full Headers
Complete Article Headers
Newsgroups: comp.unix.programmer
Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cs.utexas.edu!rice!nb.rockwell.com!wade
From: wade@nb.rockwell.com (Wade Guthrie)
Subject: RPC: clnttcp_create doesn't work
Message-ID: <1992Aug7.024026.29608@nb.rockwell.com>
Keywords: RPC clnttcp_create HELP
Sender: wade@nb.rockwell.com (Wade Guthrie)
Organization: Rockwell International
Date: Fri, 7 Aug 1992 02:40:26 GMT
Lines: 431