This class provides connection to another agentXcpp entity via a unix domain socket. More...
#include <connector.hpp>
Classes | |
| class | pdu_handler |
| Interface for classes which can handle incoming PDU's. More... | |
Public Member Functions | |
| connector (boost::asio::io_service *io_service, const std::string &unix_domain_socket, unsigned timeout) | |
| The constructor. | |
| boost::shared_ptr< ResponsePDU > | wait_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::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. | |
| uint8_t | header_buf [20] |
| Buffer to receive a PDU header. | |
| pdu_handler * | handler |
| The handler object for incoming PDU's. | |
This class provides connection to another agentXcpp entity via a unix domain socket.
A connector object is always in one of the following states:
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:
Note: The send() function invokes io_service->run_one() one or several times.
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 same timeout value is used by all operations which deal with timeouts. The value is stored in the timeout member.
For timeout detection, a boost deadline timer is used together with the timeout_status member. While the timer is not in use, it's expiry time is set to "infinite" and timeout_status is set to "unused". When starting operations which need timeout detection, the deadline timer's expiry is set to the according time, and timeout_status is set to "in_progress". If the timer expires, the callback function check_deadline() is invoked, which sets the expiry back to "infinite" and timeout_status to "expired". If the operation completes before the timer expires, the expiry is set back to "infinite" and timeout_status is reset to "unused".
Note that the callback check_deadline() may be invoked errornously, e.g. in this situation:
The check_deadline() callback also restarts the timer on each call to keep it running.
Definition at line 160 of file connector.hpp.
|
private |
Hide standard constructor.
We need an io_service object to function properly.
| connector::connector | ( | 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.
| io_service | The io_service object needed for boost::asio operations. It may also be used by other parts of the program. |
| unix_domain_socket | The path to the unix_domain_socket. |
| timeout | The timeout, in milliseconds, for sending and receiving PDU's. See the documentation of the respective methods for details. |
| None. |
Definition at line 304 of file connector.cpp.
|
inline |
Destructor.
| None. |
Definition at line 455 of file connector.hpp.
References disconnect().
| void connector::connect | ( | ) |
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.
| disconnected | If connecting fails. |
Definition at line 315 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().
| void connector::disconnect | ( | ) |
Disconnect the remote entity.
Stops receiving PDU's and disconnects the remote entity.
| None. |
Definition at line 348 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().
|
inline |
Find out whether the object is currently connected.
| None. |
Definition at line 420 of file connector.hpp.
References socket.
Referenced by agentxcpp::master_proxy::connect(), agentxcpp::master_proxy::disconnect(), and agentxcpp::master_proxy::is_connected().
|
private |
Callback function to receive a PDU.
See the class documentation to learn about the receive mechanism.
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.
| result | The result of the asynchronous read operation (provided by boost::asio). |
| None. |
Definition at line 396 of file connector.cpp.
References disconnect(), agentxcpp::connector::pdu_handler::handle_pdu(), handler, header_buf, agentxcpp::PDU::parse_pdu(), agentxcpp::read32(), responses, and socket.
Referenced by connect().
| void connector::register_handler | ( | pdu_handler * | handler | ) |
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.
| handler | A pointer to the handler object, or null. |
| None. |
Definition at line 390 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.
| pdu | The PDU to send |
| timeout_error | If 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. |
| disconnected | If 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 559 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.
| packetID | The packetID to wait for. |
| timeout_exception | If the timeout expired before the ResponsePDU was received. The connector object stays in connected state. |
| disconnected | If disconnected. This is also thrown if the operation fails and the object gets disconnected for that reason. |
Definition at line 594 of file connector.cpp.
References disconnect(), agentxcpp::timeout_timer::expired, io_service, responses, agentxcpp::timeout_timer::running, and socket.
Referenced by agentxcpp::master_proxy::connect(), agentxcpp::master_proxy::disconnect(), agentxcpp::master_proxy::do_registration(), and agentxcpp::master_proxy::undo_registration().
|
private |
The endpoint used for unix domain sockets.
Definition at line 234 of file connector.hpp.
Referenced by connect().
|
private |
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 303 of file connector.hpp.
Referenced by receive_callback(), and register_handler().
|
private |
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 292 of file connector.hpp.
Referenced by connect(), and receive_callback().
|
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 222 of file connector.hpp.
Referenced by connect(), and wait_for_response().
|
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 277 of file connector.hpp.
Referenced by receive_callback(), and wait_for_response().
|
private |
The socket.
The null pointer while disconnected.
Definition at line 229 of file connector.hpp.
Referenced by connect(), disconnect(), is_connected(), receive_callback(), send(), and wait_for_response().
|
private |
The timeout in milliseconds, used in various contexts.
Definition at line 214 of file connector.hpp.