AgentXcpp  Revision:0.1
Internals Documentation
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends
agentxcpp::connector Class Reference

This class provides connection to another agentXcpp entity via a unix domain socket. More...

#include <connector.hpp>

Collaboration diagram for agentxcpp::connector:
[legend]

List of all members.

Classes

class  pdu_handler
 Interface for classes which can handle incoming PDU's. More...

Public Member Functions

 connector (boost::shared_ptr< boost::asio::io_service > io_service, const std::string &unix_domain_socket, unsigned timeout)
 The constructor.
boost::shared_ptr< ResponsePDUwait_for_response (uint32_t packetID)
 Wait with timeout for a reponse.
void register_handler (pdu_handler *handler)
 Register a handler object for received PDU's.
void connect ()
 Connect to the remote entity.
void disconnect ()
 Disconnect the remote entity.
bool is_connected ()
 Find out whether the object is currently connected.
void send (const PDU &pdu)
 send a PDU to the remote entity.
 ~connector ()
 Destructor.

Private Member Functions

void receive_callback (const boost::system::error_code &result)
 Callback function to receive a PDU.
 connector ()
 Hide standard constructor.

Private Attributes

unsigned timeout
 The timeout in milliseconds, used in various contexts.
boost::shared_ptr
< boost::asio::io_service > 
io_service
 The mandatory io_service object.
boost::asio::local::stream_protocol::socket * socket
 The socket.
boost::asio::local::stream_protocol::endpoint endpoint
 The endpoint used for unix domain sockets.
std::map< uint32_t,
boost::shared_ptr< ResponsePDU > > 
responses
 The received, yet unprocessed ReponsePDU's.
byte_t header_buf [20]
 Buffer to receive a PDU header.
pdu_handlerhandler
 The handler object for incoming PDU's.

Detailed Description

This class provides connection to another agentXcpp entity via a unix domain socket.

A connector object is always in one of the following states:

  1. connected
    1. disconnected

When created, a connector object starts in disconnected state. The current state can be obtained using the is_connected() method. Some operations may throw a disconnected exception if the object is in disconnected state. Further, the connection may fail at any point in time, therefore a disconnected exception may also be thrown during a network operation.

The socket needed for networking is created upon connect and destroyed upon disconnect. The reason is that closing the socket may throw a system_error exception, leaving the socket in an unknown state. Destroying it and creating a new one should be safe.

Sending works as follows:

  • The user invokes the send() method.
    • The send() method sends the PDU synchronously (but with a timeout).

Note: The send() function invokes io_service->run_one() one or several times.

Receiving PDU's works as follows:

  • Upon connecting to the remote entity, an asynchronous read operation is started to receive the PDU header (fixed size). On disconnect, the asynchronous read operation is stopped again.
    • The boost::asio library writes a fixed amount of data (which is the PDU header) into the header_buf member and invokes the receive_callback() function.
    • The receive_callback() method reads the payload length from header_buf and reveives the payload synchronously (but with a timeout).
    • The receive_callback() method then constructs a PDU object and delivers it to a user-provided handler object (which implements the connector::pdu_handler interface) by calling its handle_pdu() method.
    • The handler object processes the PDU as needed. As soon as processing finishes, the receive_callback() method starts the next asynchronous read operation, so that it invoked again when the next header arrives.
Note:
As a special case, ResponsePDU's are not delivered to the registered handler object, but are handled differently. see below for details.
If no handler object is registered, the PDU is received nevertheless and is silently discarded.
The receive_callback() function, and thus the registered handler object's handle_pdu() method are executed in the io_service's run() context.

Receiving ResponsePDU's works as follows:

