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>
36 #include "IoTRMIUtil.hpp"
38 // Duplicated from winsock2.h
39 #define SD_RECEIVE 0x00
50 IoTSocket(int iPort, bool* pResult);
53 bool close(); // Close the socket
54 bool sendBytes(char* pVals, int _iLen); // Send a set of bytes
55 char* receiveBytes(char* pVals, int* len); // Receive a set of bytes
58 int m_iPort; // Port I'm listening on
59 int m_iSock; // Socket connection
60 struct sockaddr_in m_addrRemote; // Connector's address information
61 double* m_pBuffer; // Reuse the same memory for buffer
70 IoTSocket::IoTSocket(int iPort, bool* pResult) {
76 // Allocate our temporary buffers that are used to convert data types
77 m_pBuffer = (double *) malloc(sizeof(double) * SOCKET_BUFF_SIZE);
79 perror("IoTSocket: Failed to malloc buffer!");
87 IoTSocket::~IoTSocket() {
96 // Send bytes over the wire
97 bool IoTSocket::sendBytes(char* pVals, int iLen) {
99 // Critical section that is used by different objects
100 lock_guard<mutex> guard(sendBytesMutex);
103 char size[MSG_LEN_SIZE];
104 // Convert int to byte array and fix endianness
105 IoTRMIUtil::intToByteArray(iLen, size);
107 if (send(m_iSock, size, MSG_LEN_SIZE, 0) == -1) {
108 perror("IoTSocket: Send size error!");
112 IoTRMIUtil::printBytes(size, 4, false);
114 if (send(m_iSock, (char *) pVals, iLen, 0) == -1) {
115 perror("IoTSocket: Send bytes error!");
130 // Receive bytes, returns number of bytes received
131 // Generate an array of char on the heap and return it
132 char* IoTSocket::receiveBytes(char* pVals, int* len)
134 // Critical section that is used by different objects
135 lock_guard<mutex> guard(recvBytesMutex);
146 char size[MSG_LEN_SIZE];
148 while ((iTotal < 1) && (iResult != -1)) {
149 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)