Xb2.NET - Network Library for Xbase++ Network Library for Xbase++

Release: 0.0.60 (beta)
2002.08.05


Copyright © 2001-2002, Boris Borzic
All rights reserved

CLASS HIERARCHY:


   xbSocket
    |   Complete object-oriented sockets library that provides a protocol-independent
    |   base for developing virtually any kind of communications software.
    |
    +-- xbServer   (derived from: xbSocket, Thread)
    |   |   A generic protocol-independent server that can be easily configured for a
    |   |   variety of Telnet applications.
    |   |
    |   +-- xbHTTPServer   (derived from: xbServer) 
    |           A powerful object-oriented HTTP 1.1 web and SOAP server that is build right into your
    |           Xbase++ application. No need to configure and manage complex 3P web servers,
    |           gateways and CGI scripts. Your Xbase++ program is the server!
    |
    +-- xbSocketThread   (derived from: xbSocket, Thread) 
    |       This is the client thread that is spawned by xbServer when a connection with a peer
    |       is accepted. This "worker" thread will handle the request and send a response back
    |       to the connected client.
    |
    +-- xbHTTPThread   (derived from: xbSocket, Thread) 
            This is the client thread that is spawned by xbHTTPServer when a connection is accepted
            from a user agent (a browser). This "worker" thread is responsible for handling the client
            request and generating an appropriate xbHTTPResponse that will be sent back to the client.

   xbHTTPMessage
    |   An abstract class for composing and parsing HTTP messages.
    |
    +-- xbHTTPRequest   (derived from: xbHTTPMessage, xbURI)
    |       Client side: Compose HTTP request and send to HTTP server.
    |       Server side: Parse HTTP request received from client.
    |
    +-- xbHTTPResponse   (derived from: xbHTTPMessage)
            Client side: Parse HTTP response received from server.
            Server side: Compose HTTP response and send to client.

   xbSession
      HTTP by nature is stateless and in itself provides limited session management capability.
      This class simplifies session management and provides the ability of saving persistent
      data across multiple HTTP requests. Sessions are automatically managed by the
      xbHTTPServer class.

   xbURI
      Create, parse, encode and decode RFC compliant URI and URL strings.

   xbFORM
      This class represents a url-encoded form. The form typically contains data expressed as
      "name=value" pairs, encoded for safe transport over the net. This class allows you to parse
      an existing form as well as create a brand new form.

   xbSOAPEnvelope
      This class provides the code necessary to generate and parse SOAP messages. SOAP is a remote
      procedure calling protocol that encodes requests and responses in XML format. Using SOAP a
      client can execute methods or functions on a server and receive an XML response containing
      the return values.


FUNCTIONS:

xbTimezoneOffset([nMinutes]) -> nTimezoneOffset Get/set the difference between the local time and GMT as an integer representing the number of minutes. Unless the local time is GMT, this function should be called at program start so that xbGMTDate() can return the correct GMT date. If a parameter is not specified, the function returns the current timezone offset. When using Xbase++ 1.7 or higher, the timezone offset will be automatically set on startup to the return value of SetLocale(NLS_ITZBIAS). xbGMTDate([dDate],[cnTime]) -> cGMTDate Return a string representing the date and time in GMT using Internet conventions in the following form: Day, DD Mon YYYY HH:MM:SS GMT Both parameters are optional if not specified the current date/time is used. cnTime can be a numeric as returned by SECONDS(), or a string as returned by TIME() xbBase64Encode(cString) -> cBase64String Return cString in base64 encoded format. Base64 encoding coverts binary information from 8 bits per byte to 6 bits per byte. Information in 3-8bit bytes (24 bits) is converted into 4-6bit bytes (same 24 bits), resulting in a encoded string that is 1.333 times larger than the original. xbBase64Decode(cBase64String) -> cOriginalString Decodes a base64 encoded string into it's original form. xbEscape(cString, [cAllowed]) -> cEscapedString Return a string in URL encoded format where reserved characters are replaced with a percent sign followed by a hex number. For example the space character is replaced with %20, a question mark (?) is replaced with %27. xbUnEscape(cString) -> cOriginalString Decodes a URL encoded string into it's original form. xbXML2Array( cXMLDocument ) -> aXMLTree Parse an XML document into a hierarchical array of XML tags. The returned array contains subarrays of 4 elements each which may be accessed with the following define constants available in Xb2NET.CH. An empty array will be returned when the passed string is not a valid XML document.

XTAG_NAME - xml tag element name as string
XTAG_ATTRIB - element attributes as string
XTAG_CONTENT - tag contents; a string (tag value) or array containing subnodes (XTAG_TYPE = XTYPE_NODE)
XTAG_TYPE - numeric value indicating type of XTAG_CONTENT. The following values are possible:
    XTYPE_NODE - a subnode
    XTYPE_TEXT - a data value

Example: TEXT INTO cString
<env:Envelope
   xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
   xmlns:xsd="http://www.w3.org/1999/XMLSchema">
   <env:Body>
     <ns:getQuote
       xmlns:ns="urn:xmethods-delayed-quotes"
       env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
       <symbol xsi:type="xsd:string">IBM</symbol>
     </ns:getQuote>
   </env:Body>
</env:Envelope>
ENDTEXT

aXMLTree := xbXML2Array(cString)

// aXMLTree will contain the following:

{{env:Envelope, xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema",
{{env:Body, ,
{{ns:getQuote, xmlns:ns="urn:xmethods-delayed-quotes" env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/",
{{symbol, xsi:type="xsd:string", IBM, 1}}, 0}}, 0}}, 0}}
xbXMLGetAttribute( cAttrib | aXMLNode, [cAttribName] ) -> cAttribValue Return attribute value for a given attribute item. The first parameter can be specified as a string representing the entire attribute value, or as a XML Node array. If cAttribName is NIL, then the entire attribute is returned.

Example: // using aXMLTree from xbXML2Array example above ...
? xbXMLGetAttribute( aXMLTree[1], "xsd" )
// returns: http://www.w3.org/1999/XMLSchema
? xbXMLGetAttribute('se:arrayType="xsd:int[3]" xsi:type="se:Array"', 'type' )
// returns: se:Array
xbXMLGetNode( aXMLTree, cName ) -> aChildNode Scan aXMLTree for a node with the name cName and return the first node found with that name. Note, the returned node may itself contain other subnodes. The XTAG_TYPE element will specify the type of content (see above).

Example: // using aXMLTree from xbXML2Array example above ...
? xbXMLGetNode( aXMLTree, "getQuote" )

// returns the following array:
{ns:getQuote, xmlns:ns="urn:xmethods-delayed-quotes" env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/",
{{symbol, xsi:type="xsd:string", IBM, 1}}, 0}

CLASSES:

xbSocket()

xbSocket: Class methods

:New([nAddrFamily], [nSocketType], [nProtocol]) -> self, or;
:New(oParent, [nHandle]) -> self
Creates a new instance of the xbSocket class and allocates system resources to bind the newly created socket to a specific transport service provider. All parameters are optional.

Connection-oriented sockets such as SOCK_STREAM provide full-duplex connections, and must be in a connected state before any data can be sent or received on it. A connection to another socket is created with a :Connect call. Once connected, data can be transferred using :Send and :Recv calls. When a session has been completed, a :Close or :Destroy must be performed.

The communications protocols used to implement a reliable, connection-oriented socket ensure that data is not lost or duplicated. If data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable length of time, the connection is considered broken and subsequent calls will fail with the :ErrorCode set to WSAETIMEDOUT.

Connectionless, message-oriented sockets allow sending and receiving of datagrams to and from arbitrary peers. If such a socket is connected to a specific peer (see :Connect), datagrams can be sent/received only to/from this peer. Parameters: nAddrFamily
An address family, define constant AF_*. Default is AF_INET. nSocketType The socket type. Winsock 1.1 only supports types SOCK_STREAM (the default) and SOCK_DGRAM.

SOCK_STREAM - Provides sequenced, reliable, two-way, connection-based byte streams with an out-of-band data transmission mechanism. Uses TCP for the Internet address family.

SOCK_DGRAM - Supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. Uses UDP for the Internet address family. nProtocol A particular protocol to be used with the socket that is specific to the indicated address family. Default is IPPROTO_IP. Other values can be discovered by using the :GetProtoByName and :GetProtoByNumber methods. oParent A parent/child relation can be established between sockets by using this parameter. The new instance will inherit :AddrFamily, :SockType, :Protocol, :Encode, :Decode and :onError properties from oParent. This is done implicitly when a connection is accepted by the :Accept method. nHandle The :Handle of an already open socket. If a handle is not specified, a brand new socket will be created with the same address family, socket type and protocol as the oParent socket. :DllLoad() -> lSuccess Load and initialize winsock dll. :DllUnload() -> lSuccess Close all sockets and unload winsock dll. :DllReset() -> lSuccess Close all sockets and reinitialize winsock dll. :ErrorText(nErrorCode) -> cErrorText Return error description from winsock error code. :GetHostByAddr(nAddress, nType) -> aHostInfo | NIL Retrieves the host information corresponding to a network address. nAddress is a numeric IP address in network byte order, nType is the address family, eg. AF_INET. The method returns an array containing host information, or NIL on failure. The following array constants available in Xb2NET.CH provide access to the individual array elements:

HOSTENT_CNAME - character string representing the name of the host
HOSTENT_ALIAS - a one dimension array holding alternate names of the host. If none exist the array will be empty
HOSTENT_NTYPE - numeric value indicating the address family, eg. AF_INET
HOSTENT_NLEN - length, in bytes required to represent the network byte order addresses in HOSTENT_ADDR
HOSTENT_ADDR - a one dimensional array of numeric IP addresses for the host in network byte order :GetHostByName(cHostName) -> aHostInfo | NIL Retrieves the host information corresponding to a host name. cHostName is a character string representing the name of the host (eg. "sqlexpress.net") for which to retrieve the information. The method returns an array containing host information, or NIL on failure. The following array constants available in Xb2NET.CH provide access to the individual array elements:

HOSTENT_CNAME - character string representing the name of the host
HOSTENT_ALIAS - a one dimension array holding alternate names of the host. If none exist the array will be empty
HOSTENT_NTYPE - numeric value indicating the address family, eg. AF_INET
HOSTENT_NLEN - length, in bytes required to represent the network byte order addresses in HOSTENT_ADDR
HOSTENT_ADDR - a one dimensional array of numeric IP addresses for the host in network byte order :GetProtoByName(cProtocolName) -> aProtocolInfo | NIL Retrieves protocol information corresponding to a protocol name. The method returns an array containing protocol information, or NIL on failure. The following array constants available in Xb2NET.CH provide access to the individual array elements:

