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