rxSock -Rexx Function Package for TCP/IP Sockets for OS/2 2.0 by Patrick Mueller (pmuellr@vnet.ibm.com) (c) Copyright International Business Machines Corporation 1993. All rights Reserved. ---------------------------------------------------------------------- what is rxSock? ---------------------------------------------------------------------- rxSock is a REXX function package providing access to the OS/2 TCP/IP socket API as provided by the IBM TCP/IP product, version 1.2.1. The function reference below is minimalistic. It is assumed you are already familiar with the basic socket APIs, and can reference the OS/2 specific ones. A widely available book with information on the basic socket APIs is "Internetworking with TCP/IP Volume I: Principals, Protocols, and Architecture" by Douglas Comer. This function package requires the OS/2 TCP/IP product, version 1.2.1 or higher. ---------------------------------------------------------------------- installation and removal ---------------------------------------------------------------------- The rxSock rexx function package is contained in the file rxSock.dll. This file needs to be placed in a directory along your LIBPATH. To get access to the functions in the rxSock function package, execute the following rexx code: rc = RxFuncAdd("SockLoadFuncs","rxSock","SockLoadFuncs") rc = SockLoadFuncs() To unload the DLL, you should first call the SockDropFuncs() function, then exit all CMD.EXE shells. After exiting all the command shells, the DLL will be dropped by OS/2 and can be deleted or replaced. ---------------------------------------------------------------------- Parameters and Return Values ---------------------------------------------------------------------- Return values for most functions are the same as the C equivalents, unless otherwise noted. There are a number of standard parameters types referenced in the function reference. o socket This is a socket value. It is an integral number. o domain This is a domain value. The only currently supported domain is "AF_INET". o address This is the 'stem' of a stemmed variable with the following values: o address.family should always be "AF_INET" o address.port a port number o address.addr a dotted decimal address, or where appropriate, "INADDR_ANY" When this parameter is needed you should set it the name of a stem variable for the function to set (or that the function will read from). For example, if you passed the string "xxx.!" as a parameter, the variables "xxx.!family", "xxx.!port", and "xxx.!addr" will be set by the function, or queried by the function. o dotAddress the standard dotted decimal address. For example, the string "9.23.19.63" is a valid address. o host This is the 'stem' of a stemmed variable with the following values: o host.name the standard name of the host o host.alias.0 number of aliases for this host o host.alias.1 First alias for this host o host.alias.n n'th alias for this host o host.addrtype should always be "AF_INET" o host.addr a dotted decimal address (default address) | o host.addr.0 | number of addresses for this host | | o host.addr.1 | First address for this host | | o host.addr.n | n'th address for this host When this parameter is needed you should set it the name of a stem variable for the function to set (or that the function will read from). For example, if you passed the string "xxx.!" as a parameter, the variables "xxx.!name", "xxx.!alias.0", "xxx.!alias.1" ... "xxx.!alias.n", "xxx.!addrtype" "xxx.!addr" "xxx.!addr.0", "xxx.!addr.1" ... "xxx.!addr.n", will be set by the function, or queried by the function. ---------------------------------------------------------------------- Special note on stemmed variables ---------------------------------------------------------------------- The address and host type of parameters are stemmed variable names. Traditionally, you would pass a string like "addr." as a parameter, and expect to have the variables addr.family, addr.port, and addr.addr set by the function. In the examples above though, I showed using a stem like "addr.!". The exclamation point helps to distinguish the tail values, so they won't get mis-used as normal variables. For instance, look at the following code: port = 923 sNew = SockAccept(sOld,"addr.") say addr.port You might expect the say statement to write the port number of the accept'ed socket. Instead it writes the value of the variable addr.923, since the port variable is SET to a value. Since you probably don't normally use exclamation points in your variables, it's unlikely that you will be using the variable "!port" in your program. Also note, some folk prefer other characters, including "_", "0", and "1" (the digits are allowed to prefix tail values and are very secure against this kind of accidental misuse - I don't use them because the characters are hard to distinguish from O, I, and l). ---------------------------------------------------------------------- Variables set ---------------------------------------------------------------------- o errno The errno variable is set after every rxSock function call. It will have one of the following values (or a numeric value if the number isn't one of these values, probably indicating an errno value the compiler that the tcp/ip product was written in). Note the value is set even if the function that was called does not neccessarily set the variable, in which case the value has no meaning. The value 0 indicates no error occurred. "EWOULDBLOCK" "EINPROGRESS" "EALREADY" "ENOTSOCK" "EDESTADDRREQ" "EMSGSIZE" "EPROTOTYPE" "ENOPROTOOPT" "EPROTONOSUPPORT" "ESOCKTNOSUPPORT" "EOPNOTSUPP" "EPFNOSUPPORT" "EAFNOSUPPORT" "EADDRINUSE" "EADDRNOTAVAIL" "ENETDOWN" "ENETUNREACH" "ENETRESET" "ECONNABORTED" "ECONNRESET" "ENOBUFS" "EISCONN" "ENOTCONN" "ESHUTDOWN" "ETOOMANYREFS" "ETIMEDOUT" "ECONNREFUSED" "ELOOP" "ENAMETOOLONG" "EHOSTDOWN" "EHOSTUNREACH" "ENOTEMPTY" o h_errno The h_errno variable is set after every rxSock function call. It will have one of the following values (or a numeric value if the number isn't one of these values). Note the value is set even if the function that was called does not neccessarily set the variable, in which case the value has no meaning. The value 0 indicates no error occurred. "HOST_NOT_FOUND" "TRY_AGAIN" "NO_RECOVERY" "NO_ADDRESS" ---------------------------------------------------------------------- Function Reference ---------------------------------------------------------------------- Most of the functions below correspond to their like-named C functions available in the OS/2 TCP/IP socket library. ------------------------------------------------------------------- SockLoadFuncs ------------------------------------------------------------------- rc = SockLoadFuncs() Loads all the functions in the rxSock package. If ANY parameters are passed to this function, it will bypass the program/author/copyright information normally displayed. All parameters are ignored (except to determine whether or not to bypass displaying the information). ------------------------------------------------------------------- SockDropFuncs ------------------------------------------------------------------- rc = SockDropFuncs() Drops all the functions in the rxSock package. | ------------------------------------------------------------------- | SockVersion - returns version number | ------------------------------------------------------------------- | | vers = SockVersion() | | Prior to version 1.2, this function did not exist. To check | to see if a previous version of RxSock is installed, use the | following code, after loading the function package with | SockLoadFuncs(). | | /* oldVersion will be '1' if a version of RxSock < 1.2 is loaded */ | oldVersion = (1 = RxFuncQuery("SockVersion")) ------------------------------------------------------------------- SockAccept - implements C function accept() ------------------------------------------------------------------- socket = SockAccept(socket<,address>) ------------------------------------------------------------------- SockBind - implements C function bind() ------------------------------------------------------------------- rc = SockBind(socket,address) | ------------------------------------------------------------------- | SockClose - implements C function soclose()/close() | ------------------------------------------------------------------- | | rc = SockClose(socket) | | Exactly the same as SockSoClose() ------------------------------------------------------------------- SockConnect - implements C function connect() ------------------------------------------------------------------- rc = SockConnect(socket,address) ------------------------------------------------------------------- SockGetHostByAddr - implements C function gethostbyaddr() ------------------------------------------------------------------- rc = SockGetHostByAddr(dotAddress,host<,domain>) Returns 1 for success, 0 for error. ------------------------------------------------------------------- SockGetHostByName - implements C function gethostbyname() ------------------------------------------------------------------- rc = SockGetHostByName(nameAddress,host) nameAddress should be the textual name of a host, for example "pmuellr.vnet.ibm.com". Returns 1 for success, 0 for error. ------------------------------------------------------------------- SockGetHostId - implements C function gethostid() ------------------------------------------------------------------- dotAddress = SockGetHostId() ------------------------------------------------------------------- SockGetPeerName - implements C function getpeername() ------------------------------------------------------------------- rc = SockGetPeerName(socket,address) ------------------------------------------------------------------- SockGetSockName - implements C function getsockname() ------------------------------------------------------------------- rc = SockGetSockName(socket,address) | ------------------------------------------------------------------- | SockGetSockOpt - implements C function getsockopt() | ------------------------------------------------------------------- | | rc = SockGetSockOpt(socket,level,optVar,optVal) | | The only valid value for level is "SOL_SOCKET" | | optVar may be one of the following: | | "SO_BROADCAST" | "SO_DEBUG" | "SO_DONTROUTE" | "SO_ERROR" | "SO_KEEPALIVE" | "SO_LINGER" | "SO_OOBINLINE" | "SO_RCVBUF" | "SO_RCVLOWAT" | "SO_RCVTIMEO" | "SO_REUSEADDR" | "SO_SNDBUF" | "SO_SNDLOWAT" | "SO_SNDTIMEO" | "SO_TYPE" | "SO_USELOOPBACK" | | optVal is the value of the option. Most of the options' values | are integral. The exceptions are: | | "SO_LINGER" - expects two blank delimited integers - the first | is the l_onoff value, the second is the l_linger | value. | "SO_TYPE" - a string of either "STREAM", "DGRAM", or "RAW" | ------------------------------------------------------------------- SockInit - implements C function sock_init() ------------------------------------------------------------------- rc = SockInit() SockInit() is not strictly needed, as initialization is done for each RxSock function if initialization has not yet occurred. | ------------------------------------------------------------------- | SockIoctl - implements C function ioctl() | ------------------------------------------------------------------- | | rc = SockIoctl(socket,ioctlCmd,ioctlData) | | ioctlCmd is the ioctl command to perform. Valid commands are: | | "FIONBIO" | "FIONREAD" | | ioctlData is the command specific value. Values are: | | "FIONBIO" - "1" or "0" | "FIONREAD" - name of a variable to contain number of immediately | readable bytes ------------------------------------------------------------------- SockListen - implements C function listen() ------------------------------------------------------------------- rc = SockListen(socket,backlog) ------------------------------------------------------------------- SockRecv - implements C function recv() ------------------------------------------------------------------- rc = SockRecv(socket,var,len<,flags>) var is the name of a rexx variable the data should be received into. len is the maximum amount of data to read. flags is a blank delimited list of options: "MSG_OOB", "MSG_PEEK". Returns the return code from the recv() function. | ------------------------------------------------------------------- | SockSelect - implements C function select() | ------------------------------------------------------------------- | | rc = SockSelect(reads,writes,excepts<,timeout>) | | reads, writes, and excepts are stem variables which are queried | and set by this function. The stem.0 variable should contain the | number of sockets, stem.1 the first socket, etc. Upon return, | the stem variables will be reset to the sockets which are ready. | For instance, | | r.0 = 2 | r.1 = 101 | r.2 = 102 | w.0 = 1 | w.1 = 103 | e.0 = 0 | | rc = SockSelect("r.","w.","e.") | | do i = 1 to r.0 | say "socket" r.i "is ready for reading." | end | | timeout is the number of seconds to wait before timing out. | 0 should be used for polling behaviour (no waiting), and "" | should be used to wait indefinitely. If no timeout value is | passed, "" is assumed. The number must be integral (no fractional | values) - if fractional values are required, this could be | implemented - contact me. Non-numeric and negative numbers are | considered 0. | | If any of the stem variables are "", or no parameter is passed, | no sockets for that type will be checked. For instance, the | SockSelect() call above could have been invoked as either of: | | rc = SockSelect("r.","w.","") | rc = SockSelect("r.","w.",) | | The function call SockSelect(,,,x) results in the program pausing for | x seconds. | | The return code from SockSelect() is the number of ready sockets or | 0 if a timeout occurred. If a timeout occurred, the socket arrays are | not modified. ------------------------------------------------------------------- SockSend - implements C function send() ------------------------------------------------------------------- rc = SockSend(socket,data<,flags>) data is a string of text to be sent on the sock. flags is a blank delimited list of options: "MSG_OOB", "MSG_DONTROUTE". Returns the return code from the send() function. | ------------------------------------------------------------------- | SockSetSockOpt - implements C function setsockopt() | ------------------------------------------------------------------- | | rc = SockSetSockOpt(socket,level,optVar,optVal) | | The only valid value for level is "SOL_SOCKET" | | optVar is the option to set. See SockGetSockOpt() for valid | values. Some options listed in SockGetSockOpt() are not valid | for SockSetSockOpt(). They are: | "SO_ERROR" | "SO_TYPE" | | optVal is the value to set the option to. The formats are the | same as that of SockGetSockOpt(), except the actual value should | be passed in, instead of a variable name. ------------------------------------------------------------------- SockShutDown - implements C function shutdown() ------------------------------------------------------------------- rc = SockShutDown(socket,how) ------------------------------------------------------------------- SockSocket - implements C function socket() ------------------------------------------------------------------- socket = SockSocket(domain,type,protocol) domain must be "AF_INET". type may be one of "SOCK_STREAM", "SOCK_DGRAM", or "SOCK_RAW" protocol may be one of "IPPROTO_UDP", "IPPROTO_TCP", or "0" ------------------------------------------------------------------- SockSoClose - implements C function soclose()/close() ------------------------------------------------------------------- rc = SockSoClose(socket) ---------------------------------------------------------------------- Utilities Provided ---------------------------------------------------------------------- killsock.cmd ------------ This program takes socket numbers and closes them. Useful for terminating a stubborn server, or cleaning up after accidents. Use "netstat -s" to get a list of currently open sockets. rnr.cmd ------- A very basic news reader. Used to demonstrate a fairly complex application using rxSock functions. test_h.cmd ---------- A test program testing address to hostname conversions. test_c.cmd test_s.cmd ---------- These program are test client/server programs. Start test_s.cmd in one session, and then test_c.cmd in another. The programs exchange data and print some timing information before quitting. The server and client can run across two different hosts. Pass the host name of the server as a parameter to test_c.cmd test*.cmd --------- These test programs test other parts of the RxSock package. Not all that useful, unless you are looking for info on SockSelect(), SockIoctl(), Sock?etSockOpt() functions. ---------------------------------------------------------------------- History ---------------------------------------------------------------------- 08/05/93 - version 1.3 - fixed stupid bug in SockGetPeerName() and SockGetSockName() 07/16/93 - version 1.2 - added SockVersion(), SockClose(), SockIoctl(), SockSelect(), SockGetSockOpt(), SockSetSockOpt() - changed documentation for SockGetHostByName() and SockGetHostByAddr() to reflect what the code actually does - now return a list of addresses per host instead of just one 03/11/93 - version 1.1 - first release in OS/2 Employee Written Software program - simulataneous (or nearly) release on OS2TOOLS distant past - version 1.0