PROTOENT_CNAME - character string representing the official name of the protocol.
PROTOENT_ALIAS - a one dimension array holding alternate names of the protocol. If none exist the array will be empty.
PROTOENT_NUMBER - a numeric protocol number, in host byte order. :GetProtoByNumber(nProtocolNumber) -> aProtocolInfo | NIL Retrieves protocol information corresponding to a protocol number. The method returns an array containing protocol information, or NIL on failure. The following array constants available in Xb2NET.CH provide access to the individual array elements:

PROTOENT_CNAME - character string representing the official name of the protocol.
PROTOENT_ALIAS - a one dimension array holding alternate names of the protocol. If none exist the array will be empty.
PROTOENT_NUMBER - a numeric protocol number, in host byte order. :GetServByName(cServiceName, [cProtocolName]) -> aServiceInfo | NIL Retrieves service information corresponding to a service name and protocol. cProtocolName is optional, if not specified, the method returns the first service where the name matches cServiceName. The method returns an array containing service information, or NIL on failure. The following array constants available in Xb2NET.CH provide access to the individual array elements:

SERVENT_CNAME - character string representing the official name of the service.
SERVENT_ALIAS - a one dimension array holding alternate names of the service. If none exist the array will be empty.
SERVENT_NPORT - a numeric port number at which the service can be contacted.
SERVENT_CPROT - the name of the protocol to use when contacting the service. :GetServByPort(nPort, [cProtocolName]) -> aServiceInfo | NIL Retrieves service information corresponding to a port and protocol. cProtocolName is optional, if not specified, the method returns the first service where the port number matches nPort. The method returns an array containing service information, or NIL on failure. The following array constants available in Xb2NET.CH provide access to the individual array elements:

SERVENT_CNAME - character string representing the official name of the service.
SERVENT_ALIAS - a one dimension array holding alternate names of the service. If none exist the array will be empty.
SERVENT_NPORT - a numeric port number at which the service can be contacted.
SERVENT_CPROT - the name of the protocol to use when contacting the service. :InetAddr(cAddress) -> nAddress Converts a numeric string IP address (eg. 127.0.0.1) to a numeric Internet address in network byte order :InetNtoA(nAddress) -> cAddress Converts a numeric Internet network byte order address into human readable numeric string format, eg. 127.0.0.1


xbSocket: Class properties

:Copyright readonly/character Returns Xb2NET library copyright information :DisplayErrors exported/logical Enable/disable console display of winsock error and warning messages. When set to .T., a console dialog box will be displayed whenever a winsock error occurs. The default setting is .F.. The most recent winsock error is saved in the :ErrorCode ivar. :DllDescription readonly/character Description of the Windows Sockets implementation. :DllStatus readonly/character Relevant status or configuration information as returned by winsock. :DllVersion readonly/character The version of the Windows Sockets specification used on the local machine. :LocalName readonly/character Standard host name of the local machine. :Version readonly/character Returns Xb2NET library version number as a string.


xbSocket: Object methods

Life Cycle :Open([nAddrFamily], [nSocketType], [nProtocol]) -> lSuccess Allocates system resources and causes the socket to be bound to a specific transport service provider. Technically this is equivalent to calling :New() except that a new class instance is not created. For additional information on paremeters, see :New(). :Bind([xLocalAddr], [nPort]) -> lSuccess Associate a local address with a socket. This method is used to bind to either connection-oriented (stream) or connectionless (datagram) sockets before subsequent calls to the :Connect or :Listen methods. When a socket is instantiated or opened using :Open, it is associated with an address family only. In order for the socket to be able to communicate with a remote process it should be bound to a local address and port. Parameters: xLocalAddr The local address can be specified either as a numeric address in network byte order, or as an IP address in form of a dotted octet string (ex. 127.0.0.1). If an application does not care what local address is assigned, specify the constant value INADDR_ANY (the default). This allows the underlying service provider to use any appropriate network address, potentially simplifying application programming in the presence of multihomed hosts (hosts that have more than one network interface and address). nPort This is the numeric port number on the local computer to bind the socket to. The default is zero and this allows the underlying service provider to assign a unique port to the application with avalue between 1024 and 5000. Binding to a specific port number other than port 0 is discouraged for client applications, since there is a danger of conflicting with another socket already using that port number. :Connect(xRemoteAddr, nPort) -> lSuccess This method is used to establish a connection to a specified destination. If the socket is unbound, unique values are assigned to the local association by the system, and the socket is marked as bound.

Connection-oriented sockets (eg. SOCK_STREAM), must be in a connected state before data can be transmitted using :Send/:Recv. Any attempt to re-connect an active connection will fail with the :ErrorCode WSAEISCONN.

For a connectionless socket (eg. SOCK_DGRAM), the operation performed by :Connect is merely to establish a default destination address that will be used on subsequent :Send and :Recv calls. Any datagrams received from an address other than the destination address specified will be discarded. If the xRemoteAddr parameter is specifed as zero, the socket will be "dis-connected". The default destination can be changed by simply calling connect again, even if the socket is already connected. Any datagrams queued for receipt are discarded if xRemoteAddr or nPort are different from the previous connect.

Any valid xRemoteAddr and nPort can be specified for connectionless sockets, including a broadcast address. However, to connect to a broadcast address, :Broadcast(.t.) must be set first. Otherwise, :Connect will fail with the :ErrorCode WSAEACCES. Parameters: xRemoteAddr The remote address can be specified either as a numeric address in network byte order, or as an IP address in form of a dotted octet string (ex. 127.0.0.1). nPort This is the numeric port number on the remote computer to connect to. :Listen([nBacklog]) -> lSuccess Place a socket in a state where it is listening for incoming connections. This method is typically used by servers that can have more than one connection request at a time. If a connection request arrives and the queue is full, the client will receive an error with an indication of WSAECONNREFUSED.

nBacklog is an optional parameter that specifies the maximum length of the queue of pending connections. If this value is SOMAXCONN (the default), then the underlying service provider responsible for this socket will set the backlog to a maximum "reasonable" value. There is no standard provision to find out the actual backlog value.

Subsequent calls to :Listen will update the current backlog for the listening socket. If there are more pending connections than the new backlog value, the excess pending connections will be reset and dropped. :Accept([oSocketClass]) -> oClientSocket | NIL This method is used by a server process for accepting incomming connections. The method extracts the first connection in the queue of pending connections and then creates a new socket object that is bound to the extracted connection. The newly created socket inherits most of it's properties from the parent (this socket) and is the socket that will handle the actual communication with the remote process.

The optional parameter oSocketClass can be used to provide a reference to the class function from which the new socket object will be instantiated. If oSocketClass is NIL, then the client socket will be created based on one of the following conditions: (1) if the parent (this socket) is derived from either xbServer or xbHTTPServer, the client socket will be instantiated from the class object referenced by the server's :WorkerClass property (usually xbSocketThread or xbHTTPThread), (2) otherwise the new socket will be instantiated from xbSocket.

If the socket is marked as blocking (see :SetBlockingMode) and there are no pending connections on the queue, then the :Accept method will block the calling routine until a connection is present. If the socket is marked nonblocking and no pending connections are present on the queue, :Accept returns NIL. After the successful completion of :Accept, the method returns a new socket object. The original socket remains open and listens for new connection requests. :Recv([nBytes], [nFlag]) -> cReceived | NIL Read incoming data. Calling :Recv on a connection-oriented socket (eg. SOCK_STREAM), will return as much information as is currently available; up to nBytes. If the socket has been configured for in-line reception of out-of-band data (see :OOBInLine) and out-of-band data is available; only out-of-band data will be returned. The application can use :CatMark to determine whether any more out-of-band data remains to be read.

For message-oriented or connectionless sockets (eg. SOCK_DGRAM), data is extracted from the first enqueued datagram (message); up to :nBytes. If the datagram or message is larger than nBytes, the first part of the datagram is returned, and :ErrorCode will be set to WSAEMSGSIZE. For unreliable protocols (eg. UDP) the excess data is lost; for reliable protocols, the data is retained by the service provider until it is successfully read by calling :Recv with a large enough buffer. If the socket is not connected, the network address of the peer that sent the data will be copied into the :RemoteAddr and :RemotePort ivar.

If there is no incoming data available and the socket is in blocking mode (see :SetBlockingMode), then :Recv will block the calling routine and wait for data to arive. If the socket is nonblocking and the input queue is empty, :Recv returns a zero length string and :ErrorCode is set to WSAEWOULDBLOCK. After successfully reading data from the input queue :Recv returns a string containing the data read. If an error occurs, other than the ones specified above, the method returns NIL. The number of bytes read is saved in the :BytesReceived ivar and a cumulative total in :RecvCount. Parameters: nBytes The number of bytes to read from the input queue. If not specified, nBytes will default to the value returned by :GetReadCount or 1024 bytes, whichever is larger. nFlag Specifies the way data will be read from the input queue. The following options are available, default is MSG_NORMAL:
MSG_NORMAL - Read incoming data and remove it from the input queue.
MSG_PEEK - Peek at the incoming data but do not remove it from the input queue.
MSG_OOB - Process out-of-band data. :RecvLine([cEOLMarker], [nMaxBytes]) -> cReceived | NIL Read incoming data on a connection-oriented socket (eg. SOCK_STREAM) until cEOLMarker is reached or if specified; nMaxBytes have been read. If cEOLMarker is not supplied it defaults to CR+LF (Chr(13) + Chr(10)). See :Recv for additional information. :Send(cBuffer, [nFlag], [xToAddr], [nToPort]) -> nBytesSent | SOCKET_ERROR Send data to a specific destination or a connected peer. If the socket is unbound, unique values are assigned to the local association by the system, and the socket is marked as bound. The successful completion of a :Send does not indicate that the data was successfully delivered.

For message-oriented sockets, care must be taken not to exceed the maximum packet size of the underlying provider, (see :MaxMessageSize). If the data is too long to pass atomically through the underlying protocol, :ErrorCode will be set to WSAEMSGSIZE, and no data is transmitted.

