Cleaning up drivers/Cpp, Cpp/Lifxtest, virtuals, and iotrmi/C++ (revisiting the C...
[iot2.git] / iotjava / iotrmi / C++ / IoTSocketServer.hpp
1 /** Class IoTSocketServer is a communication class
2  *  that provides interfaces to connect to either
3  *  Java or C++ socket endpoint. It inherits the
4  *  methods from IoTSocket.
5  *  <p>
6  *  Adapted from Java/C++ socket implementation
7  *  by Keith Vertanen
8  *  @see        <a href="https://www.keithv.com/software/socket/</a>
9  *
10  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
11  * @version     1.0
12  * @since       2016-08-17
13  */
14 #ifndef _IOTSOCKETSERVER_HPP__
15 #define _IOTSOCKETSERVER_HPP__
16
17 #include "IoTSocket.hpp"
18
19 #define BACKLOG 10      // How many pending connections queue will hold 
20
21 class IoTSocketServer final : public IoTSocket
22 {
23         public:
24                 IoTSocketServer(int iPort, bool* pResult);
25                 bool                    connect();      // Accept a new connection
26
27         protected:              
28                 bool                    m_bReverse;     // Am I reversing byte order or not?
29                 int                     m_iListen;      // Descriptor we are listening on
30                 struct sockaddr_in      m_addrMe;       // My address information
31 };
32
33
34 // Constructor
35 IoTSocketServer::IoTSocketServer(int iPort, bool* pResult) :
36         IoTSocket(iPort, pResult) {
37
38         m_iListen               = -1;
39         if (pResult)
40                 *pResult = false;
41         if ((m_iListen = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
42         {
43                 perror("IoTSocketServer: Socket error!");
44                 return;
45         }
46
47         m_addrMe.sin_family                     = AF_INET;          // Host byte order 
48         m_addrMe.sin_port                       = htons(m_iPort);       // Short, network byte order 
49         m_addrMe.sin_addr.s_addr        = INADDR_ANY;           // Auto-fill with my IP 
50         memset(&(m_addrMe.sin_zero), 0, 8);                             // Zero the rest of the struct 
51
52         if (bind(m_iListen, (struct sockaddr *) &m_addrMe, sizeof(struct sockaddr)) == -1) 
53         {
54                 // Note, this can fail if the server has just been shutdown and not enough time has elapsed.
55                 // See: http://www.developerweb.net/forum/showthread.php?t=2977 
56                 perror("IoTSocketServer: Bind error!");
57                 return;
58         }
59
60         if (listen(m_iListen, BACKLOG) == -1) 
61         {
62                 perror("IoTSocketServer: Listen error!");
63                 return;
64         }
65
66         if (pResult)
67                 *pResult = true;
68 }
69
70
71 // Wait for somebody to connect to us on our port.
72 bool IoTSocketServer::connect()
73 {
74         socklen_t iSinSize = (socklen_t) sizeof(struct sockaddr_in);
75         if ((m_iSock = accept(m_iListen, (struct sockaddr *) &m_addrRemote, &iSinSize)) == -1) 
76         {
77                 perror("IoTSocketServer: Accept connection error!");
78                 return false;
79         }
80
81         // The client sends us an int to indicate if we should
82         // be reversing byte order on this connection.  The client 
83         // is sending 0 or 1, so a reversed 0 still looks
84         // like a 0, no worries mate!
85         char temp[1];
86         int iTotal = 0;
87         int iResult = 0;
88         while ((iTotal < 1) && (iResult != -1))
89         {
90                 iResult = recv(m_iSock, temp, 1, 0);
91                 iTotal += iResult;
92         }
93
94         if (iResult == -1)
95         {
96                 perror("IoTSocketServer: Receive data error!");
97                 return false;
98         }
99
100         int iVal = temp[0];
101         if (iVal == 0) 
102                 m_bReverse = false;
103         else 
104                 m_bReverse = true;
105         
106         return true;
107 }
108
109 #endif