/* This program is a tcpip server process. It starts. Creates a output file. Then goes to sleep. While it is sleeping, any tcpip messages that come into the computer on the port 12345, awakens an ast. Any non-null text sent to that port is printed to the file. Then the process goes back to sleep again. Once the exit signal is recieved, the process awakens, closes the output file, then exits. */ /* * INCLUDE FILES: */ #include /* define OpenVMS descriptors */ #include /* define 'EFN$C_ENF' event flag */ #include /* define internet related constants, */ /* functions, and structures */ #include /* define network address info */ #include /* define i/o function codes */ #include #include /* define network database library info */ #include /* define system service status codes */ #include /* define system service calls */ #include /* define standard i/o functions */ #include /* define standard library functions */ #include /* define string handling functions */ #include /* define condition value fields */ #include /* * NAMED CONSTANTS: */ #define MBUFSIZE 128 /* size of a message buffer */ #define MBUFQUO 384 #define SERV_BACKLOG 1 /* server backlog */ #define SERV_PORTNUM 12345 /* server port number */ /* * Structure definitions */ struct iosb { /* i/o status block */ unsigned short status; /* i/o completion status */ unsigned short bytcnt; /* bytes transfered if read/write */ void *details; /* address of buffer or parameter */ }; struct itemlst_2 { /* item-list 2 descriptor/element */ unsigned short length; /* length */ unsigned short type; /* parameter type */ void *address; /* address of item list */ }; struct itemlst_3 { /* item-list 3 descriptor/element */ unsigned short length; /* length */ unsigned short type; /* parameter type */ void *address; /* address of item list */ unsigned int *retlen; /* address of returned length */ }; struct sockchar { /* socket characteristics buffer */ unsigned short prot; /* protocol */ unsigned char type; /* type */ unsigned char af; /* address format */ }; struct itemlst_3 client_itemlst; /* client item-list 3 descriptor */ struct iosb iosb; /* i/o status block */ struct sockaddr_in client_addr; /* client socket address structure */ struct sockaddr_in serv_addr; /* server socket address structure */ struct itemlst_2 serv_itemlst; /* server item-list 2 descriptor */ unsigned short conn_channel; /* connect inet device i/o channel */ unsigned short listen_channel; /* listen inet device i/o channel */ char inbuffer[MBUFSIZE]; /* message buffer */ unsigned int inbuflen=MBUFSIZE; /* length of message buffer */ char outbuffer[MBUFSIZE]; /* server data buffer */ unsigned int outbuflen = MBUFSIZE; /* length of server data buffer */ FILE *message_file; void connectast(); int main (void) { fprintf(message_file,"I'm going to sleep now.\n"); int one = 1; /* reuseaddr option value */ unsigned int status; /* system service return status */ unsigned int client_retlen; /* returned length of client socket */ /* address structure */ struct sockchar listen_sockchar; /* listen socket char buffer */ struct itemlst_2 sockopt_itemlst; /* sockopt item-list 2 descriptor */ struct itemlst_2 reuseaddr_itemlst; /* reuseaddr item-list 2 element */ $DESCRIPTOR( inet_device, /* string descriptor with logical */ "TCPIP$DEVICE:" ); /* name of internet pseudodevice */ /* * init listen socket characteristics buffer */ listen_sockchar.prot = TCPIP$C_TCP; listen_sockchar.type = TCPIP$C_STREAM; listen_sockchar.af = TCPIP$C_AF_INET; /* * init reuseaddr's item-list element */ reuseaddr_itemlst.length = sizeof( one ); reuseaddr_itemlst.type = TCPIP$C_REUSEADDR; reuseaddr_itemlst.address = &one; /* * init sockopt's item-list descriptor */ sockopt_itemlst.length = sizeof( reuseaddr_itemlst ); sockopt_itemlst.type = TCPIP$C_SOCKOPT; sockopt_itemlst.address = &reuseaddr_itemlst; /* * init client's item-list descriptor */ memset( &client_itemlst, 0, sizeof(client_itemlst) ); client_itemlst.length = sizeof( client_addr ); client_itemlst.address = &client_addr; client_itemlst.retlen = &client_retlen; /* * init client's socket address structure */ memset( &client_addr, 0, sizeof(client_addr) ); /* * init server's item-list descriptor */ serv_itemlst.length = sizeof( serv_addr ); serv_itemlst.type = TCPIP$C_SOCK_NAME; serv_itemlst.address = &serv_addr; /* * init server's socket address structure */ memset( &serv_addr, 0, sizeof(serv_addr) ); serv_addr.sin_family = TCPIP$C_AF_INET; serv_addr.sin_port = htons( SERV_PORTNUM ); serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY; /* * assign device sockets */ status = sys$assign( &inet_device, /* device name */ &listen_channel, /* i/o channel */ 0, /* access mode */ 0); /* not used */ if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to assign i/o channel(s) to TCPIP device\n" ); exit( status ); } status = sys$assign( &inet_device, /* device name */ &conn_channel, /* i/o channel */ 0, /* access mode */ 0); /* not used */ if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to assign i/o channel(s) to TCPIP device\n" ); exit( status ); } /* * create a listener socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &listen_sockchar, /* p1 - socket char buffer */ 0,0,0, /* p2 - p4 */ &sockopt_itemlst, /* p5 - socket options */ 0); /* p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to create listener socket\n" ); exit( status ); } /* * bind server's internet address and port number to * listen socket; set socket as a passive socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_SETMODE, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0,0, /* p1 - p2 */ &serv_itemlst, /* p3 - local socket name */ SERV_BACKLOG, /* p4 - connection backlog */ 0,0); /* p5 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to bind listener socket\n" ); exit( status ); } if ((message_file = fopen("socket-output.txt","w")) == NULL) { perror ("fopen socket-output.txt"); exit (EXIT_FAILURE); } fprintf(message_file, "Program started. Awaiting input.\n"); /* * accept a connection from a client */ printf( "Waiting for a client connection on port: %d\n", ntohs(serv_addr.sin_port)); fprintf( message_file,"Waiting for a client connection on port: %d\n", ntohs(serv_addr.sin_port)); status = sys$qio( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_ACCESS|IO$M_ACCEPT, /* i/o function code */ &iosb, /* i/o status block */ &connectast, /* ast service routine */ 0, /* ast parameter */ 0,0, /* p1 - p2 */ &client_itemlst, /* p3 - remote socket name */ &conn_channel, /* p4 i/o channel for new */ /* connection */ 0,0); /* p5 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; /* if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to establish listener channel.\n"); exit( status ); } */ printf("I'm going to sleep now.\n"); fprintf(message_file,"I'm going to sleep now.\n"); /* Go into hibernation */ status = SYS$HIBER(); if (status != SS$_NORMAL) LIB$SIGNAL(status); /* After being awakened */ /* Close test file */ printf("Received termination Signal... Shutting down.\n"); fprintf(message_file, "Received termination Signal... Shutting down.\n"); fclose(message_file); /* * close listen socket */ printf("Closing listener socket.\n"); status = sys$qiow( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_DEACCESS, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0,0,0,0,0,0); /* p1 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to close socket\n" ); exit( status ); } /* * deassign all device sockets */ printf("Deassigning i/o channels.\n"); status = sys$dassgn( conn_channel ); if ( (status & STS$M_SUCCESS) ) status = sys$dassgn( listen_channel ); if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to deassign i/o channel(s) to TCPIP device\n" ); exit( status ); } exit( EXIT_SUCCESS ); } void connectast(void) { unsigned int status; /* system service return status */ char exitstr[5]; /* Exit string to signal end of exec */ printf("Entering Connection AST routine.\n"); fprintf(message_file,"Entering Connection AST routing.\n"); printf("Accepted connection from host: %s, port: %d\n", inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); fprintf(message_file,"Accepted connection from host: %s, port: %d\n", inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); /* * connection established with a client; * now attempt to read data on this connection */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_READVBLK, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &inbuffer, /* p1 - buffer address */ inbuflen, /* p2 - buffer length */ 0,0,0,0); /* p3 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to read data from client connection\n" ); exit( status ); } inbuffer[0,iosb.bytcnt] = 0; printf("Data received: %s\n",inbuffer); fprintf(message_file,"Data received: %s\n",inbuffer); strcpy(outbuffer,"acknowledged"); outbuflen = sizeof(outbuffer); /* * Write data to client */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_WRITEVBLK, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ &outbuffer, /* p1 - buffer address */ outbuflen, /* p2 - buffer length */ 0,0,0,0); /* p3 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to write data to client connection\n" ); exit( status ); } printf( "Data sent: %s\n", outbuffer ); /* output server's data buffer */ fprintf(message_file,"Data sent: %s\n", outbuffer ); /* output server's data buffer */ /* * Shutdown connection socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_DEACCESS|IO$M_SHUTDOWN, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0,0,0, /* p1 - p3 */ TCPIP$C_DSC_ALL, /* p4 - discard all packets */ 0,0); /* p5 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to shutdown client connection\n" ); exit( status ); } printf("Connection Socket Shutdown.\n"); fprintf(message_file,"Connection Socket Shutdown.\n"); /* * Close Connection Socket */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_DEACCESS, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ 0,0,0,0,0,0); /* p1 - p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to close socket\n" ); exit( status ); } printf("Connection Socket Closed.\n"); fprintf(message_file,"Connection Socket Closed.\n"); strcpy(exitstr,"exit"); if (strcmp(inbuffer,exitstr) == 0) { printf("strcmp equals zero.\n"); status = SYS$WAKE(0,0); if (status != SS$_NORMAL) LIB$SIGNAL(status); } else { printf("strcmp does not equal zero.\n"); /* * accept a connection from a client */ printf( "Waiting for a client connection on port: %d\n", ntohs(serv_addr.sin_port) ); fprintf(message_file,"Waiting for a client connection on port: %d\n", ntohs(serv_addr.sin_port) ); /* * Create another listener */ status = sys$qio( EFN$C_ENF, /* event flag */ listen_channel, /* i/o channel */ IO$_ACCESS|IO$M_ACCEPT, /* i/o function code */ &iosb, /* i/o status block */ &connectast, /* ast service routine */ 0, /* ast parameter */ 0, /* p1 */ 0, /* p2 */ &client_itemlst, /* p3 - remote socket name */ &conn_channel, /* p4 i/o channel for new */ /* connection */ 0, /* p5 */ 0); /* p6 */ if ( status & STS$M_SUCCESS ) status = iosb.status; /* if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to establish listener channel.\n"); exit( status ); } */ } return; }