
|
* SOCKET_H + /*--------- * Copyright (c) 1998,2001 Scott C. Klement + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + *********************************************************************** *** Header file for doing sockets communications. *** *** To use this, you must /COPY RMTCALL/QRPGLESRC, SOCKET_H into *** the "D" specs of your RPG IV source member.... *** (or whatever the appropriate source lib/file, member is) *** *** Most of the major socket functions and structures are prototyped *** here. There may be some that I missed (because I havent needed *** them) if you need them, you'll have to add them yourself :) *** SCK 08/06/1998 ***********************************************************************   D/if defined(SOCKET_H) D/eof D/endif D/define SOCKET_H |
  *********************************************************************** ** C O N S T A N T S *********************************************************************** D IPVERSION C CONST(4)   ** Address families. D* Only Internet will be included for now... D* If you intend to use other than IP sockets D* you will have to add them in yourself. D* D AF_INET C CONST(2)   ** Socket Types: D* stream socket (TCP) D SOCK_STREAM C CONST(1) D* datagram socket (UDP) D SOCK_DGRAM C CONST(2) D* raw socket D SOCK_RAW C CONST(3)       ** Protocols... D* These are the commonly used protocols in D* the Internet Address Family. D* D* Internet Protocol D IPPROTO_IP C CONST(0) D* Transmission Control D* Protocol D IPPROTO_TCP C CONST(6) D* Unordered Datagram D* Protocol D IPPROTO_UDP C CONST(17) D* Raw Packets D IPPROTO_RAW C CONST(255) D* Internet Control D* Msg Protocol D IPPROTO_ICMP C CONST(1) D* socket layer D SOL_SOCKET C CONST(-1)     |
** IP-Level (IPPROTO_IP) options for setsockopt()/getsockopt() ** (Note: None of the multicast options are set here, but ** they probably should be) D* ip options D IP_OPTIONS C CONST(5) D* type of service D IP_TOS C CONST(10) D* time to live D IP_TTL C CONST(15) D* recv lcl ifc addr D IP_RECVLCLIFADDR... D C CONST(99)     ** TCP level (IPPROTO_TCP) options for setsockopt()/getsockopt() D* max segment size (MSS) D TCP_MAXSEG C 5 D* dont delay small packets D TCP_NODELAY C 10     ** Socket-Level (SOL_SOCKET) options for setsockopt()/getsockopt() D* allow broadcast msgs D SO_BROADCAST C 5 D* record debug information D SO_DEBUG C 10 D* just use interfaces, D* bypass routing D SO_DONTROUTE C 15 D* error status D SO_ERROR C 20 D* keep connections alive D SO_KEEPALIVE C 25 D* linger upon close D SO_LINGER C 30 D* out-of-band data inline D SO_OOBINLINE C 35 D* receive buffer size D SO_RCVBUF C 40 D* receive low water mark D SO_RCVLOWAT C 45 D* receive timeout value D SO_RCVTIMEO C 50 D* re-use local address |
D SO_REUSEADDR C 55 D* send buffer size D SO_SNDBUF C 60 D* send low water mark D SO_SNDLOWAT C 65 D* send timeout value D SO_SNDTIMEO C 70 D* socket type D SO_TYPE C 75 D* send loopback D SO_USELOOPBACK C 80     ** Types of Service for IP packets ** These are indended to be used in the 'ip' data structure ** defined below. D* normal D IPTOS_NORMAL C CONST(x'00') D* min cost D IPTOS_MIN C CONST(x'02') D* reliability D IPTOS_RELIABLE C CONST(x'04') D* throughput D IPTOS_THRUPUT C CONST(x'08') D* low-delay D IPTOS_LOWDELAY C CONST(x'10')     ** Precedence for Types of Service ** These are indended to be used in the 'ip' data structure ** defined below. D* net control D IPTOS_NET C CONST(x'E0') D* internet control D IPTOS_INET C CONST(x'C0') D* critic ecp D IPTOS_CRIT C CONST(x'A0') D* flash override D IPTOS_FOVR C CONST(x'80') D* flash D IPTOS_FLAS C CONST(x'60') D* immediate D IPTOS_IMME C CONST(x'40') D* priority |
D IPTOS_PTY C CONST(x'20') D* routine D IPTOS_ROUT C CONST(x'10')     ** I/O flags (for send, sendto, recv, recvfrom functions) D* dont route D MSG_DONTROUTE C CONST(1) D* out-of-band data D MSG_OOB C CONST(4) D* keep data in buffer D MSG_PEEK C CONST(8)     ** "Special" IP Address values D* any address available D INADDR_ANY C CONST(0) D* broadcast D INADDR_BROADCAST... D C CONST(4294967295) D* loopback/localhost D INADDR_LOOPBACK... D C CONST(2130706433) D* no address exists D INADDR_NONE C CONST(4294967295)   ** ICMP message types D* echo reply D ICMP_ECHOR C CONST(x'00') D* unreachable D ICMP_UNREA C CONST(x'03') D* source quench D ICMP_SRCQ C CONST(x'04') D* redirect D ICMP_REDIR C CONST(x'05') D* echo D ICMP_ECHO C CONST(x'08') D* time exceeded D ICMP_TIMX C CONST(x'0B') D* parameter problem D ICMP_PARM C CONST(x'0C') D* timestamp request D ICMP_TSTP C CONST(x'0D') D* timestamp req reply |
D ICMP_TSTPR C CONST(x'0E') D* info request D ICMP_IREQ C CONST(x'0F') D* info request reply D ICMP_IREQR C CONST(x'10') D* addr mask request D ICMP_MASK C CONST(x'11') D* addr mask req reply D ICMP_MASKR C CONST(x'12')   ** ICMP subtype codes D* network unreachable D UNR_NET C CONST(x'00') D* host unreachable D UNR_HOST C CONST(x'01') D* protocol unreachble D UNR_PROTO C CONST(x'02') D* port unreachable D UNR_PORT C CONST(x'03') D* fragmentation needed D* and dont fragment D* flag is set D UNR_FRAG C CONST(x'04') D* source route failed D UNR_SRCF C CONST(x'05') D* time exceeded in D* transit D TIMX_INTRA C CONST(x'00') D* time exceeded in D* frag reassembly D TIMX_REASS C CONST(x'01') D* redir for network D REDIR_NET C CONST(x'00') D* redir for host D REDIR_HOST C CONST(x'01') D* redir for TOS & Net D REDIR_TOSN C CONST(x'02') D* redir for TOS & Host D REDIR_TOSH C CONST(x'03')   D/if not defined(FCNTL_CONSTANTS) ** fcntl() commands D F_DUPFD C CONST(0) D F_GETFL C CONST(6) |
D F_SETFL C CONST(7)
D F_GETOWN C CONST(8)
D F_SETOWN C CONST(9)
 
** fcntl() flags
D O_NONBLOCK C CONST(128)
D O_NDELAY C CONST(128)
D FNDELAY C CONST(128)
D FASYNC C CONST(512)
D/define FCNTL_CONSTANTS
D/endif
 
***********************************************************************
** D A T A S T R U C T U R E S
**
** Note that data structures here are all set up to be based on
** a pointer. The reason for this is:
** 1) Data structs that you don't use in your program won't
** have memory allocated to them.
** 2) You can have different "instances" of each data struct
** simply by moving the pointer to a different area of
** memory.
***********************************************************************
** Socket Address (Generic, for any network type)
**
** struct sockaddr {
** u_short sa_family;
** char sa_data[14];
** };
**
D p_sockaddr S *
D SockAddr DS based(p_sockaddr)
D SA_Family 5U 0
D SA_Data 14A
 
 
** Socket Address (Internet)
**
** struct sockaddr_in {
** short sin_family;
** u_short sin_port;
** struct in_addr sin_addr;
** char sin_zero[8];
** };
|
**
D sockaddr_in DS based(p_sockaddr)
D sin_Family 5I 0
D sin_Port 5U 0
D sin_addr 10U 0
D sin_zero 8A
 
 
**
** Host Database Entry (for DNS lookups, etc)
**
** (this is a partial implementation... didn't try to
** figure out how to deal with all possible addresses
** or all possible aliases for a host in RPG)
**
** struct hostent {
** char *h_name;
** char **h_aliases;
** int h_addrtype;
** int h_length;
** char **h_addr_list;
** };
**
** #define h_addr h_addr_list[0]
**
D p_hostent S *
D hostent DS Based(p_hostent)
D h_name *
D h_aliases *
D h_addrtype 5I 0
D h_length 5I 0
D h_addrlist *
D p_h_addr S * Based(h_addrlist)
D h_addr S 10U 0 Based(p_h_addr)
 
 
**
** Service Database Entry (which service = which port, etc)
**
** struct servent {
** char *s_name;
** char **s_aliases;
** int s_port;
** char *s_proto;
|
** };
**
D p_servent S *
D servent DS Based(p_servent)
D s_name *
D s_aliases *
D s_port 10I 0
D s_proto *
 
 
**
** IP structure without any opts (for RAW sockets)
**
** struct ip {
** unsigned ip_v:4; Version (first 4 bits)
** unsigned ip_hl:4; Header length (next 4)
** u_char ip_tos; Type of service
** short ip_len; Total Length
** u_short ip_id; Identification
** short ip_off; Fragment offset field
** u_char ip_ttl; Time to live
** u_char ip_p; Protocol
** u_short ip_sum; Checksum
** struct in_addr ip_src; Source Address
** struct in_addr ip_dst; Destination Address
** };
**
** Note: Since you can't define a variable to be 4 bits long
** in RPG, ip_v_hl is a combination of ip_v and ip_hl.
** with mult/div/mvr and data structures, it should still
** be usable...
**
** Since ip_tos & ip_ttl conflict with the definitions for
** setsockopt() & getsockopt(), we add an extra $ to the end...
d p_ip S *
D ip DS based(p_ip)
D ip_v_hl 1A
D ip_tos$ 1A
D ip_len 5I 0
D ip_id 5U 0
D ip_off 5I 0
D ip_ttl$ 1A
D ip_p 1A
D ip_sum 5U 0
|
D ip_src 10U 0
D ip_dst 10U 0
 
 
**
** UDP Packet Header (for RAW sockets)
**
** struct udphdr { /* UDP header */
** u_short uh_sport; /* source port */
** u_short uh_dport; /* destination port */
** short uh_ulen; /* UDP length */
** u_short uh_sum; /* UDP checksum */
** };
**
d p_udphdr S *
d udphdr DS based(p_udphdr)
D uh_sport 5U 0
D uh_dport 5U 0
D uh_ulen 5I 0
D uh_sum 5U 0
 
 
** Internet Control Message Protocol (ICMP) header
** (I THINK I did the unions correctly... but you might want to
** check that out if you're having problems...)
**
** struct icmp { /* ICMP header */
** u_char icmp_type; /* ICMP message type */
** u_char icmp_code; /* type sub code */
** u_short icmp_cksum; /* ICMP checksum */
** union { /* Message type substructures:*/
** u_char ih_pptr; /* Parameter problem pointer*/
** struct in_addr ih_gwaddr; /* Redirect gateway address */
** struct ih_idseq { /* Echo/Timestmp Req/Reply */
** u_short icd_id; /* Indentifier */
** u_short icd_seq; /* Sequence number */
** } ih_idseq;
** int ih_void; /* Unused part of some msgs */
** } icmp_hun;
** union {
** struct id_ts { /* Timestamp substructure */
** u_long its_otime; /* Originate timestamp */
** u_long its_rtime; /* Receive timestamp */
** u_long its_ttime; /* Transmit timestamp */
|
** } id_ts;
** struct id_ip { /* Imbedded 'original' IP hdr */
** struct ip idi_ip; /* in ICMP error-type msgs. */
** /* Includes IP header,IP opts,*/
** /* and 64 bits of data. */
** } id_ip;
** u_long id_mask; /* Address mask request/reply */
** char id_data[1]; /* Beginning of echo req data */
** } icmp_dun;
** };
D p_icmp S *
D icmp DS based(p_icmp)
D icmp_type 1A
D icmp_code 1A
D icmp_cksum 5U 0
D icmp_hun 4A
D ih_gwaddr 10U 0 OVERLAY(icmp_hun:1)
D ih_pptr 1A OVERLAY(icmp_hun:1)
D ih_idseq 4A OVERLAY(icmp_hun:1)
D icd_id 5U 0 OVERLAY(ih_idseq:1)
D icd_seq 5U 0 OVERLAY(ih_idseq:3)
D ih_void 5I 0 OVERLAY(icmp_hun:1)
D icmp_dun 20A
D id_ts 12A OVERLAY(icmp_dun:1)
D its_otime 10U 0 OVERLAY(id_ts:1)
D its_rtime 10U 0 OVERLAY(id_ts:5)
D its_ttime 10U 0 OVERLAY(id_ts:9)
D id_ip 20A OVERLAY(icmp_dun:1)
D idi_ip 20A OVERLAY(id_ip:1)
D id_mask 10U 0 OVERLAY(icmp_dun:1)
D id_data 1A OVERLAY(icmp_dun:1)
 
 
**
** Time Value Structure (for the select() function, etc)
**
** struct timeval {
** long tv_sec; /* seconds */
** long tv_usec; /* microseconds */
** };
**
** contrains a structure for specifying a wait time on
** a select() function...
**
|
** tv_sec = seconds. tv_usec = microseconds
**
D p_timeval S *
D timeval DS based(p_timeval)
D tv_sec 10I 0
D tv_usec 10I 0
 
 
** linger structure (used with setsockopt or getsockopt)
**
** struct linger {
** int l_onoff; /* Option Setting ON/OFF */
** int l_linger; /* Time to linger in seconds */
** };
**
D p_linger S *
D linger DS BASED(p_linger)
D l_onoff 10I 0
D l_linger 10I 0
 
 
***********************************************************************
** S U B P R O C E D U R E P R O T O T Y P E S
***********************************************************************
** --------------------------------------------------------------------
**
** socket--Create Socket
**
** int socket(int address_family,
** int type,
** int protocol)
**
**
** The socket() function is used to create an end point for
** communications. The end point is represented by the
** socket descriptor returned by the socket() function.
**
** --------------------------------------------------------------------
D socket PR 10I 0 ExtProc('socket')
D AddrFamily 10I 0 Value
D SocketType 10I 0 Value
D Protocol 10I 0 Value
 
 
|
** --------------------------------------------------------------------
**
** setsockopt()--Set Socket Options
**
** int setsockopt(int socket_descriptor,
** int level,
** int option_name,
** char *option_value
** int option_length)
**
** The setsockopt() function is used to set socket options
** (there are many, see the book.)
** --------------------------------------------------------------------
D setsockopt PR 10I 0 ExtProc('setsockopt')
D SocketDesc 10I 0 Value
D Opt_Level 10I 0 Value
D Opt_Name 10I 0 Value
D Opt_Value * Value
D Opt_Len 10I 0 Value
 
 
** --------------------------------------------------------------------
** getsockopt() -- Retrieve Info about Socket Options
**
** int getsockopt(int socket_descriptor,
** int level,
** int option_name,
** char *option_value,
** int *option_length)
**
** Gets various information about the socket's options.
** (there are many, see the book.)
** --------------------------------------------------------------------
D getsockopt PR 10I 0 extproc('getsockopt')
D SocketDesc 10I 0 VALUE
D Opt_Level 10I 0 VALUE
D Opt_Name 10I 0 VALUE
D Opt_Value * VALUE
D Opt_Length 10I 0
 
 
** --------------------------------------------------------------------
**
** getsockname()--Get Local Address for Socket
|
**
** int getsockname(int socket_descriptor,
** struct sockaddr *local_address,
** int *address_length)
**
** struct sockaddr {
** u_short sa_family;
** char sa_data[14];
** };
**
** The getsockname() function is used to retreive the local address
** asociated with a socket.
** --------------------------------------------------------------------
D getsockname PR 10I 0 ExtProc('getsockname')
D SocketDesc 10I 0 Value
D SockAddr like(Sockaddr_in)
D AddrLength 10I 0
 
 
**
** --------------------------------------------------------------------
**
** getpeername()--Retrieve Destination Address of Socket
**
** int getpeername(int socket_descriptor,
** struct sockaddr *local_address,
** int *address_length)
**
** struct sockaddr {
** u_short sa_family;
** char sa_data[14];
** };
**
**
** The getpeername() function is used to retreive the destination
** address to which the socket is connected.
**
** Note: Socket must be connected first.
**
** --------------------------------------------------------------------
D getpeername PR 10I 0 ExtProc('getpeername')
D SocketDesc 10I 0 Value
D p_sockaddr * Value
D AddrLength 10I 0
|
 
 
** --------------------------------------------------------------------
** bind()--Bind socket to specified adapter and/or port
**
** int bind(int socket_descriptor,
 
** struct sockaddr *local_address,
** int address_length)
**
** struct sockaddr {
** u_short sa_family;
** char sa_data[14];
** };
**
**
** The bind() function is used to associate a local address
** and port with a socket. This allows you to get only
** socket requests on a specific network adapter, and to
** assign a specific port to your socket.
** For example, if you're writing a telnet server, you'd
** bind to port 23, because thats the standard port for
** telnets to listen on.
** If we bind to an address of 0, it will allow requests on
** any (TCP/IP enabled) network adapter.
**
** --------------------------------------------------------------------
D bind PR 10I 0 ExtProc('bind')
D Sock_Desc 10I 0 Value
D p_Address * Value
D AddressLen 10I 0 Value
 
 
** --------------------------------------------------------------------
** listen()--Invite Incoming Connections Requests
**
** int listen(int socket_descriptor,
** int back_log)
**
**
** The listen() function is used to indicate a willingness to accept
** incoming connection requests. if a listen() is not done,
** incoming requests are refused.
**
|
** --------------------------------------------------------------------
D listen PR 10I 0 ExtProc('listen')
D SocketDesc 10I 0 Value
D Back_Log 10I 0 Value
 
 
** --------------------------------------------------------------------
** accept()--Wait for Connection Request and Make Connection
**
** int accept(int socket_descriptor,
** struct sockaddr *address,
** int *address_length)
**
** struct sockaddr {
** u_short sa_family;
** char sa_data[14];
** };
**
** The accept() function is used to wait for connection requests.
** accept() takes the first connection request on the queue of
** pending connection requests and creates a new socket to service
** the connection request.
**
** --------------------------------------------------------------------
D accept PR 10I 0 ExtProc('accept')
D Sock_Desc 10I 0 Value
D p_Address * Value
D p_AddrLen 10I 0 options(*omit)
 
 
** --------------------------------------------------------------------
** connect() -- Connect to a host.
**
** int connect(int socket_descriptor,
** struct sockaddr *destination,
** int address_length)
**
** Used to connect to a host. (Usually used on the client-side)
** In TCP applications, this takes an address & port and connects
** to a server program thats listening on that port. In UDP
** this simply specifies the address & port to send to.
**
** --------------------------------------------------------------------
D connect PR 10I 0 ExtProc('connect')
|
D Sock_Desc 10I 0 VALUE
D p_SockAddr * VALUE
D AddressLen 10I 0 VALUE
 
 
** --------------------------------------------------------------------
** send()--Send Data
**
** int send(int socket_descriptor,
** char *buffer,
** int buffer_length,
** int flags)
**
** Sends data in buffer via socket connection to another program.
**
** In the case of text, it should be converted to ASCII and then
** CR/LF terminated.
**
** --------------------------------------------------------------------
D Send PR 10I 0 ExtProc('send')
D Sock_Desc 10I 0 Value
D p_Buffer * Value
D BufferLen 10I 0 Value
D Flags 10I 0 Value
 
 
** --------------------------------------------------------------------
** sendto()--Send Data
**
** int sendto(int socket_descriptor,
** char *buffer,
** int buffer_length,
** int flags,
** struct sockaddr *destination_address,
** int address_length)
**
** Sends data in buffer via connected/connectionless sockets
**
** This is more useful for connectionless sockets (such as UDP)
** because allows you to specify the destination address.
**
** When used with a connection-oriented sockets (such as TCP)
** the destination address should be set to *NULL, and the length
** should be zero.
|
**
** --------------------------------------------------------------------
D SendTo PR 10I 0 ExtProc('sendto')
D Sock_Desc 10I 0 Value
D p_Buffer * Value
D BufferLen 10I 0 Value
D Flags 10I 0 Value
D DestAddr * Value
D AddrLen 10I 0 Value
 
 
** --------------------------------------------------------------------
** recv()--Receive Data
**
** int recv(int socket_descriptor, I
** char *buffer, I
** int buffer_length, I
** int flags)
**
**
** The recv() funcion is used to receive data through a socket.
**
** --------------------------------------------------------------------
D Recv PR 10I 0 ExtProc('recv')
D Sock_Desc 10I 0 Value
D p_Buffer * Value
D BufferLen 10I 0 Value
D Flags 10I 0 Value
 
 
** --------------------------------------------------------------------
** recvfrom()--Receive Data w/From Address
**
** int recvfrom(int socket_descriptor,
** char *buffer,
** int buffer_length,
** int flags,
** struct sockaddr *from_address,
** int *address_length)
**
**
** The recvfrom() function receives data through a connected, or
** an unconnected socket.
**
|
** This is particularly useful for UDP/Connectionless sockets
** because it allows you to ascertain who sent the data to you.
**
** The from_address and address_length parms are ignored on
** connection-oriented sockets -- or if they are set to *NULL.
** --------------------------------------------------------------------
D RecvFrom PR 10I 0 ExtProc('recvfrom')
D Sock_Desc 10I 0 Value
D p_Buffer * Value
D BufferLen 10I 0 Value
D Flags 10I 0 Value
D FromAddr * Value
D AddrLength 10I 0
 
 
** --------------------------------------------------------------------
** close()--End Socket Connection
**
** int close(int descriptor)
**
** Ends a socket connection, and deletes the socket descriptor.
**
** Note: Due to conflicts with IFSIO_H, we are only defining
** close() if it has not already been defined.
** --------------------------------------------------------------------
D/if not defined(CLOSE_PROTOTYPE)
D Close PR 10I 0 ExtProc('close')
D Sock_Desc 10I 0 Value
D/define CLOSE_PROTOTYPE
D/endif
 
 
** --------------------------------------------------------------------
** shutdown()-- disable reading/writing on a socket
**
** int shutdown(int descriptor,
** int how)
**
** Stops all reading and/or writing on a socket.
** Difference between this and close() is that with close, you
** actually delete the descriptor, and must accept() a new one,
** or allocate (socket()) a new one.
**
** The how parameter can be:
|
** 0 = no more data can be received
** 1 = no more data can be sent
** 2 = no more data can be sent or received
**
** --------------------------------------------------------------------
D shutdown PR 10I 0 ExtProc('shutdown')
D Sock_Desc 10I 0 Value
D How 10I 0 Value
 
 
** --------------------------------------------------------------------
** select() -- wait for events on multiple sockets
**
** int select(int max_descriptor,
** fd_set *read_set,
** fd_set *write_set,
** fd_set *exception_set,
** struct timeval *wait_time)
**
** Select is used to wait for i/o on multiple sockets. This
** prevents your job from "blocking" on one socket read, while
** there is data to read on another socket.
**
** It also allows you to "poll" for data to be found on a socket
** and to set a timeout value to keep your application from
** stopping forever on a "dead-end" socket.
**
** ***** To help with managing the descriptor sets, I have
** ***** created FD_SET, FD_ISSET, FD_CLR and FD_ZERO functions
** ***** in my SOCKUTIL_H/SOCKUTILR4 socket utilities functions!
**
** max_desriptor = The number of descriptors in your sets.
** (take the highest descriptor value you want
** to wait on, and add 1, and put it here)
**
** read_set = A 28-byte character field specifying, on input,
** which descriptors to wait for, and, on output,
** which descriptors have data waiting on them.
** This can be set to *NULL if you do not wish to
** wait for any sockets to be read.
**
** write_set = A 28-byte character field specifying, on input,
** which descriptors to wait for, and, on output,
** which descriptors are ready to be written to.
|
** This can be set to *NULL if you do not wish to
** wait for any sockets to be written to.
**
** exception_set = A 28-byte character field specifying, on input,
** which descriptors to test, and on output,
** which descriptors have exceptions signalled to them.
** This can be set to *NULL if you do not wish to
** check for any sockets to have exceptions.
**
** NOTE: An exception is not the same as an error.
** Exceptions are usually out-of-band data!
**
** wait_time = a timeval data structure containing the amoutn of
** time to wait for an event to occur.
** If a wait time of zero is given, select() will
** return immediately.
** If *NULL is passed instead of the timeval structure,
** select() will wait indefinitely.
**
** Returns the number of descriptors that met selection criteria
** or 0 for timeout
** or -1 for error.
** --------------------------------------------------------------------
D Select PR 10I 0 extproc('select')
D max_desc 10I 0 VALUE
D read_set * VALUE
D write_set * VALUE
D except_set * VALUE
D wait_Time * VALUE
 
 
** --------------------------------------------------------------------
** givedescriptor() -- Pass Descriptor Access to Another Job
**
** int givedescriptor(int descriptor,
** char *target_job)
**
** Allows you to pass a descriptor from one OS/400 job to another.
** (Very useful if you wanted one job to wait for incoming conn.
** then, submit a seperate job to deal with each client connection
 
** while the original keeps waiting for more)
**
** It is the programmer's responsibility to alert the target job
|
** that it needs to take the descriptor, using takedescriptor().
**
** the info for the target job can be obtained by calling a Work
** Managment API that supplies an "internal job identifier"
** (such as QUSRJOBI)
**
** returns 0 = success, -1 = failure
** --------------------------------------------------------------------
D givedescriptor PR 10I 0 extproc('givedescriptor')
D SockDesc 10I 0 VALUE
D Target_Job * VALUE
 
 
** --------------------------------------------------------------------
** takedescriptor() -- Receive Descriptor Access from Another Job
**
** int takedescriptor(char *source_job)
**
** Allows you to pass a descriptor from one OS/400 job to another.
** (Very useful if you wanted one job to wait for incoming conn.
** then, submit a seperate job to deal with each client connection
** while the original keeps waiting for more)
**
** the info for the source job can be obtained by calling a Work
** Managment API that supplies an "internal job identifier"
** (such as QUSRJOBI).
**
** You can also specify *NULL pointer for the Source_Job parm if
** you want to receive a descriptor from ANY job that gives one
** one to you.
**
** If no other jobs has referenced yours with givedescriptor()
** then this function will block.
**
** return value is the socket descriptor taken, or -1 for error.
** --------------------------------------------------------------------
D takedescriptor PR 10I 0 extproc('takedescriptor')
D Source_Job * VALUE
 
 
** --------------------------------------------------------------------
** gethostbyname() -- Resolves a domain name to an IP address
**
** struct hostent *gethostbyname(char *host_name)
|
**
** struct hostent {
** char *h_name;
** char **h_aliases;
** int h_addrtype;
** int h_length;
** char **h_addr_list;
** };
**
** Returns a pointer to a host entry structure. The aliases and
** address list items in the structure are pointers to arrays of
** pointers, which are null terminated.
**
** Note: The strings & arrays used in C are often variable length,
** null-terminated entities. Be careful to only use bytes from
** the returned pointers (in the hostent data structure) to
** the first null (x'00') character.
** --------------------------------------------------------------------
D gethostbyname PR * extProc('gethostbyname')
D HostName * value options(*string)
 
 
** --------------------------------------------------------------------
** getservbyname()--Get Port Number for Service Name
**
** struct servent *getservbyname(char *service_name,
** char *protocol_name)
**
** struct servent {
** char *s_name;
** char **s_aliases;
** int s_port;
** char *s_proto;
** };
**
** This is generally used to look up which port is used for a given
** internet service. i.e. if you want to know the port for
** TELNET, you'd do x = getservbyname('telnet': 'tcp')
** --------------------------------------------------------------------
D getservbyname PR * extproc('getservbyname')
D service_name * value options(*string)
D protocol_nam * value options(*string)
 
 
|
** --------------------------------------------------------------------
** gethostbyaddr()--Get Host Information for IP Address
**
** struct hostent *gethostbyaddr(char *host_address,
** int address_length,
** int address_type)
** struct hostent {
** char *h_name;
** char **h_aliases;
** int h_addrtype;
** int h_length;
** char **h_addr_list;
** };
**
** An IP address (32-bit integer formnat) goes in, and a
** hostent structure pops out. Really, kinda fun, if you
** havent already learned to hate the hostent structure, that is.
**
** Note: The strings & arrays used in C are often variable length,
** null-terminated entities. use caution to only use data from
** the returned pointer up until the terminating null (x'00')
**
** --------------------------------------------------------------------
D gethostbyaddr PR * ExtProc('gethostbyaddr')
D IP_Address 10U 0
D Addr_Len 10I 0 VALUE
D Addr_Fam 10I 0 VALUE
 
 
** --------------------------------------------------------------------
** inet_addr()--Converts an address from dotted-decimal format
** to a 32-bit IP address.
**
** unsigned long inet_addr(char *address_string)
**
** Converts an IP address from format 192.168.0.100 to an
** unsigned long, such as hex x'C0A80064'.
**
** returns INADDR_NONE on error.
**
** KNOWN BUG: Due to the fact that this can't return a negative value,
** it returns x'FFFFFFFF' on error. However, x'FFFFFFFF'
** is also the correct IP for the valid address of
** "255.255.255.255". (which is "worldwide broadcast")
|
** A reasonable workaround is to check for 255.255.255.255
** beforehand, and translate it manually rather than
** calling inet_addr.
** --------------------------------------------------------------------
D inet_addr PR 10U 0 ExtProc('inet_addr')
D char_addr * value options(*string)
 
 
 
** --------------------------------------------------------------------
** inet_ntoa()--Converts an address from 32-bit IP address to
** dotted-decimal format.
**
** char *inet_ntoa(struct in_addr internet_address)
**
** Converts from 32-bit to dotted decimal, such as, x'C0A80064'
** to '192.168.0.100'. Will return NULL on error
**
** Note: The strings & arrays used in C are often variable length,
** null-terminated entities. Make sure you only use bytes from
** the returned pointer to the first null (x'00') character.
**
** --------------------------------------------------------------------
D inet_ntoa PR * ExtProc('inet_ntoa')
D ulong_addr 10U 0 VALUE
 
 
** --------------------------------------------------------------------
** fcntl()--Change Descriptor Attributes
**
** int fcntl(int descriptor, int command, ...)
**
** The third parameter (when used with sockets) is also an
** integer passed by value.. it specifies an argument for
** some of the commands.
**
** commands supported in sockets are:
** F_GETFL -- Return the status flags for the descriptor
** F_SETFL -- Set status flags for the descriptor
** (Arg =)status flags (ORed) to set.
** (the commands below arent terribly useful in RPG)
** F_DUPFD -- Duplicate the descriptor
** (Arg =)minimum value that new descriptor can be
** F_GETOWN -- Return the process ID or group ID that's
|
** set to receive SIGIO & SIGURG
** F_SETOWN -- Set the process ID or group ID that's
** to receive SIGIO & SIGURG
** (Arg =)process ID (or neg value for group ID)
**
** returns -1 upon error.
** successful values are command-specific.
** --------------------------------------------------------------------
D/if not defined(FCNTL_PROTOTYPE)
D fcntl PR 10I 0 ExtProc('fcntl')
D SocketDesc 10I 0 Value
D Command 10I 0 Value
D Arg 10I 0 Value Options(*NOPASS)
D/define FCNTL_PROTOTYPE
D/endif
|