The function wait_for_response() supports the request-response communication model. After sending a request to the remote entity (using send()), wait_for_response() is used to wait for the response. It blocks while waiting for a responsePDU from the remote entity, which is then returned to the caller. The wait_for_response() function may seem to do synchronous operations only, but this is not true. In fact, it uses an asynchronous receive mechanism, because there may be other PDU's in the queue before the given response is actually received. wait_for_response() therefore invokes io_service->run_one() one ore more times, until the response is received. This may also cause other asynchronous operations to finish. For example, the registered handler object may receive other PDU types, or another asynchronous operation on the io_service object (outside this class or even outside the agentXcpp library) may be served. Here are the steps performed to receive a ResponsePDU:

  • The wait_for_response() function puts an empty boost::shared_ptr<> into the responses map, using the PacketID of the awaited ResponsePDU as key.
    • The wait_for_response() function invokes io_service->run_one() one or several times, which triggers receive_callback() if data becomes available.
    • When the receive_callback() function is invoked, it receives a single PDU and processes it as described above.
    • If a ResponsePDU is received, the registered handler object is not informed by receive_callback(). Instead, the responses map is searched for an entry with the same PacketID as the received ResponsePDU. If found, the received ResponsePDU is stored in the map. Otherwise the ResponsePDU is silently discarded (as nobody waits for it).
    • The wait_for_response() checks its map entry after each run_one() call for a received ResponsePDU. If it finds one, the entry is erased from the map and returned to the caller.

The same timeout value is used by all operations which deal with timeouts. The value is stored in the timeout member.

Definition at line 129 of file connector.hpp.


Constructor & Destructor Documentation

Hide standard constructor.

We need an io_service object to function properly.

connector::connector ( boost::shared_ptr< boost::asio::io_service >  io_service,
const std::string &  unix_domain_socket,
unsigned  timeout 
)

The constructor.

This constructor initializes the connector object to be in disconnected state.

Parameters:
io_serviceThe io_service object needed for boost::asio operations. It may also be used by other parts of the program.
unix_domain_socketThe path to the unix_domain_socket.
timeoutThe timeout, in milliseconds, for sending and receiving PDU's. See the documentation of the respective methods for details.
Exceptions:
None.

Definition at line 410 of file connector.cpp.

Destructor.

Exceptions:
None.

Definition at line 423 of file connector.hpp.

References disconnect().


Member Function Documentation

Connect to the remote entity.

This function connects to the remote entity and starts receiving PDU's. If the object is already connected, the function does nothing.

Note:
While no handler is registered, received PDU's are silently discarded.
Exceptions:
disconnectedIf connecting fails.

Definition at line 421 of file connector.cpp.

References endpoint, header_buf, io_service, receive_callback(), and socket.

Referenced by agentxcpp::master_proxy::connect(), and agentxcpp::master_proxy::reconnect().

Disconnect the remote entity.

Stops receiving PDU's and disconnects the remote entity.

Exceptions:
None.

Definition at line 454 of file connector.cpp.

References socket.

Referenced by agentxcpp::master_proxy::connect(), agentxcpp::master_proxy::disconnect(), receive_callback(), agentxcpp::master_proxy::reconnect(), send(), wait_for_response(), and ~connector().

Find out whether the object is currently connected.

Returns:
Whether the object is in state connected.
Exceptions:
None.

Definition at line 388 of file connector.hpp.

References socket.

Referenced by agentxcpp::master_proxy::connect(), agentxcpp::master_proxy::disconnect(), and agentxcpp::master_proxy::is_connected().

void connector::receive_callback ( const boost::system::error_code &  result) [private]

Callback function to receive a PDU.

See the class documentation to learn about the receive mechanism.

Note:
Exceptions thrown by the user-provided handler (if any) are catched and discarded.

The synchronous read operation (to read the payload) may time out, using the class' timeout value. If the read times out, the socket is destroyed and the connector object becomes disconnected.

Parameters:
resultThe result of the asynchronous read operation (provided by boost::asio).
Exceptions:
None.

Definition at line 502 of file connector.cpp.

References disconnect(), agentxcpp::connector::pdu_handler::handle_pdu(), handler, header_buf, agentxcpp::PDU::parse_pdu(), read32(), responses, and socket.

Referenced by connect().

Register a handler object for received PDU's.

Every time a PDU is received, the handler object's handle_pdu() method will be invoked with the PDU as argument. This method is executed in the context of the io_service object's run() or run_one() method. Care should be taken to not block the call, e.g. by doing networking.

After registering a handler it can be unregistered again by calling this function with a null pointer. While no handler object is registered, received PDU's are silently discarded.

Note:
Any exceptions thrown by the handler object are silently discarded.
There can be only one handler object registered at a time.
Parameters:
handlerA pointer to the handler object, or null.
Exceptions:
None.

Definition at line 496 of file connector.cpp.

References handler.

Referenced by agentxcpp::master_proxy::master_proxy().

