/**** * * File name : ivpserv.c * Function : Interlink TCPaccess IVP server for Open Edition * Flow : Server listens on port 2300. When client connection * is made (from ivpclnt.c), server sends 50 megabytes * of data and terminates connection to client. * Parameters: One optional parameter can be passed to the program: * a numeric address family. i.e. ivpserv 11 & ****/ #pragma runopts(POSIX(ON)) #include /* OE only - comment out for unix */ #include #include #include #include #include #define MESSAGESIZE 2048 /* maximum message size */ #define PACKETSIZE 80 /* largest packet in one send */ #define DEFAULTPORT 2300 #define SERVICE "IVPSERV" #define ASCII_CLIENTS 0 #define EBCDIC_CLIENTS 1 extern int errno; /* IP global error number */ int client_type; /* ASCII or EBCDIC */ /*<><><> function prototypes <><><>*/ int receive_from_client(int sock, char *in_buff, int in_len); int send_to_client(int sock, char *out_buff,int out_len); void EBCDICtoASCII(char *out_buff,int out_len); void ASCIItoEBCDIC(char *out_buff,int out_len); void main( int argc, char **argv) { int sd ; /* socket descriptor */ int ad ; /* accepted descriptor */ int af_inet_value = 2; /* address family value */ int backlog = 5; /* listen backlog queue size */ int status = 0; /* function return code */ int max_send_size = 0; /* send buffer size */ int addr_size = 0 ; int optlen = 0 ; struct sockaddr_in addr; char buff[MESSAGESIZE+1]; /* request/response buffer + null */ int message_len; /* length of message received */ struct servent *serv; char *Psvc_name = SERVICE; char local_host_name[64]; unsigned long IPAddress; if (argc > 1) { /* EBCDIC or ASCII clients */ client_type = atoi(argv[1]); }else { /* no - set it to default */ client_type = EBCDIC_CLIENTS; } af_inet_value = AF_INET; if (gethostname(local_host_name, 64) == 0){ local_host_name[63] = '\0'; /*<><><> gethostid() doesn't seem to be included with SAS/C strcpy(IPAddress,(char *) inet_ntoa(gethostid())); printf("s: server is on host: %s IP Address: %s\n", local_host_name,IPAddress); <><><><><>*/ printf("s: server is on host: %s\n",local_host_name); } printf("s: --> Send 'adios' or cancel process to terminate! <--\n"); addr_size = sizeof(addr); optlen = sizeof(int) ; /*** * OPEN A SOCKET ***/ sd = socket(af_inet_value, SOCK_STREAM, IPPROTO_TCP) ; if (sd < 0 ) { fprintf(stderr,"s: socket failed: errno=%d, rc=%d\n", errno, sd ) ; exit (sd) ; } /*** * BIND A SOCKET ***/ addr.sin_family = AF_INET ; /* accept connection */ addr.sin_addr.s_addr = htonl(INADDR_ANY); /* from any host */ if ((serv = getservbyname(Psvc_name,"tcp"))==NULL) { addr.sin_port = htons(DEFAULTPORT); /* on this port */ printf("s: service %s unknown and defaults to port %d\n", SERVICE, DEFAULTPORT); }else{ addr.sin_port = serv->s_port; printf("s: service %s is using port %d\n", SERVICE, serv->s_port); } status = bind(sd, (struct sockaddr *) &addr, sizeof(addr) ) ; if (status < 0 ) { if (errno == EADDRINUSE) { printf("s: Another server is already bound to port\n"); } fprintf(stderr,"s: bind failed: errno=%d, rc=%d\n", errno, status ) ; close (sd) ; exit (status) ; } /*** * LISTEN ON THE PORT ***/ status = listen (sd, backlog); if (status < 0 ) { fprintf(stderr,"s: bind failed: errno=%d, rc=%d\n", errno, status ) ; close (sd); exit (status); } printf("s: listening on port 2300\n"); /*** * ACCEPT THE CONNECTION ***/ for (;;) { ad = accept (sd, (struct sockaddr_in *) &addr, &addr_size); if ( ad < 0 ) { fprintf(stderr,"accept failed: errno=%d, rc=%d\n", errno, ad ) ; close (sd); exit (ad) ; } strcpy(buff,(char *) inet_ntoa(addr.sin_addr)); printf("\ns: session with client established on "); printf("port %d from %s\n",ntohs(addr.sin_port),buff); /*** * DETERMINE THE SEND BUFFER SIZE ***/ status = getsockopt(ad, SOL_SOCKET, SO_SNDBUF, &max_send_size, &optlen) ; if (max_send_size == 0) max_send_size = 1460 ; /* for UNIX */ strcpy(buff, "welcome - ready for requests"); message_len = strlen(buff); printf("s: sending (%s)\n",buff); if (send_to_client(ad, buff, message_len) < 0) { printf("s: Connection with client broken during send\n"); /*<><>close (sd); close (ad); exit ( -1);<><>*/ } message_len = receive_from_client(ad, buff, MESSAGESIZE+1); if (message_len < 0) { printf("s: Connection with client broken during receive\n"); /*<><>close (sd); close (ad); exit ( -1);<><>*/ } printf("s: received (%s)\n",buff); if (strcmp(buff, "adios") == 0) { printf("s: Received terminate command. Good-bye amigo!\n"); close (sd); close (ad); exit (0); } /*** * CLOSE THE ACCEPTED CONNECTION ***/ status = close (ad); if (status) { fprintf(stderr,"s: close failed, errno=%d, rc=%d\n", errno, status ); exit (status) ; } printf("s: session with client ended\n"); } } /****** * send_to_client() * * send the message in "out_buff" of length "out_len" to the server * at "sock" * the message sent consists of an 8 byte header that has the total * message length (including the header) in printable characters, * followed by the message in "out_buff", so the total message length * will be out_len + 8 * if the message is larger than PACKETSIZE, it will be sent in multiple * transmissions of PACKETSIZE bytes followed by any remaining bytes * less than PACKETSIZE * * return 0 for success, -1 otherwise * * parameters: * int sock; socket for communication * char *out_buff; string to sent to client * int out_len; length of string ******/ int send_to_client(int sock, char *out_buff,int out_len) { int bytesleft; /* remaining length */ int count_expect; /* expected # bytes sent */ int count_act; /* actual # bytes sent */ char temp_buff[MESSAGESIZE+9]; /* temp string buffer */ char *buff_ptr; /* pointer into temp string*/ int send_flags = 0; /* no flags needed */ bytesleft = out_len + 8; /* total string length */ sprintf(temp_buff,"%08u",bytesleft); /* convert to character */ buff_ptr = &temp_buff[8]; /* point past length */ strncpy(buff_ptr,out_buff,out_len); /* copy user data */ temp_buff[bytesleft] = '\0'; /* ensure null termination */ printf("s: sending (%s)\n",temp_buff); if (client_type == ASCII_CLIENTS){ EBCDICtoASCII(temp_buff,bytesleft); } buff_ptr = temp_buff; /* beginning of send buffer*/ if (bytesleft > PACKETSIZE) count_expect = PACKETSIZE; /* limit to PACKETSIZE */ else count_expect = bytesleft; /****** * send the data to socket "sock" * the data is "count_expect" bytes long and pointed to by "buff_ptr" * have send() place the number of bytes sent into "count_act" * also use flags "send_flags" * if send() fails, print an error message and return -1 * if count_act != count_expect, assume that the connection * is broken * ******/ while (bytesleft > 0) { count_act = send(sock, buff_ptr, count_expect, send_flags); if (count_act < 0) { printf("s: send function failed - errno = %d\n", errno); return(-1); }else if (count_act != count_expect) { printf("s: send error-expect: %d sent: %d\n", count_expect,count_act); } buff_ptr = buff_ptr + count_act; /* next position to send from*/ bytesleft = bytesleft - count_act; if (count_expect > bytesleft) /* only send what is left... */ count_expect = bytesleft; } return(0); } /* end of send_to_client */ /****** * receive_from_client() * * receive a message from the client at "sock" and place it in * "in_buff" which has a maximum length of "in_len" * the actual message received consists of an 8 byte header containing * total length of the message (the length is in printable characters) * followed by the actual user data * multiple receive() calls will be made until the number of bytes * specified in the header are received * the header is stripped off and the actual data bytes are placed in * "in_len" * * the length of the data is returned if successful, otherwise -1 * * parameters: * * int sock; socket for communication * char *in_buff; string from client * int in_len; max length of string ******/ int receive_from_client(int sock, char *in_buff, int in_len) { int count_recv; /* # bytes sent received */ int count_act; /* actual # bytes sent */ int total_len; /* total receive data length */ char temp_buff[MESSAGESIZE+9]; /* temp string buffer */ char *buff_ptr; /* pointer into string buffer */ int buffsize = sizeof(temp_buff); /* initial size of buffer */ int recv_flags = 0; /* no flags needed */ /****** * receive the first packet and get the expected length * use the receive function recv() and place the data in "temp_buf * of a maximum size of "buffsize" * have recv() return the number of bytes received into "count_act * use socket "sock" and flags "recv_flags" * if recv() fails, print a message and return -1 * if zero bytes are returned, assume the connection is broken * ******/ count_act = recv(sock, temp_buff, buffsize, recv_flags); if (count_act < 0) { printf("s: receive function failed - errno = %d\n", errno); return(-1); }else if (count_act == 0) { printf("s: connection terminated by client\n"); return(-1); }else if (count_act < 8) { printf("s: receive was too short\n"); return(-1); } printf("Received from client %d bytes\n",count_act); printf("Received (%s)\n",temp_buff); if (client_type == ASCII_CLIENTS){ ASCIItoEBCDIC(temp_buff,count_act); } buffsize = buffsize - count_act; buff_ptr = temp_buff; sscanf(temp_buff,"%08u",&total_len);/* total length of client data*/ buff_ptr = buff_ptr + count_act; /* skip bytes received */ while (count_act < total_len) { /* read any remaining packets */ /****** * receive the next packet with the receive function recv() * place the data in the string pointed to by "buff_ptr" * of a maximum size of "buffsize" * have recv return the number of bytes received into "count_recv" * use socket "sock" and flags "recv_flags" * if recv() fails, print a message and return -1 * if zero bytes are returned, assume the connection is broken * ******/ if ((count_recv = recv(sock,buff_ptr,buffsize,recv_flags)) < 0) { printf("s: receive function failed - errno = %d\n", errno); return(-1); }else if (count_recv == 0) { printf("s: connection terminated by client\n"); return(-1); } printf("Received from client %d bytes\n",count_recv); if (client_type == ASCII_CLIENTS){ ASCIItoEBCDIC(temp_buff,count_act); } buff_ptr = buff_ptr + count_recv; /* skip bytes just received*/ count_act = count_act + count_recv;/* running input byte count*/ buffsize = buffsize - count_act; /* remaining buffer space */ } if (count_act != total_len) { printf("s: error - expected %d bytes - received %d\n", total_len, count_act); return(-1); } total_len = total_len - 8; /* strip off length bytes */ strncpy(in_buff,&temp_buff[8],total_len); /* copy to user buffer */ in_buff[total_len] = '\0'; /* ensure null terminated */ return(total_len); } /* end of receive_from_client */ void EBCDICtoASCII(char *out_buff,int out_len) { char lookup[255]; int i, ch; /* lookup for 1 - 9 to ASCII */ ch = 0x30; for (i=240; i<250; i++){ lookup[i] = ch; ch++; } /* lookup for A - I to ASCII */ ch = 0x41; for (i=193; i<202; i++){ lookup[i] = ch; ch++; } /* lookup for J - R to ASCII */ ch = 0x4a; for (i=209; i<218; i++){ lookup[i] = ch; ch++; } /* lookup for S - Z to ASCII */ ch = 0x53; for (i=226; i<234; i++){ lookup[i] = ch; ch++; } /* lookup for a - i to ASCII */ ch = 0x61; for (i=129; i<138; i++){ lookup[i] = ch; ch++; } /* lookup for j - r to ASCII */ ch = 0x6a; for (i=145; i<154; i++){ lookup[i] = ch; ch++; } /* lookup for s - z to ASCII */ ch = 0x73; for (i=162; i<170; i++){ lookup[i] = ch; ch++; } /* lookup for special characters to ASCII */ lookup[' '] = 0x20; lookup['!'] = 0x21; lookup['"'] = 0x22; lookup['#'] = 0x23; lookup['$'] = 0x24; lookup['%'] = 0x25; lookup['&'] = 0x26; lookup[125] = 0x27; /* ' */ lookup['('] = 0x28; lookup[')'] = 0x29; lookup['*'] = 0x2a; lookup['+'] = 0x2b; lookup[','] = 0x2c; lookup['-'] = 0x2d; lookup['.'] = 0x2e; lookup['/'] = 0x2f; lookup[':'] = 0x3a; lookup[';'] = 0x3b; lookup['<'] = 0x3c; lookup['='] = 0x3d; lookup['>'] = 0x3e; lookup['?'] = 0x3f; lookup['@'] = 0x40; lookup[224] = 0x5c; /* / */ lookup[109] = 0x5f; /* _ */ lookup['`'] = 0x60; lookup[192] = 0x7b; /* { */ lookup[79] = 0x7c; /* ? */ lookup[208] = 0x7d; /* } */ lookup['~'] = 0x7e; /* questionable conversions */ lookup[0x5f] = 0x5e; /* not/hat/exponet */ lookup[0xad] = 0x5b; /* begin array */ lookup[0xbd] = 0x5d; /* close array */ /* perform conversion with lookup table */ for (i=0; i */ lookup[63] = 0x6f; /* ? */ lookup[64] = 0x7c; /* @ */ lookup[92] = 0xe0; /* \ backslash */ lookup[95] = 0x6d; /* _ underscore */ lookup[96] = 0x79; /* ` grave */ lookup[123] = 0xc0; /* { curly begin */ lookup[124] = 0x4f; /* ? logical or */ lookup[125] = 0xd0; /* } curly end */ lookup[126] = 0xa1; /* ~ */ /* questionable conversions */ lookup[94] = 0x5f; /* ^ not/hat/exponet */ lookup[91] = 0xad; /* begin array */ lookup[93] = 0xbd; /* close array */ /* perform conversion with lookup table */ for (i=0; i