/**********************************************************************/
/*                                                                    */
/* Copyright (c) 2001 by Sun Microsystems, Inc.                       */
/* All rights reserved.                                               */
/*                                                                    */
/**********************************************************************/

/*****************************************************************************
*
* Prog Name:    sock00.c
*
* Description:
*
*    Socket sample program. This program is partnered with transaction
*    SOCK (program SOCK00).
*
*    This program opens a socket and connects to the host and port of the
*    socket server specified on the command line. It invokes transaction
*    SOCK by sending a message of the form:
*
*    xxxx,12345678901234567890123456789012345
*
*    where,
*
*    "xxxx" is the tran id of 1 to 4 characters (SOCK)
*
*    "12345.......45" is up to 35 characters of optional data  
*    to be placed in the COMMAREA in CLIENT-IN-DATA.
*
*    Having sent its initial message the program must receive a message on
*    the socket. This shows the transaction has been initiated in the MTP
*    region.
*
*    Each message received is sent back until the socket is closed
*    by the transaction.
*
* Usage:
*
*    sock00 [-h host] [-p port]
*
*    where,
*
*    -h host        the socket server host (default localhost).
*    -p port        the socket server port (default 8001).
*
* Change Log:
*
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>

/* Bug 4825517  */
#include <unistd.h>
 
#define BUFSIZE  4096  /* size of message buffer */

void usage(char *progname)
{
    printf("usage: %s [-h host] [-p port]\n", progname);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    char               *host = "localhost";
    int                 port = 8001;
    char               *trans = "SOCK";
    int                 fd;
    struct hostent     *hostentry = NULL;
    struct sockaddr_in  addr;
    int                 n;
    int                 c, errflg = 0;
    char                ibuffer[4+1+35];  /* transid  4 bytes
				             ','      1 byte
				             data    35 bytes */
    char                buffer[BUFSIZE];

    char *data = {"12345678901234567890123456789012345678901234567890"};

    while ((c=getopt(argc, argv, "h:p:")) != -1) {
        switch(c) {
	case 'h':	/* server host name */
	    host = optarg;
	    break;
        case 'p':	/* server port */
            port = atoi(optarg);
            break;
        default:	/* the rest are errors */
            errflg++;
            break;
        }
    }
 
    if (host == NULL || port == 0 || errflg) {
        usage(argv[0]);
    }

    /* ignore SIGPIPE signals */
    signal(SIGPIPE, SIG_IGN);

    /* create a TCP socket */
    if ((fd=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
	printf("sock00:socket error %d\n", errno);
        exit(EXIT_FAILURE);           
    }

    printf("sock00:socket opened\n");
    
    /* connect to the socket server */
    memset(&addr, 0, sizeof(struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_port   = htons(port);

    if (strcmp(host, "any") == 0) {
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
    } else if (strcmp(host, "loopback") == 0) {
	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    } else {
	if ((hostentry = gethostbyname(host)) == NULL) {
	    printf("sock00:invalid hostname \"%s\"\n", host);
	    exit(EXIT_FAILURE);
	}
	memcpy(&addr.sin_addr.s_addr, hostentry->h_addr, hostentry->h_length);
    }                      

    if (connect(fd, (struct sockaddr *)&addr,
		sizeof(struct sockaddr)) < 0) {
	printf("sock00:connect error %d\n", errno);
        exit(EXIT_FAILURE);
    }

    printf("sock00:socket connected\n");

    /* build the initial socket message */
    memset(ibuffer, 0, sizeof(ibuffer));
    memcpy(ibuffer,   trans,  4);
    memcpy(ibuffer+4, ",",    1);
    memcpy(ibuffer+5, data,  35);

    /* send initial message to invoke the transaction */
    if (send(fd, ibuffer, sizeof(ibuffer), 0) <= 0) {
	printf("sock00:send error %d\n", errno);
	exit(EXIT_FAILURE);
    }

    printf("sock00:transaction %4.4s\n", trans);

    while (1) {

	memset(buffer, 0, sizeof(buffer));

        if ((n = recv(fd, buffer, sizeof(buffer), MSG_WAITALL)) < 0) {
	    printf("sock00:recv error %d\n", errno);
	    exit(EXIT_FAILURE);
	}

	if (n == 0) {
	    printf("sock00:socket disconnected\n");
	    break;
	}

	printf("sock00:read %d chars\n", n);

        if ((n = send(fd, buffer, n, 0)) < 0) {
	    printf("sock00:send error %d\n", errno);
	    exit(EXIT_FAILURE);
	}

	printf("sock00:sent %d chars\n", n);
    }

    close(fd);

    printf("sock00:socket closed\n");
    printf("sock00:done\n");

    return EXIT_SUCCESS;
}