If no buffer space is available within the transport system to hold the data to be transmitted, :Send will block unless the socket has been placed in a nonblocking mode. On nonblocking, stream oriented sockets, the number of bytes written can be between 1 and the requested length, depending on buffer availability on both the client and server systems. Parameters: cBuffer This is the buffer containing the data to be transmitted nFlag Specifies the way in which the call is made. The following options are available, default is MSG_NORMAL:
MSG_NORMAL - Read incoming data and remove it from the input queue.
MSG_DONTROUTE - Specifies that the data should not be subject to routing.
MSG_OOB - Send out-of-band data (SOCK_STREAM only). xToAddr This parameter is only valid when used with connectionless, message-oriented sockets. It is ignored if :SockType is SOCK_STREAM, otherwise xToAddr can be any valid address in the socket's address family, including a broadcast address. However, to send to a broadcast address, :Broadcast(.t.) must be set first. Otherwise, :Send will fail with the :ErrorCode WSAEACCES. For TCP/IP, an application can send to any multicast address without becoming a group member. If a message-oriented socket has been previously connected to a specific address (using :Connect), specifying xToAddr will override the default destination address for this datagram only. The address can be specified either as a numeric address in network byte order, or as an IP address in form of a dotted octet string (ex. 127.0.0.1). Default is INADDR_BROADCAST. nToPort This parameter is only valid when used with connectionless, message-oriented sockets. It is ignored if :SockType is SOCK_STREAM, otherwise it specifies the numeric port number on the remote computer to send to. Default is zero. :Shutdown([nHow], [lShutdownClients]) -> lSuccess This method is used on all types of sockets to disable reception and/or transmission of data. Note that :Shutdown does not close the socket. A socket can only be closed by executing the :Close or :Destroy methods. The method returns .T. when the shut down operation is successful, otherwise .F. is returned.

If the nHow parameter is set to SD_RECEIVE (the default), subsequent calls to :Recv will be disallowed. If it is set to SD_SEND, subsequent calls to :Send are disallowed. If it is set to SD_BOTH then both sends and receives are disabled.

If the socket is in a listening state and there are connected clients, the client sockets can be shut down by specifying .T. for lShutdownClients> default is .F. :Close([lCloseClients]) -> lSuccess Closes socket and releses allocated system resources. Any pending blocking, asynchronous calls issued by any thread in this process are canceled without posting any notification messages. If the socket is in a listening state and there are connected clients, the client sockets can also be closed by specifying .T. for lCloseClients, default is .F. The semantics of :Close are affected by the :LingerTimeout option, see :LingerTimeout for additional information. A socket that has been closed can later be reopened by using the :Open method. :Destroy([lDestroyClients]) -> lSuccess This method will first execute a :Close and if successful, the class instance will be dereferenced from the class object list. If the socket is in a listening state and there are connected clients, the client socket objects can also be destroyed by specifying .T. for lDestroyClients, default is .F. Configuration :Broadcast([lSet]) -> lSet Enable/disable transmission of broadcast messages on the socket. When lSet is not specified, the method will return the current setting. Default is .F. :Debug([lSet]) -> lSet Enable/disable recording of debugging information. When lSet is not specified, the method will return the current setting. The mechanism for generating the debug information and the form it takes are dependant on the winsock service provider and are beyond the scope of this manual. Default is .F. :KeepAlive([lSet]) -> lSet Enable/disable use of "keep-alive" packets on TCP connections. When lSet is not specified, the method will return the current setting. Default is .F. :LingerTimeout([nSec]) -> nSetting This method controls the action taken when unsent data is queued on a socket and a :Close or :Destroy is performed. The following types of behavior can be obtained:

nSec is specified as a negative value: Graceful shutdown, immediate return - allowing the shutdown sequence to complete in the background. Although this is the default behavior, the application has no way of knowing when (or whether) the graceful shutdown sequence actually completes.

nSec is specified as zero: Abortive shutdown sequence, immediate return from :Close

nSec is specified as a positive value: Graceful shutdown, delaying return until either shutdown sequence completes or the specified time interval elapses. If the time interval expires before the graceful shutdown sequence completes, an abortive shutdown sequence occurs, and :Close returns.

When nSec is not specified, the method will return the current setting. :OOBInLine([lSet]) -> lSet Enable/disable the reception of out-of-band data in the normal data stream. When lSet is not specified, the method will return the current setting. Default is .F. :RecvBufferSize([nSize]) -> nBytes Get/set buffer size for receives. When nSize is not specified, the method will return the current size of the receive buffer in bytes. :RecvTimeout([nMilliSec]) -> nTimeout Get/set maximun number of millisecs to wait when receiving data from a remote connection (may not work with all stack implementations). This option can be set on any type of socket in any state. The default value is zero, which refers to an infinite timeout. Any other setting is the timeout, in milliseconds. It is valid to set the timeout to any value, but values less than 500 milliseconds (half a second) are interpreted to be 500 milliseconds. When nMilliSec is not specified, the method will return the current setting. :ReuseAddr([lSet]) -> lSet By default, a socket cannot be bound to a local address that is already in use. Sometimes, however, it can be necessary to "re-use" an address in this way. Because every connection is uniquely identified by the combination of local and remote addresses, there is no problem with having two sockets bound to the same local address as long as the remote addresses are different. In order to allow the socket to be bound to an address that is allready in use, the application should call this method by specifying lSet as .T. before issuing a :Bind call. Setting or resetting the option after the :Bind has no effect on this or any other socket. When lSet is not specified, the method will return the current setting. Default is .F. :Route([lSet]) -> lSet Enable/disable routing; when disabled packets are sent directly to interface. When lSet is not specified, the method will return the current setting. Default is .T. :SendBufferSize([nSize]) -> nBytes Get/set buffer size for sends. When nSize is not specified, the method will return the current size of the send buffer in bytes. :SendTimeout(nMilliSec) -> nTimeout Get/set maximun number of millisecs to wait when sending data to a remote connection (may not work with all stack implementations). This option can be set on any type of socket in any state. The default value is zero, which refers to an infinite timeout. Any other setting is the timeout, in milliseconds. It is valid to set the timeout to any value, but values less than 500 milliseconds (half a second) are interpreted to be 500 milliseconds. When nMilliSec is not specified, the method will return the current setting. :SetBlockingMode([lSet]) -> lSet Enable/disable blocking mode on the socket. When enabled (which is the default), the process executing :Accept or sending/receiving data will wait for the operation to complete. If not specified lSet defaults to .T. :TCPNoDelay([lSet]) -> lSet Enable/disable use of Nagle algorithm for sends. The Nagle algorithm is disabled when lSet is .T. (and vice versa). The process involves buffering :Send data when there is unacknowledged data already "in flight" or buffering :Send data until a full-size packet can be sent. For most application protocols the Nagle Algorithm can deliver significant performance enhancements. However, in some cases this algorithm can impede performance, and :TCPNoDelay can be used to turn it off. These are applications where many small messages are sent, and the time delays between the messages are maintained. When lSet is not specified, the method will return the current setting. Default is .F. Status :ErrorMessage() -> cErrorText Return error description of most recent winsock error. :CatMark() -> lNoOOBDataWaiting Check if out-of-band data is waiting to be read. This applies only to a stream oriented socket (eg. SOCK_STREAM) that has been configured for in-line reception of out-of-band data; see :OOBInLine. If no out-of-band data is waiting to be read, the operation returns .T. Otherwise, it returns .F., and the next :Recv or :RecvLine performed on the socket will retrieve some or all of the data preceding the "mark". The application should use :CatMark to determine whether any data remains. :GetReadCount() -> nBytesAvailable Use to determine the amount of data pending in the network's input buffer that can be read from the socket. If the socket is stream oriented (eg. SOCK_STREAM), this method returns the amount of data that can be read in a single call to the :Recv method; this might not be the same as the total amount of data queued on the socket. If the socket message oriented (ex. SOCK_DGRAM), this method returns the size of the first datagram (message) queued on the socket. :isListening() -> lListening Check if socket is in listening mode. :isConnected() -> lConnected Check if a connected socket is still alive. :MaxMessageSize() -> nBytes Maximum size of a message for message-oriented socket types (eg., SOCK_DGRAM). Has no meaning for stream oriented sockets. :RemoteName() -> cHostName Return host name of remote machine. :UpTime() -> {nDays, nHrs, nMin, nSec} Returns a one dimensional array specifying amount of time socket has been open. The following array constants available in Xb2NET.CH provide access to the individual array elements:

UPTIME_DAY - number of days
UPTIME_HRS - number of hours
UPTIME_MIN - number of minutes
UPTIME_SEC - number of seconds Child/Parent Relation :AddClient(oSocket) -> self Create a parent/child relation between this socket (the parent) and oSocket (the child). A list of all client sockets is available in the :ClientList ivar. :DelClient(oSocket) -> self Remove parent/child relation between this socket and oSocket. A list of all client sockets is available in the :ClientList ivar. :SetParent([oParent]) -> self Create or remove a parent/child relation between this socket (the child) and oParent (the parent). If oParent is not specified, the link is removed, otherwise a link is created. A reference to the parent socket is stored in the :Parent ivar.


xbSocket: Object properties

:Handle readonly/numeric Numeric socket descriptor as used by winsock. :AddrFamily readonly/numeric The socket's address family. #define constants: AF_* :SockType readonly/numeric The socket type. #define constants: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET :Protocol readonly/numeric The protocol used. #define constants: IPPROTO_* :LocalAddr readonly/numeric The numeric IP address of the local machine in network byte order that the socket is bound to. :LocalPort readonly/numeric The numeric port number on the local machine that the socket is bound to. :RemoteAddr readonly/numeric The numeric IP address of the remote machine in network byte order that the socket is connected to. :RemotePort readonly/numeric The numeric port number on the remote machine that the socket is connected to. :BytesReceived readonly/numeric Number of bytes received by last :Recv or :RecvLine call. :BytesSent readonly/numeric Number of bytes transmitted by last :Send call. :RecvCount readonly/numeric A cumulative total of number of bytes received on this socket since it was opened. :SendCount readonly/numeric A cumulative total of number of bytes sent on this socket since it was opened. :ErrorCode exported/numeric Most recent result code returned by winsock. :onError exported/codeblock Provides the ability to optionally specify a codeblock that will be evaluated when a winsock error occurs. When evaluated two parameters are passed to the codeblock (1) a reference to socket object responsible for the error, (2) the winsock error code number. Eg: oSocket:onError := {|oOwner,nErrCode| LogError(oOwner:ErrorText(nErrCode))} :isEncoded exported/logical Provides the ability to automatically encode and decode data transmitted on the socket. When set to .T., all inbound data will be decoded (see :Decode) and all outbound data will be encoded (see :Encode). This is quite a powerful feature since it means that data can be transparently "massaged" before it is passed on. For example, using the following codeblocks, any datatype can be sent and received between Xbase++ applications. Send an array, receive an array; send a codeblock, receive a codeblock... you can immagine the possibilities.
oSocket:isEncoded := .T.
oSocket:Encode := {|xVal| Var2Bin(xVal)}
oSocket:Decode := {|cBuffer,nBytes| Bin2Var(Left(cBuffer,nBytes))}
:Encode exported/codeblock Optional codeblock that is automatically evaluated to encode outbound data when :isEncoded is .T. If no user codeblock is supplied but :isEncoded is .T. a default built-in encryption algorithm will be used. When evaluated two parameters are passed to the codeblock (1) a reference to the value being transmitted, (which may be any data type), and (2) if the value to be transmitted is a string, this parameter will contain the lenght of the string, otherwise it will be -1. See :isEncoded for more information. :Decode exported/codeblock Optional codeblock that is automatically evaluated to decode inbound data when :isEncoded is .T. If no user codeblock is supplied but :isEncoded is .T. a default built-in decryption algorithm will be used. When evaluated two parameters are passed to the codeblock (1) a text buffer of the data received, and (2) the number of bytes received. See :isEncoded for more information. :Parent readonly/object Reference to parent socket or NIL if this socket has no parent. :ClientList readonly/array A one dimensional array listing all active client sockets either created through this socket's :Accept method or :AddClient method. :StartDate readonly/date Date socket opened. :StartTime readonly/numeric Time socket opened (seconds after midnight). :ThreadID readonly/numeric Xbase++ thread ID number where socket was created. :Cargo exported/any data type Used to attach additional information to the object as required by the programmer.


