OpenVMS Source-Code Demos

TCPIP$TCP_SERVER_QIO-DECC.C

/*====================================================================
*
*			  COPYRIGHT (C) 1989, 1998 BY
*	      DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
*
* This software is furnished under a license and may be used and  copied
* only  in  accordance  with  the  terms  of  such  license and with the
* inclusion of the above copyright notice.  This software or  any  other
* copies  thereof may not be provided or otherwise made available to any
* other person.  No title to and ownership of  the  software  is  hereby
* transferred.
*
* The information in this software is subject to change  without  notice
* and  should  not  be  construed  as  a commitment by DIGITAL EQUIPMENT
* CORPORATION.
*
* DIGITAL assumes no responsibility for the use or  reliability  of  its
* software on equipment which is not supplied by DIGITAL.
*
*
*
*  FACILITY:
*	INSTALL
*
*
*  ABSTRACT:
*	This is an example of a TCP/IP client using the QIO
*	interface.
*
*  ENVIRONMENT:
*	TCPIP V5.0 or higher
*
*  BUILD INSTRUCTIONS:
*
*       To link in VAXC/VMS you must have the following
*       entries in your .opt file:
*          sys$library:tcpip$ipc.olb/lib
*          sys$share:vaxcrtl.exe/share
*
*       For DEC C or DEC C++, compile /PREFIX=ALL and link via
*          $ link TCPIP$TCP_SERVER_QIO
*
*    To build this example program use commands of the form,
*
*        using the DEC "C" compiler:
*
*            $ cc/prefix=all TCPIP$TCP_SERVER_QIO.C
*            $ link TCPIP$TCP_SERVER_QIO
*
*        using the DEC "C++" compiler:
*
*            $ cxx/prefix=all/define=VMS TCPIP$TCP_SERVER_QIO.C
*            $ link TCPIP$TCP_SERVER_QIO
*
*        using the VAX "C" compiler:
*
*            $  cc /vaxc TCPIP$TCP_SERVER_QIO.C
*            $  link TCPIP$TCP_SERVER_QIO, -
*                    SYS$LIBRARY:TCPIP$IPC/LIB, -
*                    SYS$INPUT/OPTIONS
*            SYS$SHARE:TCPIP$IPC_SHR/SHARE
*            SYS$SHARE:VAXCRTL.EXE/SHARE
*
*  AUTHORS:
*	TCPIP Developer
*
*  CREATION DATE: May 23, 1989
*
*  MODIFICATION HISTORY:
*
*       16 May 1996 Joseph J. Vlcek
*       Make compatible with the DEC C and DEC C++ compilers.
*       Add directions on how to build this example modules.
*
*       5 Nov 1997 Immi Mohammed
*       Changed ucx$inetdef.h to shrlib$:inet_user.h
*
*       31 Mar 1998 Jason Fountain
*       Initialize retval
*       Changed shrlib$:inet_user.h to tcpip$inetdef.h
*/

#include <descrip.h>        /* VMS descriptor stuff */
#include <errno.h>          /* Unix style error codes for IO routines. */
#include <in.h>             /* internet system Constants and structures. */
#include <inet.h>           /* Network address info. */
#include <iodef.h>          /* I/O FUNCTION CODE DEFS */
#include <lib$routines.h>   /* LIB$ RTL-routine signatures. */
#include <lib$routines.h>   /* LIB$ RTL-routine signatures.*/
#include <netdb.h>          /* Network database library info. */
#include <signal.h>         /* UNIX style Signal Value Definitions */
#include <socket.h>         /* TCP/IP socket definitions. */
#include <ssdef.h>          /* SS$_<xyz> sys ser return stati <8-) */
#include <starlet.h>        /* Sys ser calls */
#include <stdio.h>          /* UNIX 'Standard I/O' Definitions   */
#include <stdlib.h>         /* General Utilities */
#include <string.h>         /* String handling function definitions */
#include <tcpip$inetdef.h>    /* TCPIP network definitions */

/* Convert short port number from host to network byte order */
#define htons(x) ((unsigned short)((x<<8)|(x>>8)))

