Skip to content

Commit 258a26b

Browse files
authored
Fix/socket unit test (#33)
* Rename callback functions and fix some bugs * Add new constructor and setters to the socket implementation, additionally fix error when passing the responsibility of raw pointers to smart ptrs. * Rename thread and callback handles in SocketDefines.h * Adjust socket unit test and add new check when receiving data by the receive callback
1 parent 656e714 commit 258a26b

File tree

6 files changed

+121
-73
lines changed

6 files changed

+121
-73
lines changed

Additional/ctlib/SocketDefines.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ struct PIL_SOCKET
6868
PIL_BOOL m_IsConnected;
6969
PIL_ErrorHandle m_ErrorHandle;
7070

71-
ThreadHandle *m_callbackThreadHandle;
71+
ThreadHandle *m_ReceiveCallbackThreadHandle;
7272
ReceiveThreadCallbackArgC *m_callbackThreadArg;
73-
PIL_BOOL m_callbackActive;
73+
PIL_BOOL m_ReceiveCallback;
7474

7575
} typedef PIL_SOCKET;
7676

Communication/include/ctlib/Socket.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,7 @@ PIL_ERROR_CODE PIL_SOCKET_RegisterReceiveCallbackFunction(PIL_SOCKET *socketRet,
5858
void (*callback)(PIL_SOCKET* socket, uint8_t *buffer, uint32_t len,
5959
void *), void *additional);
6060

61-
PIL_ERROR_CODE PIL_SOCKET_UnregisterCallbackFunction(PIL_SOCKET *socketRet);
62-
//#endif // PIL_THREADING
63-
64-
65-
61+
PIL_ERROR_CODE PIL_SOCKET_UnregisterReceiveCallbackFunction(PIL_SOCKET *socketRet);
6662

6763
/**
6864
* @}

Communication/include/ctlib/Socket.hpp

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,29 @@ namespace PIL
2121
class Socket
2222
{
2323
public:
24+
25+
struct ReceiveCallbackArg {
26+
explicit ReceiveCallbackArg(std::function<void(std::shared_ptr<PIL::Socket>&, std::string&)>& c): m_ReceiveCallback(c){
27+
}
28+
std::function<void(std::shared_ptr<PIL::Socket>&, std::string&)> &m_ReceiveCallback;
29+
std::shared_ptr<PIL::Socket> m_Socket = {};
30+
};
31+
32+
/**
33+
* @brief Workaround to pass std::functions to C-acceptCallback function.
34+
*/
35+
struct ThreadAcceptArg
36+
{
37+
/** Old C-threading function. */
38+
AcceptThreadArgC argC = {};
39+
/** Function pointer to C++ function returning PIL::Socket object. */
40+
std::function<void(std::unique_ptr<PIL::Socket> &)> acceptCallback = {};
41+
};
42+
43+
Socket();
2444
Socket(TransportProtocol transportProtocol, InternetProtocol internetProtocol, const std::string &address,
2545
int port, uint16_t timeoutInMS);
26-
Socket(std::unique_ptr<PIL_SOCKET> socket, std::string &ip, uint16_t port);
46+
Socket(std::shared_ptr<PIL_SOCKET> &socket, std::string &ip, uint16_t port);
2747
~Socket();
2848

2949
PIL_ERROR_CODE Bind(PIL_BOOL reuse);
@@ -44,35 +64,20 @@ namespace PIL
4464
PIL_ERROR_CODE Send(std::string &message);
4565
PIL_ERROR_CODE SendTo(std::string &destAddr, int port, uint8_t *buffer, int *bufferLen);
4666