xbServer()    inherited from xbSocket, Thread

This class implements a generic socket listener that spawns an xbSocketThread when a client connection is accepted.

xbServer: Class methods

:New([xLocalAddr], [nPort]) -> self Creates a new instance of the xbServer class and allocates system resources to bind the newly created socket to a specific transport service provider. The xbServer class is inherited from xbSocket and Thread (part of Xbase++). An instance of this class will therefore have access to all methods and properties of it's superclasses. For information on the Thread class, please consult your Xbase++ documentation. All parameters are optional. Parameters: xLocalAddr The local address can be specified either as a numeric address in network byte order, or as an IP address in form of a dotted octet string (ex. 127.0.0.1). If an application does not care what local address is assigned, specify the constant value INADDR_ANY (the default). This allows the underlying service provider to use any appropriate network address. nPort This is the numeric port number on the local computer to bind the socket to. If not supplied, the default is 23 which is the standard port number of a Telnet server.

xbServer: Object methods

:ActiveConnections() -> nConnectionsOpen Returns the total number of connections currently open. :SetBacklog([nBacklog]) -> nBacklog Get/set the maximum length of the queue of pending connections. If this value is SOMAXCONN (the default), then the underlying service provider responsible for this socket will set the backlog to a maximum "reasonable" value. There is no standard provision to find out the actual backlog value however if nBacklog is not specified, the method will return the current backlog setting (which may not necessarily be the actual backlog value set by the service provider).

If the server is running and the socket is in a listening state, calls to :SetBacklog will update the current backlog for the socket. If there are more pending connections than the new backlog value, the excess pending connections will be reset and dropped. :Start() -> lSuccess Start running the server in its own thread. If the server thread is started successfully, the method returns .T., otherwise it returns .F. Once started, the server will begin listening for incomming connections on the address and port specified when the xbServer object was instantiated. A new xbSocketThread object will be instantiated and bound to each accepted connection. It is the xbSocketThread object that is responsible for handling the actual comminications with the client.

The server will continue running in it's own thread and listening for incomming connections until it is terminated by calling the :Stop method. Once the server has stopped, it can be restarted by calling :Start. As long as the server thread is active, repeated calls to :Start are ignored. :Stop([nTimeOut]) -> lSuccess Close server socket and signal server plus all connected clients to terminate. nTimeOut is an optional parameter specifying the maximum amount of time, in 1/100ths of a second, to wait for the xbServer thread (including all connected clients) to terminate. The default value of zero causes the current thread (where :Stop was called) to wait indefinitely until the xbServer thread and all connected clients have terminated. The method returns .F. if the server could not be terminated within the specified time interval, otherwise it returns .T.


xbServer: Object properties

:ConnectCount exported/numeric Total number of connections accepted since server started. This is not the same as :ActiveConnections. :MaxConnections exported/numeric | NIL Maximum allowable number of concurrent client connections. A value of NIL (the default) does not impose a limit on the number of concurrent client connections. See :onMaxConnect for additional information. :onConnect exported/codeblock | NIL This is the codeblock that will be executed when a client connection is accepted. If :onConnect is NIL, then the server will simply echo back to the client all received data (this is the default behaviour). For the server to do anything useful, a codeblock must be attached to this ivar. The function of this codeblock is to receive the client request, process as required and send back a response. The connected socket can be kept open as long as required or until the client disconnects. When the procedure terminates, the client socket will be automatically closed. It is important to note that the code encapsulated by the codeblock will be executed in a new xbSocketThread.

Example: oServer:onConnect := {||ServiceClient()}

Procedure ServiceClient()
   Local cRecv, cSend
   Local oClient := ThreadObject()
   Local cTempFile := "~" + NTrim(oClient:Handle) + ".tmp"

   while (cRecv := oClient:RecvLine()) != NIL
     cSend := cRecv
     cRecv := StrTran(StrTran(cRecv,chr(10),""),chr(13),"")
     RunShell( "/C " + cRecv + " > " + cTempFile,,.f.,.t. )
     cSend += MemoRead(cTempFile)
     FErase(cTempFile)
     if oClient:Send( cSend ) < 0
       exit
     endif
   end
Return
:onMaxConnect exported/character | codeblock | NIL The :onMaxConnect ivar determines what happens when :ActiveConnections reaches :MaxConnections. The following options are possible:

NIL - do not accept any more connections until an existing client connection is closed.
STRING - accept new connection, receive request, send string contained in :onMaxConnect to client and immediately close connection.
CODEBLOCK - accept new connection, create new xbSocketThread object and execute codeblock contained in :onMaxConnect within this new thread.

Example: oServer:MaxConnections := 50
oServer:onMaxConnect := "Too many connections, please try later..."
// or
oServer:onMaxConnect := {||SendBusy()}

Procedure SendBusy()
   Local oThread := ThreadObject()
   oThread:Recv()
   if oThread:BytesReceived > 0
      oThread:Send( "Too many connections, please try later...")
   endif
Return
:SleepTime exported/numeric Amount of time in 1/100ths of a second to idle the xbServer thread after accepting a new connection. :ThreadID readonly/numeric Numeric ID of thread. :WorkerClass exported/reference to class function This instance variable provides a reference to a client socket handler class function. By default :WorkerClass contains a reference to the xbSocketThread class function, however it can be used to define a custom client socket handler to be used instead of xbSocketThread. When instantiated, the init method of the worker class will receive two parameters: (1) a reference to the parent server object, and (2) a numeric handle of the newly created socket. If a custom class is used, it should be derived either from the xbSocket and Thread classes or from the xbSocketThread class.

Example: oServer:WorkerClass := MyClientHandler()

CLASS MyClientHandler FROM xbSocketThread
EXPORTED:
INLINE METHOD Init(oParent, nHandle)
  ::xbSocketThread:init(oParent, nHandle)
  // add your custom init code here
  Return self

// The :Execute method is where all the work is done, add your custom code here
INLINE METHOD Execute()
  Local cRecv := ::Recv()
  if ::BytesReceived > 0
    ::Send( cRecv ) // just echo back whatever we receive
  endif
  Return self

ENDCLASS


xbHTTPServer()    inherited from xbServer

This class implements an HTTP 1.1 listener that spawns an xbHTTPThread when a client connection is accepted.

xbHTTPServer: Class methods

:New([xLocalAddr], [nPort]) -> self Creates a new instance of the xbHTTPServer class and allocates system resources to bind the newly created socket to a specific transport service provider. The xbHTTPServer class is inherited from xbServer which in turn is inherited from xbSocket and Thread. An instance of this class will therefore have access to all methods and properties of it's superclasses. For information on the Thread class, please consult your Xbase++ documentation. All parameters are optional. Parameters: xLocalAddr The local address can be specified either as a numeric address in network byte order, or as an IP address in form of a dotted octet string (ex. 127.0.0.1). If an application does not care what local address is assigned, specify the constant value INADDR_ANY (the default). This allows the underlying service provider to use any appropriate network address. nPort This is the numeric port number on the local computer to bind the socket to. If not supplied, the default is 80 which is the standard port number of an HTTP server.


xbHTTPServer: Class properties

:ServerName readonly/character Contains server name and version number, eg. Xb2.NET/0.0.54

xbHTTPServer: Object methods

:RootDir( [cPath] ) -> cPath Get/set default root directory for HTTP server. :StatusText( nStatusCode ) -> cStatusText Return a text message corresponding to an HTTP response status code. An HTTP status code is a 3-digit integer where the first digit defines the class of response. There are 5 values for the first digit (the remaining two digits are not categorized):

1xx: Informational - Request received, continuing process
2xx: Success - The action was successfully received, understood, and accepted
3xx: Redirection - Further action must be taken in order to complete the request
4xx: Client Error - The request contains bad syntax or cannot be fulfilled
5xx: Server Error - The server failed to fulfill an apparently valid request


xbHTTPServer: Object properties

:AllowDelete exported/logical When set to .T., client is permitted to delete a file on the HTTP server by using the DELETE method. The target file is specified in the URI request. This property is ignored when the :onDELETE ivar contains a codeblock. The default value is .F. :AllowUpload exported/logical When set to .T., client is permitted to upload a file to the HTTP server by using the PUT method. The target file is specified in the URI request, with the file contents contained within the body of the request. This property is ignored when the :onPUT ivar contains a codeblock. The default value is .F. :IndexFile exported/character | character array | NIL This is the default file that will be returned to the client when no resource is requested. A single value can be specified as a character string or multiple values as an array of character strings. When multiple values are specified, the server will search the root directory for the first match. The default is: {"default.htm", "default.html", "index.htm", "index.html", "main.htm", "main.html"}

Setting :IndexFile to NIL will cause all client requests with an empty URI path component to be routed ot the :onGET codeblock. :onDELETE exported/codeblock | NIL This is an optional codeblock that will be executed when a DELETE request is received. By default DELETE requests are rejected unless :AllowDelete is set to .T. or a custom codeblock is assigned to the :onDELETE ivar. When evaluated, the codeblock will receive one parameter; a reference to the connected xbHTTPThread object.

Example: oServer:onDELETE := {|o|DeleteFile(o)}

Procedure DeleteFile( oClient )
   Local cRootDir := oClient:Parent:RootDir()
   Local cFile := oClient:HTTPRequest:Path

   cFile := cRootDir + iif(Left(cPath,1)=="/", SubStr(cPath,2), cPath)
   oClient:HTTPResponse:ContentType("text/plain")
   if FErase(cFile) == 0
     oClient:HTTPResponse:Content := "File deleted"
   else
     oClient:HTTPResponse:Content := "Unable to delete file"
   endif