void connector::send ( const PDU pdu)

send a PDU to the remote entity.

The PDU is sent to the remote entity. If the timeout expires during the send operation, a timeout_error is thrown and the object gets disconnected.

Note:
The run_one() of the io_service object is called at least one time by this operation.
Parameters:
pduThe PDU to send
Exceptions:
timeout_errorIf a timeout error occurs. The function uses the timeout value given during construction. The objects gets disconnected in this case. Some data might be sent already.
disconnectedIf disconnected. This is also thrown if sending fails and the object gets disconnected for that reason. Some data might be sent already.

Definition at line 665 of file connector.cpp.

References disconnect(), agentxcpp::PDU::serialize(), and socket.

Referenced by agentxcpp::master_proxy::connect(), agentxcpp::master_proxy::disconnect(), agentxcpp::master_proxy::do_registration(), agentxcpp::master_proxy::handle_pdu(), and agentxcpp::master_proxy::undo_registration().

boost::shared_ptr< ResponsePDU > connector::wait_for_response ( uint32_t  packetID)

Wait with timeout for a reponse.

This function blocks until a ResponsePDU with the given packetID is received or until the timeout expires, whichever comes first. The received ResponsePDU (if any) is returned.

This function calls run_one() repeatedly on the io_service object until the desired ResponsePDU arrives or the timeout expires. This may cause other asynchronous operations to be served, as well.

Parameters:
packetIDThe packetID to wait for.
Exceptions:
timeout_exceptionIf the timeout expired before the ResponsePDU was received. The connector object stays in connected state.
disconnectedIf disconnected. This is also thrown if the operation fails and the object gets disconnected for that reason.
Returns:
The received ResponsePDU.

Definition at line 733 of file connector.cpp.

References disconnect(), in_progress, io_service, responses, and socket.

Referenced by agentxcpp::master_proxy::connect(), agentxcpp::master_proxy::disconnect(), agentxcpp::master_proxy::do_registration(), and agentxcpp::master_proxy::undo_registration().


Member Data Documentation

boost::asio::local::stream_protocol::endpoint agentxcpp::connector::endpoint [private]

The endpoint used for unix domain sockets.

Definition at line 203 of file connector.hpp.

Referenced by connect().

The handler object for incoming PDU's.

This handler object is informed by receive_callback() for each received PDU (except ResponsePDU's).

The pointer may be null, which means that there is no handler object registered.

Definition at line 272 of file connector.hpp.

Referenced by receive_callback(), and register_handler().

Buffer to receive a PDU header.

See the class documentation to learn about the receive mechanism.

The PDU header is placed here before receive_callback() is called by boost::asio.

Since the AgentX-header is always 20 bytes in length, this buffer is 20 bytes in size.

Definition at line 261 of file connector.hpp.

Referenced by connect(), and receive_callback().

boost::shared_ptr<boost::asio::io_service> agentxcpp::connector::io_service [private]

The mandatory io_service object.

This object is needed for boost::asio sockets. It is provided by the user of this class.

Definition at line 191 of file connector.hpp.

Referenced by connect(), and wait_for_response().

std::map< uint32_t, boost::shared_ptr<ResponsePDU> > agentxcpp::connector::responses [private]

The received, yet unprocessed ReponsePDU's.

See the class documentation to learn about the receive mechanism.

The wait_for_response() function stores a null pointer to this map to indicate that it is waiting for a certain response.

When a response is received, the receive_callback() function stores it into the map, but only if a null pointer is found for the packetID of the received ResponsePDU. Otherwise, the received ResponsePDU is discarded.

After a ResponsePDU was received and stored into the map, the wait_for_response() function processes it and erases it from the map.

The map key is the packetID of the response which is awaited.

Definition at line 246 of file connector.hpp.

Referenced by receive_callback(), and wait_for_response().

boost::asio::local::stream_protocol::socket* agentxcpp::connector::socket [private]

The socket.

The null pointer while disconnected.

Definition at line 198 of file connector.hpp.

Referenced by connect(), disconnect(), is_connected(), receive_callback(), send(), and wait_for_response().

unsigned agentxcpp::connector::timeout [private]

The timeout in milliseconds, used in various contexts.

Definition at line 183 of file connector.hpp.


The documentation for this class was generated from the following files: