ecere/net: Properly initialized Service's to -1; Added an extra incref to ServerThrea...
[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    s = -1;
48
49    // --- Services ---
50
51    bool Start()
52    {
53    #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
54       SOCKET s;
55
56    #ifdef DEBUG_SOCKETS
57       Log("[P] [NStartService]\n");
58    #endif
59
60       s = socket(AF_INET,SOCK_STREAM,0);
61       if(s != -1)
62       {
63          SOCKADDR_IN a;
64          bool val = true;
65
66          a.sin_family=AF_INET;
67          a.sin_port=htons((uint16)port);
68          a.sin_addr.s_addr=INADDR_ANY;
69    #ifdef DEBUG_SOCKETS
70          Log("Service Socket: %x\n", s);
71    #endif
72
73          setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
74          if(!bind(s,(SOCKADDR *)&a, sizeof(a)))
75          {
76             if(!listen(s,5))
77             {
78                // Fix up the links/offsets here...
79                network.mutex.Wait();
80                network.services.Add(this);
81                this.s = s;
82
83                destroyed = false;
84                sockets.Clear();
85
86                sockets.offset = (uint)&((Socket)0).prev;
87
88                FD_SET(s, &network.readSet);
89                FD_SET(s, &network.exceptSet);
90                if(s >= network.ns) 
91                {
92                   network.ns = s+1;
93                   network.socketsSemaphore.Release();
94                }
95                network.mutex.Release();
96                return true;
97             }
98          }
99          closesocket(s);
100       }
101    #endif
102       return false;
103    }
104
105    bool Stop(void)
106    {
107    #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
108       SOCKET s = this.s;
109       Socket socket;
110
111    #ifdef DEBUG_SOCKETS
112       Log("[P] [NStopService]\n");
113    #endif
114
115       network.mutex.Wait();
116       while((socket = sockets.first))
117       {
118          socket.Free(false);
119          delete socket;
120       }
121       network.mutex.Release();
122
123       if(s != -1)
124       {
125          network.mutex.Wait();
126          this.s = -1;
127          network.services.Remove(this);
128          FD_CLR(s, &network.readSet);
129          FD_CLR(s, &network.exceptSet);
130          network.mutex.Release();
131          closesocket(s);
132       }
133
134       Network_DetermineMaxSocket();
135       return true;
136    #endif
137       return false;
138    }
139
140    bool Process()
141    {
142       bool gotEvent = false;
143       if(s != -1)
144       {
145          fd_set rs, ws, es;
146          int selectResult;
147          struct timeval tvTO = {0, 200000};
148
149          FD_ZERO(&rs);
150          FD_ZERO(&ws);
151          FD_ZERO(&es);
152          FD_SET(s, &rs);
153          //FD_SET(s, &ws);
154          FD_SET(s, &es);
155
156          selectResult = select(s+1, &rs, &ws, &es, &tvTO);
157          if(selectResult > 0)
158          {
159             if(FD_ISSET(s, &rs))
160             {
161                accepted = false;
162                OnAccept();
163                if(!accepted)
164                {
165                   SOCKET s;
166                   SOCKADDR_IN a;
167                   int addrLen = sizeof(a);
168                   s = accept(this.s,(SOCKADDR *)&a,&addrLen);
169                   closesocket(s);
170                }
171                gotEvent |= true;
172             }
173          }
174       }
175       return gotEvent;
176    }
177
178 private:
179
180    Service()
181    {
182       Network_Initialize();
183    }
184
185    ~Service()
186    {
187       Stop();
188    }
189
190    int port;
191    Service prev, next;
192
193    SOCKET s;
194    OldList sockets;
195    bool destroyed;
196    bool accepted;
197    bool processAlone;
198 }
199 #endif