Return
:onGET exported/codeblock | NIL This is an optional codeblock that is used to process dynamic requests. Client requests that fall under this category include; (a) requests with a URI query component, and (b) requests with an empty URI path component and no :IndexFile defined. If a dynamic request is received, and no :onGET codeblock is defined, then the server will reply with a 404 status code. When evaluated, the supplied codeblock will receive one parameter; a reference to the connected xbHTTPThread object. :onHTTPError exported/codeblock | NIL This is an optional codeblock that will be executed when a runtime error occurs while processing the HTTP request. If no custom codeblock is supplied, the default behaviour is to return to the client a description of the error including callstack information. If a codeblock is supplied and a runtime error occurs within the connected client's xbHTTPThread, the codeblock will be evaluated with one parameter passed; a reference to the Xbase++ Error object. The function evaluated within the supplied codeblock must terminate with a Break(). If a character string is pased to the Break() function (as in the example below), then this string will be transmitted to the client. Alternatively, if an error object is passed, then the HTTP server will generate a corresponding reply.

Example: oServer:onHTTPError := {|o|HTTPError(o)}

Procedure HTTPError( oError )
   Local oClient := ThreadObject()
   Local cCRLF := chr(10)+chr(13)
   Local cResponse

   oClient:HTTPResponse:ContentType("text/plain")
   cResponse := "An error occurred in my Xbase++ web server:" + cCRLF +;
    iif(ValType(oError:subSystem) == "C", oError:subSystem, "???" ) + "/" +;
    iif(ValType(oError:subCode) == "N", LTrim(oError:subCode), "???" ) + cCRLF +;
    iif(ValType(oError:description) == "C", oError:description, "" )
   Break( cResponse )
Return
:onInvalidCommand exported/codeblock | NIL This is an optional codeblock that will be evaluated when a non-supported method is requested by the client. If no custom codeblock is supplied, the default behaviour is to reply with an HTTP 501 status code. When evaluated, the supplied codeblock will receive one parameter; a reference to the connected xbHTTPThread object.

Example: oServer:onInvalidCommand := {|o|MethodNotSupported(o)}

Procedure MethodNotSupported( oClient )
   Local oResp := oClient:HTTPResponse
   oResp:StatusCode := 501
   oResp:ContentType := "text/plain"
   oResp:Content := "The requested method is not supported!"
Return
:onNotFound exported/codeblock | NIL This is an optional codeblock that will be evaluated when a requested resource is not found. If no custom codeblock is supplied, the default behaviour is to reply with an HTTP 404 status code. When evaluated, the supplied codeblock will receive one parameter; a reference to the connected xbHTTPThread object.

Example: oServer:onNotFound := {|o|FileNotFound(o)}

Procedure FileNotFound( oClient )
   Local oReq := oClient:HTTPRequest
   Local oResp := oClient:HTTPResponse

   if oReq:Path == "/~5" .or. oReq:Path == "\~5"
     // redirect user to the new location
     oResp:Location := "http://www.SomeOtherLocation.com"
     oResp:StatusCode := 301
   else
     oResp:StatusCode := 404
     oResp:ContentType := "text/plain"
     oResp:Content := "The requested file is not found!"
   endif
Return
:onPOST exported/codeblock | NIL This is an optional codeblock that is used to process POST commands. If a POST command is received, and an :onPOST codeblock is not defined, then the server will reply with a 501 status code. When evaluated, the supplied codeblock will receive one parameter; a reference to the connected xbHTTPThread object. :onPUT exported/codeblock | NIL This is an optional codeblock that will be executed when a PUT request is received. By default PUT requests are rejected unless :AllowUpload is set to .T. or a custom codeblock is assigned to the :onPUT ivar. When evaluated, the codeblock will receive one parameter; a reference to the connected xbHTTPThread object. See :onDELETE for an example. :onSOAP exported/codeblock | NIL This is an optional codeblock that is used to process SOAP requests. If a SOAP request is received, and an :onSOAP codeblock has not been assigned, then the :onPOST codeblock will be evaluated. If that is also not defined, then the server will reply with a 501 status code. When evaluated, the supplied codeblock will receive one parameter; a reference to the connected xbHTTPThread object.

Example: oServer:onSOAP := {|o| SOAPHandler(o)}

Procedure SOAPHandler( oClient )
  Local cAction, oSOAPReq, oSOAPResp

  // :HTTPRequest:Content contains an xbSOAPEnvelope instance
  oSOAPReq := oClient:HTTPRequest:Content
  // if the request is parsed correctly, this should be the action requested by the client
  cAction := oSOAPReq:Action
  // create another SOAP envelope object where we will write our response
  oSOAPResp := xbSOAPEnvelope():new()
  // tack on the word "Response" to the reply envelope action, eg. "GetDateTimeResponse"
  oSOAPResp:Action := cAction + "Response"
  
  do case
  case cAction == "GetDateTime"
     oSOAPResp:SetVar("Date", Date())
     oSOAPResp:SetVar("Time", Time())
  case cAction == "SQLExecute"
     if Empty(oSOAPReq:GetVar("SQLStatement"))
       // the parameter is missing - send back an appropriate fault response.
       oSOAPResp:SetFault("Client", "SQLStatement parameter is missing")
     else
       nResult := DefaultSQLConnection():Execute( oSOAPReq:GetVar("SQLStatement") )
       oSOAPResp:SetVar("Result", nResult)
     endif
  otherwise
     // They requested a method that is not available - send back a fault response.
     oSOAPResp:SetFault("Client", "Client request " + cAction + " not available")
  endcase

  // attach the SOAP response envelope to the HTTP response object
  // the Xb2.NET HTTP server will take care of the rest
  oClient:HTTPResponse:Content := oSOAPResp
Return
:SessionTag exported/character This is the tag name that will be used to track a session-state between the server and client. Each session is identified by an ID that must be communicated between the server and client with each request-response state. By default, an xbHTTPThread object will use cookies to maintain this session ID between states. However, this may not always work since a client may have cookie support turned off. In such cases, the session ID can be communicated between states by embedding the session ID in the URL (as a query parameter) or as a hidden form variable within an HTML page. Each instance of the HTTP server can have a different session tag identifier. The default is: _SID :SessionTimeout exported/numeric Inactive session timeout in minutes. An inactive client xbSession object will be maintained in memory for a minimun :SessionTimeout minutes. :SOAPParser exported/reference to class function This instance variable provides a reference to a SOAP parser class function. By default :SOAPParser contains a reference to the xbSOAPEnvelope class function, however it can be used to define a custom SOAP parser to be used instead of xbSOAPEnvelope. When instantiated, the init method of the SOAP parser will receive a single character string parameter containing the SOAP envelope. If a custom class is used, it should at minimum contain a GetVar method that returns the value of a SOAP parameter.

Example: oServer:SOAPParser := MySOAPParser()

CLASS MySOAPParser
EXPORTED:
INLINE METHOD init( cXMLString )
  // code to parse the XML SOAP envelope
  Return self

INLINE METHOD GetVar( cName )
  // code to return value of input parameter cName
  Return xValue

ENDCLASS
:WorkerClass exported/reference to class function This instance variable provides a reference to a client socket handler class function. By default :WorkerClass contains a reference to the xbHTTPThread class function, however it can be used to define a custom client socket handler to be used instead of xbHTTPThread. When instantiated, the init method of the worker class will receive two parameters: (1) a reference to the parent server object, and (2) a numeric handle of the newly created socket. If a custom class is used, it should be derived either from the xbSocket and Thread classes or from the xbHTTPThread class.

Example: oServer:WorkerClass := MyHTTPHandler()

CLASS MyHTTPHandler FROM xbHTTPThread
EXPORTED:
INLINE METHOD Init(oParent, nHandle)
  ::xbHTTPThread:init(oParent, nHandle)
  // add your custom init code here
  Return self

// The :Execute method is where all the work is done, add your custom code here
INLINE METHOD Execute()
  Local oRequest := ::HTTPRequest
  Local oResponse := ::HTTPResponse

  while !oRequest:Recv()
    do case
    case oRequest:Command == "GET"
      // code to generate GET response
    case oRequest:Command == "POST"
      // code to generate POST response
    case oRequest:Command == "HEAD"
      // code to generate HEAD response
    otherwise
      // send command not implemented status code
      oResponse:StatusCode := 501
    endcase
    oResponse:Send()
    if !oRequest:KeepAlive
      // client doesn't want to keep connection open
      ::Close()
    endif
    oResponse:Reset() // reinitialize object
  end
  Return self

ENDCLASS


xbSocketThread()    inherited from xbSocket, Thread

This is the client thread that is spawned by xbServer when a connection with a peer is accepted. This "worker" thread will handle the request and send a response back to the connected client.

xbSocketThread: Class methods

:New([nAddrFamily], [nSocketType], [nProtocol]) -> self, or;
:New(oParent, [nHandle]) -> self
Creates a new instance of the xbSocketThread class and allocates system resources to bind the newly created socket to a specific transport service provider. The xbSocketThread class is inherited from xbSocket and Thread (part of Xbase++). An instance of this class will therefore have access to all methods and properties of it's superclasses. For information on the Thread class, please consult your Xbase++ documentation. For additional information on parameters, please see xbSocket:New(). All parameters are optional.

xbSocketThread: Object methods

:Start([cFuncName|bCodeBlock], [xParamList,...] ) -> lSuccess Starts the thread and executes the function cFuncName or evaluates the code block bCodeBlock within this thread. The parameters xParamList are passed on to the function or codeblock, respectively. If the thread is started successfully, the method returns .T., otherwise it returns .F.

Once started the xbSocketThread will continue executing the code encapsulated by the specified function or codeblock until the socket is either disconnected by the remote host or, the thread is terminated by calling the :Stop method. Once the thread has stopped, it can be restarted by calling :Start. As long as the thread is active, repeated calls to :Start are ignored.

If neither cFuncName or bCodeBlock are supplied, then the default behaviour is to simply echo back to the connected peer all received data. The following is an example of a server type socket thread that implements two commands "GET TIME" and "GET DATE":

Example: oSocket:Start("ServiceClient", oSocket)

Procedure ServiceClient( oSocket )
   Local cRecv, cSend

   while (cRecv := oSocket:RecvLine()) != NIL
     cRecv := Upper(Left(cRecv,8))
     do case
     case cRecv == "GET TIME"
       cSend := Time()
     case cRecv == "GET DATE"
       cSend := DToS(Date())
     otherwise
       cSend := cRecv + " invalid command"
     endcase
     if oSocket:Send( cSend ) < 0
       exit
     endif
   end
