friendev EtherDune TCP/IP library
ChatServer.ino
Go to the documentation of this file.
1 // EtherDune Chat Server demo
2 // Author: Javier Peletier <jm@friendev.com>
3 // Summary: Implements a simple chat server, demonstrating TCP and how to handle
4 // multiple simutaneous clients
5 //
6 // Copyright (c) 2015 All Rights Reserved, http://friendev.com
7 //
8 // This source is subject to the GPLv2 license.
9 // Please see the License.txt file for more information.
10 // All other rights reserved.
11 //
12 // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
13 // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14 // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
15 // PARTICULAR PURPOSE.
16 
34 #include <ACross.h>
35 #include <TCPSocket.h>
36 #include <FlowScanner.h>
37 
38 #define AC_LOGLEVEL 6
39 #include <ACLog.h>
40 ACROSS_MODULE("ChatServer");
41 
42 
43 static const uint8_t CS_PIN = 10; //Put here what pin you are using for your ENC28J60's chip select
44 static MACAddress_P mymac = { 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64 };
45 static IPAddress_P gatewayIP = { 192, 168, 1, 1 };
46 static IPAddress_P myIP = { 192, 168, 1, 33 };
47 static IPAddress_P netmask = { 255, 255, 255, 0 };
48 
49 static const uint8_t MAX_CLIENTS = 4;
50 static const uint16_t CHAT_SERVER_TCP_PORT = 2500;
51 
52 class ChatServer : public TCPSocket
53 {
54 private:
55 
56  static ChatServer clients[MAX_CLIENTS];
57 
58 public:
59 
60  void start(uint16_t port)
61  {
62  localPort =port;
63  listen();
64  }
65 
66  void onConnectRequest()
67  {
68  ACTRACE("onConnectRequest");
69 
70  for (int i = 0; i < MAX_CLIENTS; i++)
71  {
72  ChatServer& sck = clients[i];
73  if (sck.getState() == SCK_STATE_CLOSED)
74  {
75  sck.accept(*this); // accept connection
76  return;
77  }
78  }
79 
80  ACERROR("No more connections available"); //ignore request
81 
82  }
83 
84  void onConnect()
85  {
86  write(F("Welcome to the chat room\n")); //send a welcome message
87  Serial.println(F("New client connected"));
88  say(F(">> Somebody joined the room\n"),this);
89  }
90 
91  void onClose()
92  {
93  close(); //properly close the connection.
94  }
95 
96  void onTerminate()
97  {
98  Serial.println(F("Client disconnected."));
99  say(F(">> Someone left the room\n"));
100  }
101 
102  void say(uint16_t len, const byte* data, ChatServer* exclude)
103  {
104  for (int i = 0; i < MAX_CLIENTS; i++)
105  {
106  ChatServer& sck = clients[i];
107  if (&sck != exclude && sck.state == SCK_STATE_ESTABLISHED)
108  {
109  sck.write(len, data);
110  }
111  }
112  }
113 
114  void say(const String& st, ChatServer* exclude = NULL)
115  {
116  say(st.length(), (byte*)st.c_str(),exclude);
117  }
118 
119  void onReceive(uint16_t len, const byte* data)
120  {
121  ACTRACE("onReceive: %d bytes",len);
122 
123  say(len, data, this);
124  }
125 
126 
127 } chatServer;
128 
129 ChatServer ChatServer::clients[MAX_CLIENTS];
130 
131 
132 
133 void setup()
134 {
135  Serial.begin(115200);
136  ACross::init();
137  Serial.println(F("EtherDune ChatServer sample"));
138  Serial.print(F("Free RAM: ")); Serial.println(ACross::getFreeRam());
139 
140  Serial.println(F("Press any key to start..."));
141 
142  while (!Serial.available());
143 
144 
145  net::localIP = myIP;
149 
150 
151  if (!net::begin(CS_PIN))
152  ACERROR("failed to start EtherDune");
153 
154  ACINFO("waiting for link...");
155 
156  while (!net::isLinkUp());
157 
158  ACINFO("link is up");
159 
160 
161  chatServer.start(CHAT_SERVER_TCP_PORT);
162  Serial.println(F("Chat server is up"));
163  Serial.print(F("Listening on TCP port "));
164  Serial.println(chatServer.localPort);
165 }
166 
167 
168 
169 void loop()
170 {
171  net::loop();
172 }
173 
174 
175 /// \endcond
virtual void onConnectRequest()
Called when a listening socket receives a connection request.
Definition: TCPSocket.cpp:44
#define MACAddress_P
Definition: inet.h:242
#define IPAddress_P
helper macro to store an IP address in PROGMEM
Definition: inet.h:170
uint16_t write(uint16_t len, const byte *data)
In the case of TCP, writes the given data buffer to the socket.
Definition: Socket.cpp:54
virtual void onConnect()
Fires when the socket connection is established.
Definition: TCPSocket.cpp:39
static IPAddress_P gatewayIP
void listen()
Starts listening on the local port indicated by the localPort property.
Definition: TCPSocket.cpp:91
static bool begin(uint8_t cspin)
Initializes EtherDune and the underlying hardware
static const uint8_t SCK_STATE_CLOSED
(both server and client) represents no connection state at all.
Definition: inet.h:550
static IPAddress netmask
Subnet mask.
static IPAddress gatewayIP
IP address of the gateway in this network.
ACROSS_MODULE("ARP")
static const uint8_t CS_PIN
static MACAddress_P mymac
static bool isLinkUp()
Determines whether the network link is ready
Definition: ENC28J60.cpp:306
Implements the TCP protocol.
Definition: TCPSocket.h:45
void setup()
static MACAddress localMAC
Ethernet MAC address.
static IPAddress_P myIP
static const uint8_t SCK_STATE_ESTABLISHED
(both server and client) represents an open connection, data received can be delivered to the user...
Definition: inet.h:554
static void loop()
Gives processing time to EtherDune so that it can check for incoming packets or send queued packets...
virtual void onTerminate()
Called when the socket is ready to be reused.
Definition: TCPSocket.cpp:54
static IPAddress localIP
IP address of this application.
void close()
Attempts to gracefully close a connection.
Definition: TCPSocket.cpp:194
virtual void onReceive(uint16_t len, const byte *data)
Called for each data packet received
Definition: TCPSocket.cpp:50
static IPAddress_P netmask
virtual void onClose()
Fires when the other party closed the incoming end of the connection because it has no more data to s...
Definition: TCPSocket.cpp:31
void loop()