RadioHead
RH_TCP.h
1 // RH_TCP.h
2 // Author: Mike McCauley (mikem@aierspayce.com)
3 // Copyright (C) 2014 Mike McCauley
4 // $Id: RH_TCP.h,v 1.4 2015/08/13 02:45:47 mikem Exp $
5 #ifndef RH_TCP_h
6 #define RH_TCP_h
7 
8 #include <RHGenericDriver.h>
9 #include <RHTcpProtocol.h>
10 
11 /////////////////////////////////////////////////////////////////////
12 /// \class RH_TCP RH_TCP.h <RH_TCP.h>
13 /// \brief Driver to send and receive unaddressed, unreliable datagrams via sockets on a Linux simulator
14 ///
15 /// \par Overview
16 ///
17 /// This class is intended to support the testing of RadioHead manager classes and simulated sketches
18 /// on a Linux host.
19 /// RH_TCP class sends messages to and from other simulator sketches via sockets to a 'Luminiferous Ether'
20 /// simulator server (provided).
21 /// Multiple instances of simulated clients and servers can run on a single Linux server,
22 /// passing messages to each other via the etherSimulator.pl server.
23 ///
24 /// Simple RadioHead sketches can be compiled and run on Linux using a build script and some support files.
25 ///
26 /// \par Running simulated sketches
27 ///
28 /// \code
29 /// cd whatever/RadioHead
30 /// # build the client for Linux:
31 /// tools/simBuild examples/simulator/simulator_reliable_datagram_client/simulator_reliable_datagram_client.pde
32 /// # build the server for Linux:
33 /// tools/simBuild examples/simulator/simulator_reliable_datagram_server/simulator_reliable_datagram_server.pde
34 /// # in one window, run the simulator server:
35 /// tools/etherSimulator.pl
36 /// # in another window, run the server
37 /// ./simulator_reliable_datagram_server
38 /// # in another window, run the client:
39 /// ./simulator_reliable_datagram_client
40 /// # see output:
41 /// Sending to simulator_reliable_datagram_server
42 /// got reply from : 0x02: And hello back to you
43 /// Sending to simulator_reliable_datagram_server
44 /// got reply from : 0x02: And hello back to you
45 /// Sending to simulator_reliable_datagram_server
46 /// got reply from : 0x02: And hello back to you
47 /// ...
48 /// \endcode
49 ///
50 /// You can change the listen port and the simulated baud rate with
51 /// command line arguments passed to etherSimulator.pl
52 ///
53 /// \par Implementation
54 ///
55 /// etherServer.pl is a conventional server written in Perl.
56 /// listens on a TCP socket (defaults to port 4000) for connections from sketch simulators
57 /// using RH_TCP as theur driver.
58 /// The simulated sketches send messages out to the 'ether' over the TCP connection to the etherServer.
59 /// etherServer manages the delivery of each message to any other RH_TCP sketches that are running.
60 ///
61 /// \par Prerequisites
62 ///
63 /// g++ compiler installed and in your $PATH
64 /// Perl
65 /// Perl POE library
66 ///
67 class RH_TCP : public RHGenericDriver
68 {
69 public:
70  /// Constructor
71  /// \param[in] server Name and optionally the port number of the ether simulator server to contact.
72  /// Format is "name[:port]", where name can be any valid host name or address (IPV4 or IPV6).
73  /// The trailing :port is optional, and port can be any valid
74  /// port name or port number.
75  RH_TCP(const char* server = "localhost:4000");
76 
77  /// Initialise the Driver transport hardware and software.
78  /// Make sure the Driver is properly configured before calling init().
79  /// \return true if initialisation succeeded.
80  virtual bool init();
81 
82  /// Tests whether a new message is available
83  /// from the Driver.
84  /// On most drivers, this will also put the Driver into RHModeRx mode until
85  /// a message is actually received by the transport, when it will be returned to RHModeIdle.
86  /// This can be called multiple times in a timeout loop
87  /// \return true if a new, complete, error-free uncollected message is available to be retreived by recv()
88  virtual bool available();
89 
90  /// Wait until a new message is available from the driver.
91  /// Blocks until a complete message is received as reported by available()
92  virtual void waitAvailable();
93 
94  /// Wait until a new message is available from the driver
95  /// or the timeout expires
96  /// Blocks until a complete message is received as reported by available()
97  /// \param[in] timeout The maximum time to wait in milliseconds
98  /// \return true if a message is available as reported by available()
99  virtual bool waitAvailableTimeout(uint16_t timeout);
100 
101  /// Turns the receiver on if it not already on.
102  /// If there is a valid message available, copy it to buf and return true
103  /// else return false.
104  /// If a message is copied, *len is set to the length (Caution, 0 length messages are permitted).
105  /// You should be sure to call this function frequently enough to not miss any messages
106  /// It is recommended that you call it in your main loop.
107  /// \param[in] buf Location to copy the received message
108  /// \param[in,out] len Pointer to available space in buf. Set to the actual number of octets copied.
109  /// \return true if a valid message was copied to buf
110  virtual bool recv(uint8_t* buf, uint8_t* len);
111 
112  /// Waits until any previous transmit packet is finished being transmitted with waitPacketSent().
113  /// Then loads a message into the transmitter and starts the transmitter. Note that a message length
114  /// of 0 is NOT permitted. If the message is too long for the underlying radio technology, send() will
115  /// return false and will not send the message.
116  /// \param[in] data Array of data to be sent
117  /// \param[in] len Number of bytes of data to send (> 0)
118  /// \return true if the message length was valid and it was correctly queued for transmit
119  virtual bool send(const uint8_t* data, uint8_t len);
120 
121  /// Returns the maximum message length
122  /// available in this Driver.
123  /// \return The maximum legal message length
124  virtual uint8_t maxMessageLength();
125 
126  /// Sets the address of this node. Defaults to 0xFF. Subclasses or the user may want to change this.
127  /// This will be used to test the adddress in incoming messages. In non-promiscuous mode,
128  /// only messages with a TO header the same as thisAddress or the broadcast addess (0xFF) will be accepted.
129  /// In promiscuous mode, all messages will be accepted regardless of the TO header.
130  /// In a conventional multinode system, all nodes will have a unique address
131  /// (which you could store in EEPROM).
132  /// You would normally set the header FROM address to be the same as thisAddress (though you dont have to,
133  /// allowing the possibilty of address spoofing).
134  /// \param[in] address The address of this node.
135  void setThisAddress(uint8_t address);
136 
137 protected:
138 
139 private:
140  /// Connect to the address and port specified by the server constructor argument.
141  /// Prepares the socket for use.
142  bool connectToServer();
143 
144  /// Check for new messages from the ether simulator server
145  void checkForEvents();
146 
147  /// Clear the receive buffer
148  void clearRxBuf();
149 
150  /// Sends thisAddress to the ether simulator server
151  /// in a RHTcpThisAddress message.
152  /// \param[in] thisAddress The node address of this node
153  /// \return true if successful
154  bool sendThisAddress(uint8_t thisAddress);
155 
156  /// Sends a message to the ether simulator server for delivery to
157  /// other nodes
158  /// \param[in] data Array of data to be sent
159  /// \param[in] len Number of bytes of data to send (> 0)
160  /// \return true if successful
161  bool sendPacket(const uint8_t* data, uint8_t len);
162 
163  /// Address and port of the server to which messages are sent
164  /// and received using the protocol RHTcpPRotocol
165  const char* _server;
166 
167  /// The TCP socket used to communicate with the message server
168  int _socket;
169 
170  /// Buffer to receive RHTcpProtocol messages
171  uint8_t _rxBuf[RH_TCP_MAX_PAYLOAD_LEN + 5];
172  uint16_t _rxBufLen;
173  bool _rxBufValid;
174 
175  /// Check whether the latest received message is complete and uncorrupted
176  void validateRxBuf();
177 
178  // Used in the interrupt handlers
179  /// Buf is filled but not validated
180  volatile bool _rxBufFull;
181 
182 };
183 
184 /// @example simulator_reliable_datagram_client.pde
185 /// @example simulator_reliable_datagram_server.pde
186 
187 #endif
RHGenericDriver::_rxGood
volatile uint16_t _rxGood
Count of the number of successfully transmitted messaged.
Definition: RHGenericDriver.h:292
RHTcpTypeMessage::length
uint32_t length
Number of octets following, in network byte order.
Definition: RHTcpProtocol.h:39
RHTcpPacket::payload
uint8_t payload[RH_TCP_MAX_MESSAGE_LEN]
0 or more, length deduced from length above
Definition: RHTcpProtocol.h:61
RHGenericDriver::_rxHeaderFrom
volatile uint8_t _rxHeaderFrom
FROM header in the last received mesasge.
Definition: RHGenericDriver.h:265
RHTcpThisAddress::thisAddress
uint8_t thisAddress
Node address.
Definition: RHTcpProtocol.h:49
RHTcpThisAddress::type
uint8_t type
== RH_TCP_MESSAGE_TYPE_THISADDRESS
Definition: RHTcpProtocol.h:48
RHGenericDriver::_rxHeaderTo
volatile uint8_t _rxHeaderTo
TO header in the last received mesasge.
Definition: RHGenericDriver.h:262
RH_TCP::RH_TCP
RH_TCP(const char *server="localhost:4000")
RHTcpPacket::from
uint8_t from
Node address of the sender.
Definition: RHTcpProtocol.h:58
RHTcpPacket::flags
uint8_t flags
Message flags.
Definition: RHTcpProtocol.h:60
RHGenericDriver::_txHeaderFrom
uint8_t _txHeaderFrom
FROM header to send in all messages.
Definition: RHGenericDriver.h:277
RHGenericDriver
Abstract base class for a RadioHead driver.
Definition: RHGenericDriver.h:41
RHGenericDriver::_thisAddress
uint8_t _thisAddress
This node id.
Definition: RHGenericDriver.h:256
RHTcpTypeMessage::type
uint8_t type
One of RH_TCP_MESSAGE_TYPE_*.
Definition: RHTcpProtocol.h:40
RHGenericDriver::_promiscuous
bool _promiscuous
Whether the transport is in promiscuous mode.
Definition: RHGenericDriver.h:259
RHGenericDriver::setThisAddress
virtual void setThisAddress(uint8_t thisAddress)
Definition: RHGenericDriver.cpp:108
RHGenericDriver::_rxHeaderFlags
volatile uint8_t _rxHeaderFlags
FLAGS header in the last received mesasge.
Definition: RHGenericDriver.h:271
RH_TCP::available
virtual bool available()
RH_TCP::waitAvailable
virtual void waitAvailable()
RHTcpTypeMessage
Generic RH_TCP message structure with message type.
Definition: RHTcpProtocol.h:37
RHTcpPacket::length
uint32_t length
Number of octets following, in network byte order.
Definition: RHTcpProtocol.h:55
RHTcpPacket
RH_TCP radio message passed to or from the simulator.
Definition: RHTcpProtocol.h:53
RH_TCP::send
virtual bool send(const uint8_t *data, uint8_t len)
RH_TCP::recv
virtual bool recv(uint8_t *buf, uint8_t *len)
RHGenericDriver::_txHeaderId
uint8_t _txHeaderId
ID header to send in all messages.
Definition: RHGenericDriver.h:280
RHGenericDriver::_txHeaderTo
uint8_t _txHeaderTo
TO header to send in all messages.
Definition: RHGenericDriver.h:274
RHTcpPacket::to
uint8_t to
Node address of the recipient.
Definition: RHTcpProtocol.h:57
RHGenericDriver::_txHeaderFlags
uint8_t _txHeaderFlags
FLAGS header to send in all messages.
Definition: RHGenericDriver.h:283
RH_TCP::waitAvailableTimeout
virtual bool waitAvailableTimeout(uint16_t timeout)
RH_TCP::init
virtual bool init()
RHTcpThisAddress::length
uint32_t length
Number of octets following, in network byte order.
Definition: RHTcpProtocol.h:47
RHGenericDriver::_rxHeaderId
volatile uint8_t _rxHeaderId
ID header in the last received mesasge.
Definition: RHGenericDriver.h:268
RH_TCP
Driver to send and receive unaddressed, unreliable datagrams via sockets on a Linux simulator.
Definition: RH_TCP.h:67
RH_TCP::maxMessageLength
virtual uint8_t maxMessageLength()
RH_TCP::setThisAddress
void setThisAddress(uint8_t address)
RHTcpPacket::type
uint8_t type
== RH_TCP_MESSAGE_TYPE_PACKET
Definition: RHTcpProtocol.h:56
RHTcpPacket::id
uint8_t id
Message sequence number.
Definition: RHTcpProtocol.h:59
RHTcpThisAddress
RH_TCP message Notifies the server of thisAddress of this client.
Definition: RHTcpProtocol.h:45
RHGenericDriver::waitCAD
virtual bool waitCAD()
Definition: RHGenericDriver.cpp:72