/* ******************************************************************************* ** FILE: BGdriver_UDP_server.C -- example program demonstrating usage of ** network programming library using BGDRIVER $QIO's ** ** PRODUCT: TCPware for VMS ** ** VERSION: V5.6 ** ** Copyright (c) 2001, 2002 by ** Process Software LLC ** Framingham, Massachusetts ** ** Copyright (c) 1997-9 by ** Process Software Corporation ** Framingham, Massachusetts ** ** This software is furnished under a license for use on a ** single computer system and may be copied only 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 except for use on such ** system and to one who agrees to these license terms. Title ** to and ownership of the software shall at all times remain ** in Process Software LLC's name. ** ** The information in this document is subject to change ** without notice and should not be construed as a commitment ** by Process Software LLC. Process Software LLC assumes no ** responsibility for any errors that may appear in this document. ** ** ** ABSTRACT: ** ** BGdriver_UDP_server.c and BGdriver_UDP_client.c are a pair of example ** programs illustrating the use of datagrams via VMS's SYS$QIO system service ** calls to the UDPdriver. ** ** ** ** SERVER SEQUENCE OF OPERATIONS: ** 1. Assign an I/O channel to BG0: $ASSIGN; ** 2. Open receive port: $QIO( IO$_SETMODE); ** 3. Exchange data: $QIO(IO$_WRITEVBLK), $QIO(IO$_READVBLK); ** 4. Deassign the channel: $DASSGN; ** ** ** BUILDING EXECUTABLES: ** ( /DEFINE=TCPWARE points to TCPware's ucx$inetdef.h instead of UCX's file) ** ** 1. with DECC: ** $ CC/PREFIX_LIBRARY_ENTRIES=ALL/DEFINE=TCPWARE BGDRIVER_UDP_SERVER.C ** $ LINK BGDRIVER_UDP_SERVER ** ** 2. with VAXC: ** $ CC/DEFINE=TCPWARE BGDRIVER_UDP_SERVER.C ** $ LINK BGDRIVER_UDP_SERVER, TCPWARE:UCX$IPC/LIB, SYS$INPUT/OPTIONS ** SYS$SHARE:VAXCRTL/SHARE ** ******************************************************************************* ** REQUEST: If you have comments, please send them to "support@process.com" ******************************************************************************* */ #include /* Standard C i/o */ #include #include /* VAX/VMS System services */ #include /* for STS$M_SUCCESS */ #include /* Descriptors */ #include /* VAX/VMS i/o definitions */ #include #include #include #ifdef TCPWARE #include "TCPWARE_INCLUDE:ucx$inetdef.h" /* Provided by TCPware install */ #else /* assume UCX */ #include /* Provided during UCX installation */ #endif /* ** Macros to check VMS success/failure status */ #define SUCCESS(status) (status & STS$M_SUCCESS) #define FAILURE(status) (!(status & STS$M_SUCCESS)) /* ** Service information */ #define SERVER_PORT 65000 #define SERVICE "test_discard" #define PROTO "udp" /* ** Values for boolean variables */ #define FALSE 0 #define TRUE 1 #if defined(__DECC) || defined(__DECCXX) #pragma __member_alignment __save #pragma __nomember_alignment #endif /* ** I/O status block */ struct IOSB_struct { short unsigned status; short unsigned byte_count; long dev_data; }; /* ** item list 2 descriptor used for local host name ** (used in $QIO IO$_SETMODE) */ struct item_list_2_struct { short complen; short itmcode; char *compadr; }; /* ** item list 3 descriptor used for remote host name ** (used in $QIO IO$_READVBLK) */ struct item_list_3_struct { short buflen; short itmcode; char *buffadr; short *retlenadr; }; /* ** socket definition (used in $QIO IO$SETMODE) */ struct sockdef_struct { unsigned short protocol; unsigned char type; unsigned char domain; }; #if defined(__DECC) || defined(__DECCXX) #pragma __member_alignment __restore #endif /* ** function prototypes */ void exit( int); long sys$assign( struct dsc$descriptor_s *, unsigned short *, unsigned long, struct dsc$descriptor_s *); long sys$qiow( ); /* no prototyping due to varying P1 - P6 */ long sys$dassgn( unsigned short); main() { unsigned short channel; /* UDP channel number */ int status; /* For return status */ int continue_IO; /* boolean $qio status */ char buffer[1024]; struct servent *servent_P; struct IOSB_struct iosb; struct in_addr remote_in_addr; struct hostent *hostent_P; /* setup socket definition for QIO IO$SETMODE P1 arg */ static struct sockdef_struct sockdef = { UCX$C_UDP, /* UDP protocol */ INET_PROTYP$C_DGRAM, /* datagram type of socket */ UCX$C_AF_INET /* Internet domain */ }; /* UCX's SOCKADDRIN is same as in.h's sockaddr_in Socket Address Structure*/ static struct SOCKADDRIN s_adr = { UCX$C_AF_INET, /* internetwork family */ 0, /* SIN$W_PORT is setup below */ UCX$C_INADDR_ANY, /* accept on any IP address */ 0 /* SIN$T_ZERO */ }; /* local port & address used in $QIO IO$_SETMODE */ static struct item_list_2_struct s_adr_item2 = { sizeof( s_adr), 0, (char *) &s_adr }; /* remote port & address used in $QIO IO$_READVBLK */ static int remote_adr_len; static struct SOCKADDRIN remote_s_adr; static struct item_list_3_struct remote_s_adr_item3 = /*remote port & addr*/ { sizeof( remote_s_adr), 0, (char *) &remote_s_adr, (short *) &remote_adr_len }; /* String descriptor for the UCX device BG0: */ static $DESCRIPTOR( UDP0_dev, "UCX$DEVICE"); /* Assign a channel to UCX$DEVICE to clone a new device */ status = sys$assign( &UDP0_dev, &channel, 0, 0); if (FAILURE( status) ) { printf("Failed to assign channel to UCX$DEVICE.\n"); exit( status); } /* ** Get server port number for named serice. ** If unknown ( == 0 or = -1), use default define. */ if ( (int)(servent_P = getservbyname( SERVICE, PROTO)) > 0) s_adr.SIN$W_PORT = servent_P->s_port; else s_adr.SIN$W_PORT = htons(SERVER_PORT); printf("Will receive on server port #: %d\n\n", ntohs( s_adr.SIN$W_PORT) ); /* ** Passive open a receive port on server: equivalent to BSD ** socket() & bind() functions. */ status = sys$qiow( 0, channel, IO$_SETMODE, &iosb, 0, 0, &sockdef, /* P1: socket definition */ 0, &s_adr_item2, /* P3: local socket */ 0, 0, 0); if ( SUCCESS( status) ) status = iosb.status; if ( FAILURE( status) ) { printf("Failed to open receive port\n"); exit( status); } /* ** Keep receiving messages, till "CLOSE" is input. */ for (continue_IO = TRUE; continue_IO; ) { status = sys$qiow( 0, channel, IO$_READVBLK, &iosb, 0, 0, buffer, /* P1: buffer */ sizeof(buffer), /* P2: buffer size */ &remote_s_adr_item3, /* P3: remote info */ 0,0,0); if ( SUCCESS( status) ) status = iosb.status; if ( FAILURE( status) ) { printf("Error reading message. Status = %x\n", status ); continue; } /* ** Use remote IP address to query DNS for host name. ** If unknown, just show remote IP address. */ remote_in_addr.s_addr = remote_s_adr.SIN$L_ADDR; hostent_P = gethostbyaddr( (char *) &remote_in_addr.s_addr, 4, AF_INET); if (hostent_P) printf("\nClient data received from %s = %s\n", inet_ntoa( remote_in_addr), hostent_P->h_name); else printf("\nClient data received from [%s]\n", inet_ntoa( remote_in_addr) ); buffer[ iosb.byte_count] = '\0'; /* terminate received string */ printf("Received: %s\n", buffer); /* display the message received */ if ( 0 == strcmp( buffer, "CLOSE") || 0 == strcmp( buffer, "close") ) continue_IO = FALSE; } /* Deassign the channel */ status = sys$dassgn(channel); }