Initial git commit -- Transition from CodeGuard repository
[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       while((socket = sockets.first))
114       {
115          socket.Free();
116          delete socket;
117       }
118
119       if(s)
120       {
121          network.mutex.Wait();
122          network.services.Remove(this);
123          FD_CLR(s, &network.readSet);
124          FD_CLR(s, &network.exceptSet);
125          network.mutex.Release();
126          closesocket(s);
127          this.s = 0;
128       }
129
130       Network_DetermineMaxSocket();
131       return true;
132    #endif
133       return false;
134    }
135
136    bool Process()
137    {
138       bool gotEvent = false;
139       fd_set rs, ws, es;
140       int selectResult;
141
142       FD_ZERO(&rs);
143       FD_ZERO(&ws);
144       FD_ZERO(&es);
145       FD_SET(s, &rs);
146       //FD_SET(s, &ws);
147       FD_SET(s, &es);
148
149       selectResult = select(s+1, &rs, &ws, &es, null);
150       if(selectResult > 0)
151       {
152          if(FD_ISSET(s, &rs))
153          {
154             accepted = false;
155             OnAccept();
156             if(!accepted)
157             {
158                SOCKET s;
159                SOCKADDR_IN a;
160                int addrLen = sizeof(a);
161                s = accept(this.s,(SOCKADDR *)&a,&addrLen);
162                closesocket(s);
163             }
164             gotEvent |= true;
165          }
166       }
167       return gotEvent;
168    }
169
170 private:
171
172    Service()
173    {
174       Network_Initialize();
175    }
176
177    ~Service()
178    {
179       Stop();
180    }
181
182    int port;
183    Service prev, next;
184
185    SOCKET s;
186    OldList sockets;
187    bool destroyed;
188    bool accepted;
189    bool processAlone;
190 }
191 #endif