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