d8afc90e35c8ebd0cef6d1e0022406d39a6b123a
[sdk] / ecere / src / net / network.ec
1 namespace net;
2
3 #ifndef ECERE_NONET
4
5 #if defined(__WIN32__)
6
7 #define WIN32_LEAN_AND_MEAN
8 #define String _String
9 #include <winsock.h>
10 #undef String
11 static WSADATA wsaData;
12
13 #elif defined(__unix__) || defined(__APPLE__)
14 default:
15 #define set _set
16 #define uint _uint
17 #include <sys/time.h>
18 #include <unistd.h>
19
20 #include <netinet/in.h>
21 #include <netdb.h>
22 #include <sys/select.h>
23 #include <sys/socket.h>
24 #include <sys/wait.h>
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <arpa/inet.h>
28 #undef set
29 #undef uint
30 typedef int SOCKET;
31 typedef struct hostent HOSTENT;
32 typedef struct sockaddr SOCKADDR;
33 typedef struct sockaddr_in SOCKADDR_IN;
34 typedef struct in_addr IN_ADDR;
35 #define closesocket(s) close(s)
36 private:
37 #endif
38
39 import "GuiApplication"
40 import "Service"
41 import "Socket"
42
43 private struct NetworkData
44 {
45    // Connections to the outside world
46    OldList sockets;
47    // Local services
48    OldList services;
49    // Ongoing Connections
50    OldList connectSockets;
51    // Socket Sets
52    fd_set readSet, writeSet, exceptSet;
53    fd_set selectRS, selectWS, selectES;
54
55    int ns;
56
57    // Synchronization Elements
58    Thread networkThread;
59    Semaphore socketsSemaphore;
60    Semaphore selectSemaphore;
61    bool networkEvent;
62    bool connectEvent;
63    bool networkInitialized;
64    bool networkTerminated;
65    uint errorLevel, lastErrorCode;
66    bool leftOverBytes;
67    Mutex processMutex;
68    Mutex mutex;
69    int64 mainThreadID;
70    OldList mtSemaphores;
71 };
72
73 #include <errno.h>
74
75 NetworkData network;
76
77 static class NetworkThread : Thread
78 {
79    uint Main()
80    {
81       network.mutex.Wait();
82       while(!network.networkTerminated)
83       {
84          int ns = network.ns;
85          
86          if(ns)
87          {
88             struct timeval tv = { 0, 0 }; // TESTING 0 INSTEAD OF (int)(1000000 / 18.2) };
89
90             network.selectRS = network.readSet, network.selectWS = network.writeSet, network.selectES = network.exceptSet;
91
92             network.mutex.Release();
93    #ifdef DEBUG_SOCKETS
94             Log("[N] Waiting for network event...\n");
95    #endif
96             if(select(ns, &network.selectRS, &network.selectWS, &network.selectES, &tv))
97             {
98                network.mutex.Wait();
99                network.networkEvent = true;
100    #ifdef DEBUG_SOCKETS
101                Log("[N] Signaling Network event\n");
102    #endif
103                guiApp.SignalEvent();
104    #ifdef DEBUG_SOCKETS
105                Log("[N] Waiting for select semaphore in Network Thread...\n");
106    #endif
107                network.mutex.Release();
108                network.selectSemaphore.Wait();
109                network.mutex.Wait();
110             } 
111             else
112             {
113                ecere::sys::Sleep(1 / 18.2f);
114                network.mutex.Wait();
115             }
116          }
117          else
118          {
119             network.mutex.Release();
120             network.socketsSemaphore.Wait();
121             network.mutex.Wait();
122          }
123          
124       }
125       network.mutex.Release();
126       return 0;
127    }
128 }
129
130 void Network_DetermineMaxSocket()
131 {
132    Service service;
133    Socket socket;
134
135    network.mutex.Wait();
136    network.ns = 0;
137    for(socket = network.sockets.first; socket; socket = socket.next)
138       if(!socket.processAlone && !socket.destroyed && socket.s >= network.ns)
139          network.ns = (int)(socket.s + 1);
140    for(socket = network.connectSockets.first; socket; socket = socket.next)
141       if(!socket.destroyed && socket.s >= network.ns)
142          network.ns = (int)(socket.s + 1);
143
144    for(service = network.services.first; service; service = service.next)
145    {
146       if(!service.destroyed && !service.processAlone)
147       {
148          if(service.s >= network.ns)
149             network.ns = (int)(service.s + 1);
150       }
151       for(socket = service.sockets.first; socket; socket = socket.next)
152          if(!socket.destroyed && !socket.processAlone && socket.s >= network.ns)
153             network.ns = (int)(socket.s + 1);
154    }
155    network.mutex.Release();
156 }
157
158 // --- Network System ---
159 #endif
160
161 bool Network_Initialize()
162 {
163 #ifndef ECERE_NONET
164    if(!network.networkInitialized)
165    {
166 #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
167       network.networkInitialized = true;
168       network.networkTerminated = false;
169 #if defined(__WIN32__)
170       WSAStartup(0x0002, &wsaData);
171 #endif
172
173       network.services.Clear();
174
175       network.services.offset = (uint)&((Service)0).prev;
176       network.sockets.Clear();
177
178       network.sockets.offset = (uint)&((Socket)0).prev;
179
180       network.connectSockets.Clear();
181       network.connectSockets.offset = (uint)&((Socket)0).prev;
182
183       FD_ZERO(&network.readSet);
184       FD_ZERO(&network.writeSet);
185       FD_ZERO(&network.exceptSet);
186
187       network.socketsSemaphore = Semaphore { };
188       network.selectSemaphore = Semaphore { };
189       network.networkThread = NetworkThread { };
190       incref network.networkThread;
191
192       network.errorLevel = 2;
193
194       network.processMutex = Mutex { };
195       network.mutex = Mutex { };
196
197       network.mainThreadID = GetCurrentThreadID();
198
199       network.networkThread.Create();
200 #endif
201    }
202    return true;
203 #else
204    return false;
205 #endif
206 }
207
208 void Network_Terminate()
209 {
210 #ifndef ECERE_NONET
211
212    if(network.networkInitialized)
213    {
214 #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
215       Service service;
216       Socket socket;
217
218       guiApp.PauseNetworkEvents();
219       network.networkTerminated = true;
220
221       delete network.processMutex;
222       delete network.mutex;
223
224       for(socket = network.connectSockets.first; socket; socket = socket.next)
225       {
226          socket.connectThread.Wait();
227          delete socket.connectThread;
228       }
229
230       network.socketsSemaphore.Release();
231       network.selectSemaphore.Release();
232
233       network.networkThread.Wait();
234       delete network.networkThread;
235
236       // Cleanup External network.sockets
237       while((socket = network.sockets.first))
238       {
239          incref socket;
240          //network.sockets.Remove(socket); //THIS IS ALREADY DONE IN Socket::Free
241          socket.Free(true);
242          if(socket._refCount > 1) socket._refCount--;
243          delete socket;
244       }
245       while((socket = network.connectSockets.first))
246       {
247          //network.connectSockets.Remove(socket); //THIS IS ALREADY DONE IN Socket::Free
248          socket.Free(true);
249          delete socket;
250       }
251
252       // Cleanup network.services
253       while((service = network.services.first))
254          service.Stop();
255
256       network.ns = 0;
257
258 #if defined(__WIN32__)
259       WSACleanup();
260 #endif
261
262       delete network.selectSemaphore;
263       delete network.socketsSemaphore;
264 #endif
265 #ifdef DEBUG_SOCKETS
266       Log("[P] Network System Terminated\n");
267 #endif
268       network.networkInitialized = false;
269    }
270 #endif
271 }
272
273 #ifndef ECERE_NONET
274
275 public bool GetAddressFromName(char * hostName, char * inetAddress)
276 {
277    HOSTENT * host;
278
279    if(!Network_Initialize())
280       return false;
281
282    host = gethostbyname(hostName);
283    if(host)
284    {
285       strcpy(inetAddress, inet_ntoa(*((IN_ADDR *)host->h_addr)));
286       return true;
287    }
288    return false;
289 }
290
291 public bool GetNameFromAddress(char * inetAddress, char * hostName)
292 {
293    struct in_addr in;
294    HOSTENT * host;
295
296    if(!Network_Initialize())
297       return false;
298
299    in.s_addr = inet_addr(inetAddress);
300    host = gethostbyaddr((byte *)&in, 4, PF_INET);
301    if(host)
302    {
303       strcpy(hostName, host->h_name);
304       return true;
305    }
306    return false;
307 }
308
309 public bool GetHostName(char * hostName, int size)
310 {
311    if(!Network_Initialize())
312       return false;
313
314    return !gethostname(hostName,size);
315 }
316
317 #endif