simple reliable networking over ethernet. Provides IPv4 ARP, ICMP echo reply, and UDP unicast. Does NOT provide TCP, that's not simple :-).

Committer:
altasoul
Date:
Wed Apr 01 20:58:30 2015 +0000
Revision:
7:45bae1fecc36
Parent:
5:7ed0abcc02d1
Quiet the inet unhandled protocol printf

Who changed what in which revision?

UserRevisionLine numberNew contents of line
altasoul 2:397316d97354 1 /*
altasoul 2:397316d97354 2 The MIT License (MIT)
altasoul 2:397316d97354 3
altasoul 2:397316d97354 4 Copyright (c) 2015 Tom Soulanille
altasoul 2:397316d97354 5
altasoul 2:397316d97354 6 Permission is hereby granted, free of charge, to any person obtaining a copy
altasoul 2:397316d97354 7 of this software and associated documentation files (the "Software"), to deal
altasoul 2:397316d97354 8 in the Software without restriction, including without limitation the rights
altasoul 2:397316d97354 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
altasoul 2:397316d97354 10 copies of the Software, and to permit persons to whom the Software is
altasoul 2:397316d97354 11 furnished to do so, subject to the following conditions:
altasoul 2:397316d97354 12
altasoul 2:397316d97354 13 The above copyright notice and this permission notice shall be included in
altasoul 2:397316d97354 14 all copies or substantial portions of the Software.
altasoul 2:397316d97354 15
altasoul 2:397316d97354 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
altasoul 2:397316d97354 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
altasoul 2:397316d97354 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
altasoul 2:397316d97354 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
altasoul 2:397316d97354 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
altasoul 2:397316d97354 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
altasoul 2:397316d97354 22 THE SOFTWARE.
altasoul 2:397316d97354 23
altasoul 2:397316d97354 24 @file udp.cpp
altasoul 2:397316d97354 25 @purpose simple networking
altasoul 2:397316d97354 26 @version 0.1
altasoul 2:397316d97354 27 @date 31 March 2015
altasoul 2:397316d97354 28 @author Tom Soulanille
altasoul 2:397316d97354 29 */
altasoul 2:397316d97354 30
altasoul 0:6df0a6ed91d4 31 #include "snet.h"
altasoul 0:6df0a6ed91d4 32
altasoul 0:6df0a6ed91d4 33 #if 0
altasoul 0:6df0a6ed91d4 34 //-- from util.cpp
altasoul 0:6df0a6ed91d4 35 extern void print_hex(const uint8_t *p, int len);
altasoul 2:397316d97354 36 #endif
altasoul 0:6df0a6ed91d4 37
altasoul 0:6df0a6ed91d4 38 void Snet::turn_udp_packet_around(uint8_t *buf) {
altasoul 0:6df0a6ed91d4 39 uint8_t dh, dl;
altasoul 0:6df0a6ed91d4 40 turn_ip_packet_around(buf);
altasoul 0:6df0a6ed91d4 41 dh = buf[UDP_DST_PORT_O];
altasoul 0:6df0a6ed91d4 42 dl = buf[UDP_DST_PORT_O+1];
altasoul 0:6df0a6ed91d4 43 buf[UDP_DST_PORT_O] = buf[UDP_SRC_PORT_O];
altasoul 0:6df0a6ed91d4 44 buf[UDP_DST_PORT_O+1] = buf[UDP_SRC_PORT_O+1];
altasoul 0:6df0a6ed91d4 45 buf[UDP_SRC_PORT_O] = dh;
altasoul 0:6df0a6ed91d4 46 buf[UDP_SRC_PORT_O+1] = dl;
altasoul 0:6df0a6ed91d4 47 }
altasoul 0:6df0a6ed91d4 48
altasoul 0:6df0a6ed91d4 49 // Send a UDP packet addressed as in buf, with specified payload
altasoul 0:6df0a6ed91d4 50 void Snet::send_udp_packet(uint8_t *buf, const uint8_t *payload, int payload_len) {
altasoul 0:6df0a6ed91d4 51 int ip_total_length = UDP_PAYLOAD_O - IP_HEADER_O + payload_len;
altasoul 0:6df0a6ed91d4 52 int udp_length = UDP_HEADER_LEN + payload_len;
altasoul 0:6df0a6ed91d4 53 buf[IP_TOTAL_LENGTH_O] = ip_total_length >> 8;
altasoul 0:6df0a6ed91d4 54 buf[IP_TOTAL_LENGTH_O+1] = ip_total_length;
altasoul 0:6df0a6ed91d4 55
altasoul 0:6df0a6ed91d4 56 buf[UDP_LENGTH_O] = udp_length >> 8;
altasoul 0:6df0a6ed91d4 57 buf[UDP_LENGTH_O+1] = udp_length;
altasoul 0:6df0a6ed91d4 58 #if 0
altasoul 0:6df0a6ed91d4 59 // RFC1768: "An all zero transmitted
altasoul 0:6df0a6ed91d4 60 // checksum value means that the transmitter generated no checksum (for
altasoul 0:6df0a6ed91d4 61 // debugging or for higher level protocols that don't care)."
altasoul 0:6df0a6ed91d4 62 buf[UDP_CHECKSUM_O] = buf[UDP_CHECKSUM_O+1] = 0;
altasoul 0:6df0a6ed91d4 63 #else
altasoul 0:6df0a6ed91d4 64 // find the udp checksum for a given enet packet presumed to be udp
altasoul 0:6df0a6ed91d4 65 // From rfc768:
altasoul 0:6df0a6ed91d4 66 // The pseudo header conceptually prefixed to the UDP header contains the
altasoul 0:6df0a6ed91d4 67 // source address, the destination address, the protocol, and the UDP
altasoul 0:6df0a6ed91d4 68 // length. This information gives protection against misrouted datagrams.
altasoul 0:6df0a6ed91d4 69 // This checksum procedure is the same as is used in TCP.
altasoul 0:6df0a6ed91d4 70 //
altasoul 0:6df0a6ed91d4 71 // 0 7 8 15 16 23 24 31
altasoul 0:6df0a6ed91d4 72 // +--------+--------+--------+--------+
altasoul 0:6df0a6ed91d4 73 // | source address |
altasoul 0:6df0a6ed91d4 74 // +--------+--------+--------+--------+
altasoul 0:6df0a6ed91d4 75 // | destination address |
altasoul 0:6df0a6ed91d4 76 // +--------+--------+--------+--------+
altasoul 0:6df0a6ed91d4 77 // | zero |protocol| UDP length |
altasoul 0:6df0a6ed91d4 78 // +--------+--------+--------+--------+
altasoul 0:6df0a6ed91d4 79 //
altasoul 0:6df0a6ed91d4 80 // If the computed checksum is zero, it is transmitted as all ones (the
altasoul 0:6df0a6ed91d4 81 // equivalent in one's complement arithmetic). An all zero transmitted
altasoul 0:6df0a6ed91d4 82 // checksum value means that the transmitter generated no checksum (for
altasoul 0:6df0a6ed91d4 83 // debugging or for higher level protocols that don't care).
altasoul 0:6df0a6ed91d4 84
altasoul 0:6df0a6ed91d4 85 // This is the pseudo-header sum
altasoul 0:6df0a6ed91d4 86 int sum = ones_complement_sum(&buf[IP_SADDR_O], 4+4, 0);
altasoul 0:6df0a6ed91d4 87 sum += 0x11; // proto
altasoul 0:6df0a6ed91d4 88 sum += 8 + payload_len; // UDP length
altasoul 0:6df0a6ed91d4 89
altasoul 0:6df0a6ed91d4 90 // add the real UDP header, with zeroed-out checksum
altasoul 0:6df0a6ed91d4 91 buf[UDP_CHECKSUM_O] = buf[UDP_CHECKSUM_O+1] = 0;
altasoul 0:6df0a6ed91d4 92 sum = ones_complement_sum(&buf[UDP_HEADER_O],
altasoul 0:6df0a6ed91d4 93 UDP_PAYLOAD_O - UDP_HEADER_O,
altasoul 0:6df0a6ed91d4 94 sum);
altasoul 0:6df0a6ed91d4 95
altasoul 0:6df0a6ed91d4 96 // add the payload that will be included and take the result
altasoul 0:6df0a6ed91d4 97 int chksum = ~ones_complement_sum(payload, payload_len, sum);
altasoul 0:6df0a6ed91d4 98
altasoul 0:6df0a6ed91d4 99 chksum = chksum ? chksum : ~chksum; // send -0 for +0
altasoul 0:6df0a6ed91d4 100 buf[UDP_CHECKSUM_O] = chksum >> 8;
altasoul 0:6df0a6ed91d4 101 buf[UDP_CHECKSUM_O+1] = chksum;
altasoul 0:6df0a6ed91d4 102 #endif
altasoul 0:6df0a6ed91d4 103 buf[IP_CHKSUM_O] = buf[IP_CHKSUM_O+1] = 0;
altasoul 0:6df0a6ed91d4 104 int chk = ip_checksum_of(&buf[IP_HEADER_O], IP_HEADER_LEN);
altasoul 0:6df0a6ed91d4 105 buf[IP_CHKSUM_O] = chk >> 8;
altasoul 0:6df0a6ed91d4 106 buf[IP_CHKSUM_O+1] = chk;
altasoul 0:6df0a6ed91d4 107 eth.write((char *) buf, UDP_PAYLOAD_O);
altasoul 0:6df0a6ed91d4 108 eth.write((char *) payload, payload_len);
altasoul 0:6df0a6ed91d4 109 eth.send();
altasoul 0:6df0a6ed91d4 110 #if 0
altasoul 0:6df0a6ed91d4 111 printf("rup wrote:");
altasoul 0:6df0a6ed91d4 112 print_hex(buf, UDP_PAYLOAD_O);
altasoul 0:6df0a6ed91d4 113 printf("then wrote:");
altasoul 0:6df0a6ed91d4 114 print_hex((uint8_t *) payload, payload_len);
altasoul 0:6df0a6ed91d4 115 printf("udp chksum 0x%02x%02x\r\n", buf[UDP_CHECKSUM_O], buf[UDP_CHECKSUM_O+1]);
altasoul 0:6df0a6ed91d4 116 #endif
altasoul 0:6df0a6ed91d4 117 }
altasoul 0:6df0a6ed91d4 118
altasoul 0:6df0a6ed91d4 119 // Return a UDP packet to the sender of packet in buf, with new payload
altasoul 0:6df0a6ed91d4 120 void Snet::return_udp_packet(uint8_t *buf, const uint8_t *payload, int payload_len) {
altasoul 0:6df0a6ed91d4 121 turn_udp_packet_around(buf);
altasoul 0:6df0a6ed91d4 122 send_udp_packet(buf, payload, payload_len);
altasoul 0:6df0a6ed91d4 123 }
altasoul 0:6df0a6ed91d4 124
altasoul 0:6df0a6ed91d4 125 void Snet::send_to_correspondent(const uint8_t *what, int what_len) {
altasoul 0:6df0a6ed91d4 126 send_udp_packet(correspondent_facing_packet_header, what, what_len);
altasoul 0:6df0a6ed91d4 127 }
altasoul 0:6df0a6ed91d4 128
altasoul 2:397316d97354 129 void Snet::tell_udp_correspondent(char *s) {
altasoul 0:6df0a6ed91d4 130 send_to_correspondent((const uint8_t *) s, strlen(s));
altasoul 0:6df0a6ed91d4 131 }
altasoul 0:6df0a6ed91d4 132
altasoul 1:9c211ac06a12 133 void Snet::set_udp_correspondent(uint8_t *buf, int len) {
altasoul 0:6df0a6ed91d4 134 turn_udp_packet_around(buf);
altasoul 0:6df0a6ed91d4 135 memcpy(correspondent_facing_packet_header, buf, UDP_PAYLOAD_O);
altasoul 1:9c211ac06a12 136 }
altasoul 1:9c211ac06a12 137
altasoul 0:6df0a6ed91d4 138 void Snet::handle_udp_packet(uint8_t *buf, int len) {
altasoul 0:6df0a6ed91d4 139 #if 0
altasoul 0:6df0a6ed91d4 140 printf("UDP:");
altasoul 0:6df0a6ed91d4 141 print_hex(&buf[UDP_HEADER_O], len-UDP_HEADER_O);
altasoul 0:6df0a6ed91d4 142 #endif
altasoul 1:9c211ac06a12 143 if (registered_udp_handler) (*registered_udp_handler)(buf, len);
altasoul 0:6df0a6ed91d4 144 };