Jump to content

Implementing Sockets Subclasses

From EDM2
Revision as of 23:26, 9 May 2021 by Martini (talk | contribs) (Created page with "Distributed SOM (DSOM) and the Replication Framework require basic message services for inter-process communications. The Event Management Framework must be integrated with th...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Distributed SOM (DSOM) and the Replication Framework require basic message services for inter-process communications. The Event Management Framework must be integrated with the same communication services in order to handle communications events.

To maximize their portability to a wide variety of local area network transport protocols, the DSOM, Replication, and Event Management Frameworks have been written to use a common communications interface, which is implemented by one or more SOM class libraries using available local protocols.

The common communications interface is based on the "sockets" interface used with TCP/IP, since its interface and semantics are fairly widespread and well understood. The IDL interface is named Sockets. There is no implementation associated with the Sockets interface by default; specific protocol implementations are supplied by subclass implementations.

Note: The Sockets classes supplied with the SOMobjects Developer Toolkit and run-time packages are only intended to support the DSOM, Replication, and Event Management Frameworks. These class implementations are not intended for general application usage.


Available Sockets subclasses by SOMobjects product are as follows:

  • For AIX:
TCPIPSockets class for TCP/IP, 
IPXSockets class for Netware IPX/SPX, and 
NBSockets class for NetBIOS. 
  • For OS/2 and Windows:
TCPIPSockets class (a) for TCP/IP for Windows or (b) for TCP/IP 1.2.1 on OS/2, 
TCPIPSockets32 class for TCP/IP 2.0 on OS/2 only (see Note below), 
IPXSockets class for NetWare IPX/SPX, and 
NBSockets class for NetBIOS. 

Note: The TCPIPSocket32 class gives greater performance over the TCPIPSockets class on OS/2, but requires the 32-bit version of TCPP/IP (version 2.0) rather than the 16-bit version of TCP/IP (version 1.2.1).


Application developers may need to develop their own Sockets subclass if the desired transport protocol or product version is not one of those supported by the SOMobjects run-time packages. This appendix explains how to approach the implementation of a Sockets subclass, if necessary.

Warning: this may be a non-trivial exercise!


Sockets IDL Interface

The base Sockets interface is expressed in IDL in the file somssock.idl, listed below. There is a one-to-one mapping between TCP/IP socket APIs and the methods defined in the Sockets interface.

Please note the following:

  • The semantics of each of the Sockets methods must be that of the corresponding TCP/IP call. Currently, only Internet address family (AF_INET) addresses are used by the frameworks.
(The TCP/IP sockets API is not documented as part of the SOMobjects Developer Toolkit. The implementor is referred to the programming references for IBM TCP/IP for AIX or OS/2, or to similar references that describe the sockets interface for TCP/IP.)
  • Data types, constants, and macros which are part of the Sockets interface are defined in a C include file, soms.h. This file is supplied with the SOMobjects Toolkit, and is not shown in this manual.
  • The Sockets interface is expressed in terms of a 32-bit implementation.
  • Some of the method parameters and return values are expressed using pointer types, for example:
hostent *somsGethostent ();

This has been done to map TCP/IP socket interfaces as directly as possible to their IDL equivalent. (Use of strict CORBA IDL was not a primary goal for the Sockets interface, since it is only used internally by the frameworks.)

  • The Sockets class and its subclasses are single instance classes.

Following is a listing of the file somssock.idl. Each socket call is briefly described with a comment.

// 96F8647, 96F8648 (C) Copyright IBM Corp. 1992, 1993
// All Rights Reserved
// Licensed Materials - Property of IBM

#ifndef somssock_idl
#define somssock_idl

#include <somobj.idl>
#include <snglicls.idl>

interface Sockets : SOMObject
{
    //# The following typedefs are fully defined in <soms.h>.
    typedef SOMFOREIGN sockaddr;
    #pragma modifier sockaddr : impctx="C", struct;
    typedef SOMFOREIGN iovec;
    #pragma modifier iovec : impctx="C", struct;
    typedef SOMFOREIGN msghdr;
    #pragma modifier msghdr : impctx="C", struct;
    typedef SOMFOREIGN fd_set;
    #pragma modifier fd_set : impctx="C", struct;
    typedef SOMFOREIGN timeval;
    #pragma modifier timeval : impctx="C", struct;
    typedef SOMFOREIGN hostent;
    #pragma modifier hostent : impctx="C", struct;
    typedef SOMFOREIGN servent;
    #pragma modifier servent : impctx="C", struct;
    typedef SOMFOREIGN in_addr;
    #pragma modifier in_addr : impctx="C", struct;

    long somsAccept (in long s, out sockaddr name, out long namelen);
    // Accept a connection request from a client.

    long somsBind (in long s, inout sockaddr name, in long namelen);
    // Binds a unique local name to the socket with descriptor s.

    long somsConnect (in long s, inout sockaddr name,
                      in long namelen);
    // For streams sockets, attempts to establish a connection
    // between two sockets.  For datagram sockets, specifies the
    // socket's peer.

    hostent *somsGethostbyaddr (in char *addr, in long addrlen,
                                in long domain);
    // Returns a hostent structure for the host address specified on
    // the call.

    hostent *somsGethostbyname (in string name);
    // Returns a hostent structure for the host name specified on
    // the call.

    hostent *somsGethostent ();
    // Returns a pointer to the next entry in the hosts file.

    unsigned long somsGethostid ();
    // Returns the unique identifier for the current host.

    long somsGethostname (in string name, in long namelength);
    // Retrieves the standard host name of the local host.

    long somsGetpeername (in long s, out sockaddr name,
                         out long namelen);
    // Gets the name of the peer connected to socket s.

    servent *somsGetservbyname (in string name, in string protocol);
    // Retrieves an entry from the /etc/services file using the
    // service name as a search key.

    long somsGetsockname (in long s, out sockaddr name,
                          out long namelen);
    // Stores the current name for the socket specified by the s
    // parameter into the structure pointed to by the name
    // parameter.

    long somsGetsockopt (in long s, in long level, in long optname,
                        in char *optval, out long option);
    // Returns the values of socket options at various protocol
    // levels.

    unsigned long somsHtonl (in unsigned long a);
    // Translates an unsigned long integer from host-byte order to
    // network-byte order.

    unsigned short somsHtons (in unsigned short a);
    // Translates an unsigned short integer from host-byte order to
    // network-byte order.

    long somsIoctl (in long s, in long cmd, in char *data,
                    in long length);
    // Controls the operating characteristics of sockets.

    unsigned long somsInet_addr (in string cp);
    // Interprets character strings representing numbers expressed
    // in standard '.' notation and returns numbers suitable for use
    // as internet addresses.

    unsigned long somsInet_lnaof (in in_addr addr);
    // Breaks apart the internet address and returns the local
    // network address portion.

    in_addr somsInet_makeaddr (in unsigned long net,
                               in unsigned long lna);
    // Takes a network number and a local network address and
    // constructs an internet address.

    unsigned long somsInet_netof (in in_addr addr);
    // Returns the network number portion of the given internet
    // address.

    unsigned long somsInet_network (in string cp);
    // Interprets character strings representing numbers expressed
    // in standard '.' notation and returns numbers suitable for use
    // as network numbers.

    string somsInet_ntoa (in in_addr addr);
    // Returns a pointer to a string expressed in the dotted-decimal
    // notation.

    long somsListen (in long s, in long backlog);
    // Creates a connection request queue of length backlog to queue
    // incoming connection requests, and then waits for incoming
    // connection requests.

    unsigned long somsNtohl (in unsigned long a);
    // Translates an unsigned long integer from network-byte order
    // to host-byte order.

    unsigned short somsNtohs (in unsigned short a);
    // Translates an unsigned short integer from network-byte order
    // to host-byte order.

    long somsReadv (in long s, inout iovec iov, in long iovcnt);
    // Reads data on socket s and stores it in a set of buffers
    // described by iov.

    long somsRecv (in long s, in char *buf, in long len,
                   in long flags);
    // Receives data on streams socket s and stores it in buf.

    long somsRecvfrom (in long s, in char *buf, in long len,
        in long flags, out sockaddr name, out long namelen);
    // Receives data on datagram socket s and stores it in buf.

    long somsRecvmsg (in long s, inout msghdr msg, in long flags);
    // Receives messages on a socket with descriptor s and stores
    // them in an array of message headers.

    long somsSelect (in long nfds, inout fd_set readfds,
                     inout fd_set writefds, inout fd_set exceptfds,
                     inout timeval timeout);
    // Monitors activity on a set of different sockets until a
    // timeout expires, to see if any sockets are ready for reading
    // or writing, or if an exceptional condition is pending.

    long somsSend (in long s, in char *msg, in long len,
                   in long flags);
    // Sends msg on streams socket s.

    long somsSendmsg (in long s, inout msghdr msg, in long flags);
    // Sends messages passed in an array of message headers on a
    // socket with descriptor s.

    long somsSendto (in long s, inout char msg, in long len,
                     in long flags, inout sockaddr to, in long tolen);
    // Sends msg on datagram socket s.

    long somsSetsockopt (in long s, in long level, in long optname,
                         in char *optval, in long optlen);
    // Sets options associated with a socket.

    long somsShutdown (in long s, in long how);
    // Shuts down all or part of a full-duplex connection.

    long somsSocket (in long domain, in long type,
                     in long protocol);
    // Creates an endpoint for communication and returns a socket
    // descriptor representing the endpoint.

    long somsSoclose (in long s);
    // Shuts down socket s and frees resources allocated to the
    // socket.

    long somsWritev (in long s, inout iovec iov, in long iovcnt);
    // Writes data on socket s.  The data is gathered from the
    // buffers described by iov.

    attribute long serrno;
    // Used to pass error numbers.

#ifdef __SOMIDL__
    implementation
    {
    releaseorder:
        somsAccept, somsBind, somsConnect, somsGethostbyaddr,
        somsGethostbyname, somsGethostent, somsGethostid,
        somsGethostname, somsGetpeername, somsGetsockname,
        somsGetsockopt, somsHtonl, somsHtons, somsIoctl,
        somsInet_addr, somsInet_lnaof, somsInet_makeaddr,
        somsInet_netof, somsInet_network, somsInet_ntoa,
        somsListen, somsNtohl, somsNtohs, somsReadv,
        somsRecv, somsRecvfrom, somsRecvmsg, somsSelect,
        somsSend, somsSendmsg, somsSendto, somsSetsockopt,
        somsShutdown, somsSocket, somsSoclose, somsWritev,
        _set_serrno, _get_serrno, somsGetservbyname;

    //# Class modifiers
    callstyle=idl;
    metaclass = SOMMSingleInstance;
    majorversion=1; minorversion=1;
    dll="soms.dll";
    };
#endif /* __SOMIDL__ */
};
#endif  /* somssock_idl */

IDL for a Sockets subclass

Sockets subclasses inherit their entire interface from Sockets. All methods are overridden.

For example, here is a listing of the TCPIPSockets IDL description.

// 96F8647, 96F8648 (C) Copyright IBM Corp. 1992, 1993
// All Rights Reserved
// Licensed Materials - Property of IBM

#ifndef tcpsock_idl
#define tcpsock_idl

#include <somssock.idl>
#include <snglicls.idl>

interface TCPIPSockets : Sockets
{
#ifdef __SOMIDL__
    implementation
    {
    //# Class modifiers
    callstyle=idl;
    majorversion=1; minorversion=1;
    dllname="somst.dll";
    metaclass=SOMMSingleInstance;
    //# Method modifiers
    somsAccept: override;
    somsBind: override;
    somsConnect: override;
    somsGethostbyaddr: override;
    somsGethostbyname: override;
    somsGethostent: override;
    somsGethostid: override;
    somsGethostname: override;
    somsGetpeername: override;
    somsGetservbyname: override;
    somsGetsockname: override;
    somsGetsockopt: override;
    somsHtonl: override;
    somsHtons: override;
    somsIoctl: override;
    somsInet_addr: override;
    somsInet_lnaof: override;
    somsInet_makeaddr: override;
    somsInet_netof: override;
    somsInet_network: override;
    somsInet_ntoa: override;
    somsListen: override;
    somsNtohl: override;
    somsNtohs: override;
    somsReadv: override;
    somsRecv: override;
    somsRecvfrom: override;
    somsRecvmsg: override;
    somsSelect: override;
    somsSend: override;
    somsSendmsg: override;
    somsSendto: override;
    somsSetsockopt: override;
    somsShutdown: override;
    somsSocket: override;
    somsSoclose: override;
    somsWritev: override;
    _set_serrno: override;
   _get_serrno: override;
   };
#endif /* __SOMIDL__ */
 };
#endif  /* tcpsock_idl */

Implementation Considerations

  • Only the AF_INET address family must be supported. That is, the DSOM, Replication, and Event Manager frameworks all use Internet addresses and port numbers to refer to specific sockets.
  • On OS/2, the SOMobjects run-time libraries were built using the C Set/2 32-bit compiler. If the underlying subclass implementation uses a 16-bit subroutine library, conversion of the method call arguments may be required. (This mapping of arguments is often referred to as "thunking.")
  • Sockets subclasses to be used in multi-threaded environments should be made thread-safe. That is, it is possible that concurrent threads may make calls on the (single) Sockets object, so data structures must be protected within critical regions, as appropriate.
  • Valid values for the serrno attribute are defined in the file soms.h. The subclass implementation should map local error numbers into the appropriate corresponding Sockets error numbers.

Example Code

The following code fragment shows an example of the implementation of the somsBind method of the TCPIPSockets subclass, for both AIX and OS/2. The sample illustrates that, for TCP/IP, the implementation is basically a one-to-one mapping of Sockets methods onto TCP/IP calls. For other transport protocols, the mapping from the socket abstraction to the protocol's API may be more difficult.

For AIX, the mapping from Sockets method to TCP/IP call is trivial.

SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
                                 Environment *ev,
                                 long s, Sockets_sockaddr* name,
                                 long namelen)
{
    long rc;

    TCPIPSocketsMethodDebug("TCPIPSockets","somsBind");

    rc = (long) bind((int)s, name, (int)namelen);

    if (rc == -1)
       __set_serrno(somSelf, ev, errno);

    return rc;
}