Return
:Stop([nTimeOut]) -> lSuccess Close socket and signal socket thread to terminate. nTimeOut is an optional parameter specifying the maximum amount of time, in 1/100ths of a second, to wait for the xbSocketThread thread to terminate. The default value of zero causes the current thread (where :Stop was called) to wait indefinitely until the xbSocketThread thread has terminated. The method returns .F. if the thread could not be terminated within the specified time interval, otherwise it returns .T.


xbSocketThread: Object properties

:ThreadID readonly/numeric Numeric ID of thread.


xbHTTPThread()    inherited from xbSocket, Thread

This is the client thread that is spawned by xbHTTPServer when a connection is accepted from a user agent (a browser). This "worker" thread is responsible for handling the client request and generating an appropriate xbHTTPResponse that will be sent back to the client. Typically, there is no need to instantiate this class in your code since it is automatically instantiated by the xbHTTPServer when a client connection is accepted.

xbHTTPThread: Class methods

:New([nAddrFamily], [nSocketType], [nProtocol]) -> self, or;
:New(oParent, [nHandle]) -> self
Creates a new instance of the xbHTTPThread class and allocates system resources to bind the newly created socket to a specific transport service provider. The xbHTTPThread class is inherited from xbSocket and Thread (part of Xbase++). An instance of this class will therefore have access to all methods and properties of it's superclasses. For information on the Thread class, please consult your Xbase++ documentation. For additional information on parameters, please see xbSocket:New(). All parameters are optional.

xbHTTPThread: Object methods

Life Cycle :Start([cFuncName|bCodeBlock], [xParamList,...] ) -> lSuccess Starts the HTTP server thread. If the thread is started successfully, the method returns .T., otherwise it returns .F. Once started the xbHTTPThread will continue running until the socket is either disconnected by the remote host or, the thread is terminated by calling the :Stop method. Once the thread has stopped, it can be restarted by calling :Start. As long as the thread is active, repeated calls to :Start are ignored. :Stop([nTimeOut]) -> lSuccess Close socket and signal socket thread to terminate. nTimeOut is an optional parameter specifying the maximum amount of time, in 1/100ths of a second, to wait for the xbHTTPThread thread to terminate. The default value of zero causes the current thread (where :Stop was called) to wait indefinitely until the xbHTTPThread thread has terminated. The method returns .F. if the thread could not be terminated within the specified time interval, otherwise it returns .T. Send Reply :NotFound() -> nBytesSent | SOCKET_ERROR Send default HTTP 404 error message to client. :Send([cBuffer], [nFlag], [xToAddr], [nToPort]) -> nBytesSent | SOCKET_ERROR Transmit data provided in cBuffer to connected client. If cBuffer is NIL or not specified, the method will send the data contained in the :HTTPResponse object (the other parameters are ignored). In most cases, there is no need to call this method since it will be called automatically by the xbHTTPThread object. For a detailed explanation of all parameters, see xbSocket:Send() :SendBusy() -> self Send default server busy response to client and close connection. :SendError(xError) -> self Send error message to client and close connection. xError can be either a string or an Xbase++ error object. :SendFile(cFile) -> nBytesSent | SOCKET_ERROR This method transmits a file to the client. The file path must be relative to the directory where the HTTP server application is running. If cFile is not found, then an HTTP 404 status code will be sent instead. State Management :OpenSession() -> self Open existing client session or create a new one if none exists. Session data is stored in server memory until the session is either closed using :CloseSession or the session times out (see xbHTTPServer:SessionTimeout). Note, calling :GetCargo or :SetCargo automatically opens a session. :CloseSession() -> self Close session and release any state variables maintained in memory by the xbSession class for this client. :GetSessionHandle() -> cSessionID | NIL Returns client session ID as a string or NIL if there is no session currently open for this client. :GetCargo([cName]) -> xValue | aVarList | NIL Retrieve a named state variable previously saved with :SetCargo. If a parameter is not supplied or if cName is NIL, then the method will return an array of all name/value pairs saved in the current xbSession object. Note, this method will open a new session if none exists. :SetCargo([xName], [xValue]) -> xPreviousValue | aPreviousVarList Store the value xValue using a symbolic character name xName until the session is closed. This method is quite flexible and can be used is several ways:

When xName and xValue are both NIL then delete all state variables (session is not closed)
When xValue is NIL, state variable with the name xName is deleted
When xName is an array, replace all name/value pairs with passed array
Otherwise add/replace value

This method will open a new session if none exists. Data :GetCookie([cName]) -> cValue | aCookieList | NIL This method is a shortcut to xbHTTPThread:HTTPRequest:GetCookie(). Please see the xnHTTPRequest class for more information. :SetCookie([cName],[cValue],[dExpiry],[cPath],[cDomain]) -> cPreviousValue | aPrevCookieList This method is a shortcut to xbHTTPThread:HTTPResponse:SetCookie(). Please see the xnHTTPResponse class for more information. :GetVar([cName],[nSource]) -> cValue | aVarList | NIL Retrieve a named parameter contained within the HTTP request. If cName is NIL, then the method will return an array of name/value pairs transmitted by the client as URL query parameters.

