Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/***************************************
Auteur : Pierre Aubert
Mail : pierre.aubert@lapp.in2p3.fr
Licence : CeCILL-C
****************************************/
#ifndef __PGENERIC_SOCKET_H__
#define __PGENERIC_SOCKET_H__
#include "PSocketMode.h"
#include "phoenix_mock_socket.h"
///@brief Abstract socket which has a mock mode to avoid heavy socket backend for unit tests
template<typename _TBackend, typename _TMockBackend>
class PGenericSocket{
public:
PGenericSocket(PSocketMode::PSocketMode mode);
virtual ~PGenericSocket();
bool createClientSocket(const typename _TBackend::Param & param, const typename _TMockBackend::Param & mockParam);
bool createServerSocket(const typename _TBackend::Param & param, const typename _TMockBackend::Param & mockParam);
///Send message on the given socket
/** @param data : data to be sent
* @param flags : flags to be used to send the message (none, dontwait, sndmore, etc)
* @return true on success, false otherwise
*/
template<typename U, typename _TFlag>
bool sendData(const U & data, _TFlag flags){
size_t dataSize(data_size<U>(data));
bool b(true);
if(p_mode != PSocketMode::NO_MOCK){
typename _TMockBackend::Message msg;
_TMockBackend::msgResize(msg, dataSize);
char* iter = _TMockBackend::msgData(msg);
if(data_message_save<char*, U>(iter, data)){ //Save the message
b &= _TMockBackend::send(p_mockSocket, msg, (typename _TMockBackend::SendFlag)flags);
}else{
b = false;
}
}
if(p_mode != PSocketMode::MOCK){
typename _TBackend::Message msg;
_TBackend::msgResize(msg, dataSize);
char* iter = _TBackend::msgData(msg);
if(data_message_save<char*, U>(iter, data)){ //Save the message
b &= _TBackend::send(p_socket, msg, (typename _TBackend::SendFlag)flags);
}else{
b = false;
}
}
return b;
}
///Send message on the given socket
/** @param msg : message to be sent
* @param flags : flags to be used to send the message (none, dontwait, sndmore, etc)
* @return true on success, false otherwise
*/
template<typename _TFlag>
bool sendMsg(typename _TBackend::Message & msg, _TFlag flags){
size_t dataSize(msg.size());
bool b(true);
if(p_mode != PSocketMode::NO_MOCK){
typename _TMockBackend::Message vecTmp;
_TMockBackend::msgResize(vecTmp, dataSize);
memcpy(_TMockBackend::msgData(vecTmp), _TBackend::msgData(msg), dataSize);
b &= _TMockBackend::send(p_mockSocket, vecTmp, (typename _TMockBackend::SendFlag)flags);
b &= _TBackend::send(p_socket, msg, (typename _TBackend::SendFlag)flags);
}
return b;
}
///Recieve message from the given socket
/** @param data : data to be recieved
* @param flags : flags to be used to send the message (none, dontwait, sndmore, etc)
* @return true on success, false otherwise
*/
template<typename U, typename _TFlag>
bool recvData(U & data, _TFlag flags){
bool b(true);
if(p_mode == PSocketMode::NO_MOCK){ //Normal mode
typename _TBackend::Message msg;
b &= _TBackend::recv(p_socket, msg, (typename _TBackend::RecvFlag)flags);
//If the message is empty we cannot initialise the given data, so, this is an error
b &= _TBackend::msgSize(msg) != 0lu;
if(b){
char* iter = _TBackend::msgData(msg);
b &= data_message_load<U>(iter, data);
}
}else if(p_mode == PSocketMode::MOCK){ //Mock mode
typename _TMockBackend::Message msg;
b &= _TMockBackend::recv(p_mockSocket, msg, (typename _TMockBackend::RecvFlag)flags);
//If the message is empty we cannot initialise the given data, so, this is an error
b &= _TMockBackend::msgSize(msg) != 0lu;
if(b){
char* iter = _TMockBackend::msgData(msg);
b &= data_message_load<U>(iter, data);
}
}else{ //Mock record mode
typename _TBackend::Message msg;
b &= _TBackend::recv(p_socket, msg, (typename _TBackend::RecvFlag)flags);
//If the message is empty we cannot initialise the given data, so, this is an error
b &= _TBackend::msgSize(msg) != 0lu;
if(b){
char* iter = _TBackend::msgData(msg);
b &= data_message_load<U>(iter, data);
if(b){
//Let's convert the message into the mock backend
typename _TMockBackend::Message msgMock;
size_t dataSize(_TBackend::msgSize(msg));
_TMockBackend::msgResize(msgMock, dataSize);
memcpy(_TMockBackend::msgData(msgMock), _TBackend::msgData(msg), dataSize);
b &= _TMockBackend::recv(p_mockSocket, msgMock, (typename _TMockBackend::RecvFlag)flags);
}
}
}
return b;
}
///Recieve message from the given socket
/** @param msg : message to be recieved
* @param flags : flags to be used to send the message (none, dontwait, sndmore, etc)
* @return true on success, false otherwise
*/
template<typename _TFlag>
bool recvMsg(typename _TBackend::Message & msg, _TFlag flags){
bool b(true);
if(p_mode == PSocketMode::NO_MOCK){ //Normal mode
b &= _TBackend::recv(p_socket, msg, (typename _TBackend::RecvFlag)flags);
}else if(p_mode == PSocketMode::MOCK){ //Mock mode
typename _TMockBackend::Message msgMock;
b &= _TMockBackend::recv(p_mockSocket, msgMock, (typename _TMockBackend::RecvFlag)flags);
if(b){
size_t dataSize(_TMockBackend::msgSize(msgMock));
_TBackend::msgResize(msg, dataSize);
memcpy(_TBackend::msgData(msg), _TMockBackend::msgData(msgMock), dataSize);
}
}else{ //Mock record mode
b &= _TBackend::recv(p_socket, msg, (typename _TBackend::RecvFlag)flags);
if(b){
typename _TMockBackend::Message msgMock;
size_t dataSize(_TBackend::msgSize(msg));
_TMockBackend::msgResize(msgMock, dataSize);
memcpy(_TMockBackend::msgData(msgMock), _TBackend::msgData(msg), dataSize);
b &= _TMockBackend::recv(p_mockSocket, msgMock, (typename _TMockBackend::RecvFlag)flags);
}
}
return b;
}
void close();
bool isConnected() const;
private:
void initialisationPGenericSocket(PSocketMode::PSocketMode mode);
///Mode of the Socket (no mock, mock, mock_record)
PSocketMode::PSocketMode p_mode;
///Socket to be used with the classical backend
typename _TBackend::Socket p_socket;
///Socket to be used with the mock backend
typename _TMockBackend::Socket p_mockSocket;
};
#include "PGenericSocket_impl.h"
#endif