47-
std::string GetSenderIP();
48-
PIL_ERROR_CODE GetInterfaceInfos(InterfaceInfoList *interfaceInfos);
49-
PIL_BOOL IsOpen();
50-
TransportProtocol GetTransportProtocol() const { return m_TransportProtocol; }
51-
InternetProtocol GetInternetProtocol() const { return m_InternetProtocol; }
52-
5367
PIL_ERROR_CODE CreateServerSocket(std::function<void(std::unique_ptr<PIL::Socket>&)> &receiveCallback);
54-
PIL_ERROR_CODE ConnectToServer(std::string &ipAddr, int destPort, std::function<void(std::unique_ptr<Socket>& , std::string &)> &receiveCallback);
55-
56-
57-
struct ReceiveCallbackArg {
58-
explicit ReceiveCallbackArg(std::function<void(std::unique_ptr<PIL::Socket>&, std::string&)>& c): m_ReceiveCallback(c){
59-
}
60-
std::function<void(std::unique_ptr<PIL::Socket>&, std::string&)> &m_ReceiveCallback;
61-
std::unique_ptr<PIL::Socket> m_Socket = {};
62-
};
68+
PIL_ERROR_CODE ConnectToServer(std::string &ipAddr, int destPort, std::function<void(std::shared_ptr<Socket>& , std::string &)> &receiveCallback);
6369

6470
PIL_ERROR_CODE RegisterReceiveCallbackFunction(ReceiveCallbackArg& additionalArg);
65-
PIL_ERROR_CODE UnregisterCallbackFunction();
71+
PIL_ERROR_CODE UnregisterAllCallbackFunctions();
6672

67-
/**
68-
* @brief Workaround to pass std::functions to C-acceptCallback function.
69-
*/
70-
struct ThreadAcceptArg {
71-
/** Old C-threading function. */
72-
AcceptThreadArgC argC = {};
73-
/** Function pointer to C++ function returning PIL::Socket object. */
74-
std::function<void(std::unique_ptr<PIL::Socket>&)> acceptCallback = {};
75-
};
73+
std::string GetSenderIPAddress();
74+
PIL_ERROR_CODE GetInterfaceInfos(InterfaceInfoList *interfaceInfos);
75+
PIL_BOOL IsOpen();
76+
TransportProtocol GetTransportProtocol() const { return m_TransportProtocol; }
77+
InternetProtocol GetInternetProtocol() const { return m_InternetProtocol; }
78+
void setPort(uint16_t mPort);
79+
void setIPAddress(const std::string &mIpAddress);
80+
void setSocketHandle(const std::shared_ptr<PIL_SOCKET> &mCSocketHandle);
7681

7782
private:
7883
uint16_t m_Port;
@@ -81,10 +86,12 @@ namespace PIL
8186
InternetProtocol m_InternetProtocol;
8287
uint16_t m_TimeoutInMS;
8388

84-
std::unique_ptr<PIL_SOCKET> m_CSocketHandle;
89+
90+
std::shared_ptr<PIL_SOCKET> m_CSocketHandle;
8591
std::vector<std::unique_ptr<PIL_SOCKET>> m_SocketList;
8692
// std::unique_ptr<ThreadAcceptArg> m_ThreadArg;
8793
std::unique_ptr<PIL::Threading<ThreadAcceptArg>> m_AcceptThread;
94+
std::unique_ptr<ReceiveCallbackArg> m_ReceiveCallback;
8895
PIL_ERROR_CODE RegisterAcceptCallback(std::function<void(std::unique_ptr<PIL::Socket>&)> &f);
8996
};
9097

Communication/src/Socket.c

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,11 @@ PIL_ERROR_CODE PIL_SOCKET_Close(PIL_SOCKET *socketRet)
123123
if (!socketRet)
124124
return PIL_INVALID_ARGUMENTS;
125125

126-
if(socketRet->m_callbackActive == TRUE)
127-
PIL_SOCKET_UnregisterCallbackFunction(socketRet);
126+
if(!socketRet->m_IsOpen)
127+
return PIL_NO_ERROR;
128+
129+
if(socketRet->m_ReceiveCallback == TRUE)
130+
PIL_SOCKET_UnregisterReceiveCallbackFunction(socketRet);
128131