Named parameters can be transmitted by the client as a query within the URL, eg: (http://ca.finance.yahoo.com/q?s=NT.TO&d=c&k=c4&t=1d) or as form variables within the body of the request. The optional nSource parameter can be used to specify where to retrieve the value from. If not specified the parameter will first be searched within the URL query then within the form (if available). The method will return the first value found matching the name cName or NIL if the parameter is not found. The following Xb2NET.ch define constant are provided for this purpose:

VAR_QUERY - search within URL query parameter list
VAR_CONTENT - search within the body of the HTTP request.
VAR_ANY - first search the URL query, then within the body of the HTTP request.


xbHTTPThread: Object properties

:HTTPRequest readonly/object Reference to xbHTTPRequest object. This object encapsulates the client request that was sent to the HTTP server. :HTTPResponse readonly/object Reference to xbHTTPResponse object. This object encapsulates the server response that will be sent to the client. :isSOAP readonly/logical This instance variable will be .T. when the request contains a SOAP Action. In all other cases it's value will be .F.


xbHTTPMessage    abstract class

This is an abstract class that provides a common foundation for the xbHTTPRequest and xbHTTPResponse classes. It cannot be instantiated in user code.

xbHTTPMessage: Object methods

:Reset([oSocket]) -> self Reinitialize object. :GetHeader([cName]) -> cValue | aHeaderList | NIL This is a generic method for retrieving HTTP header fields. If cName is NIL, then the method will return an array of name/value pairs representing all header fields. :SetHeader([cName], [cValue]) -> cPreviousValue | aPreviousHeaderList This is a generic method for setting HTTP header fields. This method can be used is several ways:

When cName and cValue are both NIL then delete all headers.
When cValue is NIL, header parameter with the name cName is deleted.
When cName is an array, replace all headers with passed array.
Otherwise add/replace value
:GetCookie([cName]) -> cValue | aCookieList | NIL Retrieve the value of a cookie with the name cName. If a parameter is not supplied or if cName is NIL, then the method will return an array of name/value pairs representing all cookies. :ClearContent() Clear the :Content buffer and remove all content related header fields. :GetContentAsString() Retrieve the HTTP message content as a character string. :ParseHeader( cHeader ) Parse message header. This is done automatically when a message is received using :Recv(). :AsString() -> cHTTPMessage Encode header and content suitable for HTTP transport and return as character string. :Send() -> nBytesSent | SOCKET_ERROR Encode header and content for HTTP transport and transmit to connected peer. :Recv() Read message transmitted by remote peer and parse message header from content.


xbHTTPMessage: Object properties

:BytesReceived exported/numeric Number of bytes received by last :Recv call. :BytesSent exported/numeric Number of bytes transmitted by last :Send call. :Cargo exported/any data type Used to attach additional information to the object as required by the programmer. :Content exported/character or object Message content. Can be a character string or an object. :HTTPVersion exported/character The HTTP protocol version of the message, eg. "1.1" :Message exported/character Complete HTTP header as a character string. :Socket exported/object Reference to the connected xbSocket object. Depending on the context, the peer can be either the server or the client. :StartLine exported/character First line in HTTP message. Header fields (access/assign methods) :CacheControl exported access-assign method/character Get/set the "Cache-Control" header field. This general-header field is used to control the caching mechanisms along the message route. It can be used to prevent caches from adversely interfering with the request or response. See RFC-2616, 14.9. :Connection exported access-assign method/character Get/set the "Connection" header field. This general-header field allows the sender to specify options that are desired for that particular connection. It can be used with HTTP 1.1 to keep persistent connections. See RFC-2616, 14.10. :ContentEncoding exported access-assign method/character Get/set the "Content-Encoding" header field. This header field applies to the message content and is is used as a modifier to the media-type. When present, its value indicates what additional content codings have been applied to the entity-body, and thus what decoding mechanisms must be applied in order to obtain the media-type referenced by the Content-Type header field. See RFC-2616, 14.11. :ContentLanguage exported access-assign method/character Get/set the "Content-Language" header field. This header field applies to the message content and is used to describe the natural language(s) of the intended audience for the enclosed entity. Note that this might not be equivalent to all the languages used within the entity-body. See RFC-2616, 14.12. :ContentLength exported access-assign method/numeric Get/set the "Content-Length" header field. This header field indicates the size of the message content sent to the recipient. See RFC-2616, 14.13. :ContentLocation exported access-assign method/character Get/set the "Content-Location" header field. This header field may be used to supply the location for the entity enclosed in the message when that entity is accessible from a location separate from the requested resource's URI. See RFC-2616, 14.14. :ContentMD5 exported access-assign method/character Get/set the "Content-MD5" header field. This header field is used for the purpose of providing an end-to-end message integrity check of the content. See RFC-2616, 14.15. :ContentRange exported access-assign method/character Get/set the "Content-Range" header field. This header field is sent with a partial entity-body to specify where in the full entity-body the partial body should be applied. See RFC-2616, 14.16. :ContentType exported access-assign method/character Get/set the "Content-Type" header field. This header field indicates the media type of the message content sent to the recipient or, in the case of the HEAD command, the media type that would have been sent had the request been a GET. See RFC-2616, 14.17. :KeepAlive exported access-assign method/logical Get/set the "Connection" header field. When .T. it indicates that the sender requests a persistent connection. :LastModified exported access-assign method/character Get/set the "Last-Modified" header field. This header field is used to indicate the date and time at which the message content was last modified. See RFC-2616, 14.29. :Pragma exported access-assign method/character Get/set the "Pragma" header field. This header field is used to include implementation-specific directives that might apply to any recipient along the message path. See RFC-2616, 14.32. :Trailer exported access-assign method/character Get/set the "Trailer" header field. This is a general header field whose value indicates that the given set of header fields is present in the trailer of a message encoded with chunked transfer-coding. See RFC-2616, 14.40. :TransferEncoding exported access-assign method/character Get/set the "Transfer-Encoding" header field. This is a general header field indicating what (if any) type of transformation has been applied to the message body in order to safely transfer it between the sender and the recipient. This differs from the content-coding in that the transfer-coding is a property of the message, not of the entity. See RFC-2616, 14.41. :Via exported access-assign method/character Get/set the "Via" header field. This is a general header field that indicates the intermediate protocols and recipients between the client and server on requests, and between the server and client on responses. See RFC-2616, 14.45. :Warning exported access-assign method/character Get/set the "Warning" header field. This is a general header field that is used to carry additional information about the status or transformation of a message which might not be reflected in the message. See RFC-2616, 14.46.


xbHTTPRequest()    inherited from xbHTTPMessage, xbURI

This class encapsulates an HTTP request. It can be used on the client side to compose and send a request to an HTTP server, and on the server side it is used to receive and parse the HTTP request sent by the client.

xbHTTPRequest: Class methods

:New([oSocket]) -> self Creates a new instance of the xbHTTPRequest class. The optional parameter oSocket is a reference to an xbSocket object that must be supplied in order to use the :Send and/or :Recv methods.

xbHTTPRequest: Object methods

:SetCookie([cName],[cValue]) -> cPreviousValue | aPrevCookieList This method is used on the client side to return a previously saved cookie value back to the HTTP server. An HTTP server will request that a cookie be stored on the client side by using the xbHTTPResponse:SetCookie method. Cookies are typically used by HTTP servers to store state information on the client side. This method can be used is several ways:

When cName and cValue are both NIL then delete all cookies.
When cValue is NIL, then delete the cookie the name cName
When cName is an array, replace all cookie name/value pairs with passed array
Otherwise add or replace a cookie value


xbHTTPRequest: Object properties

:Command exported/character This is the HTTP method requested, eg: GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT :isSOAP readonly/logical This instance variable will be .T. when the received request contains a SOAP Action. In all other cases it's value will be .F. Header fields (access/assign methods) :Accept exported access-assign method/character Get/set the "Accept" header field. This header field can be used by the client to specify certain media types which are acceptable for the response. See RFC-2616, 14.1. :AcceptCharset exported access-assign method/character Get/set the "Accept-Charset" header field. This header field allows a client to specify what character sets is is capable of understanding. See RFC-2616, 14.2. :AcceptEncoding exported access-assign method/character Get/set the "Accept-Encoding" header field. This request header field is similar to :Accept, but restricts the content codings that are acceptable in the response. See RFC-2616, 14.3. :AcceptLanguage exported access-assign method/character Get/set the "Accept-Language" header field. This request header field is similar to :Accept, but restricts the set of natural languages that are preferred in the response. See RFC-2616, 14.4. Language tags are defined in RFC-1766. :Authorization exported access-assign method/character Get/set the "Authorization" header field. It is used by a client to authenticate itself with a server. The field is usually, but not necessarily, included with the request after receiving a 401 response. The Authorization field value consists of credentials containing the authentication information of the client for the realm of the resource being requested. See RFC-2616, 14.8. :Expect exported access-assign method/character Get/set the "Expect" header field. This header field is used to indicate that particular server behaviors are required by the client. A "100-continue" token can be used by a client sending a request message with a request body to determine if the server is willing to accept the request (based on the request headers) before the client sends the request body. In some cases, it might either be inappropriate or highly inefficient for the client to send the body if the server will reject the message without looking at the body. See RFC-2616, 14.20. :Host exported access-assign method/character Get/set the "Host" header field. The Host request-header field specifies the HTTP host and port number of the resource being requested, as obtained from the original URI given by the user or referring resource. The :Host is equivalent to the xbURI:Authority portion of a URI. See RFC-2616, 14.23. :IfMatch exported access-assign method/character Get/set the "If-Match" header field. This header field is used to make an HTTP command conditional. As an example it can be used by clients to efficiently update cached information with a minimum amount of transaction overhead. See RFC-2616, 14.24. :IfModifiedSince exported access-assign method/character Get/set the "If-Modified-Since" header field. This header field is used to make an HTTP command conditional. If the requested variant has not been modified since the time specified in this field, an entity will not be returned from the server; instead, a 304 (not modified) response will be returned without any message-body. See RFC-2616, 14.25. :IfNoneMatch exported access-assign method/character Get/set the "If-None-Match" header field. See RFC-2616, 14.26. :IfRange exported access-assign method/character Get/set the "If-Range" header field. See RFC-2616, 14.27. :IfUnmodifiedSince exported access-assign method/character Get/set the "If-Unmodified-Since" header field. See RFC-2616, 14.28. :MaxForwards exported access-assign method/character Get/set the "Max-Forwards" header field. See RFC-2616, 14.31. :ProxyAuthorization exported access-assign method/character Get/set the "Proxy-Authorization" header field. This request header field is used by a client to identify itself to a proxy which requires authentication. The field is usually, but not necessarily, included with the request after receiving a 407 response. The :ProxyAuthorization field value consists of credentials containing the authentication information of the client for the proxy and/or realm of the resource being requested. See RFC-2616, 14.34. :Range exported access-assign method/character Get/set the "Range" header field. See RFC-2616, 14.35. :Referrer exported access-assign method/character Get/set the "Referer" header field. This request-header field allows the client to specify, for the server's benefit, the address (URI) of the resource from which the Request-URI was obtained. See RFC-2616, 14.36. :TE exported access-assign method/character Get/set the "TE" header field. See RFC-2616, 14.39. :UserAgent exported access-assign method/character Get/set the "User-Agent" header field. This header field contains information about the user agent (client) originating the request. It is used for statistical purposes, the tracing of protocol violations, and automated recognition of user agents for the sake of tailoring responses to avoid particular user agent limitations. See RFC-2616, 14.43. :UserEmail exported access-assign method/character Get/set the "From" header field. See RFC-2616, 14.22. :SOAPAction exported access-assign method/character Get/set the "SOAPAction" header field. Most HTTP servers that also provide SOAP services use this request header field to differentiate between a SOAP request and a normal web request. In most cases the content of the header field is not important, but as a general rule it should be the same as the SOAP method requested.


xbHTTPResponse()    inherited from xbHTTPMessage, xbURI

This class encapsulates an HTTP response. It can be used on the server side to compose and send an HTTP response to a connected client, and on the client side to receive and parse the HTTP response that was sent by the server.

xbHTTPResponse: Class methods

:New([oSocket]) -> self Creates a new instance of the xbHTTPResponse class. The optional parameter oSocket is a reference to an xbSocket object that must be supplied in order to use the :Send and/or :Recv methods.

xbHTTPResponse: Object methods

:SetCookie([cName],[cValue],[dExpiry],[cPath],[cDomain]) -> cPreviousValue | aPrevCookieList This method is used on the server side to store a cookie value on the client side. Cookies are typically used by HTTP servers to store state information on the client side. This method can be used is several ways:

When cName and cValue are both NIL then delete all cookies.
When cValue is NIL, then delete the cookie the name cName
When cName is an array, replace all cookie name/value pairs with passed array
Otherwise add or replace a cookie value


xbHTTPResponse: Object properties

StatusCode exported/numeric The StatusCode is a 3-digit integer result code of the attempt to understand and satisfy the request. The first digit defines the class of response while the remaining two digits are not categorized. There are 5 values for the first digit:

1xx: Informational - Request received, continuing process
2xx: Success - The action was successfully received, understood, and accepted
3xx: Redirection - Further action must be taken in order to complete the request
4xx: Client Error - The request contains bad syntax or cannot be fulfilled
5xx: Server Error - The server failed to fulfill an apparently valid request
:StatusText exported/character This is a short textual description of the :StatusCode, eg:

100: Continue
101: Switching Protocols
200: OK
201: Created
202: Accepted
203: Non-Authoritative Information
204: No Content
205: Reset Content
206: Partial Content
300: Multiple Choices
301: Moved Permanently
302: Found
303: See Other
304: Not Modified
305: Use Proxy
307: Temporary Redirect
400: Bad Request
401: Unauthorized
402: Payment Required
403: Forbidden
404: Not Found
405: Method Not Allowed
406: Not Acceptable
407: Proxy Authentication Required
408: Request Time-out
409: Conflict
410: Gone
411: Length Required
412: Precondition Failed
413: Request Entity Too Large
414: Request-URI Too Large
415: Unsupported Media Type
416: Requested range not satisfiable
417: Expectation Failed
500: Internal Server Error
501: Not Implemented
502: Bad Gateway
503: Service Unavailable
504: Gateway Time-out
505: HTTP Version not supported
Header fields (access/assign methods) :AcceptRanges exported access-assign method/character Get/set the "Accept-Ranges" header field. See RFC-2616, 14.5. :Age exported access-assign method/character Get/set the "Age" header field. This response-header field conveys the sender's estimate of the amount of time in integer seconds since the response was generated at the origin server. See RFC-2616, 14.6. :Allow exported access-assign method/character Get/set the "Allow" header field. This field lists the set of methods supported by the resource identified by the Request-URI. The purpose is to inform the recipient of commands that are supported by the resource. See RFC-2616, 14.7. :ETag Get/set the "ETag" header field. See RFC-2616, 14.19. :Expires exported access-assign method/character Get/set the "Expires" header field. This header field gives the date/time after which the message content is considered stale. See RFC-2616, 14.21. :Location exported access-assign method/character Get/set the "Location" header field. It is used to redirect the client to a location other than the Request-URI for completion of the request. For 201 (Created) responses, the Location is that of the new resource which was created by the request. For 3xx responses, the location should indicate the server's preferred URI for automatic redirection to the resource. The field value consists of a single absolute URI. See RFC-2616, 14.30. :ProxyAuthenticate exported access-assign method/character Get/set the "Proxy-Authenticate" header field. See RFC-2616, 14.33. :RetryAfter exported access-assign method/character Get/set the "RetryAfter" header field. This response-header field can be used with a 503 (Service Unavailable) response to indicate how long the service is expected to be unavailable. It may also be used with any 3xx (Redirection) response to indicate the minimum time the client is asked wait before issuing the redirected request. The value of this field can be either an HTTP-date as returned by xbGMTDate or an integer number of seconds after the time of the response. See RFC-2616, 14.37. :Server exported access-assign method/character Get/set the "Server" header field. This header field contains information about the software used by the origin server to handle the request. See RFC-2616, 14.38. :Vary exported access-assign method/character Get/set the "Vary" header field. See RFC-2616, 14.44. :WWWAuthenticate exported access-assign method/character Get/set the "WWW-Authenticate" header field. See RFC-2616, 14.47.


xbSession()

This class simplifies session management by providing the ability of saving persistent data across multiple HTTP requests. The data managed by a session is stored in memory and will therefore only persist as long as the application is active.

xbSession: Class methods

:New() -> self Creates a new instance of the xbSession class. :KeepAlive(cHandle) -> lSuccess Find the session with the given session handle cHandle and reset its idle time to zero in order to make it look active. The method returns .T. if the session was found and updated, otherwise it returns .F. :Open(cHandle) -> oSession Find the session with the given cHandle session handle and return a reference to it. If a session with this handle does not exist, then a new session is created. :SweepSessions(nMaxIdleTime) -> self Remove sessions (including data stored by those sessions) that have been idle for more than nMaxIdleTime minutes. :ActiveSessions() -> nActiveSessionCount Return a count of the number of currently active sessions.

xbSession: Class properties

:LastSweep exported/numeric The time in seconds after midnight when the last :SweepSessions was performed.

xbSession: Object methods

:Close() -> self Remove this session from the session manager and release all data maintained by it. :GetCargo([cName]) -> xValue | aVarList | NIL, or
:GetVar([cName]) -> xValue | aVarList | NIL
Retrieve a named state variable previously saved with :SetCargo. If a parameter is not supplied or if cName is NIL, then the method will return an array of all name/value pairs saved in the current session object. :SetCargo([xName], [xValue]) -> xPreviousValue | aPreviousVarList, or
:SetVar([xName], [xValue]) -> xPreviousValue | aPreviousVarList
Store the value xValue using a symbolic character name xName until the session is closed. This method is quite flexible and can be used is several ways:

When xName and xValue are both NIL then delete all state variables (session is not closed)
When xValue is NIL, state variable with the name xName is deleted
When xName is an array, replace all name/value pairs with passed array
Otherwise add/replace value
:MinutesIdle() -> nMinutesIdle Returns the number of minutes that this session has been idle. :UpTime() -> {nDays, nHrs, nMin, nSec} Returns a one dimensional array specifying amount of time the session has been open. The following array constants available in Xb2NET.CH provide access to the individual array elements:

UPTIME_DAY - number of days
UPTIME_HRS - number of hours
UPTIME_MIN - number of minutes
UPTIME_SEC - number of seconds


xbSession: Object properties

:Cargo exported/any data type Used to attach additional information to the object as required by the programmer. :Handle exported/character a unique character string representing the session ID. :StartDate readonly/date Date session was created. :StartTime readonly/numeric Time session was created (seconds after midnight).


xbURI()

A Uniform Resource Identifier (URI) is a compact string of characters for identifying an abstract or physical resource. This class provides methods for parsing a URI into its individual components as well as methods for combining these individual components into an encoded string safe for transport. A URI consists of the following components (some of which may not be present is all URI's):

[scheme]://[authority][path]?[query]#[fragment]

xbURI: Class methods

:New([cURIString]) -> self Creates a new instance of the xbURI class and optionally parses a URI string cURIString into it's individual components. If passed the cURIString must be in URL encoded format in order to parse correctly.

xbURI: Object methods

:AsString() -> cEncodedURIString Combine the URI components and encode the result suitable for HTTP transport. :GetVar([cName]) -> xValue | aVarList | NIL Retrieve a URI query parameter. If cName is NIL, then the method will return an array listing all query parameters as name/value pairs. :Parse(cURIString) -> self Parse the URI string cURIString into it's individual components. The specified URI string must be in URL encoded format in order to parse correctly. :Reset() -> self Reinitialize object. :SetVar([xName], [cValue]) -> xPreviousValue | aPreviousVarList Assign the value cValue to the query parameter xName. This method and can be used is several ways:

When xName and cValue are both NIL then delete all query parameters
When cValue is NIL, then remove the query parameter xName
When xName is an array, replace all query parameters with the passed array of name/value pairs
Otherwise add or replace a query parameter value


xbURI: Object properties

:Cargo exported/any data type Used to attach additional information to the object as required by the programmer. :isAbsolute exported/logical Indicates if URI path is absolute (.T.) or relative (.F.). Absolute URI paths include a scheme component. :Scheme exported access-assign method/character This is the name of the scheme being used. Some examples are:
http, ftp, gopher, mailto, news, telnet :Authority exported access-assign method/character The authority component is the top hierarchical element in the URI that is typically defined by a server, eg:
www.sqlexpress.net, atlas.gc.ca, cgi.ebay.ca :Path exported access-assign method/character The path component identifies the target resource within the scope of the Authority (or Scheme if there is no Authority), eg:
/, /english/facts/index.html, /aw-cgi/eBayISAPI.dll :Query exported access-assign method/character The query component is a string of information to be interpreted by the target resource. It is separated from the target resource by a question mark (?) character. The :GetVar and :SetVar methods can be used to get and set individual parameters within the query. The following is an example of a query component:
UID=1836743&ITEM=XE342&QTY=3 :Fragment exported access-assign method/character A URI fragment is used to provide additional retrieval information to the client after the target resource has been successfully loaded. Technically, a fragment is not realy a part of the URI, but is is often used in conjunction with a URI. It is separated from the URI by a crosshatch (#) character, eg:
http://www.sqlexpress.net/download.htm#sqlexpress


xbForm()

A Form is typically used by a client application in conjunction with an HTTP-POST method to send data to the server. It consists of name=value pairs encoded so that the form can be reliably disassembled into it's individual components at the server end.

xbForm: Class methods

:New([cEncodedFormString]) -> self Create a new instance of the xbForm class and optionally parse an encoded form cEncodedFormString in order to retrieve the attached variables and data.

xbForm: Object methods

:AsString() -> cEncodedFormString Encode the form variables and data suitable for safe HTTP transport. :GetVar([cName]) -> xValue | aVarList | NIL Retrieve a form variable. If cName is NIL, then the method will return an array listing all form variables as name/value pairs. :Parse(cEncodedFormString) -> self Parse an encoded form cEncodedFormString, to separate the attached variables which can later be accessed using :GetVar. :Reset() -> self Reinitialize object. :SetVar([xName], [cValue]) -> xPreviousValue | aPreviousVarList Assign the value cValue to the form variable xName. This method and can be used is several ways:

When xName and cValue are both NIL then delete all form variables
When cValue is NIL, then remove the form variable xName
When xName is an array, replace all form variables with the passed array of name/value pairs
Otherwise add or replace the value of an individual form variable xName.


xbForm: Object properties

:Cargo exported/any data type Used to attach additional information to the object as required by the programmer. :MimeType exported/character The MIME encoding type. It is set to: "application/x-www-form-urlencoded"


xbSOAPEnvelope()

SOAP (Simple Object Access Protocol) provides a simple and lightweight mechanism for exchanging structured and typed information between peers in a decentralized, distributed environment using XML. SOAP is an open standard developed by the W3C that can be used in a distributed environment to execute platform and application independent remote procedure calls (RPC).

xbSOAPEnvelope: Class methods

:New([cSOAPEnvelope]) -> self Create a new instance of the xbSOAPEnvelope class and optionally parse the SOAP envelope cSOAPEnvelope in order to retrieve the action and attached parameters.

xbSOAPEnvelope: Object methods

:AsString() -> cSOAPEnvelope Combine the action and parameters into an XML SOAP envelope. :Execute(cHostAddress, [cMethod], [cSOAPAction]) -> oSOAPReply Execute a method on a remote SOAP server. The method returns an xbSOAPEnvelope object that will contain data returned by the remote SOAP server, or a fault if the method failed to execute. Parameters: cHostAddress
The name or IP address of the remote SOAP server, including port and target resource path (if any). If not specified the port defaults to 80. cMethod
The requested action to execute on the server. If not specified cMethod defaults to :Action, in which case :Action must not be blank. cSOAPAction
An optional parameter that will set the SOAPAction header field in the HTTP request. If not specified cSOAPAction defaults to cMethod. Some SOAP servers may require a specific SOAPAction header field to be specified.

Example: oAgent := xbSOAPEnvelope():new()

oAgent:NameSpace := "urn:xmethods-CurrencyExchange"
oAgent:SetVar("Country1", "USA" )
oAgent:SetVar("Country2", "EURO")

// Execute request
oResult := oAgent:Execute("http://services.xmethods.net:80/soap", "getRate")
// Print exchange rate
? oResult:GetVar("Result")
:GetVar([cName]) -> xValue | aVarList | NIL Retrieve a SOAP parameter by name. If cName is NIL, then the method will return an array listing all parameters as name/value pairs. :Parse(cSOAPEnvelope) -> self Parse the SOAP envelope cSOAPEnvelope in order to retrieve the action and attached parameters. Once parsed, the attached parameters can be can be accessed using :GetVar. :Reset() -> self Reinitialize object. :SetFault([cFaultCode],[cFaultString],[cFaultActor],[cDetailCode],[cDetailString]) -> cFaultEnvelope Generate a SOAP fault envelope. Calling this method will clear the action and all parameters. Parameters: cFaultCode
A character string that is intended for use by software to provide an algorithmic mechanism for identifying the fault. The following is the set of faultcodes defined by the "http://schemas.xmlsoap.org/soap/envelope/" namespace: VersionMismatch, MustUnderstand, Client, Server. If not specified, the default is "Server". cFaultString
A string intended to provide a human readable explanation of the fault. It should provide some information explaining the nature of the fault. If not specified, the default is "Server Error". cFaultActor
A URI character string providing information about who caused the fault to happen within the message path. cDetailCode
A character string that can be used used to provide an application specific error code related to the body of the SOAP message. The detailcode is intended for use by software to provide an algorithmic mechanism for identifying the fault. cDetailString
A character string that can be used to provide application specific error information related to the body of the SOAP message. The detailstring is intended to provide a human readable explanation of the fault. :SetVar([xName], [xValue]) -> xPreviousValue | aPreviousVarList Assign the value xValue to the parameter xName. This method and can be used is several ways:

When xName and xValue are both NIL then delete all SOAP parameters
When xValue is NIL, then remove the parameter xName
When xName is an array, replace all SOAP parameters with the passed array of name/value pairs
Otherwise add or replace the value of an individual parameter xName.


xbSOAPEnvelope: Object properties

:Action exported/character The name of the SOAP action or method contained within the Body of the SOAP envelope. All SOAP envelopes must have an action defined. :ActionNode exported/array A reference to the array containing the method or action node within the :XMLArray array. :Cargo exported/any data type Used to attach additional information to the object as required by the programmer. :MimeType exported/character The MIME encoding type. It is set to: "text/xml" :NameSpace exported/character This is the namespace of the SOAP method. Some SOAP servers require a specific namespace to be specified when executing a method. The default is: "http://xb2.net/soap" :XMLArray exported/array A reference to the root element containing an array of the parsed XML SOAP envelope.