1 /** Class IoTSocket is a base class for IoTSocketServer.cpp
2 * and IoTSocketClient.cpp that provide interfaces to connect
3 * to either Java or C++ socket endpoint
5 * Adapted from Java/C++ socket implementation
7 * @see <a href="https://www.keithv.com/software/socket/</a>
9 * @author Rahmadi Trimananda <rtrimana @ uci.edu>
13 #ifndef _IOTSOCKET_HPP__
14 #define _IOTSOCKET_HPP__
16 // Adds in the send/recv acks after each message.
19 static const int SOCKET_BUFF_SIZE = 64000;
20 // Before, it was too short as we were just using 1 byte to receive the length
21 // Now, we allocate 4 bytes (a size of integer) to receive the message length
22 static const int MSG_LEN_SIZE = 4;
28 #include <sys/types.h>
30 #include <netinet/in.h>
32 #include <sys/socket.h>
37 #include "IoTRMIUtil.hpp"
39 // Duplicated from winsock2.h
40 #define SD_RECEIVE 0x00
51 IoTSocket(int iPort, bool* pResult);
54 bool close(); // Close the socket
55 bool sendBytes(char* pVals, int _iLen); // Send a set of bytes
56 char* receiveBytes(char* pVals, int* len); // Receive a set of bytes
59 int m_iPort; // Port I'm listening on
60 int m_iSock; // Socket connection
61 struct sockaddr_in m_addrRemote; // Connector's address information
62 double* m_pBuffer; // Reuse the same memory for buffer
71 IoTSocket::IoTSocket(int iPort, bool* pResult) {
77 // Allocate our temporary buffers that are used to convert data types
78 m_pBuffer = (double *) malloc(sizeof(double) * SOCKET_BUFF_SIZE);
80 perror("IoTSocket: Failed to malloc buffer!");
88 IoTSocket::~IoTSocket() {
97 // Send bytes over the wire
98 bool IoTSocket::sendBytes(char* pVals, int iLen) {
100 // Critical section that is used by different objects
101 lock_guard<mutex> guard(sendBytesMutex);
104 char size[MSG_LEN_SIZE];
105 // Convert int to byte array and fix endianness
106 IoTRMIUtil::intToByteArray(iLen, size);
108 if (send(m_iSock, size, MSG_LEN_SIZE, 0) == -1) {
109 perror("IoTSocket: Send size error!");
113 if (send(m_iSock, (char *) pVals, iLen, 0) == -1) {
114 perror("IoTSocket: Send bytes error!");
129 // Receive bytes, returns number of bytes received
130 // Generate an array of char on the heap and return it
131 char* IoTSocket::receiveBytes(char* pVals, int* len)
133 // Critical section that is used by different objects
134 lock_guard<mutex> guard(recvBytesMutex);
145 char size[MSG_LEN_SIZE];
147 while ((iTotal < 1) && (iResult != -1)) {
148 iResult = recv(m_iSock, size, MSG_LEN_SIZE, 0);
153 perror("IoTSocket: Receive size error!");
156 // Convert byte to int array based on correct endianness
158 IoTRMIUtil::byteArrayToInt(&iLen, size);
160 // To be returned from this method...
162 pVals = new char[iLen];
163 pTemp = (char *) m_pBuffer;
164 // We receiving the incoming ints one byte at a time.
166 if ((iNumBytes = recv(m_iSock, pTemp, SOCKET_BUFF_SIZE, 0)) == -1) {
167 perror("IoTSocket: Receive error!");
170 for (i = 0; i < iNumBytes; i++) {
174 iTotalBytes += iNumBytes;
175 if (iTotalBytes == iLen)
189 // Shut down the socket
190 bool IoTSocket::close()
192 if (shutdown(m_iSock, SD_BOTH) == -1) {
193 perror("IoTSocket: Close error!");
201 // Receive a short ack from the client
202 bool IoTSocket::receiveAck()
204 // Critical section that is used by different objects
205 lock_guard<mutex> guard(recvAckMutex);
209 while ((iTotal < 1) && (iResult != -1)) {
211 iResult = recv(m_iSock, temp, 1, 0);
216 perror("IoTSocket: ReceiveAck error!");
224 // Send a short ack to the client
225 bool IoTSocket::sendAck()
227 // Critical section that is used by different objects
228 lock_guard<mutex> guard(sendAckMutex);
232 if (send(m_iSock, temp, 1, 0) == -1)