main() {
	int	status;		/* For return status */
	short	channel;	/* INET channel */
	short	channel_1;	/* Template for ACCEPT */
	short	sck_parm[2];	/* Socket creation parameter */
	short	iosb[4];	/* I/O status block */

	char	buf[512];
	int	buflen = 512;	/* buffer length */
	int	retval = 0;
	short	port;
	unsigned char *dummy;
	unsigned int	r_retlen;
	int	one=1;
	struct	sockaddr_in local_host, remote_host;

	struct	IL2 {
		unsigned int il2_length;
		char *il2_address;
	} lhst_adrs;

	struct	IL3 {
		unsigned int il3_length;
		char *il3_address;
		unsigned int* il3_retlen;
	} rhst_adrs;
//--------------------
//	struct	dsc$descriptor inet_dev =
//		{10, DSC$K_CLASS_S, DSC$K_DTYPE_T, "TCPIP$DEVICE"};		/* original (broken) code */
//--------------------
//	struct	dsc$descriptor inet_dev =
//		{12, DSC$K_CLASS_S, DSC$K_DTYPE_T, "TCPIP$DEVICE"};		/* fixed code */
//--------------------
	$DESCRIPTOR(  inet_dev, "TCPIP$DEVICE:"  );				/* better fixed code */
//--------------------
	struct	{ short len, param; int *ptr; }
		item_list[] = {{sizeof(one), TCPIP$C_REUSEADDR, (int*)0 }},
		options = {sizeof(item_list), TCPIP$C_SOCKOPT, (int*)0 };

        item_list[0].ptr = &one;
        options.ptr = (int*)item_list;

	lhst_adrs.il2_length = sizeof local_host;
	lhst_adrs.il2_address = (char *)&local_host;

	rhst_adrs.il3_length  = sizeof remote_host;
	rhst_adrs.il3_address = (char*)&remote_host;
	rhst_adrs.il3_retlen  = &r_retlen;

	sck_parm[0] = TCPIP$C_TCP;		/* TCP/IP protocol */
	sck_parm[1] = INET_PROTYP$C_STREAM;	/* stream type of socket */
	local_host.sin_family = TCPIP$C_AF_INET;	/* INET family */
	local_host.sin_addr.s_addr = TCPIP$C_INADDR_ANY;	/* Any address */

	while (retval != 1) {
		printf("Enter local port number:\n");
		retval = scanf("%hd", &port);
		if (retval == 1)
			local_host.sin_port = htons(port);
		else scanf("%s",buf);	/* discard bad input */
	}

	/* Assign two channels to the TCPIP device. */
	status = sys$assign(&inet_dev, &channel, 0, 0);
	if (status & 1)
		status = sys$assign(&inet_dev, &channel_1, 0, 0);
	if (!(status & 1)) {
		printf("Failed to assign channel to TCPIP device.\n");
		exit(status);
	}

	/* Create the socket and set the REUSEADDR option. */
	status = sys$qiow(3,		/* Event flag */
			channel,	/* Channel number */
			IO$_SETMODE,	/* I/O function */
			iosb,		/* I/O status block */
			0, 0,
			&sck_parm, 0,	/* P1 Socket creation parameter */
			0, 0,
			&options, 0);	/* P5 Socket option descriptor */
	if (status & 1) status = iosb[0];
	if (!(status & 1)) {
		printf("Failed to create the device socket.\n");
		exit(status);
	}

	/* Bind to chosen port number (after REUSEADDR is set above). */
	status = sys$qiow(3,		/* Event flag */
			channel,	/* Channel number */
			IO$_SETMODE,	/* I/O function */
			iosb,		/* I/O status block */
			0, 0,
			0, 0,
			&lhst_adrs,	/* P3 local socket name */
			3,		/* P4 Connection backlog */
			0, 0);
	if (status & 1) status = iosb[0];
	if (!(status & 1)) {
		printf("Failed to bind the device socket.\n");
		exit(status);
	}

 printf("%d\n", channel);
 printf("%d\n", channel_1);
 printf("%d\n", sck_parm[0]);
 printf("%d\n", sck_parm[1]);
 printf("%d\n", lhst_adrs.il2_length);
 printf("%d\n", lhst_adrs.il2_address);

 printf("%d\n", rhst_adrs.il3_length);
 printf("%d\n", rhst_adrs.il3_address);
 printf("%d\n", rhst_adrs.il3_retlen);

	/* Accept a connection from a client. */
	status = sys$qiow(3,		/* Event flag */
			channel,	/* Channel number */
			IO$_ACCESS|IO$M_ACCEPT,	/* I/O function */
			iosb,		/* I/O status block */
			0, 0,
			0, 0,
			&rhst_adrs,	/* P3 Remote IP address*/
			&channel_1,	/* P4 Channel for new socket */
			0, 0);
	if (status & 1) status = iosb[0];
	if (!(status & 1)) {
		printf("Failed to accept a connection from a client.\n");
		exit(status);
	}
	dummy = (unsigned char *)&remote_host.sin_addr;
	printf("Connection from host: %d.%d.%d.%d, port: %d\n",
		dummy[0], dummy[1], dummy[2], dummy[3],
		htons(remote_host.sin_port));

	/* Read I/O buffer. */
	status = sys$qiow(3,		/* Event flag */
			channel_1, /* Channel number */
			IO$_READVBLK,	/* I/O function */
			iosb,		/* I/O status block */
			0, 0,
			buf,		/* P1 buffer */
			buflen,		/* P2 buffer length */
			0, 0, 0, 0);
	if (status & 1) status = iosb[0];
	if (!(status & 1))
		printf("Failed to read from socket.\n");

	/* If all is well, print message */
	printf ("Received text: %s\n", buf);

	/* Shut down the socket (optional). */
	status = sys$qiow(3,
			channel_1,
			IO$_DEACCESS|IO$M_SHUTDOWN,
			iosb,
			0, 0,
			0, 0, 0,
			TCPIP$C_DSC_ALL,	/* P4 Discard all packets */
			0, 0);
	if (status & 1) status = iosb[0];
	if (!(status & 1))
		printf("Failed to shut down the socket.\n");

	/* Close the sockets -- accepted and listner (optional). */
	status = sys$qiow(3,
			channel_1,
			IO$_DEACCESS,
			iosb,
			0, 0,
			0, 0, 0, 0, 0, 0);
	if (status & 1) status = sys$qiow(3,
			channel,
			IO$_DEACCESS,
			iosb,
			0, 0,
			0, 0, 0, 0, 0, 0);
	if (status & 1) status = iosb[0];
	if (!(status & 1))
		printf("Failed to close the socket.\n");

	/* Deassign the TCPIP device channels. */
	status = sys$dassgn(channel_1);
	if (status & 1) status = sys$dassgn(channel);
	if (!(status & 1))
		printf("Failed to deassign the channel.\n");
}

Back to OpenVMS
Back to OpenVMS Demo Index
Back to Home
Neil Rieck
Kitchener - Waterloo - Cambridge, Ontario, Canada.