@section sec5-1 Section 5.1: Introduction
- This chapter documents the API for the Rx facility. Included are descriptions of all the constants, structures, exported variables, macros, and interface functions available to the application programmer. This interface is identical regardless of whether the application lives within the unix kernel or above it.
- This chapter actually provides more information than what may be strictly considered the Rx API. Many objects that were intended to be opaque and for Rx internal use only are also described here. The reason driving the inclusion of this "extra" information is that such exported Rx interface files as rx.h make these objects visible to application programmers. It is prefereable to describe these objects here than to ignore them and leave application programmers wondering as to their meaning.
- An example application illustrating the use of this interface, showcasing code from both server and client sides, appears in the following chapter.
@section sec5-2 Section 5.2: Constants
- This section covers the basic constant definitions of interest to the Rx application programmer. Each subsection is devoted to describing the constants falling into the following categories:
- Configuration quantities
- Waiting options
- Connection ID operations
- Connection flags
- Connection types
- Call states
- Call flags
- Call modes
- Packet header flags
- Packet sizes
- Packet types
- Packet classes
- Conditions prompting ack packets
- Ack types
- Error codes
- Debugging values
- An attempt has been made to relate these constant definitions to the objects or routines that utilize them.
@subsection sec5-2-1 Section 5.2.1: Configuration Quantities
- These definitions provide some basic Rx configuration parameters, including the number of simultaneous calls that may be handled on a single connection, lightweight thread parameters, and timeouts for various operations.
- Name
- RX IDLE DEAD TIME
- Value
- 60
- Description
- Default idle dead time for connections, in seconds.
- Name
- RX MAX SERVICES
- Value
- 20
- Description
- The maximum number of Rx services that may be installed within one application.
- Name
- RX PROCESS MAXCALLS
- Value
- 4
- Description
- The maximum number of asynchronous calls active simultaneously on any given Rx connection. This value must be set to a power of two.
- Name
- RX DEFAULT STACK SIZE
- Value
- 16,000
- Description
- Default lightweight thread stack size, measured in bytes. This value may be overridden by calling the rx_SetStackSize() macro.
- Name
- RX PROCESS PRIORITY
- Value
- LWP NORMAL PRIORITY
- Description
- This is the priority under which an Rx thread should run. There should not generally be any reason to change this setting.
- Name
- RX CHALLENGE TIMEOUT
- Value
- 2
- Description
- The number of seconds before another authentication request packet is generated.
- Name
- RX MAXACKS
- Value
- 255
- Description
- Maximum number of individual acknowledgements that may be carried in an Rx acknowledgement packet.
@subsection sec5-2-2 Section 5.2.2: Waiting Options
- These definitions provide readable values indicating whether an operation should block when packet buffer resources are not available.
- Name
- RX DONTWAIT
- Value
- 0
- Description
- Wait until the associated operation completes.
- Name
- RX WAIT
- Value
- 1
- Description
- Don't wait if the associated operation would block.
@subsection sec5-2-3 Section 5.2.3: Connection ID Operations
- These values assist in extracting the call channel number from a connection identifier. A call channel is the index of a particular asynchronous call structure within a single Rx connection.
- Name
- RX CIDSHIFT
- Value
- 2
- Description
- Number of bits to right-shift to isolate a connection ID. Must be set to the log (base two) of RX MAXCALLS.
- Name
- RX CHANNELMASK
- Value
- (RX MAXCALLS-1)
- Description
- Mask used to isolate a call channel from a connection ID field.
- Name
- RX CIDMASK
- Value
- (~RX CHANNELMASK)
- Description
- Mask used to isolate the connection ID from its field, masking out the call channel information.
@subsection sec5-2-4 Section 5.2.4: Connection Flags
- The values defined here appear in the flags field of Rx connections, as defined by the rx connection structure described in Section 5.3.2.2.
- Name
- RX CONN MAKECALL WAITING
- Value
- 1
- Description
- rx MakeCall() is waiting for a channel.
- Name
- RX CONN DESTROY ME
- Value
- 2
- Description
- Destroy this (client) connection after its last call completes.
- Name
- RX CONN USING PACKET CKSUM
- Value
- 4
- Description
- This packet is using security-related check-summing (a non-zero header, spare field has been seen.)
@subsection sec5-2-5 Section 5.2.5: Connection Types
- Rx stores different information in its connection structures, depending on whether the given connection represents the server side (the one providing the service) or the client side (the one requesting the service) of the protocol. The type field within the connection structure (described in Section 5.3.2.2) takes on the following values to differentiate the two types of connections, and identifies the fields that are active within the connection structure.
- Name
- RX CLIENT CONNECTION
- Value
- 0
- Description
- This is a client-side connection.
- Name
- CONNECTION
- Value
- 1
- Description
- This is a server-side connection.
@subsection sec5-2-6 Section 5.2.6: Call States
- An Rx call on a particular connection may be in one of several states at any instant in time. The following definitions identify the range of states that a call may assume.
- Name
- RX STATE NOTINIT
- Value
- 0
- Description
- The call structure has never been used, and is thus still completely uninitialized.
- Name
- RX STATE PRECALL
- Value
- 1
- Description
- A call is not yet in progress, but packets have arrived for it anyway. This only applies to calls within server-side connections.
- Name
- RX STATE ACTIVE
- Value
- 2
- Description
- This call is fully active, having an attached lightweight thread operating on its behalf.
- Name
- RX STATE DAILY
- Value
- 3
- Description
- The call structure is "dallying" after its lightweight thread has completed its most recent call. This is a "hot-standby" condition, where the call structure preserves state from the previous call and thus optimizes the arrival of further, related calls.
@subsection sec5-2-7 Section 5.2.7: Call Flags:
- These values are used within the flags field of a variable declared to be of type struct rx call, as described in Section 5.3.2.4. They provide additional information as to the state of the given Rx call, such as the type of event for which it is waiting (if any) and whether or not all incoming packets have been received in support of the call.
- Name
- RX CALL READER WAIT
- Value
- 1
- Description
- Reader is waiting for next packet.
- Name
- RX CALL WAIT WINDOW ALLOC
- Value
- 2
- Description
- Sender is waiting for a window so that it can allocate buffers.
- Name
- RX CALL WAIT WINDOW SEND
- Value
- 4
- Description
- Sender is waiting for a window so that it can send buffers.
- Name
- RX CALL WAIT PACKETS
- Value
- 8
- Description
- Sender is waiting for packet buffers.
- Name
- RX CALL RECEIVE DONE
- Value
- 16
- Description
- The call is waiting for a lightweight thread to be assigned to the operation it has just received.
- Name
- RX CALL RECEIVE DONE
- Value
- 32
- Description
- All packets have been received on this call.
- Name
- RX CALL CLEARED
- Value
- 64
- Description
- The receive queue has been cleared when in precall state.
@subsection sec5-2-8 Section 5.2.8: Call Modes
- These values define the modes of an Rx call when it is in the RX STATE ACTIVE state, having a lightweight thread assigned to it.
- Name
- RX MODE SENDING
- Value
- 1
- Description
- We are sending or ready to send.
- Name
- RX MODE RECEIVING
- Value
- 2
- Description
- We are receiving or ready to receive.
- Name
- RX MODE ERROR
- Value
- 3
- Description
- Something went wrong in the current conversation.
- Name
- RX MODE EOF
- Value
- 4
- Description
- The server side has flushed (or the client side has read) the last reply packet.
@subsection sec5-2-9 Section 5.2.9: Packet Header Flags
- Rx packets carry a flag field in their headers, providing additional information regarding the packet's contents. The Rx packet header's flag field's bits may take the following values:
- Name
- RX CLIENT INITIATED
- Value
- 1
- Description
- Signifies that a packet has been sent/received from the client side of the call.
- Name
- RX REQUEST ACK
- Value
- 2
- Description
- The Rx calls' peer entity requests an acknowledgement.
- Name
- RX LAST PACKET
- Value
- 4
- Description
- This is the final packet from this side of the call.
- Name
- RX MORE PACKETS
- Value
- 8
- Description
- There are more packets following this, i.e., the next sequence number seen by the receiver should be greater than this one, rather than a retransmission of an earlier sequence number.
- Name
- RX PRESET FLAGS
- Value
- (RX CLIENT INITIATED | RX LAST PACKET)
- Description
- This flag is preset once per Rx packet. It doesn't change on retransmission of the packet.
@subsection sec5-3-10 Section 5.2.10: Packet Sizes
- These values provide sizing information on the various regions within Rx packets. These packet sections include the IP/UDP headers and bodies as well Rx header and bodies. Also covered are such values as different maximum packet sizes depending on whether they are targeted to peers on the same local network or a more far-flung network. Note that the MTU term appearing below is an abbreviation for Maximum Transmission Unit.
- Name
- RX IPUDP SIZE
- Value
- 28
- Description
- The number of bytes taken up by IP/UDP headers.
- Name
- RX MAX PACKET SIZE
- Value
- (1500 - RX IPUDP SIZE)
- Description
- This is the Ethernet MTU minus IP and UDP header sizes.
- Name
- RX HEADER SIZE
- Value
- sizeof (struct rx header)
- Description
- The number of bytes in an Rx packet header.
- Name
- RX MAX PACKET DATA SIZE
- Value
- (RX MAX PACKET SIZE RX - HEADER SIZE)
- Description
- Maximum size in bytes of the user data in a packet.
- Name
- RX LOCAL PACKET SIZE
- Value
- RX MAX PACKET SIZE
- Description
- Packet size in bytes to use when being sent to a host on the same net.
- Name
- RX REMOTE PACKET SIZE
- Value
- (576 - RX IPUDP SIZE)
- Description
- Packet size in bytes to use when being sent to a host on a different net.
@subsection sec5-2-11 Section 5.2.11: Packet Types
- The following values are used in the packetType field within a struct rx packet, and define the different roles assumed by Rx packets. These roles include user data packets, different flavors of acknowledgements, busies, aborts, authentication challenges and responses, and debugging vehicles.
- Name
- RX PACKET TYPE DATA
- Value
- 1
- Description
- A user data packet.
- Name
- RX PACKET TYPE ACK
- Value
- 2
- Description
- Acknowledgement packet.
- Name
- RX PACKET TYPE BUSY
- Value
- 3
- Description
- Busy packet. The server-side entity cannot accept the call at the moment, but the requestor is encouraged to try again later.
- Name
- RX PACKET TYPE ABORT
- Value
- 4
- Description
- Abort packet. No response is needed for this packet type.
- Name
- RX PACKET TYPE ACKALL
- Value
- 5
- Description
- Acknowledges receipt of all packets on a call.
- Name
- RX PACKET TYPE CHALLENGE
- Value
- 6
- Description
- Challenge the client's identity, requesting credentials.
- Name
- RX PACKET TYPE RESPONSE
- Value
- 7
- Description
- Response to a RX PACKET TYPE CHALLENGE authentication challenge packet.
- Name
- RX PACKET TYPE DEBUG
- Value
- 8
- Description
- Request for debugging information.
- Name
- RX N PACKET TYPES
- Value
- 9
- Description
- The number of Rx packet types defined above. Note that it also includes packet type 0 (which is unused) in the count.
- The RX PACKET TYPES definition provides a mapping of the above values to human-readable string names, and is exported by the rx packetTypes variable catalogued in Section 5.4.9.
{
"data",
"ack",
"busy",
"abort",
"ackall",
"challenge",
"response",
"debug"
}
@subsection sec5-2-12 Section 5.2.12: Packet Classes
- These definitions are used internally to manage alloction of Rx packet buffers according to quota classifications. Each packet belongs to one of the following classes, and its buffer is derived from the corresponding pool.
- Name
- RX PACKET CLASS RECEIVE
- Value
- 0
- Description
- Receive packet for user data.
- Name
- RX PACKET CLASS SEND
- Value
- 1
- Description
- Send packet for user data.
- Name
- RX PACKET CLASS SPECIAL
- Value
- 2
- Description
- A special packet that does not hold user data, such as an acknowledgement or authentication challenge.
- Name
- RX N PACKET CLASSES
- Value
- 3
- Description
- The number of Rx packet classes defined above.
@subsection sec5-2-13 Section 5.2.13: Conditions Prompting Ack Packets
- Rx acknowledgement packets are constructed and sent by the protocol according to the following reasons. These values appear in the Rx packet header of the ack packet itself.
- Name
- RX ACK REQUESTED
- Value
- 1
- Description
- The peer has explicitly requested an ack on this packet.
- Name
- RX ACK DUPLICATE
- Value
- 2
- Description
- A duplicate packet has been received.
- Name
- RX ACK OUT OF SEQUENCE
- Value
- 3
- Description
- A packet has arrived out of sequence.
- Name
- RX ACK EXCEEDS WINDOW
- Value
- 4
- Description
- A packet sequence number higher than maximum value allowed by the call's window has been received.
- Name
- RX ACK NOSPACE
- Value
- 5
- Description
- No packet buffer space is available.
- Name
- RX ACK PING
- Value
- 6
- Description
- Acknowledgement for keep-alive purposes.
- Name
- RX ACK PING RESPONSE
- Value
- 7
- Description
- Response to a RX ACK PING packet.
- Name
- RX ACK DELAY
- Value
- 8
- Description
- An ack generated due to a period of inactivity after normal packet receptions.
@subsection -2-14 Section 5.2.14: Acknowledgement Types
- These are the set of values placed into the acks array in an Rx acknowledgement packet, whose data format is defined by struct rx ackPacket. These definitions are used to convey positive or negative acknowledgements for a given range of packets.
- Name
- RX ACK TYPE NACK
- Value
- 0
- Description
- Receiver doesn't currently have the associated packet; it may never hae been received, or received and then later dropped before processing.
- Name
- RX ACK TYPE ACK
- Value
- 1
- Description
- Receiver has the associated packet queued, although it may later decide to discard it.
@subsection sec5-2-15 Section 5.2.15: Error Codes
- Rx employs error codes ranging from -1 to -64. The Rxgen stub generator may use other error codes less than -64. User programs calling on Rx, on the other hand, are expected to return positive error codes. A return value of zero is interpreted as an indication that the given operation completed successfully.
- Name
- RX CALL DEAD
- Value
- -1
- Description
- A connection has been inactive past Rx's tolerance levels and has been shut down.
- Name
- RX INVALID OPERATION
- Value
- -2
- Description
- An invalid operation has been attempted, including such protocol errors as having a client-side call send data after having received the beginning of a reply from its server-side peer.
- Name
- RX CALL TIMEOUT
- Value
- -3
- Description
- The (optional) timeout value placed on this call has been exceeded (see Sections 5.5.3.4 and 5.6.5).
- Name
- RX EOF
- Value
- -4
- Description
- Unexpected end of data on a read operation.
- Name
- RX PROTOCOL ERROR
- Value
- -5
- Description
- An unspecified low-level Rx protocol error has occurred.
- Name
- RX USER ABORT
- Value
- -6
- Description
- A generic user abort code, used when no more specific error code needs to be communicated. For example, Rx clients employing the multicast feature (see Section 1.2.8) take advantage of this error code.
@subsection sec5-2-16 Section 5.2.16: Debugging Values
- Rx provides a set of data collections that convey information about its internal status and performance. The following values have been defined in support of this debugging and statistics-collection feature.
@subsubsection sec5-3-16-1 Section 5.2.16.1: Version Information
- Various versions of the Rx debugging/statistics interface are in existance, each defining different data collections and handling certain bugs. Each Rx facility is stamped with a version number of its debugging/statistics interface, allowing its clients to tailor their requests to the precise data collections that are supported by a particular Rx entity, and to properly interpret the data formats received through this interface. All existing Rx implementations should be at revision M.
- Name
- RX DEBUGI VERSION MINIMUM
- Value
- 'L'
- Description
- The earliest version of Rx statistics available.
- Name
- RX DEBUGI VERSION
- Value
- 'M'
- Description
- The latest version of Rx statistics available.
- Name
- RX DEBUGI VERSION W SECSTATS
- Value
- 'L'
- Description
- Identifies the earliest version in which statistics concerning Rx security objects is available.
- Name
- RX DEBUGI VERSION W GETALLCONN
- Value
- 'M'
- Description
- The first version that supports getting information about all current Rx connections, as specified y the RX DEBUGI GETALLCONN debugging request packet opcode described below.
- Name
- RX DEBUGI VERSION W RXSTATS
- Value
- 'M'
- Description
- The first version that supports getting all the Rx statistics in one operation, as specified by the RX DEBUGI RXSTATS debugging request packet opcode described below.
- Name
- RX DEBUGI VERSION W UNALIGNED CONN
- Value
- 'L'
- Description
- There was an alignment problem discovered when returning Rx connection information in older versions of this debugging/statistics interface. This identifies the last version that exhibited this alignment problem.
@subsubsection sec5-2-16-2 Section 5.2.16.2: Opcodes
- When requesting debugging/statistics information, the caller specifies one of the following supported data collections:
- Name
- RX DEBUGI GETSTATS
- Value
- 1
- Description
- Get basic Rx statistics.
- Name
- RX DEBUGI GETCONN
- Value
- 2
- Description
- Get information on all Rx connections considered "interesting" (as defined below), and no others.
- Name
- RX DEBUGI GETALLCONN
- Value
- 3
- Description
- Get information on all existing Rx connection structures, even "uninteresting" ones.
- Name
- RX DEBUGI RXSTATS
- Value
- 4
- Description
- Get all available Rx stats.
- An Rx connection is considered "interesting" if it is waiting for a call channel to free up or if it has been marked for destruction. If neither is true, a connection is still considered interesting if any of its call channels is actively handling a call or in its preparatory pre-call state. Failing all the above conditions, a connection is still tagged as interesting if any of its call channels is in either of the RX MODE SENDING or RX MODE RECEIVING modes, which are not allowed when the call is not active.
@subsubsection sec5-2-16-3 Section 5.2.16.3: Queuing
- These two queueing-related values indicate whether packets are present on the incoming and outgoing packet queues for a given Rx call. These values are only used in support of debugging and statistics-gathering operations.
- Name
- RX OTHER IN
- Value
- 1
- Description
- Packets available in in queue.
- Name
- RX OTHER OUT
- Value
- 2
- Description
- Packets available in out queue.
@section sec5-3 Section 5.3: Structures
- This section describes the major exported Rx data structures of interest to application programmers. The following categories are utilized for the purpose of organizing the structure descriptions:
- Security objects
- Protocol objects
- Packet formats
- Debugging and statistics
- Miscellaneous
- Please note that many fields described in this section are declared to be VOID. This is defined to be char, and is used to get around some compiler limitations.
- As explained in Section 1.2.1, Rx provides a modular, extensible security model. This allows Rx applications to either use one of the built-in security/authentication protocol packages or write and plug in one of their own. This section examines the various structural components used by Rx to support generic security and authentication modules.
@subsubsection sec5-3-1-1 Section 5.3.1.1: struct rx securityOps
- As previously described, each Rx security object must export a fixed set of interface functions, providing the full set of operations defined on the object. The rx securityOps structure defines the array of functions comprising this interface. The Rx facility calls these routines at the appropriate times, without knowing the specifics of how any particular security object implements the operation.
- A complete description of these interface functions, including information regarding their exact purpose, parameters, and calling conventions, may be found in Section 5.5.7.
- fields
- Variables of type struct rx securityClass are used to represent instantiations of a particular security model employed by Rx. It consists of a pointer to the set of interface operations implementing the given security object, along with a pointer to private storage as necessary to support its operations. These security objects are also reference-counted, tracking the number of Rx connections in existance that use the given security object. If the reference count drops to zero, the security module may garbage-collect the space taken by the unused security object.
- fields
- This structure is used to report characteristics for an instantiation of a security object on a particular Rx connection, as well as performance figures for that object. It is used by the debugging portions of the Rx package. Every security object defines and manages fields such as level and flags differently.
- fields
- The structures describing the main abstractions and entities provided by Rx, namely services, peers, connections and calls are covered in this section.
@subsubsection sec5-3-2-1 Section 5.3.2.1: struct rx service
- An Rx-based server exports services, or specific RPC interfaces that accomplish certain tasks. Services are identified by (host-address, UDP-port, serviceID) triples. An Rx service is installed and initialized on a given host through the use of the rx NewService() routine (See Section 5.6.3). Incoming calls are stamped with the Rx service type, and must match an installed service to be accepted. Internally, Rx services also carry string names for purposes of identification. These strings are useful to remote debugging and statistics-gathering programs. The use of a service ID allows a single server process to export multiple, independently-specified Rx RPC services.
- Each Rx service contains one or more security classes, as implemented by individual security objects. These security objects implement end-to-end security protocols. Individual peer-to-peer connections established on behalf of an Rx service will select exactly one of the supported security objects to define the authentication procedures followed by all calls associated with the connection. Applications are not limited to using only the core set of built-in security objects offered by Rx. They are free to define their own security objects in order to execute the specific protocols they require.
- It is possible to specify both the minimum and maximum number of lightweight processes available to handle simultaneous calls directed to an Rx service. In addition, certain procedures may be registered with the service and called at set times in the course of handling an RPC request.
- fields
- An Rx connection represents an authenticated communication path, allowing multiple asynchronous conversations (calls). Each connection is identified by a connection ID. The low-order bits of the connection ID are reserved so they may be stamped with the index of a particular call channel. With up to RX MAXCALLS concurrent calls (set to 4 in this implementation), the bottom two bits are set aside for this purpose. The connection ID is not sufficient by itself to uniquely identify an Rx connection. Should a client crash and restart, it may reuse a connection ID, causing inconsistent results. In addition to the connection ID, the epoch, or start time for the client side of the connection, is used to identify a connection. Should the above scenario occur, a different epoch value will be chosen by the client, differentiating this incarnation from the orphaned connection record on the server side.
- Each connection is associated with a parent service, which defines a set of supported security models. At creation time, an Rx connection selects the particular security protocol it will implement, referencing the associated service. The connection structure maintains state about the individual calls being simultaneously handled.
- fields
- For each connection, Rx maintains information describing the entity, or peer, on the other side of the wire. A peer is identified by a (host, UDP-port) pair. Included in the information kept on this remote communication endpoint are such network parameters as the maximum packet size supported by the host, current readings on round trip time to retransmission delays, and packet skew (see Section 1.2.7). There are also congestion control fields, ranging from descriptions of the maximum number of packets that may be sent to the peer without pausing and retransmission statistics. Peer structures are shared between connections whenever possible, and hence are reference-counted. A peer object may be garbage-collected if it is not actively referenced by any connection structure and a sufficient period of time has lapsed since the reference count dropped to zero.
- fields
- This structure records the state of an active call proceeding on a given Rx connection. As described above, each connection may have up to RX MAXCALLS calls active at any one instant, and thus each connection maintains an array of RX MAXCALLS rx call structures. The information contained here is specific to the given call; "permanent" call state, such as the call number, is maintained in the connection structure itself.
- fields
- The following sections cover the different data formats employed by the suite of Rx packet types, as enumerated in Section 5.2.11. A description of the most commonly-employed Rx packet header appears first, immediately followed by a description of the generic packet container and descriptor. The formats for Rx acknowledgement packets and debugging/statistics packets are also examined.
@subsubsection sec5-3-3-1 Section 5.3.3.1: struct rx header
- Every Rx packet has its own header region, physically located after the leading IP/UDP headers. This header contains connection, call, security, and sequencing information. Along with a type identifier, these fields allow the receiver to properly interpret the packet. In addition, every client relates its "epoch", or Rx incarnation date, in each packet. This assists in identifying protocol problems arising from reuse of connection identifiers due to a client restart. Also included in the header is a byte of user-defined status information, allowing out-of-band channel of communication for the higher-level application using Rx as a transport mechanism.
- fields
- This structure is used to describe an Rx packet, and includes the wire version of the packet contents, where all fields exist in network byte order. It also includes acknowledgement, length, type, and queueing information.
- fields
- struct queue queueItemHeader - field used for internal queueing.
- u char acked - If non-zero, this field indicates that this packet has been tentatively (soft-) acknowledged. Thus, the packet has been accepted by the rx peer entity on the other side of the connection, but has not yet necessarily been passed to the true reader. The sender is not free to throw the packet away, as it might still get dropped by the peer before it is delivered to its destination process.
- short length - Length in bytes of the user data section.
- u char packetType - The type of Rx packet described by this record. The set of legal choices is available in Section 5.2.11.
- struct clock retryTime - The time when this packet should be retransmitted next.
- struct clock timeSent - The last time this packet was transmitted.
- struct rx header header - A copy of the internal Rx packet header.
- wire - The text of the packet as it appears on the wire. This structure has the following sub-fields:
- u long head[RX HEADER SIZE/sizeof(long)] The wire-level contents of IP, UDP, and Rx headers.
- u long data[RX MAX PACKET DATA SIZE/sizeof(long)] The wire form of the packet's "payload", namely the user data it carries.
- This is the format for the data portion of an Rx acknowledgement packet, used to inform a peer entity performing packet transmissions that a subset of its packets has been properly received.
- fields
- u short bufferSpace - Number of packet buffers available. Specifically, the number of packet buffers that the ack packet's sender is willing to provide for data on this or subsequent calls. This number does not have to fully accurate; it is acceptable for the sender to provide an estimate.
- u short maxSkew - The maximum difference seen between the serial number of the packet being acknowledged and highest packet yet received. This is an indication of the degree to which packets are arriving out of order at the receiver.
- u long firstPacket - The serial number of the first packet in the list of acknowledged packets, as represented by the acks field below.
- u long previousPacket - The previous packet serial number received.
- u long serial - The serial number of the packet prompted the acknowledgement.
- u char reason - The reason given for the acknowledgement; legal values for this field are described in Section 5.2.13.
- u char nAcks - Number of acknowledgements active in the acks array immediately following.
- u char acks[RX MAXACKS] - Up to RX MAXACKS packet acknowledgements. The legal values for each slot in the acks array are described in Section 5.2.14. Basically, these fields indicate either positive or negative acknowledgements.
- All packets with serial numbers prior to firstPacket are implicitly acknowledged by this packet, indicating that they have been fully processed by the receiver. Thus, the sender need no longer be concerned about them, and may release all of the resources that they occupy. Packets with serial numbers firstPacket + nAcks and higher are not acknowledged by this ack packet. Packets with serial numbers in the range [firstPacket, firstPacket + nAcks) are explicitly acknowledged, yet their sender-side resources must not yet be released, as there is yet no guarantee that the receiver will not throw them away before they can be processed there.
- There are some details of importance to be noted. For one, receiving a positive acknowlegement via the acks array does not imply that the associated packet is immune from being dropped before it is read and processed by the receiving entity. It does, however, imply that the sender should stop retransmitting the packet until further notice. Also, arrival of an ack packet should prompt the transmitter to immediately retransmit all packets it holds that have not been explicitly acknowledged and that were last transmitted with a serial number less than the highest serial number acknowledged by the acks array. Note: The fields in this structure are always kept in wire format, namely in network byte order.
@subsection sec5-3-4 Section 5.3.4: Debugging and Statistics
- The following structures are defined in support of the debugging and statistics-gathering interfaces provided by Rx.
@subsubsection sec5-3-4-1 Section 5.3.4.1: struct rx stats
- This structure maintains Rx statistics, and is gathered by such tools as the rxdebug program. It must be possible for all of the fields placed in this structure to be successfully converted from their on-wire network byte orderings to the host-specific ordering.
- fields
- This structure defines the data format for a packet requesting one of the statistics collections maintained by Rx.
- fields
- This structure describes the data format for a reply to an RX DEBUGI GETSTATS debugging request packet. These fields are given values indicating the current state of the Rx facility.
- fields
- This structure defines the data format returned when a caller requests information concerning an Rx connection. Thus, rx debugConn defines the external packaging of interest to external parties. Most of these fields are set from the rx connection structure, as defined in Section 5.3.2.2, and others are obtained by indirecting through such objects as the connection's peer and call structures.
- fields
- This structure is identical to rx debugConn defined above, except for the fact that it is missing the sparec field. This sparec field is used in rx debugConn to fix an alignment problem that was discovered in version L of the debugging/statistics interface (hence the trailing "tt vL tag in the structure name). This alignment problem is fixed in version M, which utilizes and exports the rx debugConn structure exclusively. Information regarding the range of version-numbering values for the Rx debugging/statistics interface may be found in Section 5.2.16.1.
Section 5.4: Exported Variables
- This section describes the set of variables that the Rx facility exports to its applications. Some of these variables have macros defined for the sole purpose of providing the caller with a convenient way to manipulate them. Note that some of these exported variables are never meant to be altered by application code (e.g., rx nPackets).
@subsection sec5-4-1 Section 5.4.1: rx connDeadTime
- This integer-valued variable determines the maximum number of seconds that a connection may remain completely inactive, without receiving packets of any kind, before it is eligible for garbage collection. Its initial value is 12 seconds. The rx SetRxDeadTime macro sets the value of this variable.
@subsection sec5-4-2 Section 5.4.2: rx idleConnectionTime
- This integer-valued variable determines the maximum number of seconds that a server connection may "idle" (i.e., not have any active calls and otherwise not have sent a packet) before becoming eligible for garbage collection. Its initial value is 60 seconds.
@subsection sec5-4-3 Section 5.4.3: rx idlePeerTime
- This integer-valued variable determines the maximum number of seconds that an Rx peer structure is allowed to exist without any connection structures referencing it before becoming eligible for garbage collection. Its initial value is 60 seconds.
@subsection sec5-4-4 Section 5.4.4: rx extraQuota
- This integer-valued variable is part of the Rx packet quota system (see Section 1.2.6), which is used to avoid system deadlock. This ensures that each server-side thread has a minimum number of packets at its disposal, allowing it to continue making progress on active calls. This particular variable records how many extra data packets a user has requested be allocated. Its initial value is 0.
@subsection sec5-4-5 Section 5.4.5: rx extraPackets
- This integer-valued variable records how many additional packet buffers are to be created for each Rx server thread. The caller, upon setting this variable, is applying some application-specific knowledge of the level of network activity expected. The rx extraPackets variable is used to compute the overall number of packet buffers to reserve per server thread, namely rx nPackets, described below. The initial value is 32 packets.
@subsection sec5-4-6 Section 5.4.6: rx nPackets
- This integer-valued variable records the total number of packet buffers to be allocated per Rx server thread. It takes into account the quota packet buffers and the extra buffers requested by the caller, if any.
- Note
- This variable should never be set directly; the Rx facility itself computes its value. Setting it incorrectly may result in the service becoming deadlocked due to insufficient resources. Callers wishing to allocate more packet buffers to their server threads should indicate that desire by setting the rx extraPackets variable described above.
@subsection sec5-4-7 Section 5.4.7: rx nFreePackets
- This integer-valued variable records the number of Rx packet buffers not currently used by any call. These unused buffers are collected into a free pool.
@subsection sec5-4-8 Section 5.4.8: rx stackSize
- This integer-valued variable records the size in bytes for the lightweight process stack. The variable is initially set to RX DEFAULT STACK SIZE, and is typically manipulated via the rx SetStackSize() macro.
@subsection sec5-4-9 Section 5.4.9: rx packetTypes
- This variable holds an array of string names used to describe the different roles for Rx packets. Its value is derived from the RX PACKET TYPES definition found in Section 5.2.11.
@subsection sec5-4-10 Section 5.4.10: rx stats
- This variable contains the statistics structure that keeps track of Rx statistics. The struct rx stats structure it provides is defined in Section 5.3.4.1.
@section sec5-5 Section 5.5: Macros
- Rx uses many macro definitions in preference to calling C functions directly. There are two main reasons for doing this:
- field selection: Many Rx operations are easily realized by returning the value of a particular structure's field. It is wasteful to invoke a C routine to simply fetch a structure's field, incurring unnecessary function call overhead. Yet, a convenient, procedure-oriented operation is still provided to Rx clients for such operations by the use of macros. For example, the rx ConnectionOf() macro, described in Section 5.5.1.1, simply indirects through the Rx call structure pointer parameter to deliver the conn field.
- Performance optimization: In some cases, a simple test or operation can be performed to accomplish a particular task. When this simple, straightforward operation fails, then a true C routine may be called to handle to more complex (and rarer) situation. The Rx macro rx Write(), described in Section 5.5.6.2, is a perfect example of this type of optimization. Invoking rx Write() first checks to determine whether or not the outgoing call's internal buffer has enough room to accept the specified data bytes. If so, it copies them into the call's buffer, updating counts and pointers as appropriate. Otherwise, rx Write() calls the rx WriteProc() to do the work, which in this more complicated case involves packet manipulations, dispatches, and allocations. The result is that the common, simple cases are often handled in-line, with more complex (and rarer) cases handled through true function invocations.
- The set of Rx macros is described according to the following categories.
- These macros facilitate the fetching and setting of fields from the structures described Chapter 5.3.
@subsubsection sec5-5-1-1 Section 5.5.1.1: rx ConnectionOf()
- #define rx_ConnectionOf(call) ((call)->conn)
- Generate a reference to the connection field within the given Rx call structure. The value supplied as the call argument must resolve into an object of type (struct rx call *). An application of the rx ConnectionOf() macro itself yields an object of type rx peer.
@subsubsection sec5-5-1-2 Section 5.5.1.2: rx PeerOf()
- #define rx_PeerOf(conn) ((conn)->peer)
- Generate a reference to the peer field within the given Rx call structure. The value supplied as the conn argument must resolve into an object of type (struct rx connection *). An instance of the rx PeerOf() macro itself resolves into an object of type rx peer.
@subsubsection sec5-5-1-3 Section 5.5.1.3: rx HostOf()
- #define rx_HostOf(peer) ((peer)->host)
- Generate a reference to the host field within the given Rx peer structure. The value supplied as the peer argument must resolve into an object of type (struct rx peer *). An instance of the rx HostOf() macro itself resolves into an object of type u long.
@subsubsection sec5-5-1-4 Section 5.5.1.4: rx PortOf()
- #define rx_PortOf(peer) ((peer)->port)
- Generate a reference to the port field within the given Rx peer structure. The value supplied as the peer argument must resolve into an object of type (struct rx peer *). An instance of the rx PortOf() macro itself resolves into an object of type u short.
@subsubsection sec5-5-1-5 Section 5.5.1.5: rx GetLocalStatus()
- #define rx_GetLocalStatus(call, status) ((call)->localStatus)
- Generate a reference to the localStatus field, which specifies the local user status sent out of band, within the given Rx call structure. The value supplied as the call argument must resolve into an object of type (struct rx call *). The second argument, status, is not used. An instance of the rx GetLocalStatus() macro itself resolves into an object of type u char.
@subsubsection sec5-5-1-6 Section 5.5.1.6: rx SetLocalStatus()
- #define rx_SetLocalStatus(call, status) ((call)->localStatus = (status))
- Assign the contents of the localStatus field, which specifies the local user status sent out of band, within the given Rx call structure. The value supplied as the call argument must resolve into an object of type (struct rx call *). The second argument, status, provides the new value of the localStatus field, and must resolve into an object of type u char. An instance of the rx GetLocalStatus() macro itself resolves into an object resulting from the assignment, namely the u char status parameter.
@subsubsection sec5-5-1-7 Section 5.5.1.7: rx GetRemoteStatus()
- #define rx_GetRemoteStatus(call) ((call)->remoteStatus)
- Generate a reference to the remoteStatus field, which specifies the remote user status received out of band, within the given Rx call structure. The value supplied as the call argument must resolve into an object of type (struct rx call *). An instance of the rx GetRemoteStatus() macro itself resolves into an object of type u char.
@subsubsection sec5-5-1-8 Section 5.5.1.8: rx Error()
- #define rx_Error(call) ((call)->error)
- Generate a reference to the error field, which specifies the current error condition, within the given Rx call structure. The value supplied as the call argument must resolve into an object of type (struct rx call *). An instance of the rx Error() macro itself resolves into an object of type long.
@subsubsection sec5-5-1-9 Section 5.5.1.9: rx DataOf()
- #define rx_DataOf(packet) ((char *) (packet)->wire.data)
- Generate a reference to the beginning of the data portion within the given Rx packet as it appears on the wire. Any encryption headers will be resident at this address. For Rx packets of type RX PACKET TYPE DATA, the actual user data will appear at the address returned by the rx DataOf macro plus the connection's security header size. The value supplied as the packet argument must resolve into an object of type (struct rx packet *). An instance of the rx DataOf() macro itself resolves into an object of type (u long *).
@subsubsection sec5-5-1-10 Section 5.5.1.10: rx GetDataSize()
- #define rx_GetDataSize(packet) ((packet)->length)
- Generate a reference to the length field, which specifies the number of bytes of user data contained within the wire form of the packet, within the given Rx packet description structure. The value supplied as the packet argument must resolve into an object of type (struct rx packet *). An instance of the rx GetDataSize() macro itself resolves into an object of type short.
@subsubsection sec5-5-1-11 Section 5.5.1.11: rx SetDataSize()
- #define rx_SetDataSize(packet, size) ((packet)->length = (size))
- Assign the contents of the length field, which specifies the number of bytes of user data contained within the wire form of the packet, within the given Rx packet description structure. The value supplied as the packet argument must resolve into an object of type (struct rx packet *). The second argument, size, provides the new value of the length field, and must resolve into an object of type short. An instance of the rx SetDataSize() macro itself resolves into an object resulting from the assignment, namely the short length parameter.
@subsubsection sec5-5-1-12 Section 5.5.1.12: rx GetPacketCksum()
- #define rx_GetPacketCksum(packet) ((packet)->header.spare)
- Generate a reference to the header checksum field, as used by the built-in rxkad security module (See Chapter 3), within the given Rx packet description structure. The value supplied as the packet argument must resolve into an object of type (struct rx packet *). An instance of the rx GetPacketCksum() macro itself resolves into an object of type u short.
@subsubsection sec5-5-1-13 Section 5.5.1.13: rx SetPacketCksum()
- #define rx_SetPacketCksum(packet, cksum) ((packet)->header.spare = (cksum))
- Assign the contents of the header checksum field, as used by the built-in rxkad security module (See Chapter 3), within the given Rx packet description structure. The value supplied as the packet argument must resolve into an object of type (struct rx packet *). The second argument, cksum, provides the new value of the checksum, and must resolve into an object of type u short. An instance of the rx SetPacketCksum() macro itself resolves into an object resulting from the assignment, namely the u short checksum parameter.
@subsubsection sec5-5-1-14 Section 5.5.1.14: rx GetRock()
- #define rx_GetRock(obj, type) ((type)(obj)->rock)
- Generate a reference to the field named rock within the object identified by the obj pointer. One common Rx structure to which this macro may be applied is struct rx connection. The specified rock field is casted to the value of the type parameter, which is the overall value of the rx GetRock() macro.
@subsubsection sec5-5-1-15 Section 5.5.1.15: rx SetRock()
- #define rx_SetRock(obj, newrock) ((obj)->rock = (VOID *)(newrock))
- Assign the contents of the newrock parameter into the rock field of the object pointed to by obj. The given object's rock field must be of type (VOID *). An instance of the rx SetRock() macro itself resolves into an object resulting from the assignment and is of type (VOID *).
@subsubsection sec5-5-1-16 Section 5.5.1.16: rx SecurityClassOf()
- #define rx_SecurityClassOf(conn) ((conn)->securityIndex)
- Generate a reference to the security index field of the given Rx connection description structure. This identifies the security class used by the connection. The value supplied as the conn argument must resolve into an object of type (struct rx connection *). An instance of the rx SecurityClassOf() macro itself resolves into an object of type u char.
@subsubsection sec5-5-1-17 Section 5.5.1.17: rx SecurityObjectOf()
- #define rx_SecurityObjectOf(conn) ((conn)->securityObject)
- Generate a reference to the security object in use by the given Rx connection description structure. The choice of security object determines the authentication protocol enforced by the connection. The value supplied as the conn argument must resolve into an object of type (struct rx connection *). An instance of the rx SecurityObjectOf() macro itself resolves into an object of type (struct rx securityClass *).
@subsection sec5-5-2 Section 5.5.2: Boolean Operations
- The macros described in this section all return Boolean values. They are used to query such things as the whether a connection is a server-side or client-side one and if extra levels of checksumming are being used in Rx packet headers.
@subsubsection sec5-5-2-1 Section 5.5.2.1: rx IsServerConn()
- #define rx_IsServerConn(conn) ((conn)->type == RX_SERVER_CONNECTION)
- Determine whether or not the Rx connection specified by the conn argument is a server-side connection. The value supplied for conn must resolve to an object of type struct rx connection. The result is determined by testing whether or not the connection's type field is set to RX SERVER CONNECTION.
- Note
- Another macro, rx ServerConn(), performs the identical operation.
@subsubsection sec5-5-2-2 Section 5.5.2.2: rx IsClientConn()
- #define rx_IsClientConn(conn) ((conn)->type == RX_CLIENT_CONNECTION)
- Determine whether or not the Rx connection specified by the conn argument is a client-side connection. The value supplied for conn must resolve to an object of type struct rx connection. The result is determined by testing whether or not the connection's type field is set to RX CLIENT CONNECTION.
- Note
- Another macro, rx ClientConn(), performs the identical operation.
@subsubsection sec5-5-2-3 Section 5.5.2.2: rx IsUsingPktCksum()
- #define rx_IsUsingPktCksum(conn) ((conn)->flags & RX_CONN_USING_PACKET_CKSUM)
- Determine whether or not the Rx connection specified by the conn argument is checksum-ming the headers of all packets on its calls. The value supplied for conn must resolve to an object of type struct rx connection. The result is determined by testing whether or not the connection's flags field has the RX CONN USING PACKET CKSUM bit enabled.
@subsection sec5-5-3 Section 5.5.3: Service Attributes
- This section describes user-callable macros that manipulate the attributes of an Rx service. Note that these macros must be called (and hence their operations performed) before the given service is installed via the appropriate invocation of the associated rx StartServer() function.
@subsubsection sec5-5-3-1 Section 5.5.3.1: rx SetStackSize()
- rx_stackSize = (((stackSize) stackSize) > rx_stackSize) ? stackSize : rx_stackSize)
- Inform the Rx facility of the stack size in bytes for a class of threads to be created in support of Rx services. The exported rx stackSize variable tracks the high-water mark for all stack size requests before the call to rx StartServer(). If no calls to rx SetStackSize() are made, then rx stackSize will retain its default setting of RX DEFAULT STACK SIZE.
- In this macro, the first argument is not used. It was originally intended that thread stack sizes would be settable on a per-service basis. However, calls to rx SetStackSize() will ignore the service parameter and set the high-water mark for all Rx threads created after the use of rx SetStackSize(). The second argument, stackSize, specifies determines the new stack size, and should resolve to an object of type int. The value placed in the stackSize parameter will not be recorded in the global rx stackSize variable unless it is greater than the variable's current setting.
- An instance of the rx SetStackSize() macro itself resolves into the result of the assignment, which is an object of type int.
@subsubsection sec5-5-3-2 Section 5.5.3.2: rx SetMinProcs()
- #define rx_SetMinProcs(service, min) ((service)->minProcs = (min))
- Choose min as the minimum number of threads guaranteed to be available for parallel execution of the given Rx service. The service parameter should resolve to an object of type struct rx service. The min parameter should resolve to an object of type short. An instance of the rx SetMinProcs() macro itself resolves into the result of the assignment, which is an object of type short.
@subsubsection sec5-5-3-3 Section 5.5.3.3: rx SetMaxProcs()
- #define rx_SetMaxProcs(service, max) ((service)->maxProcs = (max))
- Limit the maximum number of threads that may be made available to the given Rx service for parallel execution to be max. The service parameter should resolve to an object of type struct rx service. The max parameter should resolve to an object of type short. An instance of the rx SetMaxProcs() macro itself resolves into the result of the assignment, which is an object of type short.
@subsubsection sec5-5-3-4 Section 5.5.3.4: rx SetIdleDeadTime()
- #define rx_SetIdleDeadTime(service, time) ((service)->idleDeadTime = (time))
- Every Rx service has a maximum amount of time it is willing to have its active calls sit idle (i.e., no new data is read or written for a call marked as RX STATE ACTIVE) before unilaterally shutting down the call. The expired call will have its error field set to RX CALL TIMEOUT. The operative assumption in this situation is that the client code is exhibiting a protocol error that prevents progress from being made on this call, and thus the call's resources on the server side should be freed. The default value, as recorded in the service's idleDeadTime field, is set at service creation time to be 60 seconds. The rx SetIdleTime() macro allows a caller to dynamically set this idle call timeout value.
- The service parameter should resolve to an object of type struct rx service. Also, the time parameter should resolve to an object of type short. finally, an instance of the rx SetIdleDeadTime() macro itself resolves into the result of the assignment, which is an object of type short.
@subsubsection sec5-5-3-5 Section 5.5.3.5: rx SetServiceDeadTime()
- #define rx_SetServiceDeadTime(service, seconds) ((service)->secondsUntilDead = (seconds))
- Note
- This macro definition is obsolete and should NOT be used. Including it in application code will generate a compile-time error, since the service structure no longer has such a field defined.
- See the description of the rx SetConnDeadTime() macro below to see how hard timeouts may be set for situations of complete call inactivity.
@subsubsection sec5-5-3-6 Section 5.5.3.6: rx SetRxDeadTime()
- #define rx_SetRxDeadTime(seconds) (rx_connDeadTime = (seconds))
- Inform the Rx facility of the maximum number of seconds of complete inactivity that will be tolerated on an active call. The exported rx connDeadTime variable tracks this value, and is initialized to a value of 12 seconds. The current value of rx connDeadTime will be copied into new Rx service and connection records upon their creation.
- The seconds argument determines the value of rx connDeadTime, and should resolve to an object of type int. An instance of the rx SetRxDeadTime() macro itself resolves into the result of the assignment, which is an object of type int.
@subsubsection sec5-5-3-7 Section 5.5.3.7: rx SetConnDeadTime()
- #define rx_SetConnDeadTime(conn, seconds) (rxi_SetConnDeadTime(conn, seconds))
- Every Rx connection has a maximum amount of time it is willing to have its active calls on a server connection sit without receiving packets of any kind from its peer. After such a quiescent time, during which neither data packets (regardless of whether they are properly sequenced or duplicates) nor keep-alive packets are received, the call's error field is set to RX CALL DEAD and the call is terminated. The operative assumption in this situation is that the client making the call has perished, and thus the call's resources on the server side should be freed. The default value, as recorded in the connection's secondsUntilDead field, is set at connection creation time to be the same as its parent service. The rx SetConnDeadTime() macro allows a caller to dynamically set this timeout value.
- The conn parameter should resolve to an object of type struct rx connection. Also, the seconds parameter should resolve to an object of type int. finally, an instance of the rx SetConnDeadTime() macro itself resolves into the a call to rxi SetConnDeadTime(), whose return value is void.
@subsubsection sec5-5-3-8 Section 5.5.3.8: rx SetConnHardDeadTime()
- #define rx_SetConnHardDeadTime(conn, seconds) ((conn)->hardDeadTime = (seconds))
- It is convenient to be able to specify that calls on certain Rx connections have a hard absolute timeout. This guards against protocol errors not caught by other checks in which one or both of the client and server are looping. The rx SetConnHardDeadTime() macro is available for this purpose. It will limit calls on the connection identified by the conn parameter to execution times of no more than the given number of seconds. By default, active calls on an Rx connection may proceed for an unbounded time, as long as they are not totally quiescent (see Section 5.5.3.7 for a description of the rx SetConnDeadTime()) or idle (see Section 5.5.3.4 for a description of the rx SetIdleDeadTime()).
- The conn parameter should resolve to an object of type (struct rx connection *). The seconds parameter should resolve to an object of type u short. An instance of the rx SetConnHardDeadTime() macro itself resolves into the result of the assignment, which is an object of type u short.
@subsubsection sec5-5-3-9 Section 5.5.3.9: rx GetBeforeProc()
- #define rx_GetBeforeProc(service) ((service)->beforeProc)
- Return a pointer of type (VOID *)() to the procedure associated with the given Rx service that will be called immediately upon activation of a server thread to handle an incoming call. The service parameter should resolve to an object of type struct rx service.
- When an Rx service is first created (via a call to the rx NewService() function), its beforeProc field is set to a null pointer. See the description of the rx SetBeforeProc() below.
@subsubsection sec5-5-3-10 Section 5.5.3.10: rx SetBeforeProc()
- #define rx_SetBeforeProc(service, proc) ((service)->beforeProc = (proc))
- Instruct the Rx facility to call the procedure identified by the proc parameter immediately upon activation of a server thread to handle an incoming call. The specified procedure will be called with a single parameter, a pointer of type struct rx call, identifying the call this thread will now be responsible for handling. The value returned by the procedure, if any, is discarded.
- The service parameter should resolve to an object of type struct rx service. The proc parameter should resolve to an object of type (VOID *)(). An instance of the rx SetBeforeProc() macro itself resolves into the result of the assignment, which is an object of type (VOID *)().
@subsubsection sec5-5-3-11 Section 5.5.3.11: rx GetAfterProc()
- #define rx_GetAfterProc(service) ((service)->afterProc)
- Return a pointer of type (VOID *)() to the procedure associated with the given Rx service that will be called immediately upon completion of the particular Rx call for which a server thread was activated. The service parameter should resolve to an object of type struct rx service.
- When an Rx service is first created (via a call to the rx NewService() function), its afterProc field is set to a null pointer. See the description of the rx SetAfterProc() below.
@subsubsection sec5-5-3-12 Section 5.5.3.12: rx SetAfterProc()
- #define rx_SetAfterProc(service, proc) ((service)->afterProc = (proc))
- Instruct the Rx facility to call the procedure identified by the proc parameter immediately upon completion of the particular Rx call for which a server thread was activated. The specified procedure will be called with a single parameter, a pointer of type struct rx call, identifying the call this thread just handled. The value returned by the procedure, if any, is discarded.
- The service parameter should resolve to an object of type struct rx service. The proc parameter should resolve to an object of type (VOID *)(). An instance of the rx SetAfterProc() macro itself resolves into the result of the assignment, which is an object of type (VOID *)().
@subsubsection sec5-5-3-13 Section 5.5.3.13: rx SetNewConnProc()
- #define rx_SetNewConnProc(service, proc) ((service)->newConnProc = (proc))
- Instruct the Rx facility to call the procedure identified by the proc parameter as the last step in the creation of a new Rx server-side connection for the given service. The specified procedure will be called with a single parameter, a pointer of type (struct rx connection *), identifying the connection structure that was just built. The value returned by the procedure, if any, is discarded.
- The service parameter should resolve to an object of type struct rx service. The proc parameter should resolve to an object of type (VOID *)(). An instance of the rx SetNewConnProc() macro itself resolves into the result of the assignment, which is an object of type (VOID *)().
- Note
- There is no access counterpart defined for this macro, namely one that returns the current setting of a service's newConnProc.
@subsubsection sec5-5-3-14 Section 5.5.3.14: rx SetDestroyConnProc()
- #define rx_SetDestroyConnProc(service, proc) ((service)->destroyConnProc = (proc))
- Instruct the Rx facility to call the procedure identified by the proc parameter just before a server connection associated with the given Rx service is destroyed. The specified procedure will be called with a single parameter, a pointer of type (struct rx connection *), identifying the connection about to be destroyed. The value returned by the procedure, if any, is discarded.
- The service parameter should resolve to an object of type struct rx service. The proc parameter should resolve to an object of type (VOID *)(). An instance of the rx SetDestroyConnProc() macro itself resolves into the result of the assignment, which is an object of type (VOID *)().
- Note
- There is no access counterpart defined for this macro, namely one that returns the current setting of a service's destroyConnProc.
@subsection sec5-5-4 Section 5.5.4: Security-Related Operations
- The following macros are callable by Rx security modules, and assist in getting and setting header and trailer lengths, setting actual packet size, and finding the beginning of the security header (or data).
@subsubsection sec5-5-4-1 Section 5.5.4.1: rx GetSecurityHeaderSize()
- #define rx_GetSecurityHeaderSize(conn) ((conn)->securityHeaderSize)
- Generate a reference to the field in an Rx connection structure that records the length in bytes of the associated security module's packet header data.
- The conn parameter should resolve to an object of type struct rx connection. An instance of the rx GetSecurityHeaderSize() macro itself resolves into an object of type u short.
@subsubsection sec5-5-4-2 Section 5.5.4.2: rx SetSecurityHeaderSize()
- #define rx_SetSecurityHeaderSize(conn, length) ((conn)->securityHeaderSize = (length))
- Set the field in a connection structure that records the length in bytes of the associated security module's packet header data.
- The conn parameter should resolve to an object of type struct rx connection. The length parameter should resolve to an object of type u short. An instance of the rx SetSecurityHeaderSize() macro itself resolves into the result of the assignment, which is an object of type u short.
@subsubsection sec5-5-4-3 Section 5.5.4.3: rx
GetSecurityMaxTrailerSize()
- #define rx_GetSecurityMaxTrailerSize(conn) ((conn)->securityMaxTrailerSize)
- Generate a reference to the field in an Rx connection structure that records the maximum length in bytes of the associated security module's packet trailer data.
- The conn parameter should resolve to an object of type struct rx connection. An instance of the rx GetSecurityMaxTrailerSize() macro itself resolves into an object of type u short.
@subsubsection sec5-5-4-4 Section 5.5.4.4: rx
SetSecurityMaxTrailerSize()
- #define rx_SetSecurityMaxTrailerSize(conn, length) ((conn)->securityMaxTrailerSize = (length))
- Set the field in a connection structure that records the maximum length in bytes of the associated security module's packet trailer data.
- The conn parameter should resolve to an object of type struct rx connection. The length parameter should resolve to an object of type u short. An instance of the rx SetSecurityHeaderSize() macro itself resolves into the result of the assignment, which is an object of type u short.
@subsection sec5-5-5 Section 5.5.5: Sizing Operations
- The macros described in this section assist the application programmer in determining the sizes of the various Rx packet regions, as well as their placement within a packet buffer.
@subsubsection sec5-5-5-1 Section 5.5.5.1: rx UserDataOf()
- #define rx_UserDataOf(conn, packet) (((char *) (packet)->wire.data) + (conn)->securityHeaderSize)
- Generate a pointer to the beginning of the actual user data in the given Rx packet, that is associated with the connection described by the conn pointer. User data appears immediately after the packet's security header region, whose length is determined by the security module used by the connection. The conn parameter should resolve to an object of type struct rx connection. The packet parameter should resolve to an object of type struct rx packet. An instance of the rx UserDataOf() macro itself resolves into an object of type (char *).
@subsubsection sec5-5-5-2 Section 5.5.5.2: rx MaxUserDataSize()
- #define rx_MaxUserDataSize(conn)
((conn)->peer->packetSize
-RX_HEADER_SIZE
-(conn)->securityHeaderSize
-(conn)->securityMaxTrailerSize)
- Return the maximum number of user data bytes that may be carried by a packet on the Rx connection described by the conn pointer. The overall packet size is reduced by the IP, UDP, and Rx headers, as well as the header and trailer areas required by the connection's security module.
- The conn parameter should resolve to an object of type struct rx connection. An instance of the rx MaxUserDataSize() macro itself resolves into the an object of type (u short).
@subsection sec5-5-6 Section 5.5.6: Complex Operations
- Two Rx macros are designed to handle potentially complex operations, namely reading data from an active incoming call and writing data to an active outgoing call. Each call structure has an internal buffer that is used to collect and cache data traveling through the call. This buffer is used in conjunction with reading or writing to the actual Rx packets traveling on the wire in support of the call. The rx Read() and rx Write() macros allow their caller to simply manipulate the internal data buffer associated with the Rx call structures whenever possible, thus avoiding the overhead associated with a function call. When buffers are either filled or drained (depending on the direction of the data flow), these macros will then call functions to handle the more complex cases of generating or receiving packets in support of the operation.
@subsubsection sec5-5-6-1 Section 5.5.6.1: rx Read()
- #define rx_Read(call, buf, nbytes)
((call)->nLeft > (nbytes) ?
bcopy((call)->bufPtr, (buf), (nbytes)),
(call)->nLeft -= (nbytes), (call)->bufPtr += (nbytes), (nbytes)
: rx_ReadProc((call), (buf), (nbytes)))
- Read nbytes of data from the given Rx call into the buffer to which buf points. If the call's internal buffer has at least nbytes bytes already filled, then this is done in-line with a copy and some pointer and counter updates within the call structure. If the call's internal buffer doesn't have enough data to satisfy the request, then the rx ReadProc() function will handle this more complex situation.
- In either case, the rx Read() macro returns the number of bytes actually read from the call, resolving to an object of type int. If rx Read() returns fewer than nbytes bytes, the call status should be checked via the rx Error() macro.
@subsubsection sec5-5-6-2 Section 5.5.6.2: rx Write()
- #define rx_Write(call, buf, nbytes)
((call)->nFree > (nbytes) ?
bcopy((buf), (call)->bufPtr, (nbytes)),
(call)->nFree -= (nbytes),
(call)->bufPtr += (nbytes), (nbytes)
: rx_WriteProc((call), (buf), (nbytes)))
- Write nbytes of data from the buffer pointed to by buf into the given Rx call. If the call's internal buffer has at least nbytes bytes free, then this is done in-line with a copy and some pointer and counter updates within the call structure. If the call's internal buffer doesn't have room, then the rx WriteProc() function will handle this more complex situation.
- In either case, the rx Write() macro returns the number of bytes actually written to the call, resolving to an object of type int. If zero is returned, the call status should be checked via the rx Error() macro.
@subsection sec5-5-7 Section 5.5.7: Security Operation Invocations
- Every Rx security module is required to implement an identically-named set of operations, through which the security mechanism it defines is invoked. This characteristic interface is reminiscent of the vnode interface defined and popularized for file systems by Sun Microsystems [4]. The structure defining this function array is described in Section 5.3.1.1.
- These security operations are part of the struct rx securityClass, which keeps not only the ops array itself but also any private data they require and a reference count. Every Rx service contains an array of these security class objects, specifying the range of security mechanisms it is capable of enforcing. Every Rx connection within a service is associated with exactly one of that service's security objects, and every call issued on the connection will execute the given security protocol.
- The macros described below facilitate the execution of the security module interface functions. They are covered in the same order they appear in the struct rx securityOps declaration.
@subsubsection sec5-5-7-1 Section 5.5.7.1: RXS OP()
#if defined(__STDC__) && !defined(__HIGHC__)
#define RXS_OP(obj, op, args)
((obj->ops->op_ ## op) ? (*(obj)->ops->op_ ## op)args : 0)
#else
#define RXS_OP(obj, op, args)
((obj->ops->op_op) ? (*(obj)->ops->op_op)args : 0)
#endif
- The RXS OP macro represents the workhorse macro in this group, used by all the others. It takes three arguments, the first of which is a pointer to the security object to be referenced. This obj parameter must resolve to an object of type (struct rx securityOps *). The second parameter identifies the specific op to be performed on this security object. The actual text of this op argument is used to name the desired opcode function. The third and final argument, args, specifies the text of the argument list to be fed to the chosen security function. Note that this argument must contain the bracketing parentheses for the function call's arguments. In fact, note that each of the security function access macros defined below provides the enclosing parentheses to this third RXS OP() macro.
@subsubsection sec5-5-7-2 Section 5.5.7.1: RXS Close()
- #define RXS_Close(obj) RXS_OP(obj, Close, (obj))
- This macro causes the execution of the interface routine occupying the op Close() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx immediately before a security object is discarded. Among the responsibilities of such a function might be decrementing the object's refCount field, and thus perhaps freeing up any space contained within the security object's private storage region, referenced by the object's privateData field.
- The obj parameter must resolve into an object of type (struct rx securityOps *). In generating a call to the security object's op Close() routine, the obj pointer is used as its single parameter. An invocation of the RXS Close() macro results in a return value identical to that of the op Close() routine, namely a value of type int.
@subsubsection sec5-5-7-3 Section 5.5.7.3: RXS NewConnection()
- #define RXS_NewConnection(obj, conn) RXS_OP(obj, NewConnection, (obj, conn))
- This macro causes the execution of the interface routine in the op NewConnection() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx immediately after a connection using the given security object is created. Among the responsibilities of such a function might be incrementing the object's refCount field, and setting any per-connection information based on the associated security object's private storage region, as referenced by the object's privateData field.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The conn argument contains a pointer to the newly-created connection structure, and must resolve into an object of type (struct rx connection *).
- In generating a call to the routine located at the security object's op NewConnection() slot, the obj and conn pointers are used as its two parameters. An invocation of the RXS NewConnection() macro results in a return value identical to that of the op NewConnection() routine, namely a value of type int.
@subsubsection sec5-5-7-4 Section 5.5.7.4: RXS PreparePacket()
- #define RXS_PreparePacket(obj, call, packet)
RXS_OP(obj, PreparePacket, (obj, call, packet))
- This macro causes the execution of the interface routine in the op PreparePacket() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx each time it prepares an outward-bound packet. Among the responsibilities of such a function might be computing information to put into the packet's security header and/or trailer.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The call argument contains a pointer to the Rx call to which the given packet belongs, and must resolve to an object of type (struct rx call *). The final argument, packet, contains a pointer to the packet itself. It should resolve to an object of type (struct rx packet *).
- In generating a call to the routine located at the security object's op PreparePacket() slot, the obj, call, and packet pointers are used as its three parameters. An invocation of the RXS PreparePacket() macro results in a return value identical to that of the op PreparePacket() routine, namely a value of type int.
@subsubsection sec5-5-7-5 Section 5.5.7.5: RXS SendPacket()
- #define RXS_SendPacket(obj, call, packet) RXS_OP(obj, SendPacket, (obj, call, packet))
- This macro causes the execution of the interface routine occupying the op SendPacket() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx each time it physically transmits an outward-bound packet. Among the responsibilities of such a function might be recomputing information in the packet's security header and/or trailer.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The call argument contains a pointer to the Rx call to which the given packet belongs, and must resolve to an object of type (struct rx call *). The final argument, packet, contains a pointer to the packet itself. It should resolve to an object of type (struct rx packet *).
- In generating a call to the routine located at the security object's op SendPacket() slot, the obj, call, and packet pointers are used as its three parameters. An invocation of the RXS SendPacket() macro results in a return value identical to that of the op SendPacket() routine, namely a value of type int.
@subsubsection sec5-5-7-6 Section 5.5.7.6: RXS CheckAuthentication()
- #define RXS_CheckAuthentication(obj, conn) RXS_OP(obj, CheckAuthentication, (obj, conn))
- This macro causes the execution of the interface routine in the op CheckAuthentication() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx each time it needs to check whether the given connection is one on which authenticated calls are being performed. Specifically, a value of 0 is returned if authenticated calls are not being executed on this connection, and a value of 1 is returned if they are.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The conn argument contains a pointer to the Rx connection checked as to whether authentication is being performed, and must resolve to an object of type (struct rx connection *).
- In generating a call to the routine in the security object's op CheckAuthentication() slot, the obj and conn pointers are used as its two parameters. An invocation of the RXS CheckAuthentication() macro results in a return value identical to that of the op CheckAuthentication() routine, namely a value of type int.
@subsubsection sec5-5-7-7 Section 5.5.7.7: RXS CreateChallenge()
- #define RXS_CreateChallenge(obj, conn) RXS_OP(obj, CreateChallenge, (obj, conn))
- This macro causes the execution of the interface routine in the op CreateChallenge() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx each time a challenge event is constructed for a given connection. Among the responsibilities of such a function might be marking the connection as temporarily unauthenticated until the given challenge is successfully met.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The conn argument contains a pointer to the Rx connection for which the authentication challenge is being constructed, and must resolve to an object of type (struct rx connection *).
- In generating a call to the routine located at the security object's op CreateChallenge() slot, the obj and conn pointers are used as its two parameters. An invocation of the RXS CreateChallenge() macro results in a return value identical to that of the op CreateChallenge() routine, namely a value of type int.
@subsubsection sec5-5-7-8 Section 5.5.7.8: RXS GetChallenge()
- #define RXS_GetChallenge(obj, conn, packet) RXS_OP(obj, GetChallenge, (obj, conn, packet))
- This macro causes the execution of the interface routine occupying the op GetChallenge() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx each time a challenge packet is constructed for a given connection. Among the responsibilities of such a function might be constructing the appropriate challenge structures in the area of packet dedicated to security matters.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The conn argument contains a pointer to the Rx connection to which the given challenge packet belongs, and must resolve to an object of type (struct rx connection *). The final argument, packet, contains a pointer to the challenge packet itself. It should resolve to an object of type (struct rx packet *).
- In generating a call to the routine located at the security object's op GetChallenge() slot, the obj, conn, and packet pointers are used as its three parameters. An invocation of the RXS GetChallenge() macro results in a return value identical to that of the op GetChallenge() routine, namely a value of type int.
@subsubsection sec5-5-7-9 Section 5.5.7.9: RXS GetResponse()
- #define RXS_GetResponse(obj, conn, packet) RXS_OP(obj, GetResponse, (obj, conn, packet))
- This macro causes the execution of the interface routine occupying the op GetResponse() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx on the server side each time a response to a challenge packet must be received.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The conn argument contains a pointer to the Rx client connection that must respond to the authentication challenge, and must resolve to a (struct rx connection *) object. The final argument, packet, contains a pointer to the packet to be built in response to the challenge. It should resolve to an object of type (struct rx packet *).
- In generating a call to the routine located at the security object's op GetResponse() slot, the obj, conn, and packet pointers are used as its three parameters. An invocation of the RXS GetResponse() macro results in a return value identical to that of the op GetResponse() routine, namely a value of type int.
@subsubsection sec5-5-7-10 Section 5.5.7.10: RXS CheckResponse()
- #define RXS_CheckResponse(obj, conn, packet) RXS_OP(obj, CheckResponse, (obj, conn, packet))
- This macro causes the execution of the interface routine in the op CheckResponse() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx on the server side each time a response to a challenge packet is received for a given connection. The responsibilities of such a function might include verifying the integrity of the response, pulling out the necessary security information and storing that information within the affected connection, and otherwise updating the state of the connection.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The conn argument contains a pointer to the Rx server connection to which the given challenge response is directed. This argument must resolve to an object of type (struct rx connection *). The final argument, packet, contains a pointer to the packet received in response to the challenge itself. It should resolve to an object of type (struct rx packet *).
- In generating a call to the routine located at the security object's op CheckResponse() slot, the obj, conn, and packet pointers are ued as its three parameters. An invocation of the RXS CheckResponse() macro results in a return value identical to that of the op CheckResponse() routine, namely a value of type int.
@subsubsection sec5-5-7-11 Section 5.5.7.11: RXS CheckPacket()
- #define RXS_CheckPacket(obj, call, packet) RXS_OP(obj, CheckPacket, (obj, call, packet))
- This macro causes the execution of the interface routine occupying the op CheckPacket() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx each time a packet is received. The responsibilities of such a function might include verifying the integrity of given packet, detecting any unauthorized modifications or tampering.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The conn argument contains a pointer to the Rx connection to which the given challenge response is directed, and must resolve to an object of type (struct rx connection *). The final argument, packet, contains a pointer to the packet received in response to the challenge itself. It should resolve to an object of type (struct rx packet *).
- In generating a call to the routine located at the security object's op CheckPacket() slot, the obj, conn, and packet pointers are used as its three parameters. An invocation of the RXS CheckPacket() macro results in a return value identical to that of the op CheckPacket() routine, namely a value of type int.
- Please note that any non-zero return will cause Rx to abort all calls on the connection. Furthermore, the connection itself will be marked as being in error in such a case, causing it to reject any further incoming packets.
@subsubsection sec5-5-7-12 Section 5.5.7.12: RXS DestroyConnection()
- #define RXS_DestroyConnection(obj, conn) RXS_OP(obj, DestroyConnection, (obj, conn))
- This macro causes the execution of the interface routine in the op DestroyConnection() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx each time a connection employing the given security object is being destroyed. The responsibilities of such a function might include deleting any private data maintained by the security module for this connection.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The conn argument contains a pointer to the Rx connection being reaped, and must resolve to a (struct rx connection *) object.
- In generating a call to the routine located at the security object's op DestroyConnection() slot, the obj and conn pointers are used as its two parameters. An invocation of the RXS DestroyConnection() macro results in a return value identical to that of the op DestroyConnection() routine, namely a value of type int.
@subsubsection sec5-5-7-13 Section 5.5.7.13: RXS GetStats()
- #define RXS_GetStats(obj, conn, stats) RXS_OP(obj, GetStats, (obj, conn, stats))
- This macro causes the execution of the interface routine in the op GetStats() slot in the Rx security object identified by the obj pointer. This interface function is invoked by Rx each time current statistics concerning the given security object are desired.
- The obj parameter must resolve into an object of type (struct rx securityOps *). The conn argument contains a pointer to the Rx connection using the security object to be examined, and must resolve to an object of type (struct rx connection *). The final argument, stats, contains a pointer to a region to be filled with the desired statistics. It should resolve to an object of type (struct rx securityObjectStats *).
- In generating a call to the routine located at the security object's op GetStats() slot, the obj, conn, and stats pointers are used as its three parameters. An invocation of the RXS GetStats() macro results in a return value identical to that of the op GetStats() routine, namely a value of type int.
@section sec5-6 Section 5.6: Functions
- Rx exports a collection of functions that, in conjuction with the macros explored in Section 5.5, allows its clients to set up and export services, create and tear down connections to these services, and execute remote procedure calls along these connections.
- This paper employs two basic categorizations of these Rx routines. One set of functions is meant to be called directly by clients of the facility, and are referred to as the exported operations. The individual members of the second set of functions are not meant to be called directly by Rx clients, but rather are called by the collection of defined macros, so they must still be lexically visible. These indirectly-executed routines are referred to here as the semi-exported operations.
- All Rx routines return zero upon success. The range of error codes employed by Rx is defined in Section 5.2.15.
@subsection sec5-6-1 Section 5.6.1: Exported Operations
@subsection sec5-6-2 Section 5.6.2: rx Init _ Initialize Rx
- int rx Init(IN int port)
- Description
- Initialize the Rx facility. If a non-zero port number is provided, it becomes the default port number for any service installed later. If 0 is provided for the port, a random port will be chosen by the system. The rx Init() function sets up internal tables and timers, along with starting up the listener thread.
- Error Codes
- RX ADDRINUSE The port provided has already been taken.
@subsection sec5-6-3 Section 5.6.3: rx NewService _ Create and install
a new service
- struct rx service *rx NewService(IN u short port; IN u short serviceId; IN char *serviceName; IN struct rx securityClass **securityObjects; IN int nSecurityObjects; IN long (*serviceProc)())
- Description
- Create and advertise a new Rx service. A service is uniquely named by a UDP port number plus a non-zero 16-bit serviceId on the given host. The port argument may be set to zero if rx Init() was called with a non-zero port number, in which case that original port will be used. A serviceName must also be provided, to be used for identification purposes (e.g., the service name might be used for probing for statistics). A pointer to an array of nSecurityObjects security objects to be associated with the new service is given in . securityObjects. The service's executeRequestProc() pointer is set to serviceProc.
- The function returns a pointer to a descriptor for the requested Rx service. A null return value indicates that the new service could not be created. Possible reasons include:
- The serviceId parameter was found to be zero.
- A port value of zero was specified at Rx initialization time (i.e., when rx init() was called), requiring a non-zero value for the port parameter here.
- Another Rx service is already using serviceId.
- Rx has already created the maximum RX MAX SERVICES Rx services (see Section 5.2.1).
- Error Codes
- (struct rx service *) NULL The new Rx service could not be created, due to one of the errors listed above.
@subsection sec5-6-4 Section 5.6.4: rx NewConnection _ Create a new
connection to a given service
- struct rx connection *rx NewConnection( IN u long shost, IN u short sport, IN u short sservice, IN struct rx securityClass *securityObject, IN int service SecurityIndex)
- Description
- Create a new Rx client connection to service sservice on the host whose IP address is contained in shost and to that host's sport UDP port. The corresponding Rx service identifier is expected in sservice. The caller also provides a pointer to the security object to use for the connection in securityObject, along with that object's serviceSecurityIndex among the security objects associated with service sservice via a previous rx NewService() call (see Section 5.6.3).
- Note
- It is permissible to provide a null value for the securityObject parameter if the chosen serviceSecurityIndex is zero. This corresponds to the pre-defined null security object, which does not engage in authorization checking of any kind.
- Error Codes
- — A pointer to an initialized Rx connection is always returned, unless osi Panic() is called due to memory allocation failure.
@subsection sec5-6-5 Section 5.6.5: rx NewCall _ Start a new call on
the given connection
- struct rx call *rx NewCall( IN struct rx connection *conn)
- Description
- Start a new Rx remote procedure call on the connection specified by the conn parameter. The existing call structures (up to RX MAXCALLS of them) are examined in order. The first non-active call encountered (i.e., either unused or whose call->state is RX STATE DALLY) will be appropriated and reset if necessary. If all call structures are in active use, the RX CONN MAKECALL WAITING flag is set in the conn->flags field, and the thread handling this request will sleep until a call structure comes free. Once a call structure has been reserved, the keep-alive protocol is enabled for it.
- The state of the given connection determines the detailed behavior of the function. The conn->timeout field specifies the absolute upper limit of the number of seconds this particular call may be in operation. After this time interval, calls to such routines as rx SendData() or rx ReadData() will fail with an RX CALL TIMEOUT indication.
- Error Codes
- — A pointer to an initialized Rx call is always returned, unless osi Panic() is called due to memory allocation failure.
@subsection sec5-6-6 Section 5.6.6: rx EndCall _ Terminate the given
call
- int rx EndCall(
- Parameters
-
IN | struct rx call *call, |
IN | long rc
) |
- Description
- Indicate that the Rx call described by the structure located at call is finished, possibly prematurely. The value passed in the rc parameter is returned to the peer, if appropriate. The final error code from processing the call will be returned as rx EndCall()'s value. The given call's state will be set to RX STATE DALLY, and threads waiting to establish a new call on this connection are signalled (see the description of the rx NewCall() in Section 5.6.5).
- Error Codes
- -1 Unspecified error has occurred.
@subsection sec5-6-7 Section 5.6.7: rx StartServer _ Activate installed
rx service(s)
- void rx StartServer( IN int donateMe)
- Description
- This function starts server threads in support of the Rx services installed via calls to rx NewService() (see Section 5.6.3). This routine first computes the number of server threads it must create, governed by the minProcs and maxProcs fields in the installed service descriptors. The minProcs field specifies the minimum number of threads that are guaranteed to be concurrently available to the given service. The maxProcs field specifies the maximum number of threads that may ever be concurrently assigned to the particular service, if idle threads are available. Using this information, rx StartServer() computes the correct overall number of threads as follows: For each installed service, minProcs threads will be created, enforcing the minimality guarantee. Calculate the maximum difference between the maxProcs and minProcs fields for each service, and create this many additional server threads, enforcing the maximality guarantee.
- If the value placed in the donateMe argument is zero, then rx StartServer() will simply return after performing as described above. Otherwise, the thread making the rx StartServer() call will itself begin executing the server thread loop. In this case, the rx StartServer() call will never return.
- Error Codes
- —None.
@subsection sec5-6-8 Section 5.6.8: rx PrintStats -- Print basic
statistics to a file
- void rx PrintStats( IN FILE *file)
- Description
- Prints Rx statistics (basically the contents of the struct rx stats holding the statistics for the Rx facility) to the open file descriptor identified by file. The output is ASCII text, and is intended for human consumption.
- Note
- This function is available only if the Rx package has been compiled with the RXDEBUG flag.
- Error Codes
- —None.
@subsection sec5-6-9 Section 5.6.9: rx PrintPeerStats _ Print peer
statistics to a file
- void rx PrintPeerStats( IN FILE *file, IN struct rx peer *peer)
- Description
- Prints the Rx peer statistics found in peer to the open file descriptor identified by file. The output is in normal ASCII text, and is intended for human consumption.
- Note
- This function is available only if the Rx package has been compiled with the RXDEBUG flag.
- Error Codes
- —None.
@subsection sec5-6-10 Section 5.6.10: rx finalize _ Shut down Rx
gracefully
- void rx finalize()
- Description
- This routine may be used to shut down the Rx facility for either server or client applications. All of the client connections will be gracefully garbage-collected after their active calls are cleaned up. The result of calling rx finalize() from a client program is that the server-side entity will be explicitly advised that the client has terminated. This notification frees the server-side application from having to probe the client until its records eventually time out, and also allows it to free resources currently assigned to that client's support.
- Error Codes
- —None.
@subsection sec5-6-11 Section 5.6.11: Semi-Exported Operations
- As described in the introductory text in Section 5.6, entries in this lexically-visible set of Rx functions are not meant to be called directly by client applications, but rather are invoked by Rx macros called by users.
@subsection sec5-6-12 Section 5.6.12: rx WriteProc _ Write data to an
outgoing call
- int rx WriteProc( IN struct rx call *call, IN char *buf, IN int nbytes)
- Description
- Write nbytes of data from buffer buf into the Rx call identified by the call parameter. The value returned by rx WriteProc() reports the number of bytes actually written into the call. If zero is returned, then the rx Error() macro may be used to obtain the call status.
- This routine is called by the rx Write() macro, which is why it must be exported by the Rx facility.
- Error Codes
- Indicates error in the given Rx call; use the rx Error() macro to determine the call status.
@subsection sec5-6-13 Section 5.6.13: rx ReadProc _ Read data from an
incoming call
- int rx ReadProc( IN struct rx call *call, IN char *buf, IN int nbytes)
- Description
- Read up to nbytes of data from the Rx call identified by the call parameter into the buf buffer. The value returned by rx ReadProc() reports the number of bytes actually read from the call. If zero is returned, then the rx Error() macro may be used to obtain the call status.
- This routine is called by the rx Read() macro, which is why it must be exported by the Rx facility.
- Error Codes
- Indicates error in the given Rx call; use the rx Error() macro to determine the call status.
@subsection sec5-6-1 Section 5.6.1: rx FlushWrite -- Flush buffered
data on outgoing call
- void rx FlushWrite( IN struct rx call *call)
- Description
- Flush any buffered data on the given Rx call to the stream. If the call is taking place on a server connection, the call->mode is set to RX MODE EOF. If the call is taking place on a client connection, the call->mode is set to RX MODE RECEIVING.
- Error Codes
- —None.
@subsection sec5-6-15 Section 5.6.15: rx SetArrivalProc _ Set function
to invoke upon call packet arrival
- void rx SetArrivalProc( IN struct rx call *call, IN VOID (*proc)(), IN VOID *handle, IN VOID *arg)
- Description
- Establish a procedure to be called when a packet arrives for a call. This routine will be called at most once after each call, and will also be called if there is an error condition on the call or the call is complete. The rx SetArrivalProc() function is used by multicast Rx routines to build a selection function that determines which of several calls is likely to be a good one to read from. The implementor's comments in the Rx code state that, due to the current implementation, it is probably only reasonable to use rx SetArrivalProc() immediately after an rx NewCall(), and to only use it once.
- Error Codes
- —None.