d49cdb1262cdba7d936bc7a4b26620bb6d856fbb
[sdk] / samples / net / networkFile / NetworkServer / server.ec
1 import "ecere"
2
3 /////////////////////////////////////////////////////////////////////
4
5 typedef byte XDWord[4];
6 typedef byte XWord[2];
7
8 #define MDWORD(a,b) ((((uint32)((uint16)(b)))<<16)+((uint16)(a)))
9 #define LOWORD(l)   ((uint16)(l))
10 #define HIWORD(l)   ((uint16)(((uint32)(l) >> 16) & 0xFFFF))
11
12 #define SWAP_WORD(word) (((uint16)(word) & 0x00ff) << 8) \
13                       | (((uint16)(word) & 0xff00) >> 8)
14
15 #define SWAP_DWORD(dword) ((((uint32)(dword) & 0x000000ff) << 24) \
16                          | (((uint32)(dword) & 0x0000ff00) <<  8) \
17                          | (((uint32)(dword) & 0x00ff0000) >>  8) \
18                          | (((uint32)(dword) & 0xff000000) >> 24))
19
20 #define PUTXDWORD(b, d) \
21    (b)[0] = (byte)(((d) >> 24) & 0xFF); \
22    (b)[1] = (byte)(((d) >> 16) & 0xFF); \
23    (b)[2] = (byte)(((d) >> 8)  & 0xFF); \
24    (b)[3] = (byte)( (d)        & 0xFF);
25
26 #define XDWORD(d) \
27    { \
28       (byte)(((d) >> 24) & 0xFF), \
29       (byte)(((d) >> 16) & 0xFF), \
30       (byte)(((d) >> 8)  & 0xFF), \
31       (byte)((d)         & 0xFF) \
32    }
33
34 #define GETXDWORD(b) (uint32)(((b)[0] << 24) | ((b)[1] << 16) | ((b)[2] << 8) | (b)[3])
35
36 #define PUTXWORD(b, w) \
37    (b)[0] = (byte)(((w) >> 8) & 0xFF); \
38    (b)[1] = (byte)(((w)     ) & 0xFF);
39
40 #define XWORD(w) \
41    { \
42       (byte)(((w) >> 8)  & 0xFF), \
43       (byte)((w)         & 0xFF) \
44    }
45
46 #define GETXWORD(b) (uint16)(((b)[0] << 8) | (b)[1])
47
48 /////////////////////////////////////////////////////////////////////
49
50 define SERVER_PORT = 7649;
51
52 define MAX_HANDLES = 16;
53
54 // Packets sent from Client to Server
55
56 class BasePacket : struct
57 {
58    byte type[4];
59    byte size[4];
60 };
61
62 class OpenPacket : BasePacket
63 {
64    byte fileNameLen[4];
65    char fileName[1]; // Rest follows, null terminated
66 };
67
68 class ClosePacket : BasePacket
69 {
70    byte handle[4];
71 };
72
73 class ReadPacket : BasePacket
74 {
75    byte handle[4];
76    byte readStart[4];
77    byte readSize[4];
78 };
79
80 class SizePacket : BasePacket
81 {
82    byte handle[4];
83 };
84
85 enum PacketType { open, close, read, size };
86
87 class NetworkServer : Service
88 {
89    OldList clients { offset = (uint)&((ClientConnection)0).prev };
90    void OnAccept()
91    {
92       ClientConnection socket { this };
93       clients.Add(socket);
94       Logf("Connection from %s, port %d\n", socket.inetAddress, SERVER_PORT);
95    }
96 };
97
98 class ClientConnection : Socket
99 {
100    ClientConnection prev, next;
101    File handles[MAX_HANDLES];
102    byte * readBuf;
103    uint readSize;
104
105    uint OnReceive(const byte * buffer, uint count)
106    {
107       if(count >= sizeof(class Packet))
108       {
109          BasePacket packetHeader = (BasePacket) buffer;
110          if(count >= GETXDWORD(packetHeader.size))
111          {
112             Log("received packet\n");
113             switch((PacketType)GETXDWORD(packetHeader.type))
114             {
115                case open:
116                {
117                   OpenPacket packet = (OpenPacket) packetHeader;
118                   byte reply[4] = XDWORD(MAXDWORD);
119                   int c;
120                   
121                   Log("Open\n");
122                   for(c = 0; c < MAX_HANDLES; c++)
123                   {
124                      if(!handles[c])
125                         break;
126                   }
127                   // Test valid free handle
128                   if(c < MAX_HANDLES)
129                   {
130                      handles[c] = FileOpen(packet.fileName, read);
131                      if(handles[c])
132                         PUTXDWORD(reply, c+1);
133                   }
134                   Send(reply, sizeof(reply));
135                   break;
136                }
137                case close:
138                {
139                   ClosePacket packet = (ClosePacket) packetHeader;
140                   uint handle = GETXDWORD(packet.handle);
141                   Log("Close\n");
142                   if(handle > 0 && handle <= MAX_HANDLES)
143                   {
144                      File file = handles[handle-1];
145                      if(file)
146                      {
147                         delete file;
148                         handles[handle-1] = null;
149                      }
150                   }
151                   break;
152                }
153                case read:
154                {
155                   ReadPacket packet = (ReadPacket) packetHeader;
156                   byte reply[4];
157                   uint handle = GETXDWORD(packet.handle);
158                   uint realRead = 0;
159                   Log("Read\n");
160                   if(handle > 0 && handle <= MAX_HANDLES)
161                   {
162                      File file = handles[handle-1];
163                      if(file)
164                      {
165                         uint readSize = GETXDWORD(packet.readSize);
166
167                         if(readSize > this.readSize)
168                         {
169                            readBuf = renew readBuf byte[readSize];
170                            this.readSize = readSize;
171                         }
172                         if(readBuf)
173                         {
174                            file.Seek(GETXDWORD(packet.readStart), start);
175                            realRead = file.Read(readBuf, 1, readSize);
176                         }
177                      }
178                   }
179                   PUTXDWORD(reply, realRead);
180                   Send(reply, sizeof(reply));
181                   Send(readBuf, realRead);
182                   break;
183                }
184                case size:
185                {
186                   SizePacket packet = (SizePacket) packetHeader;
187                   byte reply[4] = XDWORD(0);
188                   uint handle = GETXDWORD(packet.handle);
189                   Logf("Size %d\n",handle);
190                   if(handle > 0 && handle <= MAX_HANDLES)
191                   {
192                      File file = handles[handle-1];
193                      if(file)
194                      {
195                         uint size;
196                         file.Seek(0, end);
197                         size = file.Tell();
198                         PUTXDWORD(reply, size);
199                      }
200                   }
201                   Send(reply, sizeof(reply));
202                   break;
203                }
204                default:
205                   Log("Unknown packet type\n");
206             }
207             Log("Request processed\n");
208             return GETXDWORD(packetHeader.size);
209          }
210       }
211       return 0;
212    }
213
214    void OnDisconnect(int code)
215    {
216       delete readBuf;
217       ((NetworkServer)service).clients.Remove(this);
218    }
219 }
220
221 NetworkServer tcpServer { port = SERVER_PORT };
222
223 class ServerApp : GuiApplication
224 {
225    void Main()
226    {
227       // SetLoggingMode(stdout, null);
228       SetLoggingMode(0, null);
229       if(tcpServer.Start())
230       {
231          Log("Server started\n");
232          while(true)
233          {
234             WaitEvent();
235             ProcessNetworkEvents();
236          }
237       } 
238    }
239 }