1+ // The MIT License (MIT)
2+
3+ // Copyright (c) Microsoft Corporation
4+
5+ // Permission is hereby granted, free of charge, to any person obtaining a copy
6+ // of this software and associated documentation files (the "Software"), to deal
7+ // in the Software without restriction, including without limitation the rights
8+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ // copies of the Software, and to permit persons to whom the Software is
10+ // furnished to do so, subject to the following conditions:
11+
12+ // The above copyright notice and this permission notice shall be included in
13+ // all copies or substantial portions of the Software.
14+
15+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+ // THE SOFTWARE.
22+
23+ // Portions of this repo are provided under the SIL Open Font License.
24+ // See the LICENSE file in individual samples for additional details.
25+
26+ #include < iostream>
27+ #include < fstream>
28+ #include < stdlib.h>
29+ #include < vector>
30+ #include < string>
31+ #include < chrono>
32+
33+ #ifndef _WIN32
34+ #include < netdb.h>
35+ #include < sys/select.h>
36+ #include < sys/socket.h>
37+ #include < sys/un.h>
38+ #include < unistd.h>
39+ #include < poll.h>
40+ #include < cerrno>
41+ #else
42+ #include < winsock2.h>
43+ #include < ws2tcpip.h>
44+ #include < mstcpip.h>
45+ #include < process.h>
46+ #endif
47+
48+ constexpr char socket_path[14 ]{" tmpsoc" };
49+
50+ #ifndef _WIN32
51+ constexpr int INVALID_SOCKET = -1 ;
52+ constexpr int SOCKET_ERROR = -1 ;
53+ using SOCKET = int ;
54+ static inline int WSAGetLastError () {
55+ return errno;
56+ }
57+ #else
58+ static inline const int poll (LPWSAPOLLFD fdArray, ULONG fds, INT timeout) {
59+ return WSAPoll (fdArray, fds, timeout);
60+ }
61+ static inline const int close (SOCKET ConnectSocket) {
62+ int result = closesocket (ConnectSocket);
63+ WSACleanup ();
64+ return result;
65+ }
66+ #endif
67+
68+ static int readDataFromFile (std::string inputCmdsList, std::vector<std::string>& filenames) {
69+ std::ifstream inputf;
70+ inputf.open (inputCmdsList);
71+ if (inputf.is_open ()) {
72+ std::string line;
73+ while (getline (inputf, line)) {
74+ filenames.push_back (line);
75+ }
76+ filenames.push_back (" finish" );
77+ inputf.close ();
78+ return 0 ;
79+ }
80+ std::cout << " Error opening file" ;
81+ return -1 ;
82+ }
83+
84+ int usoc_manager (int isNoPresent, std::string& inputCmdsList) {
85+ sockaddr addr;
86+ std::vector<std::string> filenames;
87+ if (readDataFromFile (inputCmdsList, filenames) == -1 ) {
88+ return 1 ;
89+ }
90+
91+ SOCKET listen_sd;
92+ if ((listen_sd = socket (AF_UNIX , SOCK_STREAM , 0 )) == -1 ) {
93+ perror (" socket error" );
94+ exit (-1 );
95+ }
96+
97+ unlink (socket_path);
98+
99+ memset (&addr, 0 , sizeof (addr));
100+ addr.sa_family = AF_UNIX ;
101+ strncpy (addr.sa_data , socket_path, sizeof (addr.sa_data ) - 1 );
102+
103+ if (bind (listen_sd, (struct sockaddr *)&addr, sizeof (addr)) == -1 ) {
104+ perror (" bind error" );
105+ exit (-1 );
106+ }
107+
108+ if (listen (listen_sd, 256 ) == -1 ) {
109+ perror (" listen error" );
110+ exit (-1 );
111+ }
112+
113+ pollfd fdarray;
114+ constexpr int DEFAULT_WAIT = 30000 ;
115+ int ret;
116+ SOCKET lsock = INVALID_SOCKET , asock = INVALID_SOCKET ;
117+ int stop_server = 0 ;
118+ for (int i = 0 ; !stop_server;) {
119+ fdarray.fd = listen_sd;
120+ fdarray.events = POLLIN | POLLOUT ;
121+ int data_sent = 0 ;
122+
123+ data_sent = 0 ;
124+ printf (" Manager: poll is waiting for incoming events (timeout %d s)\n " , DEFAULT_WAIT / 1000 );
125+ if (SOCKET_ERROR == (ret = poll (&fdarray, 1 , DEFAULT_WAIT ))) {
126+ printf (" Main: poll operation failed: %d\n " , WSAGetLastError ());
127+ return 1 ;
128+ }
129+
130+ if (ret == 0 ) {
131+ stop_server = 1 ;
132+ }
133+
134+ if (ret) {
135+ if (fdarray.revents & POLLIN ) {
136+ printf (" Manager: Connection established.\n " );
137+
138+ if (INVALID_SOCKET == (asock = accept (listen_sd, NULL , NULL ))) {
139+ WSAGetLastError ();
140+ return 1 ;
141+ }
142+ char buf[512 ] = {0 };
143+ if (SOCKET_ERROR == (ret = recv (asock, buf, sizeof (buf), 0 ))) {
144+ WSAGetLastError ();
145+ return 1 ;
146+ } else
147+ printf (" Manager: recvd %d bytes\n " , ret);
148+ if (ret) {
149+ i = std::min<int >(i, (int )filenames.size () - 1 );
150+ if (SOCKET_ERROR == (ret = send (asock, filenames[i].c_str (), (int )filenames[i].length () + 1 , 0 ))) {
151+ printf (" Manager: send socket failed %d \n " , WSAGetLastError ());
152+ return 1 ;
153+ }
154+ printf (" Manager: sent %d bytes\n " , ret);
155+ data_sent = 1 ;
156+ }
157+ if (ret) {
158+ if (SOCKET_ERROR == (ret = recv (asock, buf, sizeof (buf), 0 ))) {
159+ WSAGetLastError ();
160+ return 1 ;
161+ } else if (ret >= 8 ) {
162+ printf (" Manager: recvd confirm %d bytes\n " , ret);
163+ if (strncmp (" received" , buf, 8 ) == 0 ) {
164+ i++;
165+ }
166+ }
167+ }
168+ }
169+ }
170+ }
171+
172+ close (fdarray.fd );
173+ return 0 ;
174+ }
175+
176+ constexpr int DEFAULT_BUFLEN = 512 ;
177+
178+ // The following function is a further modification of the main function from the file at the link below:
179+ // https://learn.microsoft.com/en-us/windows/win32/winsock/complete-client-code
180+ int clientConnectServer (std::string& recvbuf, const char * usocfilename) {
181+ int iResult;
182+ #if defined(_WIN32)
183+ WSADATA wsaData;
184+ iResult = WSAStartup (MAKEWORD (2 , 2 ), &wsaData);
185+ if (iResult != 0 ) {
186+ printf (" WSAStartup failed with error: %d\n " , iResult);
187+ return 1 ;
188+ }
189+ #endif
190+ sockaddr saddr{saddr.sa_family = AF_UNIX };
191+ strncpy (saddr.sa_data , socket_path, sizeof (socket_path));
192+ SOCKET ConnectSocket = socket (AF_UNIX , SOCK_STREAM , IPPROTO_IP );
193+ if (ConnectSocket == INVALID_SOCKET ) {
194+ printf (" socket failed with error: %d\n " , WSAGetLastError ());
195+ return -1 ;
196+ }
197+ do {
198+ iResult = connect (ConnectSocket, &saddr, sizeof (saddr) + (int )strlen (saddr.sa_data ));
199+ if (iResult == -1 ) {
200+ #if defined(_WIN32)
201+ closesocket (ConnectSocket);
202+ #else
203+ close (ConnectSocket);
204+ #endif
205+ ConnectSocket = INVALID_SOCKET ;
206+ }
207+ } while (iResult == -1 );
208+
209+ if (ConnectSocket == INVALID_SOCKET ) {
210+ printf (" Unable to connect to server! %d\n " , WSAGetLastError ());
211+ #if defined(_WIN32)
212+ WSACleanup ();
213+ #endif
214+ return -1 ;
215+ }
216+ int hasNewBitstreamReceived = 0 ;
217+ int recvbuflen = DEFAULT_BUFLEN ;
218+ std::string sendbuf{" data request" };
219+ iResult = send (ConnectSocket, sendbuf.c_str (), (int )sendbuf.length (), 0 );
220+ if (iResult == SOCKET_ERROR ) {
221+ printf (" send failed with error: %d\n " , WSAGetLastError ());
222+ close (ConnectSocket);
223+ return -1 ;
224+ }
225+ printf (" bytes Sent: %d (pid %d)\n " , iResult, getpid ());
226+ iResult = recv (ConnectSocket, (char *)recvbuf.c_str (), recvbuflen, 0 );
227+ if (iResult == SOCKET_ERROR ) {
228+ printf (" recv failed with error: %d\n " , WSAGetLastError ());
229+ close (ConnectSocket);
230+ return -1 ;
231+ }
232+ if (iResult > 0 ) {
233+ hasNewBitstreamReceived = 1 ;
234+ }
235+ sendbuf = {" received" };
236+ iResult = send (ConnectSocket, (char *)sendbuf.c_str (), (int )sendbuf.length (), 0 );
237+ if (iResult == SOCKET_ERROR ) {
238+ printf (" send failed with error: %d\n " , WSAGetLastError ());
239+ close (ConnectSocket);
240+ return -1 ;
241+ }
242+ close (ConnectSocket);
243+ return hasNewBitstreamReceived;
244+ }
0 commit comments