1 #include <ciso646>
2 #include <string.h>
3 #ifdef __unix__
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <sys/time.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <arpa/inet.h>
10 #else
11 #include <windows.h>
12 #endif
13 #include <fcntl.h>
14 #include <thread>
15 #include <chrono>
16 #include "LMS64CProtocol.h"
17 #include "Logger.h"
18 #include "threadHelper.h"
19 
20 namespace lime
21 {
22 
InitRemote()23 void LMS64CProtocol::InitRemote()
24 {
25     remoteOpen = true;
26     socketFd = -1;
27     const int port = 5000;
28 #ifndef __unix__
29     WSADATA wsaData;
30     if( int err = WSAStartup(0x0202, &wsaData))
31         lime::log(LOG_LEVEL_ERROR, "RemoteControl: WSAStartup error %i\n", err);
32 #endif
33 
34     socketFd = socket(AF_INET, SOCK_STREAM, 0);
35     if(socketFd < 0)
36     {
37         lime::log(LOG_LEVEL_ERROR, "RemoteControl: socket error %i\n", socketFd);
38         return;
39     }
40 #ifdef __unix__
41     fcntl(socketFd, F_SETFL, O_NONBLOCK);
42 #else
43     u_long NonBlock = 1;
44     ioctlsocket(socketFd, FIONBIO, &NonBlock);
45 #endif
46 
47     struct sockaddr_in host;
48     memset((void *)&host, 0, sizeof(sockaddr_in));
49     host.sin_family = AF_INET;
50     host.sin_addr.s_addr = INADDR_ANY;
51     host.sin_port = htons(port);
52     if(bind(socketFd, (struct sockaddr*)&host, sizeof(host)) < 0)
53     {
54         lime::log(LOG_LEVEL_ERROR, "RemoteControl: bind error on port %i\n", port);
55         CloseRemote();
56         return;
57     }
58 
59     lime::log(LOG_LEVEL_INFO, "RemoteControl Listening on port: %i\n", port);
60     if(int error = listen(socketFd, SOMAXCONN) )
61     {
62 #ifndef __unix__
63         error =  WSAGetLastError();
64 #endif
65         lime::log(LOG_LEVEL_ERROR, "RemoteControl listen error %i\n", error);
66         CloseRemote();
67         return;
68     }
69 
70     remoteThread = std::thread(&LMS64CProtocol::ProcessConnections, this);
71     SetOSThreadPriority(ThreadPriority::LOW, ThreadPolicy::DEFAULT, &remoteThread);
72     if(not remoteThread.joinable())
73     {
74         lime::log(LOG_LEVEL_ERROR, "RemoteControl: Error creating listening thread\n");
75         CloseRemote();
76         return;
77     }
78     return;
79 }
80 
CloseRemote()81 void LMS64CProtocol::CloseRemote()
82 {
83     if (!remoteOpen)
84         return;
85     remoteOpen = false;
86 
87     if(remoteThread.joinable())
88         remoteThread.join();
89 
90     if(socketFd > 0)
91     {
92 #ifndef __unix__
93     //shutdown(socketFd, SD_BOTH);
94     closesocket(socketFd);
95 #else
96     shutdown(socketFd, SHUT_RDWR);
97     close(socketFd);
98 #endif
99     }
100 
101 #ifndef __unix__
102     WSACleanup();
103 #endif
104 }
105 
106 
ProcessConnections()107 void LMS64CProtocol::ProcessConnections()
108 {
109     struct sockaddr_in cli_addr;
110 #ifndef __unix__
111     SOCKET clientFd;
112     int clilen = sizeof(cli_addr);
113 #else
114     int clientFd;
115     unsigned int clilen = sizeof(cli_addr);
116 #endif // __unix__
117 
118     while(remoteOpen && socketFd >= 0)
119     {
120         memset(&cli_addr, 0, sizeof(cli_addr));
121         clientFd = accept(socketFd, (struct sockaddr*)&cli_addr, &clilen);
122 
123         //if(clientFd == EAGAIN || clientFd == EWOULDBLOCK)
124             //continue;
125         if(clientFd < 0)
126         {
127             continue;
128         }
129 
130         bool connected = true;
131 
132         const int msgSize = 64;
133         char data[msgSize] = {0};
134 
135         while(connected && remoteOpen)
136         {
137             unsigned int r = 0;
138             do
139             {
140                 int brecv = recv(clientFd, data+r, msgSize-r, 0);
141                 r += brecv;
142                 if(brecv == 0)
143                 {
144                     connected = false;
145                     break;
146                 }
147                 if(brecv < 0 )
148                 {
149 #ifndef __unix__
150                     brecv = WSAGetLastError();
151 #endif
152                     lime::log(LOG_LEVEL_ERROR, "RemoteControl recv with error: %d\n", brecv);
153                     connected = false;
154                     break;
155                 }
156             }
157             while(r < msgSize);
158 
159             if(not connected)
160                 break;
161 
162             mControlPortLock.lock();
163             Write((unsigned char*)data, msgSize);
164             Read((unsigned char*)data, msgSize);
165             mControlPortLock.unlock();
166 
167             int bsent = 0;
168             while(bsent < msgSize)
169             {
170                 int r = send(clientFd, data+bsent, msgSize-bsent, 0);
171                 if(r < 0)
172                 {
173                     lime::log(LOG_LEVEL_ERROR, "RemoteControl send with error: %d\n", r);
174                     connected = false;
175                     break;
176                 }
177                 bsent += r;
178             }
179         }
180         if (clientFd >= 0)
181         {
182 #ifndef __unix__
183             //shutdown(socketFd, SD_BOTH);
184             closesocket(clientFd);
185 #else
186             shutdown(clientFd, SHUT_RDWR);
187             close(clientFd);
188 #endif
189         }
190     }
191     return;
192 }
193 
194 
195 }
196