ecere/networking: Added 'mustLock' to Socket::Free() to prevent network.mutex to...
[sdk] / ecere / src / net / Service.ec
1 namespace net;
2
3 #ifndef ECERE_NONET
4
5 #if defined(__WIN32__)
6
7 #define WIN32_LEAN_AND_MEAN
8 #include <winsock.h>
9 static WSADATA wsaData;
10
11 #elif defined(__unix__) || defined(__APPLE__)
12 default:
13 #define uint _uint
14 #include <sys/time.h>
15 #include <unistd.h>
16
17 #include <netinet/in.h>
18 #include <netdb.h>
19 #include <sys/socket.h>
20 #include <sys/wait.h>
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <arpa/inet.h>
24 #undef uint
25 private:
26
27 typedef int SOCKET;
28 typedef struct hostent HOSTENT;
29 typedef struct sockaddr SOCKADDR;
30 typedef struct sockaddr_in SOCKADDR_IN;
31 typedef struct in_addr IN_ADDR;
32 #define closesocket(s) close(s)
33
34 #endif
35
36 import "network"
37
38 public class Service
39 {
40 public:
41    property int port { set { port = value; } get { return port; } };
42    property Socket firstClient { get { return sockets.first; } };
43    property bool processAlone { get { return processAlone; } set { processAlone = value; } };
44
45    virtual void OnAccept();
46
47    // --- Services ---
48
49    bool Start()
50    {
51    #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
52       SOCKET s;
53
54    #ifdef DEBUG_SOCKETS
55       Log("[P] [NStartService]\n");
56    #endif
57
58       s = socket(AF_INET,SOCK_STREAM,0);
59       if(s != -1)
60       {
61          SOCKADDR_IN a;
62          bool val = true;
63
64          a.sin_family=AF_INET;
65          a.sin_port=htons((uint16)port);
66          a.sin_addr.s_addr=INADDR_ANY;
67    #ifdef DEBUG_SOCKETS
68          Log("Service Socket: %x\n", s);
69    #endif
70
71          setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
72          if(!bind(s,(SOCKADDR *)&a, sizeof(a)))
73          {
74             if(!listen(s,5))
75             {
76                // Fix up the links/offsets here...
77                network.mutex.Wait();
78                network.services.Add(this);
79                this.s = s;
80
81                destroyed = false;
82                sockets.Clear();
83
84                sockets.offset = (uint)&((Socket)0).prev;
85
86                FD_SET(s, &network.readSet);
87                FD_SET(s, &network.exceptSet);
88                if(s >= network.ns) 
89                {
90                   network.ns = s+1;
91                   network.socketsSemaphore.Release();
92                }
93                network.mutex.Release();
94                return true;
95             }
96          }
97          closesocket(s);
98       }
99    #endif
100       return false;
101    }
102
103    bool Stop(void)
104    {
105    #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
106       SOCKET s = this.s;
107       Socket socket;
108
109    #ifdef DEBUG_SOCKETS
110       Log("[P] [NStopService]\n");
111    #endif
112
113       network.mutex.Wait();
114       while((socket = sockets.first))
115       {
116          socket.Free(false);
117          delete socket;
118       }
119       network.mutex.Release();
120
121       if(s)
122       {
123          network.mutex.Wait();
124          network.services.Remove(this);
125          FD_CLR(s, &network.readSet);
126          FD_CLR(s, &network.exceptSet);
127          network.mutex.Release();
128          closesocket(s);
129          this.s = 0;
130       }
131
132       Network_DetermineMaxSocket();
133       return true;
134    #endif
135       return false;
136    }
137
138    bool Process()
139    {
140       bool gotEvent = false;
141       fd_set rs, ws, es;
142       int selectResult;
143
144       FD_ZERO(&rs);
145       FD_ZERO(&ws);
146       FD_ZERO(&es);
147       FD_SET(s, &rs);
148       //FD_SET(s, &ws);
149       FD_SET(s, &es);
150
151       selectResult = select(s+1, &rs, &ws, &es, null);
152       if(selectResult > 0)
153       {
154          if(FD_ISSET(s, &rs))
155          {
156             accepted = false;
157             OnAccept();
158             if(!accepted)
159             {
160                SOCKET s;
161                SOCKADDR_IN a;
162                int addrLen = sizeof(a);
163                s = accept(this.s,(SOCKADDR *)&a,&addrLen);
164                closesocket(s);
165             }
166             gotEvent |= true;
167          }
168       }
169       return gotEvent;
170    }
171
172 private:
173
174    Service()
175    {
176       Network_Initialize();
177    }
178
179    ~Service()
180    {
181       Stop();
182    }
183
184    int port;
185    Service prev, next;
186
187    SOCKET s;
188    OldList sockets;
189    bool destroyed;
190    bool accepted;
191    bool processAlone;
192 }
193 #endif