On OS/2, however, the TCP/IP Release 1.2.1 library is a 16-bit library. Consequently, many of the method calls require conversion ("thunking") of 32-bit parameters into 16-bit parameters, before the actual TCP/IP calls can be invoked. For example, the function prototype for the somsBind method is defined as:

SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
                                 Environment *ev,
                                 long s, Sockets_sockaddr* name,
                                 long namelen);

whereas the file socket.h on OS/2 declares the bind function with the following prototype:

short _Far16 _Cdecl bind(short /*s*/, void * _Seg16 /*name*/,
                         short /*len*/);

In this case, the pointer to the "name" structure, passed as a 32-bit address, cannot be used directly in the bind call: a 16-bit address must be passed instead. This can be accomplished by dereferencing the 32-bit pointer provided by the "name" parameter in the somsBind call, copying the caller's Sockets_sockaddr structure into a local structure ("name16"), and then passing the address of the local structure ("&name16") as a 16-bit address in the bind call.

SOM_Scope long  SOMLINK somsBind(TCPIPSockets somSelf,
                                 Environment *ev,
                                 long s, Sockets_sockaddr* name,
                                 long namelen)
{
    long rc;
    Sockets_sockaddr name16;

    TCPIPSocketsMethodDebug("TCPIPSockets","somsBind");

    /* copy user's parameter into a local structure */
    memcpy ((char *)&name16, (char *)((sockaddr32 *)name), namelen);
    rc = (long) bind((short)s, (void *)&name16, (short)namelen);

    if (rc == -1)
       __set_serrno(somSelf, ev, tcperrno());

    return rc;
}