Free (GPLv2) TCP/IP stack developed by TASS Belgium

Fork of PicoTCP by Daniele Lacamera

Committer:
daniele
Date:
Sat Aug 03 08:50:27 2013 +0000
Revision:
51:18637a3d071f
Parent:
3:b4047e8a0123
Branch for CDC-ECM: Work in progress

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 3:b4047e8a0123 1 /*********************************************************************
daniele 3:b4047e8a0123 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 3:b4047e8a0123 3 See LICENSE and COPYING for usage.
daniele 3:b4047e8a0123 4
daniele 3:b4047e8a0123 5 .
daniele 3:b4047e8a0123 6
daniele 3:b4047e8a0123 7 Authors: Daniele Lacamera
daniele 3:b4047e8a0123 8 *********************************************************************/
daniele 3:b4047e8a0123 9
daniele 3:b4047e8a0123 10
daniele 3:b4047e8a0123 11 #include "pico_udp.h"
daniele 3:b4047e8a0123 12 #include "pico_config.h"
daniele 3:b4047e8a0123 13 #include "pico_eth.h"
daniele 3:b4047e8a0123 14 #include "pico_socket.h"
daniele 3:b4047e8a0123 15 #include "pico_stack.h"
daniele 3:b4047e8a0123 16
daniele 3:b4047e8a0123 17
daniele 3:b4047e8a0123 18 /* Queues */
daniele 3:b4047e8a0123 19 static struct pico_queue udp_in = {};
daniele 3:b4047e8a0123 20 static struct pico_queue udp_out = {};
daniele 3:b4047e8a0123 21
daniele 3:b4047e8a0123 22
daniele 3:b4047e8a0123 23 /* Functions */
daniele 3:b4047e8a0123 24
daniele 3:b4047e8a0123 25 uint16_t pico_udp_checksum_ipv4(struct pico_frame *f)
daniele 3:b4047e8a0123 26 {
daniele 3:b4047e8a0123 27 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 3:b4047e8a0123 28 struct pico_udp_hdr *udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
daniele 3:b4047e8a0123 29 struct pico_socket *s = f->sock;
daniele 3:b4047e8a0123 30 struct pico_ipv4_pseudo_hdr pseudo;
daniele 3:b4047e8a0123 31
daniele 3:b4047e8a0123 32 if (s) {
daniele 3:b4047e8a0123 33 /* Case of outgoing frame */
daniele 3:b4047e8a0123 34 //dbg("UDP CRC: on outgoing frame\n");
daniele 3:b4047e8a0123 35 pseudo.src.addr = s->local_addr.ip4.addr;
daniele 3:b4047e8a0123 36 pseudo.dst.addr = s->remote_addr.ip4.addr;
daniele 3:b4047e8a0123 37 } else {
daniele 3:b4047e8a0123 38 /* Case of incomming frame */
daniele 3:b4047e8a0123 39 //dbg("UDP CRC: on incomming frame\n");
daniele 3:b4047e8a0123 40 pseudo.src.addr = hdr->src.addr;
daniele 3:b4047e8a0123 41 pseudo.dst.addr = hdr->dst.addr;
daniele 3:b4047e8a0123 42 }
daniele 3:b4047e8a0123 43 pseudo.zeros = 0;
daniele 3:b4047e8a0123 44 pseudo.proto = PICO_PROTO_UDP;
daniele 3:b4047e8a0123 45 pseudo.len = short_be(f->transport_len);
daniele 3:b4047e8a0123 46
daniele 3:b4047e8a0123 47 return pico_dualbuffer_checksum(&pseudo, sizeof(struct pico_ipv4_pseudo_hdr), udp_hdr, f->transport_len);
daniele 3:b4047e8a0123 48 }
daniele 3:b4047e8a0123 49
daniele 3:b4047e8a0123 50
daniele 3:b4047e8a0123 51 static int pico_udp_process_out(struct pico_protocol *self, struct pico_frame *f)
daniele 3:b4047e8a0123 52 {
daniele 3:b4047e8a0123 53 return pico_network_send(f);
daniele 3:b4047e8a0123 54 }
daniele 3:b4047e8a0123 55
daniele 3:b4047e8a0123 56 static int pico_udp_push(struct pico_protocol *self, struct pico_frame *f)
daniele 3:b4047e8a0123 57 {
daniele 3:b4047e8a0123 58 struct pico_udp_hdr *hdr = (struct pico_udp_hdr *) f->transport_hdr;
daniele 3:b4047e8a0123 59 struct pico_remote_duple *remote_duple = (struct pico_remote_duple *) f->info;
daniele 3:b4047e8a0123 60
daniele 3:b4047e8a0123 61 /* this (fragmented) frame should contain a transport header */
daniele 3:b4047e8a0123 62 if (f->transport_hdr != f->payload) {
daniele 3:b4047e8a0123 63 hdr->trans.sport = f->sock->local_port;
daniele 3:b4047e8a0123 64 if (remote_duple) {
daniele 3:b4047e8a0123 65 hdr->trans.dport = remote_duple->remote_port;
daniele 3:b4047e8a0123 66 } else {
daniele 3:b4047e8a0123 67 hdr->trans.dport = f->sock->remote_port;
daniele 3:b4047e8a0123 68 }
daniele 3:b4047e8a0123 69 hdr->len = short_be(f->transport_len);
daniele 3:b4047e8a0123 70 /* do not perform CRC validation. If you want to, a system needs to be
daniele 3:b4047e8a0123 71 implemented to calculate the CRC over the total payload of a
daniele 3:b4047e8a0123 72 fragmented payload */
daniele 3:b4047e8a0123 73 hdr->crc = 0;
daniele 3:b4047e8a0123 74 }
daniele 3:b4047e8a0123 75
daniele 3:b4047e8a0123 76 if (pico_enqueue(self->q_out, f) > 0) {
daniele 3:b4047e8a0123 77 return f->payload_len;
daniele 3:b4047e8a0123 78 } else {
daniele 3:b4047e8a0123 79 return 0;
daniele 3:b4047e8a0123 80 }
daniele 3:b4047e8a0123 81 }
daniele 3:b4047e8a0123 82
daniele 3:b4047e8a0123 83 /* Interface: protocol definition */
daniele 3:b4047e8a0123 84 struct pico_protocol pico_proto_udp = {
daniele 3:b4047e8a0123 85 .name = "udp",
daniele 3:b4047e8a0123 86 .proto_number = PICO_PROTO_UDP,
daniele 3:b4047e8a0123 87 .layer = PICO_LAYER_TRANSPORT,
daniele 3:b4047e8a0123 88 .process_in = pico_transport_process_in,
daniele 3:b4047e8a0123 89 .process_out = pico_udp_process_out,
daniele 3:b4047e8a0123 90 .push = pico_udp_push,
daniele 3:b4047e8a0123 91 .q_in = &udp_in,
daniele 3:b4047e8a0123 92 .q_out = &udp_out,
daniele 3:b4047e8a0123 93 };
daniele 3:b4047e8a0123 94
daniele 3:b4047e8a0123 95
daniele 3:b4047e8a0123 96 #define PICO_UDP_MODE_UNICAST 0x01
daniele 3:b4047e8a0123 97 #define PICO_UDP_MODE_MULTICAST 0x02
daniele 3:b4047e8a0123 98 #define PICO_UDP_MODE_BROADCAST 0xFF
daniele 3:b4047e8a0123 99
daniele 3:b4047e8a0123 100 struct pico_socket_udp
daniele 3:b4047e8a0123 101 {
daniele 3:b4047e8a0123 102 struct pico_socket sock;
daniele 3:b4047e8a0123 103 int mode;
daniele 3:b4047e8a0123 104 #ifdef PICO_SUPPORT_MCAST
daniele 3:b4047e8a0123 105 uint8_t mc_ttl; /* Multicasting TTL */
daniele 3:b4047e8a0123 106 #endif
daniele 3:b4047e8a0123 107 };
daniele 3:b4047e8a0123 108
daniele 3:b4047e8a0123 109 #ifdef PICO_SUPPORT_MCAST
daniele 3:b4047e8a0123 110 int pico_udp_set_mc_ttl(struct pico_socket *s, uint8_t ttl)
daniele 3:b4047e8a0123 111 {
daniele 3:b4047e8a0123 112 struct pico_socket_udp *u;
daniele 3:b4047e8a0123 113 if(!s) {
daniele 3:b4047e8a0123 114 pico_err = PICO_ERR_EINVAL;
daniele 3:b4047e8a0123 115 return -1;
daniele 3:b4047e8a0123 116 }
daniele 3:b4047e8a0123 117 u = (struct pico_socket_udp *) s;
daniele 3:b4047e8a0123 118 u->mc_ttl = ttl;
daniele 3:b4047e8a0123 119 return 0;
daniele 3:b4047e8a0123 120 }
daniele 3:b4047e8a0123 121
daniele 3:b4047e8a0123 122 int pico_udp_get_mc_ttl(struct pico_socket *s, uint8_t *ttl)
daniele 3:b4047e8a0123 123 {
daniele 3:b4047e8a0123 124 struct pico_socket_udp *u;
daniele 3:b4047e8a0123 125 if(!s)
daniele 3:b4047e8a0123 126 return -1;
daniele 3:b4047e8a0123 127 u = (struct pico_socket_udp *) s;
daniele 3:b4047e8a0123 128 *ttl = u->mc_ttl;
daniele 3:b4047e8a0123 129 return 0;
daniele 3:b4047e8a0123 130 }
daniele 3:b4047e8a0123 131 #endif /* PICO_SUPPORT_MCAST */
daniele 3:b4047e8a0123 132
daniele 3:b4047e8a0123 133 struct pico_socket *pico_udp_open(void)
daniele 3:b4047e8a0123 134 {
daniele 3:b4047e8a0123 135 struct pico_socket_udp *u = pico_zalloc(sizeof(struct pico_socket_udp));
daniele 3:b4047e8a0123 136 if (!u)
daniele 3:b4047e8a0123 137 return NULL;
daniele 3:b4047e8a0123 138 u->mode = PICO_UDP_MODE_UNICAST;
daniele 3:b4047e8a0123 139
daniele 3:b4047e8a0123 140 #ifdef PICO_SUPPORT_MCAST
daniele 3:b4047e8a0123 141 u->mc_ttl = PICO_IP_DEFAULT_MULTICAST_TTL;
daniele 3:b4047e8a0123 142 /* enable multicast loopback by default */
daniele 3:b4047e8a0123 143 u->sock.opt_flags |= (1 << PICO_SOCKET_OPT_MULTICAST_LOOP);
daniele 3:b4047e8a0123 144 #endif
daniele 3:b4047e8a0123 145
daniele 3:b4047e8a0123 146 return &u->sock;
daniele 3:b4047e8a0123 147 }
daniele 3:b4047e8a0123 148
daniele 3:b4047e8a0123 149 int pico_udp_recv(struct pico_socket *s, void *buf, int len, void *src, uint16_t *port)
daniele 3:b4047e8a0123 150 {
daniele 3:b4047e8a0123 151 struct pico_frame *f = pico_queue_peek(&s->q_in);
daniele 3:b4047e8a0123 152 if (f) {
daniele 3:b4047e8a0123 153 f->payload = f->transport_hdr + sizeof(struct pico_udp_hdr);
daniele 3:b4047e8a0123 154 f->payload_len = f->transport_len - sizeof(struct pico_udp_hdr);
daniele 3:b4047e8a0123 155 // dbg("expected: %d, got: %d\n", len, f->payload_len);
daniele 3:b4047e8a0123 156 if (src)
daniele 3:b4047e8a0123 157 pico_store_network_origin(src, f);
daniele 3:b4047e8a0123 158 if (port) {
daniele 3:b4047e8a0123 159 struct pico_trans *hdr = (struct pico_trans *)f->transport_hdr;
daniele 3:b4047e8a0123 160 *port = hdr->sport;
daniele 3:b4047e8a0123 161 }
daniele 3:b4047e8a0123 162 if (f->payload_len > len) {
daniele 3:b4047e8a0123 163 memcpy(buf, f->payload, len);
daniele 3:b4047e8a0123 164 f->payload += len;
daniele 3:b4047e8a0123 165 f->payload_len -= len;
daniele 3:b4047e8a0123 166 return len;
daniele 3:b4047e8a0123 167 } else {
daniele 3:b4047e8a0123 168 int ret = f->payload_len;
daniele 3:b4047e8a0123 169 memcpy(buf, f->payload, f->payload_len);
daniele 3:b4047e8a0123 170 f = pico_dequeue(&s->q_in);
daniele 3:b4047e8a0123 171 pico_frame_discard(f);
daniele 3:b4047e8a0123 172 return ret;
daniele 3:b4047e8a0123 173 }
daniele 3:b4047e8a0123 174 } else return 0;
daniele 3:b4047e8a0123 175 }
daniele 3:b4047e8a0123 176