Free (GPLv2) TCP/IP stack developed by TASS Belgium
Dependents: lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more
pico_udp.c
00001 /********************************************************************* 00002 PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved. 00003 See LICENSE and COPYING for usage. 00004 00005 . 00006 00007 Authors: Daniele Lacamera 00008 *********************************************************************/ 00009 00010 00011 #include "pico_udp.h" 00012 #include "pico_config.h" 00013 #include "pico_eth.h" 00014 #include "pico_socket.h" 00015 #include "pico_stack.h" 00016 00017 #define UDP_FRAME_OVERHEAD (sizeof(struct pico_frame)) 00018 #define udp_dbg(...) do {} while(0) 00019 00020 /* Queues */ 00021 static struct pico_queue udp_in = { 00022 0 00023 }; 00024 static struct pico_queue udp_out = { 00025 0 00026 }; 00027 00028 00029 /* Functions */ 00030 00031 uint16_t pico_udp_checksum_ipv4(struct pico_frame *f) 00032 { 00033 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr; 00034 struct pico_udp_hdr *udp_hdr = (struct pico_udp_hdr *) f->transport_hdr; 00035 struct pico_socket *s = f->sock; 00036 struct pico_ipv4_pseudo_hdr pseudo; 00037 00038 if (s) { 00039 /* Case of outgoing frame */ 00040 udp_dbg("UDP CRC: on outgoing frame\n"); 00041 pseudo.src.addr = s->local_addr.ip4.addr; 00042 pseudo.dst.addr = s->remote_addr.ip4.addr; 00043 } else { 00044 /* Case of incomming frame */ 00045 udp_dbg("UDP CRC: on incomming frame\n"); 00046 pseudo.src.addr = hdr->src.addr; 00047 pseudo.dst.addr = hdr->dst.addr; 00048 } 00049 00050 pseudo.zeros = 0; 00051 pseudo.proto = PICO_PROTO_UDP; 00052 pseudo.len = short_be(f->transport_len); 00053 00054 return pico_dualbuffer_checksum(&pseudo, sizeof(struct pico_ipv4_pseudo_hdr), udp_hdr, f->transport_len); 00055 } 00056 00057 #ifdef PICO_SUPPORT_IPV6 00058 uint16_t pico_udp_checksum_ipv6(struct pico_frame *f) 00059 { 00060 struct pico_ipv6_hdr *ipv6_hdr = (struct pico_ipv6_hdr *)f->net_hdr; 00061 struct pico_udp_hdr *udp_hdr = (struct pico_udp_hdr *)f->transport_hdr; 00062 struct pico_ipv6_pseudo_hdr pseudo = { 00063 .src = {{0}}, .dst = {{0}}, .len = 0, .zero = {0}, .nxthdr = 0 00064 }; 00065 struct pico_socket *s = f->sock; 00066 struct pico_remote_endpoint *remote_endpoint = (struct pico_remote_endpoint *)f->info; 00067 00068 /* XXX If the IPv6 packet contains a Routing header, the Destination 00069 * Address used in the pseudo-header is that of the final destination */ 00070 if (s) { 00071 /* Case of outgoing frame */ 00072 pseudo.src = s->local_addr.ip6; 00073 if (remote_endpoint) 00074 pseudo.dst = remote_endpoint->remote_addr.ip6; 00075 else 00076 pseudo.dst = s->remote_addr.ip6; 00077 } else { 00078 /* Case of incomming frame */ 00079 pseudo.src = ipv6_hdr->src; 00080 pseudo.dst = ipv6_hdr->dst; 00081 } 00082 00083 pseudo.len = long_be(f->transport_len); 00084 pseudo.nxthdr = PICO_PROTO_UDP; 00085 00086 return pico_dualbuffer_checksum(&pseudo, sizeof(struct pico_ipv6_pseudo_hdr), udp_hdr, f->transport_len); 00087 } 00088 #endif 00089 00090 00091 00092 static int pico_udp_process_out(struct pico_protocol *self, struct pico_frame *f) 00093 { 00094 IGNORE_PARAMETER(self); 00095 return (int)pico_network_send(f); 00096 } 00097 00098 static int pico_udp_push(struct pico_protocol *self, struct pico_frame *f) 00099 { 00100 struct pico_udp_hdr *hdr = (struct pico_udp_hdr *) f->transport_hdr; 00101 struct pico_remote_endpoint *remote_endpoint = (struct pico_remote_endpoint *) f->info; 00102 00103 /* this (fragmented) frame should contain a transport header */ 00104 if (f->transport_hdr != f->payload) { 00105 hdr->trans.sport = f->sock->local_port; 00106 if (remote_endpoint) { 00107 hdr->trans.dport = remote_endpoint->remote_port; 00108 } else { 00109 hdr->trans.dport = f->sock->remote_port; 00110 } 00111 00112 hdr->len = short_be(f->transport_len); 00113 00114 /* do not perform CRC validation. If you want to, a system needs to be 00115 implemented to calculate the CRC over the total payload of a 00116 fragmented payload 00117 */ 00118 hdr->crc = 0; 00119 } 00120 00121 if (pico_enqueue(self->q_out, f) > 0) { 00122 return f->payload_len; 00123 } else { 00124 return 0; 00125 } 00126 } 00127 00128 /* Interface: protocol definition */ 00129 struct pico_protocol pico_proto_udp = { 00130 .name = "udp", 00131 .proto_number = PICO_PROTO_UDP, 00132 .layer = PICO_LAYER_TRANSPORT, 00133 .process_in = pico_transport_process_in, 00134 .process_out = pico_udp_process_out, 00135 .push = pico_udp_push, 00136 .q_in = &udp_in, 00137 .q_out = &udp_out, 00138 }; 00139 00140 00141 00142 struct pico_socket *pico_udp_open(void) 00143 { 00144 struct pico_socket_udp *u = PICO_ZALLOC(sizeof(struct pico_socket_udp)); 00145 if (!u) 00146 return NULL; 00147 00148 u->mode = PICO_UDP_MODE_UNICAST; 00149 00150 #ifdef PICO_SUPPORT_MCAST 00151 u->mc_ttl = PICO_IP_DEFAULT_MULTICAST_TTL; 00152 /* enable multicast loopback by default */ 00153 u->sock.opt_flags |= (1 << PICO_SOCKET_OPT_MULTICAST_LOOP); 00154 #endif 00155 00156 return &u->sock; 00157 } 00158 00159 static void pico_udp_get_msginfo(struct pico_frame *f, struct pico_msginfo *msginfo) 00160 { 00161 msginfo->dev = f->dev; 00162 if (!msginfo || !f->net_hdr) 00163 return; 00164 00165 if (IS_IPV4(f)) { /* IPV4 */ 00166 #ifdef PICO_SUPPORT_IPV4 00167 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)(f->net_hdr); 00168 msginfo->ttl = hdr->ttl; 00169 msginfo->tos = hdr->tos; 00170 #endif 00171 } else { 00172 #ifdef PICO_SUPPORT_IPV6 00173 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)(f->net_hdr); 00174 msginfo->ttl = hdr->hop; 00175 msginfo->tos = (hdr->vtf >> 20) & 0xFF; /* IPv6 traffic class */ 00176 #endif 00177 } 00178 } 00179 00180 uint16_t pico_udp_recv(struct pico_socket *s, void *buf, uint16_t len, void *src, uint16_t *port, struct pico_msginfo *msginfo) 00181 { 00182 struct pico_frame *f = pico_queue_peek(&s->q_in); 00183 if (f) { 00184 if(!f->payload_len) { 00185 f->payload = f->transport_hdr + sizeof(struct pico_udp_hdr); 00186 f->payload_len = (uint16_t)(f->transport_len - sizeof(struct pico_udp_hdr)); 00187 } 00188 00189 udp_dbg("expected: %d, got: %d\n", len, f->payload_len); 00190 if (src) 00191 pico_store_network_origin(src, f); 00192 00193 if (port) { 00194 struct pico_trans *hdr = (struct pico_trans *)f->transport_hdr; 00195 *port = hdr->sport; 00196 } 00197 00198 if (msginfo) { 00199 pico_udp_get_msginfo(f, msginfo); 00200 } 00201 00202 if (f->payload_len > len) { 00203 memcpy(buf, f->payload, len); 00204 f->payload += len; 00205 f->payload_len = (uint16_t)(f->payload_len - len); 00206 return len; 00207 } else { 00208 uint16_t ret = f->payload_len; 00209 memcpy(buf, f->payload, f->payload_len); 00210 f = pico_dequeue(&s->q_in); 00211 pico_frame_discard(f); 00212 return ret; 00213 } 00214 } else return 0; 00215 } 00216
Generated on Tue Jul 12 2022 15:59:22 by 1.7.2