Connect to a unix domain socket. More...
#include <UnixDomainConnector.hpp>
Signals | |
void | pduArrived (QSharedPointer< PDU >) |
Emitted when a PDU arrived. More... | |
Public Member Functions | |
UnixDomainConnector (const std::string &unix_domain_socket="/var/agentx/master", unsigned timeout=1000) | |
Standard constructor. More... | |
virtual | ~UnixDomainConnector () |
Destructor. More... | |
bool | connect () |
Connect to the remote entity. More... | |
void | disconnect () |
Disconnect from the remote entity. More... | |
bool | is_connected () |
Find out whether the object is currently connected. More... | |
void | send (QSharedPointer< PDU > pdu) |
Send a PDU. More... | |
QSharedPointer< ResponsePDU > | request (QSharedPointer< PDU > pdu) |
Send a PDU and wait for the response. More... | |
Private Slots | |
void | do_receive () |
Internal slot to receive data. More... | |
void | do_send (QSharedPointer< PDU > pdu) |
Internal slot to send data. More... | |
void | do_connect () |
Connect to the remote entity. More... | |
void | do_disconnect () |
Disconnect from a remote entity. More... | |
Private Attributes | |
QLocalSocket | m_socket |
The socket used internally for networking. More... | |
QString | m_filename |
The filename of the unix domain socket. More... | |
unsigned | m_timeout |
The timeout in milliseconds. More... | |
QMutex | m_connection_mutex |
Needed for m_connection_waitcondition. More... | |
QWaitCondition | m_connection_waitcondition |
A waitcondition to synchronize connect actions. More... | |
bool | m_is_connected |
Whether the object is currently connected. More... | |
QMutex | m_mutex_is_connected |
A mutex to protect m_is_connected. More... | |
std::map< quint32, QSharedPointer< ResponsePDU > > | m_responses |
Storage for ResponsePDU's. More... | |
QMutex | m_response_mutex |
Used to protect m_responses and for m_response_arrived. More... | |
QWaitCondition | m_response_arrived |
A waitcondition to inform waiters of ResponsePDU's. More... | |
Connect to a unix domain socket.
This class connects to a unix domain socket and provides the following services:
An object of this class is intended to run in its own thread, like so:
The UnixDomainConnector object communicates with its "outside world" via the QT signal/slot mechanism (which is thread-safe). In addition, the class offers methods which can directly be called from any thread and which are also thread-safe (and often use the signal/slot mechanism internally).
The UnixDomainConnector class uses QLocalSocket to communicate over a unix domain socket. It always starts in disconnected state, which means that the QLocalSocket is disconnected. The private slots do_connect() and do_disconnect() are invoked to connect resp. disconnect the socket. However, these slots should not be invoked from outside the object (therefore they are private slots). The methods connect() and disconnect() are offered to handle connection. These methods invoke do_connect() resp. do_disconnect().
The connect() method blocks until the connection is established or a timeout is detected. It does so by invoking do_connect(), then waiting for a QWaitCondition to be triggered. The disconnect() method works the same way.
The connection state is tracked with the m_is_connected member, which is protected by a mutex. The is_connected() method can access m_is_connected to inspect the state.
AgentX is a protocol based on a request-response model. A subagent can send a request and wait for a response, while the master can also send requests and expect a response. Furthermore, a subagent or a master can send multiple requests, then wait for all the responses. All those PDU's can be interleaved.
The UnixDomainConnector class handles sending and receiving PDU's separately. Sending is done using the do_send() slot, which works for all types of PDU: all request-PDU's (such as OpenPDU) can be send without considering special cases, and ResponsePDU's also are no exception. Received PDU's are forwarded using the pduArrived() signal to whoever is listening, which works for PDU's except ResponsePDU's: these are the answer to a sent request-PDU and must be routed differently.
Received ResponsePDU's are transmitted via the m_responses map. This map assigns a packetID a ResponsePDU. Each time a request is sent, do_send() adds an entry to the map with the packetID of the request and a NULL ResponsePDU (i.e. a NULL pointer). This entry indicates that a ResponsePDU with the same packetID is awaited. The do_receive() slot then adds the ResponsePDU to the map, when it arrived. However, when a ResponsePDU arrives which is not awaited, it is discarded.
Definition at line 114 of file UnixDomainConnector.hpp.
UnixDomainConnector::UnixDomainConnector | ( | const std::string & | unix_domain_socket = "/var/agentx/master" , |
unsigned | timeout = 1000 |
||
) |
Standard constructor.
This constructor initializes the connector object to be in disconnected state.
unix_domain_socket | The path to the unix_domain_socket. |
timeout | The timeout, in milliseconds, used for for connecting, disconnecting, sending and receiving PDU's. See the documentation of the respective methods for details. |
Definition at line 34 of file UnixDomainConnector.cpp.
References do_receive(), and m_socket.
|
virtual |
Destructor.
Definition at line 148 of file UnixDomainConnector.cpp.
bool UnixDomainConnector::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.
For the attempt to connect, the configured timeout is used.
This function invokes the do_connect() slot and then wait until m_connection_waitcondition is triggered (or a timeout is detected).
Definition at line 94 of file UnixDomainConnector.cpp.
References is_connected(), m_connection_mutex, m_connection_waitcondition, and m_timeout.
Referenced by agentxcpp::MasterProxy::connect(), and agentxcpp::MasterProxy::reconnect().
void UnixDomainConnector::disconnect | ( | ) |
Disconnect from the remote entity.
Stops receiving PDU's and disconnects the remote entity.
For the attempt to disconnect, the configured timeout is used.
This function invokes the do_disconnect() slot and then waits until m_connection_waitcondition is triggered (or a timeout is detected).
The object will be in disconnected state after this method, no matter whether disconnecting times out or not.
Definition at line 129 of file UnixDomainConnector.cpp.
References m_connection_mutex, m_connection_waitcondition, and m_timeout.
Referenced by do_receive(), and agentxcpp::MasterProxy::reconnect().
|
privateslot |
Connect to the remote entity.
This function connects to the remote entity and waits until connection is established, or until the timeout expires.
If the UnixDomainConnector is already connected, this function does nothing. If the socket was disconnected, and the disconnect operation is still in progress, this function also does nothing.
If connecting times out, m_is_connected is set to false.
If connecting succeeds, m_is_connected is set to true.
After the work is done, m_connection_waitcondition.wakeAll() is invoked in any case.
Definition at line 51 of file UnixDomainConnector.cpp.
References m_connection_waitcondition, m_filename, m_is_connected, m_mutex_is_connected, m_socket, and m_timeout.
|
privateslot |
Disconnect from a remote entity.
This function disconnects from the remote entity and waits until the operation finished, or until the timeout expires.
If disconnecting times out, m_socket may be left in state ClosingState.
m_is_connected is set to false in any case.
conjunction with m_c After the work is done, m_connection_waitcondition.wakeAll() is invoked in any case.
Definition at line 109 of file UnixDomainConnector.cpp.
References m_connection_waitcondition, m_is_connected, m_mutex_is_connected, m_socket, and m_timeout.
|
privateslot |
Internal slot to receive data.
This slot is connected to QLocalSocket::readyRead() and thus called when data arrives on the socket.
The function reads as many complete PDU's from the socket, parses them and invokes the pduArrived() signal for each PDU, except for ResponsePDU's.
ResponsePDU's are stored to the m_responses map, if the map has an entry for the packetID of the received ResponsePDU. Otherwise, the ResponsePDU is discarded.
Certain errors cause the UnixDomainConnector object to disconnect. Other errors are ignored and the respective PDU is discarded.
Definition at line 153 of file UnixDomainConnector.cpp.
References disconnect(), m_response_arrived, m_response_mutex, m_responses, m_socket, agentxcpp::PDU::parse_pdu(), pduArrived(), and agentxcpp::read32().
Referenced by UnixDomainConnector().
|
privateslot |
Internal slot to send data.
This slot is invoked when data must be sent. It serializes the given PDU and sends it. Errors are ignored.
Definition at line 299 of file UnixDomainConnector.cpp.
References m_socket.
bool UnixDomainConnector::is_connected | ( | ) |
Find out whether the object is currently connected.
Definition at line 140 of file UnixDomainConnector.cpp.
References m_is_connected, and m_mutex_is_connected.
Referenced by connect(), and agentxcpp::MasterProxy::is_connected().
|
signal |
Emitted when a PDU arrived.
This signal is emitted once for every arrived PDU, except for ResponsePDU's.
Referenced by do_receive().
QSharedPointer< ResponsePDU > UnixDomainConnector::request | ( | QSharedPointer< PDU > | pdu | ) |
Send a PDU and wait for the response.
This method sends a PDU. Then, it adds an entry to m_responses to indicate that a ResponsePDU is awaited. Finally, it waits until that ResponsePDU arrives and returns it (it is removed from m_responses).
Definition at line 276 of file UnixDomainConnector.cpp.
References m_response_arrived, m_response_mutex, and m_responses.
Referenced by agentxcpp::MasterProxy::connect(), agentxcpp::MasterProxy::disconnect(), agentxcpp::MasterProxy::do_registration(), agentxcpp::MasterProxy::send_notification(), and agentxcpp::MasterProxy::undo_registration().
void UnixDomainConnector::send | ( | QSharedPointer< PDU > | pdu | ) |
Send a PDU.
This function enqueues a PDU for sending, by invoking do_send(). This means the this function returns before the PDU is actually sent.
Definition at line 308 of file UnixDomainConnector.cpp.
Referenced by agentxcpp::MasterProxy::handle_pdu().
|
private |
Needed for m_connection_waitcondition.
Definition at line 138 of file UnixDomainConnector.hpp.
Referenced by connect(), and disconnect().
|
private |
A waitcondition to synchronize connect actions.
This condition is used to synchronize connect() and do_connect() respectively disconnect() and do_disconnect(). It is used in conjunction with m_connection_mutex.
Definition at line 147 of file UnixDomainConnector.hpp.
Referenced by connect(), disconnect(), do_connect(), and do_disconnect().
|
private |
The filename of the unix domain socket.
Definition at line 128 of file UnixDomainConnector.hpp.
Referenced by do_connect().
|
private |
Whether the object is currently connected.
The member is protected by m_mutex_is_connected.
Definition at line 154 of file UnixDomainConnector.hpp.
Referenced by do_connect(), do_disconnect(), and is_connected().
|
private |
A mutex to protect m_is_connected.
Definition at line 159 of file UnixDomainConnector.hpp.
Referenced by do_connect(), do_disconnect(), and is_connected().
|
private |
A waitcondition to inform waiters of ResponsePDU's.
The m_response_mutex is used for synchronization.
Definition at line 182 of file UnixDomainConnector.hpp.
Referenced by do_receive(), and request().
|
private |
Used to protect m_responses and for m_response_arrived.
Definition at line 175 of file UnixDomainConnector.hpp.
Referenced by do_receive(), and request().
|
private |
Storage for ResponsePDU's.
This map contains entries with packetID as key and ResponsePDU's as values. An entry with a NULL pointer value means that a ResponsePDU with the given packetID is awaited.
This member is protected by m_response_mutex.
Definition at line 170 of file UnixDomainConnector.hpp.
Referenced by do_receive(), and request().
|
private |
The socket used internally for networking.
Definition at line 123 of file UnixDomainConnector.hpp.
Referenced by do_connect(), do_disconnect(), do_receive(), do_send(), and UnixDomainConnector().
|
private |
The timeout in milliseconds.
Definition at line 133 of file UnixDomainConnector.hpp.
Referenced by connect(), disconnect(), do_connect(), and do_disconnect().