129132
#ifndef embedded
130133
if (socketRet->m_IsOpen)
@@ -435,13 +438,13 @@ PIL_ERROR_CODE PIL_SOCKET_Receive(PIL_SOCKET *socketRet, uint8_t *buffer, uint32
435438
*/
436439
void* PIL_ReceiveThreadFunction(void *handle)
437440
{
438-
assert(handle);
441+
assert(handle);
439442
ReceiveThreadCallbackArgC *arg = (ReceiveThreadCallbackArgC*) handle;
440443
assert(arg->socket && arg->receiveCallback);
441444

442445
uint8_t buffer[DEFAULT_SOCK_BUFF_SIZE];
443446
uint32_t len = DEFAULT_SOCK_BUFF_SIZE;
444-
while(arg->socket->m_callbackActive)
447+
while(arg->socket->m_ReceiveCallback)
445448
{
446449
memset(buffer, 0, DEFAULT_SOCK_BUFF_SIZE);
447450
PIL_ERROR_CODE ret = PIL_SOCKET_WaitTillDataAvail(arg->socket, DEFAULT_TIMEOUT_MS);
@@ -455,9 +458,7 @@ void* PIL_ReceiveThreadFunction(void *handle)
455458
{
456459
ret = PIL_SOCKET_Receive(arg->socket, buffer, &len, 0);
457460
if(ret == PIL_NO_ERROR)
458-
{
459461
arg->receiveCallback(arg->socket, buffer, len, arg->additionalArg);
460-
}
461462
}
462463
}
463464
return arg;
@@ -481,20 +482,20 @@ PIL_ERROR_CODE PIL_SOCKET_RegisterReceiveCallbackFunction(PIL_SOCKET *socketRet,
481482
socketRet->m_callbackThreadArg ->receiveCallback = callback;
482483
socketRet->m_callbackThreadArg ->additionalArg = additional;
483484

484-
socketRet->m_callbackThreadHandle = malloc(sizeof(ThreadHandle));
485-
socketRet->m_callbackThreadHandle->m_ThreadArgument.m_ThreadArgument = (void*)&socketRet->m_callbackThreadArg ;
486-
socketRet->m_callbackThreadHandle->m_ThreadArgument.m_ThreadFunction = PIL_ReceiveThreadFunction;
487-
PIL_ERROR_CODE createSockRet = PIL_THREADING_CreateThread(socketRet->m_callbackThreadHandle, PIL_ReceiveThreadFunction, (void*)socketRet->m_callbackThreadArg);
485+
socketRet->m_ReceiveCallbackThreadHandle = malloc(sizeof(ThreadHandle));
486+
socketRet->m_ReceiveCallbackThreadHandle->m_ThreadArgument.m_ThreadArgument = (void*)&socketRet->m_callbackThreadArg ;
487+
socketRet->m_ReceiveCallbackThreadHandle->m_ThreadArgument.m_ThreadFunction = PIL_ReceiveThreadFunction;
488+
PIL_ERROR_CODE createSockRet = PIL_THREADING_CreateThread(socketRet->m_ReceiveCallbackThreadHandle, PIL_ReceiveThreadFunction, (void*)socketRet->m_callbackThreadArg);
488489
if (createSockRet == PIL_NO_ERROR)
489490
{
490-
socketRet->m_callbackActive = TRUE;
491-
createSockRet = PIL_THREADING_RunThread(socketRet->m_callbackThreadHandle, FALSE);
491+
socketRet->m_ReceiveCallback = TRUE;
492+
createSockRet = PIL_THREADING_RunThread(socketRet->m_ReceiveCallbackThreadHandle, FALSE);
492493
}
493494

494495
if (createSockRet != PIL_NO_ERROR)
495496
{
496-
free(socketRet->m_callbackThreadHandle);
497-
socketRet->m_callbackThreadHandle = NULL;
497+
free(socketRet->m_ReceiveCallbackThreadHandle);
498+
socketRet->m_ReceiveCallbackThreadHandle = NULL;
498499
free(socketRet->m_callbackThreadArg);
499500
socketRet->m_callbackThreadArg = NULL;
500501
return createSockRet;
@@ -508,19 +509,19 @@ PIL_ERROR_CODE PIL_SOCKET_RegisterReceiveCallbackFunction(PIL_SOCKET *socketRet,
508509
* @param socketRet socket for which the callback was registered.
509510
* @return PIL_NO_ERROR on success.
510511
*/
511-
PIL_ERROR_CODE PIL_SOCKET_UnregisterCallbackFunction(PIL_SOCKET *socketRet)
512+
PIL_ERROR_CODE PIL_SOCKET_UnregisterReceiveCallbackFunction(PIL_SOCKET *socketRet)
512513
{
513514
if (!socketRet)
514515
return PIL_INVALID_ARGUMENTS;
515516

516-
if (socketRet->m_callbackActive)
517+
if (socketRet->m_ReceiveCallback)
517518
{
518-
socketRet->m_callbackActive = FALSE;
519-
if (!socketRet->m_callbackThreadHandle)
519+
socketRet->m_ReceiveCallback = FALSE;
520+
if (!socketRet->m_ReceiveCallbackThreadHandle)
520521
return PIL_INVALID_ARGUMENTS;
521-
PIL_ERROR_CODE ret = PIL_THREADING_JoinThread(socketRet->m_callbackThreadHandle, NULL);
522-
free(socketRet->m_callbackThreadHandle);
523-
socketRet->m_callbackThreadHandle = NULL;
522+
PIL_ERROR_CODE ret = PIL_THREADING_JoinThread(socketRet->m_ReceiveCallbackThreadHandle, NULL);
523+
free(socketRet->m_ReceiveCallbackThreadHandle);
524+
socketRet->m_ReceiveCallbackThreadHandle = NULL;
524525
free(socketRet->m_callbackThreadArg);
525526
socketRet->m_callbackThreadArg = NULL;
526527
if (ret != PIL_NO_ERROR)

Communication/src/Socket.cpp

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@ extern "C" {
1818

1919
namespace PIL
2020
{
21-
Socket::Socket(std::unique_ptr<PIL_SOCKET> socket, std::string &ip, uint16_t port) :
22-
m_CSocketHandle(std::move(socket)), m_IPAddress(ip), m_Port(port),
21+
Socket::Socket(): m_IPAddress(""), m_Port(0),
22+
m_TransportProtocol(TCP), m_InternetProtocol(IPv4), m_TimeoutInMS(0){
23+
24+
}
25+
26+
Socket::Socket(std::shared_ptr<PIL_SOCKET> &socket, std::string &ip, uint16_t port) :
27+
m_CSocketHandle(socket), m_IPAddress(ip), m_Port(port),
2328
m_TransportProtocol(TCP), m_InternetProtocol(IPv4), m_TimeoutInMS(0){
2429
}
2530

@@ -40,7 +45,7 @@ namespace PIL
4045
}
4146

4247
PIL_ERROR_CODE Socket::Disconnect(){
43-
auto retCode = UnregisterCallbackFunction();
48+
auto retCode = UnregisterAllCallbackFunctions();
4449
if(retCode != PIL_NO_ERROR){
4550
#ifdef PIL_EXCEPTION_HANDLING
4651
throw PIL::Exception(retCode, __FILENAME__, __LINE__);
@@ -164,7 +169,7 @@ namespace PIL
164169
return ret;
165170
}
166171

167-
std::string Socket::GetSenderIP(){
172+
std::string Socket::GetSenderIPAddress(){
168173
const char *senderIP = PIL_SOCKET_GetSenderIP(m_CSocketHandle.get());
169174
#ifdef PIL_EXCEPTION_HANDLING
170175
if(!senderIP)
@@ -182,11 +187,15 @@ namespace PIL
182187

183188
char ipAddr[MAX_IP_LEN];
184189

190+
std::unique_ptr<PIL::Socket> socketPtr = std::make_unique<PIL::Socket>();
185191
do {
186192
if(!arg->argC.socket->m_IsOpen){
187193
return arg.get();
188194
}
189-
std::unique_ptr<PIL_SOCKET> retHandle = std::make_unique<PIL_SOCKET>();
195+
auto retHandle = std::make_shared<PIL_SOCKET>();
196+
retHandle->m_IsOpen = TRUE;
197+
retHandle->m_ReceiveCallback = FALSE;
198+
190199
int ret = PIL_SOCKET_Accept(arg->argC.socket, ipAddr, retHandle.get());
191200
if(ret == PIL_INTERFACE_CLOSED)
192201
return arg.get();
@@ -199,7 +208,11 @@ namespace PIL
199208
retHandle->m_IsOpen = TRUE;
200209
retHandle->m_IsConnected = TRUE;
201210
std::string ipStr = ipAddr;
202-
std::unique_ptr<PIL::Socket> socketPtr = std::make_unique<PIL::Socket>(std::move(retHandle), ipStr, retHandle->m_port);
211+
212+
socketPtr->setSocketHandle(retHandle);
213+
socketPtr->setIPAddress(ipStr);
214+
socketPtr->setPort(retHandle->m_port);
215+
203216
arg->acceptCallback(socketPtr);
204217
}while(arg->argC.socket->m_IsOpen);
205218
return arg.get();
@@ -235,7 +248,7 @@ namespace PIL
235248
}
236249

237250
PIL_ERROR_CODE
238-
Socket::ConnectToServer(std::string &ipAddr, int destPort, std::function<void(std::unique_ptr<Socket>& , std::string &)> &receiveCallback){
251+
Socket::ConnectToServer(std::string &ipAddr, int destPort, std::function<void(std::shared_ptr<Socket>& , std::string &)> &receiveCallback){
239252
auto functionPtr = [](PIL_SOCKET* socket, uint8_t *buffer, uint32_t bufferLen, void* additionalArg){
240253
if(!additionalArg){
241254
#ifdef PIL_EXCEPTION_HANDLING
@@ -244,16 +257,30 @@ namespace PIL
244257
return;
245258
}
246259
std::string ip = socket->m_IPAddress;
247-
std::unique_ptr<PIL_SOCKET> s = std::unique_ptr<PIL_SOCKET>(socket);
248-
std::unique_ptr<PIL::Socket> socketCXX = std::make_unique<PIL::Socket>(std::move(s), ip, socket->m_port);
260+
261+
// Create new socket object now managed by shared_ptr
262+
auto sock = new PIL_SOCKET;
263+
*sock = *socket;
264+
265+
std::shared_ptr<PIL_SOCKET> s = std::shared_ptr<PIL_SOCKET>(sock);
266+
267+
// Set old socket to closed!
268+
socket->m_IsOpen = FALSE;
269+
socket->m_IsConnected = FALSE;
270+
271+
s->m_IsOpen = TRUE;
272+
s->m_ReceiveCallback = FALSE;
273+
274+
auto socketCXX = std::make_shared<PIL::Socket>(s, ip, socket->m_port);
249275
std::string value = std::string((char *)buffer, bufferLen);
250-
auto *arg = reinterpret_cast<ReceiveCallbackArg*>(additionalArg);
251-
arg->m_ReceiveCallback(socketCXX, value);
276+
auto *callbackFunction = reinterpret_cast<std::unique_ptr<ReceiveCallbackArg>*>(additionalArg);
277+
(*callbackFunction)->m_ReceiveCallback(socketCXX, value);
252278
};
253279

280+
m_ReceiveCallback = std::move(std::make_unique<ReceiveCallbackArg>(receiveCallback));
254281
auto ret = PIL_SOCKET_ConnectToServer(m_CSocketHandle.get(), ipAddr.c_str(),
255282
m_Port, destPort, m_TimeoutInMS, functionPtr,
256-
&receiveCallback);
283+
&m_ReceiveCallback);
257284
#ifdef PIL_EXCEPTION_HANDLING
258285
if(ret != PIL_NO_ERROR)
259286
throw PIL::Exception(ret, __FILENAME__, __LINE__);
@@ -268,8 +295,8 @@ namespace PIL
268295
std::string ip = socket->m_IPAddress;
269296
std::string value = std::string((char *)buffer, bufferLen);
270297
auto *arg = reinterpret_cast<ReceiveCallbackArg*>(additionalArg);
271-
auto s = std::unique_ptr<PIL_SOCKET>(socket);
272-
arg->m_Socket = std::make_unique<PIL::Socket>(std::move(s), ip, socket->m_port);
298+
auto s = std::shared_ptr<PIL_SOCKET>(socket);
299+
arg->m_Socket = std::make_shared<PIL::Socket>(s, ip, socket->m_port);
273300
arg->m_ReceiveCallback(arg->m_Socket, value);
274301
};
275302

@@ -281,10 +308,10 @@ namespace PIL
281308
return ret;
282309
}
283310

284-
PIL_ERROR_CODE Socket::UnregisterCallbackFunction(){
311+
PIL_ERROR_CODE Socket::UnregisterAllCallbackFunctions(){
285312
if(m_CSocketHandle == nullptr)
286313
return PIL_NO_ERROR;
287-
auto ret = PIL_SOCKET_UnregisterCallbackFunction(m_CSocketHandle.get());
314+
auto ret = PIL_SOCKET_UnregisterReceiveCallbackFunction(m_CSocketHandle.get());
288315
#ifdef PIL_EXCEPTION_HANDLING
289316
if(ret != PIL_NO_ERROR)
290317
throw PIL::Exception(ret, __FILENAME__, __LINE__);
@@ -302,5 +329,20 @@ namespace PIL
302329
return ret;
303330
}
304331

332+
void Socket::setPort(uint16_t mPort)
333+
{
334+
m_Port = mPort;
335+
}
336+
337+
void Socket::setIPAddress(const std::string &mIpAddress)
338+
{
339+
m_IPAddress = mIpAddress;
340+
}
341+
342+
void Socket::setSocketHandle(const std::shared_ptr<PIL_SOCKET> &mCSocketHandle)
343+
{
344+
m_CSocketHandle = mCSocketHandle;
345+
}
346+
305347
}
306348
#endif // PIL_CXX

UnitTesting/SocketUnitTest.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ void ReceiveHandlerC(PIL_SOCKET *socket, uint8_t* buffer, uint32_t len, void*)
2727
}
2828

2929

30-
void ReceiveHandlerCPP(std::unique_ptr<PIL::Socket> &socket, std::string& buffer)
30+
void ReceiveHandlerCPP(std::shared_ptr<PIL::Socket> &socket, std::string& buffer)
3131
{
3232
strncpy(recvBuff, (char*)buffer.c_str(), buffer.length());
33+
EXPECT_TRUE(strcmp(recvBuff, loram_ipsum.c_str()) == 0);
3334
}
3435

3536

@@ -88,8 +89,9 @@ TEST(SocketTest_CPP, SimpleSocketTest)
8889
EXPECT_EQ(ret, PIL_NO_ERROR);
8990
PIL::Socket clientSock(TCP, IPv4, "localhost", 14003, 1000);
9091
std::string destIP = "127.0.0.1";
91-
std::function<void(std::unique_ptr<PIL::Socket>& , std::string &)> callbackFunc = ReceiveHandlerCPP;
92+
std::function<void(std::shared_ptr<PIL::Socket>& , std::string &)> callbackFunc = ReceiveHandlerCPP;
9293
ret = clientSock.ConnectToServer(destIP, 14002, callbackFunc);
94+
std::this_thread::sleep_for(std::chrono::microseconds(10000));
9395
EXPECT_EQ(ret, PIL_NO_ERROR);
9496
}
9597

0 commit comments

Comments
 (0)