samples/net/SocketSample: Fixed wrong explanation in comment
[sdk] / samples / net / SocketSample / socketSample.ec
1 import "ecere"
2
3 // We'll use TCP/IP port 5623 for this sample
4 define samplePort = 5623;
5
6 // We will use this simple structure for our messages
7 struct SamplePacket
8 {
9    int stringLen;
10    // stringLen + 1 bytes are actually used (variable size depending on string)
11    char string[1];   
12 };
13
14 class SampleService : Service
15 {
16    void OnAccept()
17    {
18       // When we get an incoming connection to our service, we spawn a SampleSocket (Can only serve one right now)
19       if(!servingSocket)
20       {
21          servingSocket = SampleSocket { this };
22          form.UpdateButtonStates();
23       }
24    }
25 }
26
27 class SampleSocket : Socket
28 {
29    void OnConnect()
30    {
31       // We want a non blocking Connect() call, so we define an OnConnect() that simply updates the button disabled states
32       form.UpdateButtonStates();
33    }
34
35    void OnDisconnect(int code)
36    {
37       // On disconnection we need to null the socket pointers, and update the buttons
38       if(connectedSocket == this)
39          connectedSocket = null;
40       else if(servingSocket == this)
41          servingSocket = null;
42
43       form.UpdateButtonStates();      
44    }
45
46    unsigned int OnReceive(unsigned char * buffer, unsigned int count)
47    {
48       // We only process the data if we've received enough bytes to make up the message
49       // This first if just checks if we have reveived enough bytes for the header
50       if(count >= sizeof(SamplePacket))
51       {
52          SamplePacket * packet = (SamplePacket *) buffer;
53          uint size = sizeof(SamplePacket) + packet->stringLen;
54          // Here we check if we've actually received the entire message
55          if(count >= size)
56          {
57             // We've received a complete message, so we change the contents of the recvString EditBox
58             form.recvString.contents = packet->string;
59             // and we return the size of the message we've processed.
60             // If more data is already buffered, this method will be called again right away.
61             return size;
62          }
63       }
64       // We haven't received enough data to process this message yet: return 0 bytes processed
65       // This method will be called again once more data has been received.
66       return 0;
67    }
68 }
69
70 class SocketSample : Window
71 {
72    text = "Socket Sample";
73    background = activeBorder;
74    borderStyle = sizable;
75    hasMaximize = true;
76    hasMinimize = true;
77    hasClose = true;
78    tabCycle = true;
79    size = { 416, 176 };
80    nativeDecorations = true;
81
82    // Service is missing a property to tell us if it's listening or not already, so we keep track of it in this variable
83    bool listening;
84
85    void UpdateButtonStates()
86    {
87       bool connected = (connectedSocket && connectedSocket.connected) || (servingSocket && servingSocket.connected);
88
89       // The Send button is disabled if we're not connected
90       btnSend.disabled = !connected;
91       // The Connect button is disabled if we've already defined a connectedSocket
92       btnConnect.disabled = connectedSocket != null;
93       // The Listen button is disabled if we're already listening
94       btnListen.disabled = listening;
95    }
96    
97    Button btnSend 
98    {      
99       this, text = "Send", position = { 344, 64 }, disabled = true;
100
101       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
102       {
103          // We build up a SamplePacket here with our message from the sentString EditBox
104          String string = sentString.contents;
105          int len = strlen(string);
106          int size = sizeof(SamplePacket) + len;
107          SamplePacket * packet = (SamplePacket *)new byte[size];
108          packet->stringLen = len;
109          memcpy(packet->string, string, len+1);
110          // If we've connected to another server, we use the connectedSocket, otherwise we use the servingSocket (Send back to whom connected to us)
111          (connectedSocket ? connectedSocket : servingSocket).Send(packet, size);
112          // Make sure to free memory allocated with 'new'
113          delete packet;
114          return true;
115       }
116    };
117    EditBox serverAddress { this, text = "Server Address", size = { 174, 19 }, position = { 8, 40 }, contents = "localhost" };
118    Label lblServerAddress { this, position = { 8, 16 }, labeledWindow = serverAddress };
119    Button btnListen 
120    {      
121       this, text = "Listen", position = { 144, 104 };
122
123       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
124       {
125          // Start listening here
126          if(service.Start())
127          {
128             listening = true;
129             UpdateButtonStates();
130          }
131          return true;
132       }
133    };
134    EditBox sentString { this, text = "Sent String", size = { 166, 19 }, position = { 224, 40 } };
135    Label lblSentString { this, position = { 224, 16 }, labeledWindow = sentString };
136    EditBox recvString { this, text = "Received String", size = { 166, 19 }, position = { 224, 104 } };
137    Label label1 { this, position = { 224, 80 }, labeledWindow = recvString };
138    Button btnConnect 
139    {      
140       this, text = "Connect", position = { 8, 72 };
141
142       bool NotifyClicked(Button button, int x, int y, Modifiers mods)
143       {
144          btnConnect.disabled = true;
145          // Create a socket and attempt a connection to the address specified in the serverAddress EditBox
146          connectedSocket = SampleSocket { };
147          // Connect is a blocking call if no OnConnect method is defined in the Socket, a non-blocking call otherwise
148          connectedSocket.Connect(serverAddress.contents, samplePort);
149          return true;
150       }
151    };
152
153    void OnDestroy()
154    {
155       // We need to disconnect the socket and stop the service before destroying the application,
156       // otherwise we'll get a crash with the SampleSocket accessing the form that is already destroyed
157       if(connectedSocket)
158          connectedSocket.Disconnect(0);
159       service.Stop();
160    }
161 }
162
163 // The form
164 SocketSample form {};
165
166 // The service
167 SampleService service { port = samplePort };
168
169 // We use 2 sockets: one for when we connect to a server, one for the incoming connections to our SampleService
170 SampleSocket connectedSocket, servingSocket;