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