friendev EtherDune TCP/IP library
/home/jander/temp/etherdune/Socket.cpp
Go to the documentation of this file.
1 // EtherDune Socket base class
2 // Author: Javier Peletier <jm@friendev.com>
3 // Summary: Base class for TCP and UDP sockets
4 //
5 // Copyright (c) 2015 All Rights Reserved, http://friendev.com
6 //
7 // This source is subject to the GPLv2 license.
8 // Please see the License.txt file for more information.
9 // All other rights reserved.
10 //
11 // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
12 // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13 // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
14 // PARTICULAR PURPOSE.
15 
16 #include "Socket.h"
17 #include "Checksum.h"
18 
19 #define AC_LOGLEVEL 2
20 #include <ACLog.h>
21 ACROSS_MODULE("Socket");
22 
23 uint8_t Socket::srcPort_L_count = 0;
24 
25 
26 
28 {
30  //packet.ip.version = 4;
31  //packet.ip.IHL = 0x05; //20 bytes
32  //packet.ip.raw[1] = 0x00; //DSCP/ECN=0;
33  //packet.ip.identification.zero();
34  //packet.ip.flags = 0;
35  //packet.ip.fragmentOffset = 0;
36  //packet.ip.checksum.zero();
37  //packet.ip.sourceIP = localIP;
38  //packet.ip.destinationIP = remoteIP;
39  //packet.ip.TTL = 255;
40  //packet.ip.checksum.rawValue = ~Checksum::calc(sizeof(IPHeader), (uint8_t*)&packet.ip);
41 }
42 
43 
44 
45 
54 uint16_t Socket::write(uint16_t len, const byte* data)
55 {
56  ACTRACE("write %d bytes. Dump:",len )
57  AC_TRACE(Serial.write(data, len));
58  AC_TRACE(Serial.println());
59 
60  return buffer.write(len, data);
61 }
62 
70 uint16_t Socket::write(const String& s)
71 {
72  return write(s.length(), (uint8_t*)s.c_str());
73 }
74 
103 uint16_t Socket::write(const __FlashStringHelper* pattern, ...)
104 {
105  char c;
106  char buf[16];
107  uint8_t i = 0;
108  va_list args;
109  va_start(args, pattern);
110  PGM_P p = (PGM_P)pattern;
111  uint16_t bytes = 0;
112 
113  for (;;)
114  {
115  c = (char)pgm_read_byte(p++);
116 
117  if (c == '%')
118  {
119  c = (char)pgm_read_byte(p);
120  if (c != '%')
121  {
122  bytes += write(i, (uint8_t*)buf);
123  bytes += write(*va_arg(args, String*));
124  i = 0;
125  continue;
126  }
127  p++;
128  }
129 
130  if (c == 0)
131  {
132  bytes += write(i, (uint8_t*)buf);
133  va_end(args);
134  return bytes;
135  }
136 
137  buf[i] = c;
138  i++;
139  if (i == sizeof(buf))
140  {
141  bytes += write(i, (uint8_t*)buf);
142  i = 0;
143 
144  }
145 
146 
147  }
148 
149 }
150 
158 uint16_t Socket::calcPseudoHeaderChecksum(uint8_t protocol, uint16_t length)
159 {
160  nint32_t pseudo;
161  pseudo.h.h = 0;
162  pseudo.h.l = protocol;
163  pseudo.l=length;
164 
165  uint16_t sum = Checksum::calc(sizeof(IPAddress) * 2, (uint8_t*)&packet.ip.sourceIP);
166  return Checksum::calc(sum, sizeof(pseudo), (uint8_t*)&pseudo);
167 }
168 
177 uint16_t Socket::calcTCPChecksum(bool options, uint16_t dataLength, uint16_t dataChecksum)
178 {
179  uint8_t headerLength = options ? sizeof(TCPOptions) + sizeof(TCPHeader) : sizeof(TCPHeader);
180  uint16_t sum = calcPseudoHeaderChecksum(IP_PROTO_TCP, dataLength + headerLength);
181  sum = Checksum::calc(sum, headerLength, (uint8_t*)&packet.tcp);
182  sum = Checksum::add(sum, dataChecksum);
183  return ~sum;
184 }
185 
192 uint16_t Socket::calcUDPChecksum(uint16_t dataLength, uint16_t dataChecksum)
193 {
194  uint16_t headerChecksum = calcPseudoHeaderChecksum(IP_PROTO_UDP, dataLength + sizeof(UDPHeader));
195  headerChecksum = Checksum::calc(headerChecksum, sizeof(UDPHeader), (uint8_t*)&packet.udp);
196 
197  return ~Checksum::add(headerChecksum, dataChecksum);
198 }
199 
200 
206 {
207 #if ENABLE_UDPTCP_RX_CHECKSUM
208  uint8_t headerLength;
209  uint16_t dataOffset;
210  switch (packet.ip.protocol)
211  {
212  case IP_PROTO_TCP:
213  {
214  headerLength = sizeof(IPHeader) + sizeof(TCPHeader);
215  dataOffset = sizeof(EthernetHeader) + sizeof(IPHeader) + sizeof(TCPHeader);
216  }break;
217  case IP_PROTO_UDP:
218  {
219  headerLength = sizeof(IPHeader) + sizeof(UDPHeader);
220  dataOffset = sizeof(EthernetHeader) + sizeof(IPHeader) + sizeof(UDPHeader);
221  }break;
222  default:
223  return true;
224  }
225 
226  uint16_t dataChecksum;
227 
228  uint16_t totalLength = packet.ip.totalLength;
229  uint16_t dataLength = totalLength - headerLength;
230 
231  dataChecksum = Checksum::calc(dataLength, packet.raw + dataOffset);
232 
233  uint16_t sum;
235  sum = calcTCPChecksum(false, dataLength, dataChecksum);
236  else
237  sum = calcUDPChecksum(dataLength, dataChecksum);
238 
239  return 0 == sum;
240 
241 
242 #else
243  return true;
244 #endif
245 
246 }
247 
IPAddress sourceIP
Source address.
Definition: inet.h:320
nint16_t h
most significant integer
Definition: inet.h:114
Structure to represent an UDP header.
Definition: inet.h:388
uint8_t raw[566]
Definition: inet.h:537
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
void prepareIPPacket()
Definition: Socket.cpp:27
static EthBuffer packet
in-memory packet buffer currently being processed.
nint16_t l
least significant integer
Definition: inet.h:115
static bool verifyUDPTCPChecksum()
Verifies if the UDP or TCP checksum of the current packet is correct.
Definition: Socket.cpp:205
Represents the header of an Ethernet frame.
Definition: inet.h:457
static uint16_t calc(uint16_t len, const uint8_t *data)
Calculates the checksum of the specified buffer in memory
Definition: Checksum.cpp:59
UDPHeader udp
Definition: inet.h:512
represents an IP address in memory
Definition: inet.h:181
SharedBuffer buffer
output buffer for this socket
Definition: Socket.h:42
uint8_t protocol
Protocol.
Definition: inet.h:318
ACROSS_MODULE("Socket")
Represents a network byte order 32 bit integer.
Definition: inet.h:109
IP header.
Definition: inet.h:296
static uint16_t add(uint16_t a, uint16_t b)
Adds two checksums, taking carry into account.
Definition: Checksum.cpp:25
TCP Header data structure.
Definition: inet.h:353
static uint16_t calcUDPChecksum(uint16_t dataLength, uint16_t dataChecksum)
Calculates the UDP checksum.
Definition: Socket.cpp:192
Contains functions to perform IP checksum operations.
Definition: Checksum.h:26
uint16_t write(uint16_t len, const byte *data)
Writes a fragment to the shared buffer
static uint16_t calcTCPChecksum(bool options, uint16_t dataLength, uint16_t dataChecksum)
Calculates the TCP checksum.
Definition: Socket.cpp:177
Structure to encode one 2-byte long TCP option.
Definition: inet.h:378
static const uint8_t IP_PROTO_TCP
IP header protocol type for TCP.
Definition: inet.h:571
static void prepareIPPacket(const IPAddress &remoteIP)
Sets up common IP header values for all outgoing IP packets and calculates the IP header checksum ...
static uint8_t srcPort_L_count
self-incrementing counter for local ports.
Definition: Socket.h:43
uint8_t l
least significant byte
Definition: inet.h:65
static uint16_t calcPseudoHeaderChecksum(uint8_t protocol, uint16_t length)
Calculates the TCP or UDP pseudo header checksum.
Definition: Socket.cpp:158
IPHeader ip
Definition: inet.h:506
IPAddress remoteIP
remote IP address to connect to (TCP) or send the next packet to (UDP)
Definition: Socket.h:55
nint16_t totalLength
This 16-bit field defines the entire packet (fragment) size, including header and data...
Definition: inet.h:310
uint8_t h
most significant byte
Definition: inet.h:64
TCPHeader tcp
Definition: inet.h:527
static const uint8_t IP_PROTO_UDP
IP header protocol type for UDP.
Definition: inet.h:572