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

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass picotcp@tass.be
Date:
Wed Apr 09 14:31:41 2014 +0200
Revision:
149:5f4cb161cec3
Parent:
138:0a7a449980e6
Child:
150:551effcf6a39
Update from git masterbranch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
TASS Belgium NV 131:4758606c9316 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
tass 68:0847e35d08a6 5
TASS Belgium NV 131:4758606c9316 6 Authors: Daniele Lacamera
TASS Belgium NV 131:4758606c9316 7 *********************************************************************/
tass 68:0847e35d08a6 8
tass 68:0847e35d08a6 9
tass 68:0847e35d08a6 10 #include "pico_config.h"
tass 68:0847e35d08a6 11 #include "pico_queue.h"
tass 68:0847e35d08a6 12 #include "pico_socket.h"
tass 68:0847e35d08a6 13 #include "pico_ipv4.h"
tass 68:0847e35d08a6 14 #include "pico_ipv6.h"
tass 68:0847e35d08a6 15 #include "pico_udp.h"
tass 68:0847e35d08a6 16 #include "pico_tcp.h"
tass 68:0847e35d08a6 17 #include "pico_stack.h"
tass 68:0847e35d08a6 18 #include "pico_icmp4.h"
tass 68:0847e35d08a6 19 #include "pico_nat.h"
tass 68:0847e35d08a6 20 #include "pico_tree.h"
tass 68:0847e35d08a6 21 #include "pico_device.h"
tass picotcp@tass.be 149:5f4cb161cec3 22 #include "pico_socket_multicast.h"
tass picotcp@tass.be 149:5f4cb161cec3 23 #include "pico_socket_tcp.h"
tass picotcp@tass.be 149:5f4cb161cec3 24 #include "pico_socket_udp.h"
tass 68:0847e35d08a6 25
tass 68:0847e35d08a6 26 #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
tass 68:0847e35d08a6 27 #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
tass 68:0847e35d08a6 28
tass 68:0847e35d08a6 29
tass 68:0847e35d08a6 30 #define PROTO(s) ((s)->proto->proto_number)
tass 68:0847e35d08a6 31 #define PICO_SOCKET4_MTU 1480 /* Ethernet MTU(1500) - IP header size(20) */
tass 68:0847e35d08a6 32 #define PICO_SOCKET6_MTU 1460 /* Ethernet MTU(1500) - IP header size(40) */
tass 68:0847e35d08a6 33 #define TCP_STATE(s) (s->state & PICO_SOCKET_STATE_TCP)
tass 68:0847e35d08a6 34
tass 68:0847e35d08a6 35 #ifdef PICO_SUPPORT_MUTEX
TASS Belgium NV 131:4758606c9316 36 static void *Mutex = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 37 #define PICOTCP_MUTEX_LOCK(x) { \
TASS Belgium NV 131:4758606c9316 38 if (x == NULL) \
TASS Belgium NV 131:4758606c9316 39 x = pico_mutex_init(); \
TASS Belgium NV 131:4758606c9316 40 pico_mutex_lock(x); \
tass 68:0847e35d08a6 41 }
tass picotcp@tass.be 149:5f4cb161cec3 42 #define PICOTCP_MUTEX_UNLOCK(x) pico_mutex_unlock(x)
tass 68:0847e35d08a6 43
tass 68:0847e35d08a6 44 #else
tass picotcp@tass.be 149:5f4cb161cec3 45 #define PICOTCP_MUTEX_LOCK(x) do {} while(0)
tass picotcp@tass.be 149:5f4cb161cec3 46 #define PICOTCP_MUTEX_UNLOCK(x) do {} while(0)
tass 68:0847e35d08a6 47 #endif
tass 68:0847e35d08a6 48
tass 68:0847e35d08a6 49
tass 68:0847e35d08a6 50 #define PROTO(s) ((s)->proto->proto_number)
tass 68:0847e35d08a6 51
tass 68:0847e35d08a6 52 #define PICO_SOCKET_MTU 1480 /* Ethernet MTU(1500) - IP header size(20) */
tass 68:0847e35d08a6 53
tass 68:0847e35d08a6 54 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 55 # define IS_SOCK_IPV4(s) ((s->net == &pico_proto_ipv4))
tass 68:0847e35d08a6 56 #else
tass 68:0847e35d08a6 57 # define IS_SOCK_IPV4(s) (0)
tass 68:0847e35d08a6 58 #endif
tass 68:0847e35d08a6 59
tass 68:0847e35d08a6 60 #ifdef PICO_SUPPORT_IPV6
tass 68:0847e35d08a6 61 # define IS_SOCK_IPV6(s) ((s->net == &pico_proto_ipv6))
tass 68:0847e35d08a6 62 #else
tass 68:0847e35d08a6 63 # define IS_SOCK_IPV6(s) (0)
tass 68:0847e35d08a6 64 #endif
tass 68:0847e35d08a6 65
TASS Belgium NV 131:4758606c9316 66 # define frag_dbg(...) do {} while(0)
tass 68:0847e35d08a6 67
tass 68:0847e35d08a6 68
TASS Belgium NV 131:4758606c9316 69 static struct pico_sockport *sp_udp = NULL, *sp_tcp = NULL;
tass 68:0847e35d08a6 70
tass 70:cd218dd180e5 71 struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, uint16_t len);
tass 68:0847e35d08a6 72
tass picotcp@tass.be 149:5f4cb161cec3 73 static int socket_cmp_family(struct pico_socket *a, struct pico_socket *b)
tass 68:0847e35d08a6 74 {
TASS Belgium NV 131:4758606c9316 75 uint32_t a_is_ip6 = is_sock_ipv6(a);
TASS Belgium NV 131:4758606c9316 76 uint32_t b_is_ip6 = is_sock_ipv6(b);
tass picotcp@tass.be 149:5f4cb161cec3 77 (void)a;
tass picotcp@tass.be 149:5f4cb161cec3 78 (void)b;
TASS Belgium NV 131:4758606c9316 79 if (a_is_ip6 < b_is_ip6)
TASS Belgium NV 131:4758606c9316 80 return -1;
tass 68:0847e35d08a6 81
TASS Belgium NV 131:4758606c9316 82 if (a_is_ip6 > b_is_ip6)
TASS Belgium NV 131:4758606c9316 83 return 1;
tass 68:0847e35d08a6 84
tass picotcp@tass.be 149:5f4cb161cec3 85 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 86 }
tass picotcp@tass.be 149:5f4cb161cec3 87
TASS Belgium NV 131:4758606c9316 88
tass picotcp@tass.be 149:5f4cb161cec3 89 static int socket_cmp_ipv6(struct pico_socket *a, struct pico_socket *b)
tass picotcp@tass.be 149:5f4cb161cec3 90 {
tass picotcp@tass.be 149:5f4cb161cec3 91 int ret = 0;
tass picotcp@tass.be 149:5f4cb161cec3 92 (void)a;
tass picotcp@tass.be 149:5f4cb161cec3 93 (void)b;
tass picotcp@tass.be 149:5f4cb161cec3 94 if (!is_sock_ipv6(a) || !is_sock_ipv6(b))
tass picotcp@tass.be 149:5f4cb161cec3 95 return 0;
tass 68:0847e35d08a6 96
tass 68:0847e35d08a6 97 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 98 if ((memcmp(a->local_addr.ip6.addr, PICO_IP6_ANY, PICO_SIZE_IP6) == 0) || (memcmp(b->local_addr.ip6.addr, PICO_IP6_ANY, PICO_SIZE_IP6) == 0))
tass picotcp@tass.be 149:5f4cb161cec3 99 ret = 0;
tass picotcp@tass.be 149:5f4cb161cec3 100 else
tass picotcp@tass.be 149:5f4cb161cec3 101 ret = memcmp(a->local_addr.ip6.addr, b->local_addr.ip6.addr, PICO_SIZE_IP6);
tass picotcp@tass.be 149:5f4cb161cec3 102
tass picotcp@tass.be 149:5f4cb161cec3 103 #endif
tass picotcp@tass.be 149:5f4cb161cec3 104 return ret;
tass picotcp@tass.be 149:5f4cb161cec3 105 }
tass picotcp@tass.be 149:5f4cb161cec3 106
tass picotcp@tass.be 149:5f4cb161cec3 107 static int socket_cmp_ipv4(struct pico_socket *a, struct pico_socket *b)
tass picotcp@tass.be 149:5f4cb161cec3 108 {
tass picotcp@tass.be 149:5f4cb161cec3 109 int ret = 0;
tass picotcp@tass.be 149:5f4cb161cec3 110 (void)a;
tass picotcp@tass.be 149:5f4cb161cec3 111 (void)b;
tass picotcp@tass.be 149:5f4cb161cec3 112 if (!is_sock_ipv4(a) || !is_sock_ipv4(b))
tass picotcp@tass.be 149:5f4cb161cec3 113 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 114
tass picotcp@tass.be 149:5f4cb161cec3 115 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 116 if ((a->local_addr.ip4.addr == PICO_IP4_ANY) || (b->local_addr.ip4.addr == PICO_IP4_ANY))
tass picotcp@tass.be 149:5f4cb161cec3 117 ret = 0;
tass picotcp@tass.be 149:5f4cb161cec3 118 else
tass picotcp@tass.be 149:5f4cb161cec3 119 ret = (int)(a->local_addr.ip4.addr - b->local_addr.ip4.addr);
TASS Belgium NV 131:4758606c9316 120
tass 68:0847e35d08a6 121 #endif
tass picotcp@tass.be 149:5f4cb161cec3 122 return ret;
tass picotcp@tass.be 149:5f4cb161cec3 123 }
tass picotcp@tass.be 149:5f4cb161cec3 124
tass picotcp@tass.be 149:5f4cb161cec3 125 static int socket_cmp_remotehost(struct pico_socket *a, struct pico_socket *b)
tass picotcp@tass.be 149:5f4cb161cec3 126 {
tass picotcp@tass.be 149:5f4cb161cec3 127 int ret = 0;
tass picotcp@tass.be 149:5f4cb161cec3 128 if (is_sock_ipv6(a))
tass picotcp@tass.be 149:5f4cb161cec3 129 ret = memcmp(a->remote_addr.ip6.addr, b->remote_addr.ip6.addr, PICO_SIZE_IP6);
tass picotcp@tass.be 149:5f4cb161cec3 130 else
tass picotcp@tass.be 149:5f4cb161cec3 131 ret = (int)(a->remote_addr.ip4.addr - b->remote_addr.ip4.addr);
tass 68:0847e35d08a6 132
tass picotcp@tass.be 149:5f4cb161cec3 133 return ret;
tass picotcp@tass.be 149:5f4cb161cec3 134 }
tass 68:0847e35d08a6 135
tass picotcp@tass.be 149:5f4cb161cec3 136 static int socket_cmp_addresses(struct pico_socket *a, struct pico_socket *b)
tass picotcp@tass.be 149:5f4cb161cec3 137 {
tass picotcp@tass.be 149:5f4cb161cec3 138 int ret = 0;
tass picotcp@tass.be 149:5f4cb161cec3 139 /* At this point, sort by local host */
tass picotcp@tass.be 149:5f4cb161cec3 140 ret = socket_cmp_ipv6(a, b);
tass picotcp@tass.be 149:5f4cb161cec3 141
tass picotcp@tass.be 149:5f4cb161cec3 142 if (ret == 0)
tass picotcp@tass.be 149:5f4cb161cec3 143 ret = socket_cmp_ipv4(a, b);
tass 68:0847e35d08a6 144
TASS Belgium NV 131:4758606c9316 145 /* Sort by remote host */
tass picotcp@tass.be 149:5f4cb161cec3 146 if (ret == 0)
tass picotcp@tass.be 149:5f4cb161cec3 147 ret = socket_cmp_remotehost(a, b);
tass picotcp@tass.be 149:5f4cb161cec3 148
tass picotcp@tass.be 149:5f4cb161cec3 149 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 150 }
tass 68:0847e35d08a6 151
tass picotcp@tass.be 149:5f4cb161cec3 152 static int socket_cmp(void *ka, void *kb)
tass picotcp@tass.be 149:5f4cb161cec3 153 {
tass picotcp@tass.be 149:5f4cb161cec3 154 struct pico_socket *a = ka, *b = kb;
tass picotcp@tass.be 149:5f4cb161cec3 155 int ret = 0;
tass picotcp@tass.be 149:5f4cb161cec3 156
tass picotcp@tass.be 149:5f4cb161cec3 157 /* First, order by network family */
tass picotcp@tass.be 149:5f4cb161cec3 158 ret = socket_cmp_family(a, b);
tass picotcp@tass.be 149:5f4cb161cec3 159
tass picotcp@tass.be 149:5f4cb161cec3 160 /* Then, compare by source/destination addresses */
tass picotcp@tass.be 149:5f4cb161cec3 161 if (ret == 0)
tass picotcp@tass.be 149:5f4cb161cec3 162 ret = socket_cmp_addresses(a, b);
tass 68:0847e35d08a6 163
TASS Belgium NV 131:4758606c9316 164 /* And finally by remote port. The two sockets are coincident if the quad is the same. */
tass picotcp@tass.be 149:5f4cb161cec3 165 if (ret == 0)
tass picotcp@tass.be 149:5f4cb161cec3 166 ret = b->remote_port - a->remote_port;
tass picotcp@tass.be 149:5f4cb161cec3 167
tass picotcp@tass.be 149:5f4cb161cec3 168 return ret;
tass 68:0847e35d08a6 169 }
tass 68:0847e35d08a6 170
tass 68:0847e35d08a6 171
TASS Belgium NV 131:4758606c9316 172 #define INIT_SOCKPORT { {&LEAF, socket_cmp}, 0, 0 }
tass 68:0847e35d08a6 173
TASS Belgium NV 131:4758606c9316 174 int sockport_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 175 {
TASS Belgium NV 131:4758606c9316 176 struct pico_sockport *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 177 if (a->number < b->number)
TASS Belgium NV 131:4758606c9316 178 return -1;
TASS Belgium NV 131:4758606c9316 179
TASS Belgium NV 131:4758606c9316 180 if (a->number > b->number)
TASS Belgium NV 131:4758606c9316 181 return 1;
TASS Belgium NV 131:4758606c9316 182
TASS Belgium NV 131:4758606c9316 183 return 0;
tass 68:0847e35d08a6 184 }
tass 68:0847e35d08a6 185
TASS Belgium NV 131:4758606c9316 186 PICO_TREE_DECLARE(UDPTable, sockport_cmp);
TASS Belgium NV 131:4758606c9316 187 PICO_TREE_DECLARE(TCPTable, sockport_cmp);
tass 68:0847e35d08a6 188
tass picotcp@tass.be 149:5f4cb161cec3 189 struct pico_sockport *pico_get_sockport(uint16_t proto, uint16_t port)
tass 68:0847e35d08a6 190 {
TASS Belgium NV 131:4758606c9316 191 struct pico_sockport test = INIT_SOCKPORT;
TASS Belgium NV 131:4758606c9316 192 test.number = port;
tass 68:0847e35d08a6 193
TASS Belgium NV 131:4758606c9316 194 if (proto == PICO_PROTO_UDP)
TASS Belgium NV 131:4758606c9316 195 return pico_tree_findKey(&UDPTable, &test);
tass 68:0847e35d08a6 196
TASS Belgium NV 131:4758606c9316 197 else if (proto == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 198 return pico_tree_findKey(&TCPTable, &test);
tass 68:0847e35d08a6 199
TASS Belgium NV 131:4758606c9316 200 else return NULL;
tass 68:0847e35d08a6 201 }
tass 68:0847e35d08a6 202
tass picotcp@tass.be 149:5f4cb161cec3 203 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 204
tass picotcp@tass.be 149:5f4cb161cec3 205 static int pico_port_in_use_by_nat(uint16_t proto, uint16_t port)
tass picotcp@tass.be 149:5f4cb161cec3 206 {
tass picotcp@tass.be 149:5f4cb161cec3 207 int ret = 0;
tass picotcp@tass.be 149:5f4cb161cec3 208 (void) proto;
tass picotcp@tass.be 149:5f4cb161cec3 209 (void) port;
tass 68:0847e35d08a6 210 #ifdef PICO_SUPPORT_NAT
TASS Belgium NV 131:4758606c9316 211 if (pico_ipv4_nat_find(port, NULL, 0, (uint8_t)proto)) {
TASS Belgium NV 131:4758606c9316 212 dbg("In use by nat....\n");
tass picotcp@tass.be 149:5f4cb161cec3 213 ret = 1;
TASS Belgium NV 131:4758606c9316 214 }
TASS Belgium NV 131:4758606c9316 215
tass 68:0847e35d08a6 216 #endif
tass picotcp@tass.be 149:5f4cb161cec3 217 return ret;
tass picotcp@tass.be 149:5f4cb161cec3 218 }
TASS Belgium NV 131:4758606c9316 219
tass picotcp@tass.be 149:5f4cb161cec3 220 static int pico_port_in_use_with_this_ipv4_address(struct pico_sockport *sp, struct pico_ip4 ip)
tass picotcp@tass.be 149:5f4cb161cec3 221 {
TASS Belgium NV 131:4758606c9316 222 if (sp) {
TASS Belgium NV 131:4758606c9316 223 struct pico_ip4 *s_local;
TASS Belgium NV 131:4758606c9316 224 struct pico_tree_node *idx;
TASS Belgium NV 131:4758606c9316 225 struct pico_socket *s;
TASS Belgium NV 131:4758606c9316 226 pico_tree_foreach(idx, &sp->socks) {
TASS Belgium NV 131:4758606c9316 227 s = idx->keyValue;
TASS Belgium NV 131:4758606c9316 228 if (s->net == &pico_proto_ipv4) {
TASS Belgium NV 131:4758606c9316 229 s_local = (struct pico_ip4*) &s->local_addr;
tass picotcp@tass.be 149:5f4cb161cec3 230 if ((s_local->addr == PICO_IPV4_INADDR_ANY) || (s_local->addr == ip.addr)) {
tass picotcp@tass.be 149:5f4cb161cec3 231 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 232 }
tass picotcp@tass.be 149:5f4cb161cec3 233 }
tass picotcp@tass.be 149:5f4cb161cec3 234 }
tass picotcp@tass.be 149:5f4cb161cec3 235 }
tass picotcp@tass.be 149:5f4cb161cec3 236
tass picotcp@tass.be 149:5f4cb161cec3 237 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 238 }
tass picotcp@tass.be 149:5f4cb161cec3 239
tass picotcp@tass.be 149:5f4cb161cec3 240
tass picotcp@tass.be 149:5f4cb161cec3 241 static int pico_port_in_use_ipv4(struct pico_sockport *sp, void *addr)
tass picotcp@tass.be 149:5f4cb161cec3 242 {
tass picotcp@tass.be 149:5f4cb161cec3 243 struct pico_ip4 ip;
tass picotcp@tass.be 149:5f4cb161cec3 244 /* IPv4 */
tass picotcp@tass.be 149:5f4cb161cec3 245 if (addr)
tass picotcp@tass.be 149:5f4cb161cec3 246 ip.addr = ((struct pico_ip4 *)addr)->addr;
tass picotcp@tass.be 149:5f4cb161cec3 247 else
tass picotcp@tass.be 149:5f4cb161cec3 248 ip.addr = PICO_IPV4_INADDR_ANY;
tass picotcp@tass.be 149:5f4cb161cec3 249
tass picotcp@tass.be 149:5f4cb161cec3 250 if (ip.addr == PICO_IPV4_INADDR_ANY) {
tass picotcp@tass.be 149:5f4cb161cec3 251 if (!sp)
tass picotcp@tass.be 149:5f4cb161cec3 252 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 253 else {
tass picotcp@tass.be 149:5f4cb161cec3 254 dbg("In use, and asked for ANY\n");
tass picotcp@tass.be 149:5f4cb161cec3 255 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 256 }
tass picotcp@tass.be 149:5f4cb161cec3 257 }
tass picotcp@tass.be 149:5f4cb161cec3 258
tass picotcp@tass.be 149:5f4cb161cec3 259 return pico_port_in_use_with_this_ipv4_address(sp, ip);
tass picotcp@tass.be 149:5f4cb161cec3 260 }
tass picotcp@tass.be 149:5f4cb161cec3 261 #endif
tass picotcp@tass.be 149:5f4cb161cec3 262
tass picotcp@tass.be 149:5f4cb161cec3 263 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 264 static int pico_port_in_use_with_this_ipv6_address(struct pico_sockport *sp, struct pico_ip6 ip)
tass picotcp@tass.be 149:5f4cb161cec3 265 {
tass picotcp@tass.be 149:5f4cb161cec3 266 if (sp) {
tass picotcp@tass.be 149:5f4cb161cec3 267 struct pico_ip6 *s_local;
tass picotcp@tass.be 149:5f4cb161cec3 268 struct pico_tree_node *idx;
tass picotcp@tass.be 149:5f4cb161cec3 269 struct pico_socket *s;
tass picotcp@tass.be 149:5f4cb161cec3 270 pico_tree_foreach(idx, &sp->socks) {
tass picotcp@tass.be 149:5f4cb161cec3 271 s = idx->keyValue;
tass picotcp@tass.be 149:5f4cb161cec3 272 if (s->net == &pico_proto_ipv6) {
tass picotcp@tass.be 149:5f4cb161cec3 273 s_local = (struct pico_ip6*) &s->local_addr;
tass picotcp@tass.be 149:5f4cb161cec3 274 if ((pico_ipv6_is_unspecified(s_local->addr)) || (!memcmp(s_local->addr, ip.addr, PICO_SIZE_IP6))) {
tass picotcp@tass.be 149:5f4cb161cec3 275 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 276 }
TASS Belgium NV 131:4758606c9316 277 }
TASS Belgium NV 131:4758606c9316 278 }
tass 68:0847e35d08a6 279 }
TASS Belgium NV 131:4758606c9316 280
tass picotcp@tass.be 149:5f4cb161cec3 281 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 282 }
tass picotcp@tass.be 149:5f4cb161cec3 283
tass picotcp@tass.be 149:5f4cb161cec3 284 static int pico_port_in_use_ipv6(struct pico_sockport *sp, void *addr)
tass picotcp@tass.be 149:5f4cb161cec3 285 {
tass picotcp@tass.be 149:5f4cb161cec3 286 struct pico_ip6 ip;
tass picotcp@tass.be 149:5f4cb161cec3 287 /* IPv6 */
tass picotcp@tass.be 149:5f4cb161cec3 288 if (addr)
tass picotcp@tass.be 149:5f4cb161cec3 289 memcpy(&ip.addr, ((struct pico_ip6 *)addr)->addr, sizeof(struct pico_ip6));
tass picotcp@tass.be 149:5f4cb161cec3 290 else
tass picotcp@tass.be 149:5f4cb161cec3 291 memcpy(&ip.addr, PICO_IP6_ANY, sizeof(struct pico_ip6));
tass picotcp@tass.be 149:5f4cb161cec3 292
tass picotcp@tass.be 149:5f4cb161cec3 293 if (memcmp(ip.addr, PICO_IP6_ANY, sizeof(struct pico_ip6)) == 0) {
tass picotcp@tass.be 149:5f4cb161cec3 294 if (!sp)
tass picotcp@tass.be 149:5f4cb161cec3 295 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 296 else {
tass picotcp@tass.be 149:5f4cb161cec3 297 dbg("In use, and asked for ANY\n");
tass picotcp@tass.be 149:5f4cb161cec3 298 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 299 }
tass picotcp@tass.be 149:5f4cb161cec3 300 }
tass picotcp@tass.be 149:5f4cb161cec3 301
tass picotcp@tass.be 149:5f4cb161cec3 302 return pico_port_in_use_with_this_ipv6_address(sp, ip);
tass picotcp@tass.be 149:5f4cb161cec3 303 }
tass picotcp@tass.be 149:5f4cb161cec3 304 #endif
tass picotcp@tass.be 149:5f4cb161cec3 305
tass picotcp@tass.be 149:5f4cb161cec3 306
tass picotcp@tass.be 149:5f4cb161cec3 307
tass picotcp@tass.be 149:5f4cb161cec3 308 static int pico_generic_port_in_use(uint16_t proto, uint16_t port, struct pico_sockport *sp, void *addr)
tass picotcp@tass.be 149:5f4cb161cec3 309 {
tass picotcp@tass.be 149:5f4cb161cec3 310 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 311 if (pico_port_in_use_by_nat(proto, port)) {
tass picotcp@tass.be 149:5f4cb161cec3 312 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 313 }
tass picotcp@tass.be 149:5f4cb161cec3 314
tass picotcp@tass.be 149:5f4cb161cec3 315 if (pico_port_in_use_ipv4(sp, addr)) {
tass picotcp@tass.be 149:5f4cb161cec3 316 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 317 }
tass picotcp@tass.be 149:5f4cb161cec3 318
tass picotcp@tass.be 149:5f4cb161cec3 319 #endif
tass picotcp@tass.be 149:5f4cb161cec3 320
tass picotcp@tass.be 149:5f4cb161cec3 321 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 322 if (pico_port_in_use_ipv6(sp, addr)) {
tass picotcp@tass.be 149:5f4cb161cec3 323 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 324 }
tass picotcp@tass.be 149:5f4cb161cec3 325
tass picotcp@tass.be 149:5f4cb161cec3 326 #endif
tass picotcp@tass.be 149:5f4cb161cec3 327
tass picotcp@tass.be 149:5f4cb161cec3 328 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 329 }
tass picotcp@tass.be 149:5f4cb161cec3 330
tass picotcp@tass.be 149:5f4cb161cec3 331 int pico_is_port_free(uint16_t proto, uint16_t port, void *addr, void *net)
tass picotcp@tass.be 149:5f4cb161cec3 332 {
tass picotcp@tass.be 149:5f4cb161cec3 333 struct pico_sockport *sp;
tass picotcp@tass.be 149:5f4cb161cec3 334 (void) net;
tass picotcp@tass.be 149:5f4cb161cec3 335 sp = pico_get_sockport(proto, port);
tass picotcp@tass.be 149:5f4cb161cec3 336
tass picotcp@tass.be 149:5f4cb161cec3 337 if (pico_generic_port_in_use(proto, port, sp, addr))
tass picotcp@tass.be 149:5f4cb161cec3 338 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 339
TASS Belgium NV 131:4758606c9316 340 return 1;
tass 68:0847e35d08a6 341 }
tass 68:0847e35d08a6 342
tass 68:0847e35d08a6 343 static int pico_check_socket(struct pico_socket *s)
tass 68:0847e35d08a6 344 {
TASS Belgium NV 131:4758606c9316 345 struct pico_sockport *test;
TASS Belgium NV 131:4758606c9316 346 struct pico_socket *found;
TASS Belgium NV 131:4758606c9316 347 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 348
TASS Belgium NV 131:4758606c9316 349 test = pico_get_sockport(PROTO(s), s->local_port);
tass 68:0847e35d08a6 350
TASS Belgium NV 131:4758606c9316 351 if (!test) {
TASS Belgium NV 131:4758606c9316 352 return -1;
TASS Belgium NV 131:4758606c9316 353 }
TASS Belgium NV 131:4758606c9316 354
TASS Belgium NV 131:4758606c9316 355 pico_tree_foreach(index, &test->socks){
TASS Belgium NV 131:4758606c9316 356 found = index->keyValue;
TASS Belgium NV 131:4758606c9316 357 if (s == found) {
TASS Belgium NV 131:4758606c9316 358 return 0;
TASS Belgium NV 131:4758606c9316 359 }
TASS Belgium NV 131:4758606c9316 360 }
TASS Belgium NV 131:4758606c9316 361
tass 68:0847e35d08a6 362 return -1;
tass 68:0847e35d08a6 363 }
tass 68:0847e35d08a6 364
tass picotcp@tass.be 149:5f4cb161cec3 365 struct pico_socket *pico_sockets_find(uint16_t local, uint16_t remote)
tass 68:0847e35d08a6 366 {
TASS Belgium NV 131:4758606c9316 367 struct pico_socket *sock = NULL;
TASS Belgium NV 131:4758606c9316 368 struct pico_tree_node *index = NULL;
TASS Belgium NV 131:4758606c9316 369 struct pico_sockport *sp = NULL;
tass 68:0847e35d08a6 370
TASS Belgium NV 131:4758606c9316 371 sp = pico_get_sockport(PICO_PROTO_TCP, local);
TASS Belgium NV 131:4758606c9316 372 if(sp)
TASS Belgium NV 131:4758606c9316 373 {
TASS Belgium NV 131:4758606c9316 374 pico_tree_foreach(index, &sp->socks)
TASS Belgium NV 131:4758606c9316 375 {
TASS Belgium NV 131:4758606c9316 376 if(((struct pico_socket *)index->keyValue)->remote_port == remote)
TASS Belgium NV 131:4758606c9316 377 {
TASS Belgium NV 131:4758606c9316 378 sock = (struct pico_socket *)index->keyValue;
TASS Belgium NV 131:4758606c9316 379 break;
TASS Belgium NV 131:4758606c9316 380 }
TASS Belgium NV 131:4758606c9316 381 }
TASS Belgium NV 131:4758606c9316 382 }
tass 68:0847e35d08a6 383
TASS Belgium NV 131:4758606c9316 384 return sock;
tass 68:0847e35d08a6 385 }
tass 68:0847e35d08a6 386
tass 68:0847e35d08a6 387
tass 70:cd218dd180e5 388 int8_t pico_socket_add(struct pico_socket *s)
tass 68:0847e35d08a6 389 {
TASS Belgium NV 131:4758606c9316 390 struct pico_sockport *sp = pico_get_sockport(PROTO(s), s->local_port);
tass picotcp@tass.be 149:5f4cb161cec3 391 PICOTCP_MUTEX_LOCK(Mutex);
tass 68:0847e35d08a6 392 if (!sp) {
TASS Belgium NV 131:4758606c9316 393 /* dbg("Creating sockport..%04x\n", s->local_port); / * In comment due to spam during test * / */
tass picotcp@tass.be 149:5f4cb161cec3 394 sp = PICO_ZALLOC(sizeof(struct pico_sockport));
TASS Belgium NV 131:4758606c9316 395
TASS Belgium NV 131:4758606c9316 396 if (!sp) {
TASS Belgium NV 131:4758606c9316 397 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 398 PICOTCP_MUTEX_UNLOCK(Mutex);
TASS Belgium NV 131:4758606c9316 399 return -1;
TASS Belgium NV 131:4758606c9316 400 }
tass 68:0847e35d08a6 401
TASS Belgium NV 131:4758606c9316 402 sp->proto = PROTO(s);
TASS Belgium NV 131:4758606c9316 403 sp->number = s->local_port;
TASS Belgium NV 131:4758606c9316 404 sp->socks.root = &LEAF;
TASS Belgium NV 131:4758606c9316 405 sp->socks.compare = socket_cmp;
tass 68:0847e35d08a6 406
TASS Belgium NV 131:4758606c9316 407 if (PROTO(s) == PICO_PROTO_UDP)
TASS Belgium NV 131:4758606c9316 408 {
TASS Belgium NV 131:4758606c9316 409 pico_tree_insert(&UDPTable, sp);
TASS Belgium NV 131:4758606c9316 410 }
TASS Belgium NV 131:4758606c9316 411 else if (PROTO(s) == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 412 {
TASS Belgium NV 131:4758606c9316 413 pico_tree_insert(&TCPTable, sp);
TASS Belgium NV 131:4758606c9316 414 }
tass 68:0847e35d08a6 415 }
tass 68:0847e35d08a6 416
TASS Belgium NV 131:4758606c9316 417 pico_tree_insert(&sp->socks, s);
TASS Belgium NV 131:4758606c9316 418 s->state |= PICO_SOCKET_STATE_BOUND;
tass picotcp@tass.be 149:5f4cb161cec3 419 PICOTCP_MUTEX_UNLOCK(Mutex);
TASS Belgium NV 131:4758606c9316 420 #if DEBUG_SOCKET_TREE
TASS Belgium NV 131:4758606c9316 421 {
TASS Belgium NV 131:4758606c9316 422 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 423 /* RB_FOREACH(s, socket_tree, &sp->socks) { */
TASS Belgium NV 131:4758606c9316 424 pico_tree_foreach(index, &sp->socks){
TASS Belgium NV 131:4758606c9316 425 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 426 dbg(">>>> List Socket lc=%hu rm=%hu\n", short_be(s->local_port), short_be(s->remote_port));
TASS Belgium NV 131:4758606c9316 427 }
TASS Belgium NV 131:4758606c9316 428
TASS Belgium NV 131:4758606c9316 429 }
tass 68:0847e35d08a6 430 #endif
TASS Belgium NV 131:4758606c9316 431 return 0;
tass 68:0847e35d08a6 432 }
tass 68:0847e35d08a6 433
tass picotcp@tass.be 149:5f4cb161cec3 434
tass 68:0847e35d08a6 435 static void socket_clean_queues(struct pico_socket *sock)
tass 68:0847e35d08a6 436 {
TASS Belgium NV 131:4758606c9316 437 struct pico_frame *f_in = pico_dequeue(&sock->q_in);
TASS Belgium NV 131:4758606c9316 438 struct pico_frame *f_out = pico_dequeue(&sock->q_out);
TASS Belgium NV 131:4758606c9316 439 while(f_in || f_out)
tass 68:0847e35d08a6 440 {
TASS Belgium NV 131:4758606c9316 441 if(f_in)
TASS Belgium NV 131:4758606c9316 442 {
TASS Belgium NV 131:4758606c9316 443 pico_frame_discard(f_in);
TASS Belgium NV 131:4758606c9316 444 f_in = pico_dequeue(&sock->q_in);
TASS Belgium NV 131:4758606c9316 445 }
tass 68:0847e35d08a6 446
TASS Belgium NV 131:4758606c9316 447 if(f_out)
TASS Belgium NV 131:4758606c9316 448 {
TASS Belgium NV 131:4758606c9316 449 pico_frame_discard(f_out);
TASS Belgium NV 131:4758606c9316 450 f_out = pico_dequeue(&sock->q_out);
TASS Belgium NV 131:4758606c9316 451 }
tass 68:0847e35d08a6 452 }
tass picotcp@tass.be 149:5f4cb161cec3 453 pico_socket_tcp_cleanup(sock);
tass 68:0847e35d08a6 454 }
tass 68:0847e35d08a6 455
tass 128:ae39e6e81531 456 static void socket_garbage_collect(pico_time now, void *arg)
tass 68:0847e35d08a6 457 {
TASS Belgium NV 131:4758606c9316 458 struct pico_socket *s = (struct pico_socket *) arg;
TASS Belgium NV 131:4758606c9316 459 IGNORE_PARAMETER(now);
tass 128:ae39e6e81531 460
TASS Belgium NV 131:4758606c9316 461 socket_clean_queues(s);
tass picotcp@tass.be 149:5f4cb161cec3 462 PICO_FREE(s);
tass 68:0847e35d08a6 463 }
tass 68:0847e35d08a6 464
tass picotcp@tass.be 149:5f4cb161cec3 465
tass picotcp@tass.be 149:5f4cb161cec3 466 static void pico_socket_check_empty_sockport(struct pico_socket *s, struct pico_sockport *sp)
tass 68:0847e35d08a6 467 {
TASS Belgium NV 131:4758606c9316 468 if(pico_tree_empty(&sp->socks)) {
TASS Belgium NV 131:4758606c9316 469 if (PROTO(s) == PICO_PROTO_UDP)
TASS Belgium NV 131:4758606c9316 470 {
TASS Belgium NV 131:4758606c9316 471 pico_tree_delete(&UDPTable, sp);
TASS Belgium NV 131:4758606c9316 472 }
TASS Belgium NV 131:4758606c9316 473 else if (PROTO(s) == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 474 {
TASS Belgium NV 131:4758606c9316 475 pico_tree_delete(&TCPTable, sp);
TASS Belgium NV 131:4758606c9316 476 }
tass 68:0847e35d08a6 477
tass picotcp@tass.be 149:5f4cb161cec3 478 if(sp_tcp == sp)
tass picotcp@tass.be 149:5f4cb161cec3 479 sp_tcp = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 480
tass picotcp@tass.be 149:5f4cb161cec3 481 if(sp_udp == sp)
tass picotcp@tass.be 149:5f4cb161cec3 482 sp_udp = NULL;
TASS Belgium NV 131:4758606c9316 483
tass picotcp@tass.be 149:5f4cb161cec3 484 PICO_FREE(sp);
tass picotcp@tass.be 149:5f4cb161cec3 485 }
tass picotcp@tass.be 149:5f4cb161cec3 486 }
tass 68:0847e35d08a6 487
tass picotcp@tass.be 149:5f4cb161cec3 488 int8_t pico_socket_del(struct pico_socket *s)
tass picotcp@tass.be 149:5f4cb161cec3 489 {
tass picotcp@tass.be 149:5f4cb161cec3 490 struct pico_sockport *sp = pico_get_sockport(PROTO(s), s->local_port);
tass picotcp@tass.be 149:5f4cb161cec3 491 if (!sp) {
tass picotcp@tass.be 149:5f4cb161cec3 492 pico_err = PICO_ERR_ENXIO;
tass picotcp@tass.be 149:5f4cb161cec3 493 return -1;
TASS Belgium NV 131:4758606c9316 494 }
tass 68:0847e35d08a6 495
tass picotcp@tass.be 149:5f4cb161cec3 496 PICOTCP_MUTEX_LOCK(Mutex);
tass picotcp@tass.be 149:5f4cb161cec3 497 pico_tree_delete(&sp->socks, s);
tass picotcp@tass.be 149:5f4cb161cec3 498 pico_socket_check_empty_sockport(s, sp);
tass picotcp@tass.be 149:5f4cb161cec3 499 pico_multicast_delete(s);
tass picotcp@tass.be 149:5f4cb161cec3 500 pico_socket_tcp_delete(s);
TASS Belgium NV 131:4758606c9316 501 s->state = PICO_SOCKET_STATE_CLOSED;
TASS Belgium NV 131:4758606c9316 502 pico_timer_add(3000, socket_garbage_collect, s);
tass picotcp@tass.be 149:5f4cb161cec3 503 PICOTCP_MUTEX_UNLOCK(Mutex);
TASS Belgium NV 131:4758606c9316 504 return 0;
tass 68:0847e35d08a6 505 }
tass 68:0847e35d08a6 506
tass picotcp@tass.be 149:5f4cb161cec3 507 static void pico_socket_update_tcp_state(struct pico_socket *s, uint16_t tcp_state)
tass picotcp@tass.be 149:5f4cb161cec3 508 {
tass picotcp@tass.be 149:5f4cb161cec3 509 if (tcp_state) {
tass picotcp@tass.be 149:5f4cb161cec3 510 s->state &= 0x00FF;
tass picotcp@tass.be 149:5f4cb161cec3 511 s->state |= tcp_state;
tass picotcp@tass.be 149:5f4cb161cec3 512 }
tass picotcp@tass.be 149:5f4cb161cec3 513 }
tass picotcp@tass.be 149:5f4cb161cec3 514
tass 70:cd218dd180e5 515 static int8_t pico_socket_alter_state(struct pico_socket *s, uint16_t more_states, uint16_t less_states, uint16_t tcp_state)
tass 68:0847e35d08a6 516 {
TASS Belgium NV 131:4758606c9316 517 struct pico_sockport *sp;
TASS Belgium NV 131:4758606c9316 518 if (more_states & PICO_SOCKET_STATE_BOUND)
TASS Belgium NV 131:4758606c9316 519 return pico_socket_add(s);
tass 68:0847e35d08a6 520
TASS Belgium NV 131:4758606c9316 521 if (less_states & PICO_SOCKET_STATE_BOUND)
TASS Belgium NV 131:4758606c9316 522 return pico_socket_del(s);
tass 68:0847e35d08a6 523
TASS Belgium NV 131:4758606c9316 524 sp = pico_get_sockport(PROTO(s), s->local_port);
TASS Belgium NV 131:4758606c9316 525 if (!sp) {
TASS Belgium NV 131:4758606c9316 526 pico_err = PICO_ERR_ENXIO;
TASS Belgium NV 131:4758606c9316 527 return -1;
TASS Belgium NV 131:4758606c9316 528 }
tass 68:0847e35d08a6 529
TASS Belgium NV 131:4758606c9316 530 s->state |= more_states;
TASS Belgium NV 131:4758606c9316 531 s->state = (uint16_t)(s->state & (~less_states));
tass picotcp@tass.be 149:5f4cb161cec3 532 pico_socket_update_tcp_state(s, tcp_state);
TASS Belgium NV 131:4758606c9316 533 return 0;
tass 68:0847e35d08a6 534 }
tass 68:0847e35d08a6 535
tass picotcp@tass.be 149:5f4cb161cec3 536
tass picotcp@tass.be 149:5f4cb161cec3 537 static int pico_socket_transport_deliver(struct pico_protocol *p, struct pico_sockport *sp, struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 538 {
tass picotcp@tass.be 149:5f4cb161cec3 539 if (p->proto_number == PICO_PROTO_TCP)
tass picotcp@tass.be 149:5f4cb161cec3 540 return pico_socket_tcp_deliver(sp, f);
tass picotcp@tass.be 149:5f4cb161cec3 541
tass picotcp@tass.be 149:5f4cb161cec3 542 if (p->proto_number == PICO_PROTO_UDP)
tass picotcp@tass.be 149:5f4cb161cec3 543 return pico_socket_udp_deliver(sp, f);
tass picotcp@tass.be 149:5f4cb161cec3 544
tass picotcp@tass.be 149:5f4cb161cec3 545 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 546 }
tass picotcp@tass.be 149:5f4cb161cec3 547
tass picotcp@tass.be 149:5f4cb161cec3 548
tass 68:0847e35d08a6 549 static int pico_socket_deliver(struct pico_protocol *p, struct pico_frame *f, uint16_t localport)
tass 68:0847e35d08a6 550 {
TASS Belgium NV 131:4758606c9316 551 struct pico_sockport *sp = NULL;
TASS Belgium NV 131:4758606c9316 552 struct pico_trans *tr = (struct pico_trans *) f->transport_hdr;
tass 125:96003ae6f1d8 553
TASS Belgium NV 131:4758606c9316 554 if (!tr)
TASS Belgium NV 131:4758606c9316 555 return -1;
tass 68:0847e35d08a6 556
TASS Belgium NV 131:4758606c9316 557 sp = pico_get_sockport(p->proto_number, localport);
TASS Belgium NV 131:4758606c9316 558 if (!sp) {
TASS Belgium NV 131:4758606c9316 559 dbg("No such port %d\n", short_be(localport));
TASS Belgium NV 131:4758606c9316 560 return -1;
TASS Belgium NV 131:4758606c9316 561 }
tass 68:0847e35d08a6 562
tass picotcp@tass.be 149:5f4cb161cec3 563 return pico_socket_transport_deliver(p, sp, f);
tass picotcp@tass.be 149:5f4cb161cec3 564 }
tass picotcp@tass.be 149:5f4cb161cec3 565
tass picotcp@tass.be 149:5f4cb161cec3 566 int pico_socket_set_family(struct pico_socket *s, uint16_t family)
tass picotcp@tass.be 149:5f4cb161cec3 567 {
tass picotcp@tass.be 149:5f4cb161cec3 568 (void) family;
TASS Belgium NV 131:4758606c9316 569
tass picotcp@tass.be 149:5f4cb161cec3 570 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 571 if (family == PICO_PROTO_IPV4)
tass picotcp@tass.be 149:5f4cb161cec3 572 s->net = &pico_proto_ipv4;
TASS Belgium NV 131:4758606c9316 573
tass picotcp@tass.be 149:5f4cb161cec3 574 #endif
TASS Belgium NV 131:4758606c9316 575
tass picotcp@tass.be 149:5f4cb161cec3 576 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 577 if (family == PICO_PROTO_IPV6)
tass picotcp@tass.be 149:5f4cb161cec3 578 s->net = &pico_proto_ipv6;
TASS Belgium NV 131:4758606c9316 579
tass picotcp@tass.be 149:5f4cb161cec3 580 #endif
tass 68:0847e35d08a6 581
tass picotcp@tass.be 149:5f4cb161cec3 582 if (s->net == NULL)
tass picotcp@tass.be 149:5f4cb161cec3 583 return -1;
TASS Belgium NV 131:4758606c9316 584
tass picotcp@tass.be 149:5f4cb161cec3 585 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 586 }
TASS Belgium NV 131:4758606c9316 587
tass picotcp@tass.be 149:5f4cb161cec3 588 static struct pico_socket *pico_socket_transport_open(uint16_t proto, uint16_t family)
tass picotcp@tass.be 149:5f4cb161cec3 589 {
tass picotcp@tass.be 149:5f4cb161cec3 590 struct pico_socket *s = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 591 if (proto == PICO_PROTO_UDP)
tass picotcp@tass.be 149:5f4cb161cec3 592 s = pico_socket_udp_open();
TASS Belgium NV 131:4758606c9316 593
tass picotcp@tass.be 149:5f4cb161cec3 594 if (proto == PICO_PROTO_TCP)
tass picotcp@tass.be 149:5f4cb161cec3 595 s = pico_socket_tcp_open(family);
TASS Belgium NV 131:4758606c9316 596
tass picotcp@tass.be 149:5f4cb161cec3 597 return s;
tass picotcp@tass.be 149:5f4cb161cec3 598
tass 68:0847e35d08a6 599 }
tass 68:0847e35d08a6 600
tass 68:0847e35d08a6 601 struct pico_socket *pico_socket_open(uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *))
tass 68:0847e35d08a6 602 {
tass 68:0847e35d08a6 603
TASS Belgium NV 131:4758606c9316 604 struct pico_socket *s = NULL;
tass 68:0847e35d08a6 605
tass picotcp@tass.be 149:5f4cb161cec3 606 s = pico_socket_transport_open(proto, net);
tass 68:0847e35d08a6 607
TASS Belgium NV 131:4758606c9316 608 if (!s) {
TASS Belgium NV 131:4758606c9316 609 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 610 return NULL;
TASS Belgium NV 131:4758606c9316 611 }
tass 68:0847e35d08a6 612
tass picotcp@tass.be 149:5f4cb161cec3 613 if (pico_socket_set_family(s, net) != 0) {
tass picotcp@tass.be 149:5f4cb161cec3 614 PICO_FREE(s);
tass picotcp@tass.be 149:5f4cb161cec3 615 pico_err = PICO_ERR_ENETUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 616 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 617 }
tass 68:0847e35d08a6 618
TASS Belgium NV 131:4758606c9316 619 s->q_in.max_size = PICO_DEFAULT_SOCKETQ;
TASS Belgium NV 131:4758606c9316 620 s->q_out.max_size = PICO_DEFAULT_SOCKETQ;
tass 110:0ece1bbbd36e 621
TASS Belgium NV 131:4758606c9316 622 s->wakeup = wakeup;
TASS Belgium NV 131:4758606c9316 623 return s;
tass 68:0847e35d08a6 624 }
tass 68:0847e35d08a6 625
tass 68:0847e35d08a6 626
tass picotcp@tass.be 149:5f4cb161cec3 627 static void pico_socket_clone_assign_address(struct pico_socket *s, struct pico_socket *facsimile)
tass 68:0847e35d08a6 628 {
tass 68:0847e35d08a6 629
tass 68:0847e35d08a6 630 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 631 if (facsimile->net == &pico_proto_ipv4) {
TASS Belgium NV 131:4758606c9316 632 s->net = &pico_proto_ipv4;
TASS Belgium NV 131:4758606c9316 633 memcpy(&s->local_addr, &facsimile->local_addr, sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 634 memcpy(&s->remote_addr, &facsimile->remote_addr, sizeof(struct pico_ip4));
TASS Belgium NV 131:4758606c9316 635 }
TASS Belgium NV 131:4758606c9316 636
tass 68:0847e35d08a6 637 #endif
tass 68:0847e35d08a6 638
tass 68:0847e35d08a6 639 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 640 if (facsimile->net == &pico_proto_ipv6) {
TASS Belgium NV 131:4758606c9316 641 s->net = &pico_proto_ipv6;
TASS Belgium NV 131:4758606c9316 642 memcpy(&s->local_addr, &facsimile->local_addr, sizeof(struct pico_ip6));
TASS Belgium NV 131:4758606c9316 643 memcpy(&s->remote_addr, &facsimile->remote_addr, sizeof(struct pico_ip6));
TASS Belgium NV 131:4758606c9316 644 }
TASS Belgium NV 131:4758606c9316 645
tass 68:0847e35d08a6 646 #endif
tass picotcp@tass.be 149:5f4cb161cec3 647
tass picotcp@tass.be 149:5f4cb161cec3 648 }
tass picotcp@tass.be 149:5f4cb161cec3 649
tass picotcp@tass.be 149:5f4cb161cec3 650 struct pico_socket *pico_socket_clone(struct pico_socket *facsimile)
tass picotcp@tass.be 149:5f4cb161cec3 651 {
tass picotcp@tass.be 149:5f4cb161cec3 652 struct pico_socket *s = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 653
tass picotcp@tass.be 149:5f4cb161cec3 654 s = pico_socket_transport_open(facsimile->proto->proto_number, facsimile->net->proto_number);
tass picotcp@tass.be 149:5f4cb161cec3 655 if (!s) {
tass picotcp@tass.be 149:5f4cb161cec3 656 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass picotcp@tass.be 149:5f4cb161cec3 657 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 658 }
tass picotcp@tass.be 149:5f4cb161cec3 659
tass picotcp@tass.be 149:5f4cb161cec3 660 s->local_port = facsimile->local_port;
tass picotcp@tass.be 149:5f4cb161cec3 661 s->remote_port = facsimile->remote_port;
tass picotcp@tass.be 149:5f4cb161cec3 662 s->state = facsimile->state;
tass picotcp@tass.be 149:5f4cb161cec3 663 pico_socket_clone_assign_address(s, facsimile);
TASS Belgium NV 131:4758606c9316 664 if (!s->net) {
tass picotcp@tass.be 149:5f4cb161cec3 665 PICO_FREE(s);
TASS Belgium NV 131:4758606c9316 666 pico_err = PICO_ERR_ENETUNREACH;
TASS Belgium NV 131:4758606c9316 667 return NULL;
TASS Belgium NV 131:4758606c9316 668 }
TASS Belgium NV 131:4758606c9316 669
tass picotcp@tass.be 149:5f4cb161cec3 670 s->q_in.max_size = PICO_DEFAULT_SOCKETQ;
tass picotcp@tass.be 149:5f4cb161cec3 671 s->q_out.max_size = PICO_DEFAULT_SOCKETQ;
tass picotcp@tass.be 149:5f4cb161cec3 672 s->wakeup = NULL;
TASS Belgium NV 131:4758606c9316 673 return s;
tass 68:0847e35d08a6 674 }
tass 68:0847e35d08a6 675
tass picotcp@tass.be 149:5f4cb161cec3 676 static int pico_socket_transport_read(struct pico_socket *s, void *buf, int len)
tass picotcp@tass.be 149:5f4cb161cec3 677 {
tass picotcp@tass.be 149:5f4cb161cec3 678 if (PROTO(s) == PICO_PROTO_UDP)
tass picotcp@tass.be 149:5f4cb161cec3 679 return pico_socket_udp_recv(s, buf, (uint16_t)len, NULL, NULL);
tass picotcp@tass.be 149:5f4cb161cec3 680 else if (PROTO(s) == PICO_PROTO_TCP)
tass picotcp@tass.be 149:5f4cb161cec3 681 return pico_socket_tcp_read(s, buf, (uint32_t)len);
tass picotcp@tass.be 149:5f4cb161cec3 682 else return 0;
tass picotcp@tass.be 149:5f4cb161cec3 683 }
tass picotcp@tass.be 149:5f4cb161cec3 684
tass 68:0847e35d08a6 685 int pico_socket_read(struct pico_socket *s, void *buf, int len)
tass 68:0847e35d08a6 686 {
TASS Belgium NV 131:4758606c9316 687 if (!s || buf == NULL) {
TASS Belgium NV 131:4758606c9316 688 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 689 return -1;
TASS Belgium NV 131:4758606c9316 690 } else {
TASS Belgium NV 131:4758606c9316 691 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 692 /* See task #178 */
TASS Belgium NV 131:4758606c9316 693 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 694 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 695 return -1;
TASS Belgium NV 131:4758606c9316 696 }
tass 68:0847e35d08a6 697 }
tass 68:0847e35d08a6 698
TASS Belgium NV 131:4758606c9316 699 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 700 pico_err = PICO_ERR_EIO;
TASS Belgium NV 131:4758606c9316 701 return -1;
TASS Belgium NV 131:4758606c9316 702 }
TASS Belgium NV 131:4758606c9316 703
tass picotcp@tass.be 149:5f4cb161cec3 704 return pico_socket_transport_read(s, buf, len);
tass picotcp@tass.be 149:5f4cb161cec3 705 }
tass 68:0847e35d08a6 706
tass picotcp@tass.be 149:5f4cb161cec3 707 static int pico_socket_write_check_state(struct pico_socket *s)
tass picotcp@tass.be 149:5f4cb161cec3 708 {
tass picotcp@tass.be 149:5f4cb161cec3 709 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
tass picotcp@tass.be 149:5f4cb161cec3 710 pico_err = PICO_ERR_EIO;
tass picotcp@tass.be 149:5f4cb161cec3 711 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 712 }
tass picotcp@tass.be 149:5f4cb161cec3 713
tass picotcp@tass.be 149:5f4cb161cec3 714 if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) {
tass picotcp@tass.be 149:5f4cb161cec3 715 pico_err = PICO_ERR_ENOTCONN;
tass picotcp@tass.be 149:5f4cb161cec3 716 return -1;
tass 68:0847e35d08a6 717 }
TASS Belgium NV 131:4758606c9316 718
tass picotcp@tass.be 149:5f4cb161cec3 719 if (s->state & PICO_SOCKET_STATE_SHUT_LOCAL) { /* check if in shutdown state */
tass picotcp@tass.be 149:5f4cb161cec3 720 pico_err = PICO_ERR_ESHUTDOWN;
tass picotcp@tass.be 149:5f4cb161cec3 721 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 722 }
tass picotcp@tass.be 149:5f4cb161cec3 723
TASS Belgium NV 131:4758606c9316 724 return 0;
tass 68:0847e35d08a6 725 }
tass 68:0847e35d08a6 726
tass picotcp@tass.be 149:5f4cb161cec3 727 static int pico_socket_write_attempt(struct pico_socket *s, const void *buf, int len)
tass picotcp@tass.be 149:5f4cb161cec3 728 {
tass picotcp@tass.be 149:5f4cb161cec3 729 if (pico_socket_write_check_state(s) < 0) {
tass picotcp@tass.be 149:5f4cb161cec3 730 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 731 } else {
tass picotcp@tass.be 149:5f4cb161cec3 732 return pico_socket_sendto(s, buf, len, &s->remote_addr, s->remote_port);
tass picotcp@tass.be 149:5f4cb161cec3 733 }
tass picotcp@tass.be 149:5f4cb161cec3 734 }
tass picotcp@tass.be 149:5f4cb161cec3 735
tass 68:0847e35d08a6 736 int pico_socket_write(struct pico_socket *s, const void *buf, int len)
tass 68:0847e35d08a6 737 {
TASS Belgium NV 131:4758606c9316 738 if (!s || buf == NULL) {
TASS Belgium NV 131:4758606c9316 739 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 740 return -1;
TASS Belgium NV 131:4758606c9316 741 } else {
TASS Belgium NV 131:4758606c9316 742 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 743 /* See task #178 */
TASS Belgium NV 131:4758606c9316 744 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 745 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 746 return -1;
TASS Belgium NV 131:4758606c9316 747 }
tass 68:0847e35d08a6 748 }
tass 68:0847e35d08a6 749
tass picotcp@tass.be 149:5f4cb161cec3 750 return pico_socket_write_attempt(s, buf, len);
tass 68:0847e35d08a6 751 }
tass 68:0847e35d08a6 752
tass 68:0847e35d08a6 753 uint16_t pico_socket_high_port(uint16_t proto)
tass 68:0847e35d08a6 754 {
TASS Belgium NV 131:4758606c9316 755 uint16_t port;
TASS Belgium NV 131:4758606c9316 756 if (0 ||
tass 68:0847e35d08a6 757 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 758 (proto == PICO_PROTO_TCP) ||
tass 68:0847e35d08a6 759 #endif
tass 68:0847e35d08a6 760 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 761 (proto == PICO_PROTO_UDP) ||
tass 68:0847e35d08a6 762 #endif
TASS Belgium NV 131:4758606c9316 763 0) {
TASS Belgium NV 131:4758606c9316 764 do {
TASS Belgium NV 131:4758606c9316 765 uint32_t rand = pico_rand();
TASS Belgium NV 131:4758606c9316 766 port = (uint16_t) (rand & 0xFFFFU);
TASS Belgium NV 131:4758606c9316 767 port = (uint16_t)((port % (65535 - 1024)) + 1024U);
TASS Belgium NV 131:4758606c9316 768 if (pico_is_port_free(proto, port, NULL, NULL)) {
TASS Belgium NV 131:4758606c9316 769 return short_be(port);
TASS Belgium NV 131:4758606c9316 770 }
TASS Belgium NV 131:4758606c9316 771 } while(1);
TASS Belgium NV 131:4758606c9316 772 }
TASS Belgium NV 131:4758606c9316 773 else return 0U;
tass 68:0847e35d08a6 774 }
tass 68:0847e35d08a6 775
tass picotcp@tass.be 149:5f4cb161cec3 776 static void *pico_socket_sendto_get_ip4_src(struct pico_socket *s, struct pico_ip4 *dst)
tass 68:0847e35d08a6 777 {
tass picotcp@tass.be 149:5f4cb161cec3 778 struct pico_ip4 *src4 = NULL;
tass picotcp@tass.be 134:cc4e6d2654d9 779
tass 68:0847e35d08a6 780 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 781 /* Check if socket is connected: destination address MUST match the
tass picotcp@tass.be 149:5f4cb161cec3 782 * current connected endpoint
tass picotcp@tass.be 149:5f4cb161cec3 783 */
tass picotcp@tass.be 149:5f4cb161cec3 784 if ((s->state & PICO_SOCKET_STATE_CONNECTED)) {
tass picotcp@tass.be 149:5f4cb161cec3 785 src4 = &s->local_addr.ip4;
tass picotcp@tass.be 149:5f4cb161cec3 786 if (s->remote_addr.ip4.addr != ((struct pico_ip4 *)dst)->addr ) {
tass picotcp@tass.be 149:5f4cb161cec3 787 pico_err = PICO_ERR_EADDRNOTAVAIL;
tass picotcp@tass.be 149:5f4cb161cec3 788 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 789 }
tass picotcp@tass.be 149:5f4cb161cec3 790 } else {
tass picotcp@tass.be 149:5f4cb161cec3 791
tass picotcp@tass.be 149:5f4cb161cec3 792 src4 = pico_ipv4_source_find(dst);
tass picotcp@tass.be 149:5f4cb161cec3 793 if (!src4) {
tass picotcp@tass.be 149:5f4cb161cec3 794 pico_err = PICO_ERR_EHOSTUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 795 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 796 }
tass picotcp@tass.be 149:5f4cb161cec3 797
tass picotcp@tass.be 149:5f4cb161cec3 798 }
tass picotcp@tass.be 149:5f4cb161cec3 799
tass picotcp@tass.be 149:5f4cb161cec3 800 if (src4->addr != PICO_IPV4_INADDR_ANY)
tass picotcp@tass.be 149:5f4cb161cec3 801 s->local_addr.ip4.addr = src4->addr;
tass picotcp@tass.be 149:5f4cb161cec3 802
tass picotcp@tass.be 149:5f4cb161cec3 803 #else
tass picotcp@tass.be 149:5f4cb161cec3 804 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass 68:0847e35d08a6 805 #endif
tass picotcp@tass.be 149:5f4cb161cec3 806 return src4;
tass picotcp@tass.be 149:5f4cb161cec3 807 }
tass picotcp@tass.be 149:5f4cb161cec3 808
tass picotcp@tass.be 149:5f4cb161cec3 809 static void *pico_socket_sendto_get_ip6_src(struct pico_socket *s, struct pico_ip6 *dst)
tass picotcp@tass.be 149:5f4cb161cec3 810 {
tass picotcp@tass.be 149:5f4cb161cec3 811 struct pico_ip6 *src6 = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 812 (void)s;
tass picotcp@tass.be 149:5f4cb161cec3 813 (void)dst;
tass 68:0847e35d08a6 814
tass 68:0847e35d08a6 815 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 816
tass picotcp@tass.be 149:5f4cb161cec3 817 /* Check if socket is connected: destination address MUST match the
tass picotcp@tass.be 149:5f4cb161cec3 818 * current connected endpoint
tass picotcp@tass.be 149:5f4cb161cec3 819 */
tass picotcp@tass.be 149:5f4cb161cec3 820 if ((s->state & PICO_SOCKET_STATE_CONNECTED)) {
tass picotcp@tass.be 149:5f4cb161cec3 821 src6 = &s->local_addr.ip6;
tass picotcp@tass.be 149:5f4cb161cec3 822 if (memcmp(&s->remote_addr, dst, PICO_SIZE_IP6)) {
tass picotcp@tass.be 149:5f4cb161cec3 823 pico_err = PICO_ERR_EADDRNOTAVAIL;
tass picotcp@tass.be 149:5f4cb161cec3 824 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 825 }
tass picotcp@tass.be 149:5f4cb161cec3 826 } else {
tass picotcp@tass.be 149:5f4cb161cec3 827 src6 = pico_ipv6_source_find(dst);
tass picotcp@tass.be 149:5f4cb161cec3 828 if (!src6) {
tass picotcp@tass.be 149:5f4cb161cec3 829 pico_err = PICO_ERR_EHOSTUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 830 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 831 }
tass picotcp@tass.be 149:5f4cb161cec3 832
tass picotcp@tass.be 149:5f4cb161cec3 833 if (!pico_ipv6_is_unspecified(src6->addr))
tass picotcp@tass.be 149:5f4cb161cec3 834 s->local_addr.ip6 = *src6;
tass picotcp@tass.be 149:5f4cb161cec3 835 }
tass picotcp@tass.be 149:5f4cb161cec3 836
tass picotcp@tass.be 149:5f4cb161cec3 837 #else
tass picotcp@tass.be 149:5f4cb161cec3 838 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass 68:0847e35d08a6 839 #endif
tass picotcp@tass.be 149:5f4cb161cec3 840 return src6;
tass picotcp@tass.be 149:5f4cb161cec3 841 }
tass picotcp@tass.be 149:5f4cb161cec3 842
tass picotcp@tass.be 149:5f4cb161cec3 843
tass picotcp@tass.be 149:5f4cb161cec3 844 static int pico_socket_sendto_dest_check(struct pico_socket *s, void *dst, uint16_t port)
tass picotcp@tass.be 149:5f4cb161cec3 845 {
tass picotcp@tass.be 149:5f4cb161cec3 846
tass picotcp@tass.be 149:5f4cb161cec3 847 /* For the sendto call to be valid,
tass picotcp@tass.be 149:5f4cb161cec3 848 * dst and remote_port should be always populated.
tass picotcp@tass.be 149:5f4cb161cec3 849 */
tass picotcp@tass.be 149:5f4cb161cec3 850 if (!dst || !port) {
tass picotcp@tass.be 149:5f4cb161cec3 851 pico_err = PICO_ERR_EADDRNOTAVAIL;
tass picotcp@tass.be 149:5f4cb161cec3 852 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 853 }
tass picotcp@tass.be 149:5f4cb161cec3 854
tass picotcp@tass.be 149:5f4cb161cec3 855 /* When coming from pico_socket_send (or _write),
tass picotcp@tass.be 149:5f4cb161cec3 856 * the destination is automatically assigned to the currently connected endpoint.
tass picotcp@tass.be 149:5f4cb161cec3 857 * This check will ensure that there is no mismatch when sendto() is called directly
tass picotcp@tass.be 149:5f4cb161cec3 858 * on a connected socket
tass picotcp@tass.be 149:5f4cb161cec3 859 */
tass picotcp@tass.be 149:5f4cb161cec3 860 if ((s->state & PICO_SOCKET_STATE_CONNECTED) != 0) {
tass picotcp@tass.be 149:5f4cb161cec3 861 if (port != s->remote_port) {
tass picotcp@tass.be 149:5f4cb161cec3 862 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 863 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 864 }
tass picotcp@tass.be 149:5f4cb161cec3 865 }
tass picotcp@tass.be 149:5f4cb161cec3 866
tass picotcp@tass.be 149:5f4cb161cec3 867 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 868 }
tass picotcp@tass.be 149:5f4cb161cec3 869
tass picotcp@tass.be 149:5f4cb161cec3 870 static int pico_socket_sendto_initial_checks(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port)
tass picotcp@tass.be 149:5f4cb161cec3 871 {
TASS Belgium NV 131:4758606c9316 872 if (len == 0) {
TASS Belgium NV 131:4758606c9316 873 return 0;
TASS Belgium NV 131:4758606c9316 874 } else if (len < 0) {
TASS Belgium NV 131:4758606c9316 875 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 876 return -1;
TASS Belgium NV 131:4758606c9316 877 }
tass 68:0847e35d08a6 878
TASS Belgium NV 131:4758606c9316 879 if (buf == NULL || s == NULL) {
TASS Belgium NV 131:4758606c9316 880 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 881 return -1;
TASS Belgium NV 131:4758606c9316 882 }
tass 68:0847e35d08a6 883
tass picotcp@tass.be 149:5f4cb161cec3 884 return pico_socket_sendto_dest_check(s, dst, remote_port);
tass picotcp@tass.be 149:5f4cb161cec3 885 }
tass picotcp@tass.be 149:5f4cb161cec3 886
tass picotcp@tass.be 149:5f4cb161cec3 887 static void *pico_socket_sendto_get_src(struct pico_socket *s, void *dst)
tass picotcp@tass.be 149:5f4cb161cec3 888 {
tass picotcp@tass.be 149:5f4cb161cec3 889 void *src = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 890 if (is_sock_ipv4(s))
tass picotcp@tass.be 149:5f4cb161cec3 891 src = pico_socket_sendto_get_ip4_src(s, (struct pico_ip4 *)dst);
tass picotcp@tass.be 149:5f4cb161cec3 892
tass picotcp@tass.be 149:5f4cb161cec3 893 if (is_sock_ipv6(s))
tass picotcp@tass.be 149:5f4cb161cec3 894 src = pico_socket_sendto_get_ip6_src(s, (struct pico_ip6 *)dst);
tass picotcp@tass.be 149:5f4cb161cec3 895
tass picotcp@tass.be 149:5f4cb161cec3 896 return src;
tass picotcp@tass.be 149:5f4cb161cec3 897 }
tass picotcp@tass.be 149:5f4cb161cec3 898
tass picotcp@tass.be 149:5f4cb161cec3 899 static struct pico_remote_endpoint *pico_socket_sendto_destination_ipv4(struct pico_socket *s, struct pico_ip4 *dst, uint16_t port)
tass picotcp@tass.be 149:5f4cb161cec3 900 {
tass picotcp@tass.be 149:5f4cb161cec3 901 struct pico_remote_endpoint *ep = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 902 (void)s;
tass picotcp@tass.be 149:5f4cb161cec3 903 ep = PICO_ZALLOC(sizeof(struct pico_remote_endpoint));
tass picotcp@tass.be 149:5f4cb161cec3 904 if (!ep) {
tass picotcp@tass.be 149:5f4cb161cec3 905 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 906 return NULL;
TASS Belgium NV 131:4758606c9316 907 }
tass 68:0847e35d08a6 908
tass picotcp@tass.be 149:5f4cb161cec3 909 ep->remote_addr.ip4.addr = ((struct pico_ip4 *)dst)->addr;
tass picotcp@tass.be 149:5f4cb161cec3 910 ep->remote_port = port;
tass picotcp@tass.be 149:5f4cb161cec3 911 return ep;
tass picotcp@tass.be 149:5f4cb161cec3 912 }
tass picotcp@tass.be 149:5f4cb161cec3 913
tass picotcp@tass.be 149:5f4cb161cec3 914 static void pico_endpoint_free(struct pico_remote_endpoint *ep)
tass picotcp@tass.be 149:5f4cb161cec3 915 {
tass picotcp@tass.be 149:5f4cb161cec3 916 if (ep)
tass picotcp@tass.be 149:5f4cb161cec3 917 PICO_FREE(ep);
tass picotcp@tass.be 149:5f4cb161cec3 918 }
tass picotcp@tass.be 149:5f4cb161cec3 919
tass picotcp@tass.be 149:5f4cb161cec3 920 static struct pico_remote_endpoint *pico_socket_sendto_destination_ipv6(struct pico_socket *s, struct pico_ip6 *dst, uint16_t port)
tass picotcp@tass.be 149:5f4cb161cec3 921 {
tass picotcp@tass.be 149:5f4cb161cec3 922 struct pico_remote_endpoint *ep = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 923 (void)s;
tass picotcp@tass.be 149:5f4cb161cec3 924 (void)dst;
tass picotcp@tass.be 149:5f4cb161cec3 925 (void)port;
tass picotcp@tass.be 149:5f4cb161cec3 926 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 927 ep = PICO_ZALLOC(sizeof(struct pico_remote_endpoint));
tass picotcp@tass.be 149:5f4cb161cec3 928 if (!ep) {
tass picotcp@tass.be 149:5f4cb161cec3 929 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 930 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 931 }
tass picotcp@tass.be 149:5f4cb161cec3 932
tass picotcp@tass.be 149:5f4cb161cec3 933 memcpy(&ep->remote_addr.ip6, dst, sizeof(struct pico_ip6));
tass picotcp@tass.be 149:5f4cb161cec3 934 ep->remote_port = port;
tass picotcp@tass.be 149:5f4cb161cec3 935 #endif
tass picotcp@tass.be 149:5f4cb161cec3 936 return ep;
tass picotcp@tass.be 149:5f4cb161cec3 937 }
tass picotcp@tass.be 149:5f4cb161cec3 938
tass picotcp@tass.be 149:5f4cb161cec3 939
tass picotcp@tass.be 149:5f4cb161cec3 940 static struct pico_remote_endpoint *pico_socket_sendto_destination(struct pico_socket *s, void *dst, uint16_t port)
tass picotcp@tass.be 149:5f4cb161cec3 941 {
tass picotcp@tass.be 149:5f4cb161cec3 942 struct pico_remote_endpoint *ep = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 943 (void)pico_socket_sendto_destination_ipv6;
tass picotcp@tass.be 149:5f4cb161cec3 944 /* socket remote info could change in a consecutive call, make persistent */
tass picotcp@tass.be 149:5f4cb161cec3 945 # ifdef PICO_SUPPORT_UDP
tass picotcp@tass.be 149:5f4cb161cec3 946 if (PROTO(s) == PICO_PROTO_UDP) {
tass picotcp@tass.be 149:5f4cb161cec3 947 # ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 948 if (is_sock_ipv6(s))
tass picotcp@tass.be 149:5f4cb161cec3 949 ep = pico_socket_sendto_destination_ipv6(s, (struct pico_ip6 *)dst, port);
tass picotcp@tass.be 149:5f4cb161cec3 950
tass picotcp@tass.be 149:5f4cb161cec3 951 # endif
tass picotcp@tass.be 149:5f4cb161cec3 952 # ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 953 if (is_sock_ipv4(s))
tass picotcp@tass.be 149:5f4cb161cec3 954 ep = pico_socket_sendto_destination_ipv4(s, (struct pico_ip4 *)dst, port);
tass picotcp@tass.be 149:5f4cb161cec3 955
tass picotcp@tass.be 149:5f4cb161cec3 956 # endif
tass picotcp@tass.be 149:5f4cb161cec3 957 }
tass picotcp@tass.be 149:5f4cb161cec3 958
tass picotcp@tass.be 149:5f4cb161cec3 959 # endif
tass picotcp@tass.be 149:5f4cb161cec3 960 return ep;
tass picotcp@tass.be 149:5f4cb161cec3 961 }
tass picotcp@tass.be 149:5f4cb161cec3 962
tass picotcp@tass.be 149:5f4cb161cec3 963 static int32_t pico_socket_sendto_set_localport(struct pico_socket *s)
tass picotcp@tass.be 149:5f4cb161cec3 964 {
tass picotcp@tass.be 149:5f4cb161cec3 965
tass picotcp@tass.be 149:5f4cb161cec3 966 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
tass picotcp@tass.be 149:5f4cb161cec3 967 s->local_port = pico_socket_high_port(s->proto->proto_number);
tass picotcp@tass.be 149:5f4cb161cec3 968 if (s->local_port == 0) {
TASS Belgium NV 131:4758606c9316 969 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 970 return -1;
TASS Belgium NV 131:4758606c9316 971 }
tass 68:0847e35d08a6 972 }
tass 68:0847e35d08a6 973
tass picotcp@tass.be 149:5f4cb161cec3 974 return s->local_port;
tass picotcp@tass.be 149:5f4cb161cec3 975 }
TASS Belgium NV 131:4758606c9316 976
tass picotcp@tass.be 149:5f4cb161cec3 977 static int pico_socket_sendto_transport_offset(struct pico_socket *s)
tass picotcp@tass.be 149:5f4cb161cec3 978 {
tass picotcp@tass.be 149:5f4cb161cec3 979 int header_offset = -1;
tass picotcp@tass.be 149:5f4cb161cec3 980 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 981 if (PROTO(s) == PICO_PROTO_TCP)
tass picotcp@tass.be 149:5f4cb161cec3 982 header_offset = pico_tcp_overhead(s);
TASS Belgium NV 131:4758606c9316 983
tass picotcp@tass.be 149:5f4cb161cec3 984 #endif
TASS Belgium NV 131:4758606c9316 985
tass picotcp@tass.be 149:5f4cb161cec3 986 #ifdef PICO_SUPPORT_UDP
tass picotcp@tass.be 149:5f4cb161cec3 987 if (PROTO(s) == PICO_PROTO_UDP)
tass picotcp@tass.be 149:5f4cb161cec3 988 header_offset = sizeof(struct pico_udp_hdr);
TASS Belgium NV 131:4758606c9316 989
tass 68:0847e35d08a6 990 #endif
tass picotcp@tass.be 149:5f4cb161cec3 991 return header_offset;
TASS Belgium NV 131:4758606c9316 992 }
tass picotcp@tass.be 149:5f4cb161cec3 993
TASS Belgium NV 131:4758606c9316 994
tass picotcp@tass.be 149:5f4cb161cec3 995 static struct pico_remote_endpoint *pico_socket_set_info(struct pico_remote_endpoint *ep)
tass picotcp@tass.be 149:5f4cb161cec3 996 {
tass picotcp@tass.be 149:5f4cb161cec3 997 struct pico_remote_endpoint *info;
tass picotcp@tass.be 149:5f4cb161cec3 998 info = PICO_ZALLOC(sizeof(struct pico_remote_endpoint));
tass picotcp@tass.be 149:5f4cb161cec3 999 if (!info) {
tass picotcp@tass.be 149:5f4cb161cec3 1000 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 1001 return NULL;
tass 68:0847e35d08a6 1002 }
TASS Belgium NV 131:4758606c9316 1003
tass picotcp@tass.be 149:5f4cb161cec3 1004 memcpy(info, ep, sizeof(struct pico_remote_endpoint));
tass picotcp@tass.be 149:5f4cb161cec3 1005 return info;
tass picotcp@tass.be 149:5f4cb161cec3 1006 }
tass picotcp@tass.be 149:5f4cb161cec3 1007
tass picotcp@tass.be 149:5f4cb161cec3 1008 static void pico_xmit_frame_set_nofrag(struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 1009 {
tass picotcp@tass.be 149:5f4cb161cec3 1010 #ifdef PICO_SUPPORT_IPFRAG
tass picotcp@tass.be 149:5f4cb161cec3 1011 f->frag = short_be(PICO_IPV4_DONTFRAG);
tass 68:0847e35d08a6 1012 #endif
TASS Belgium NV 131:4758606c9316 1013 }
tass 68:0847e35d08a6 1014
tass picotcp@tass.be 149:5f4cb161cec3 1015 static int pico_socket_final_xmit(struct pico_socket *s, struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 1016 {
tass picotcp@tass.be 149:5f4cb161cec3 1017 if (s->proto->push(s->proto, f) > 0) {
tass picotcp@tass.be 149:5f4cb161cec3 1018 return f->payload_len;
tass picotcp@tass.be 149:5f4cb161cec3 1019 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1020 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 1021 return 0;
tass 68:0847e35d08a6 1022 }
TASS Belgium NV 131:4758606c9316 1023 }
TASS Belgium NV 131:4758606c9316 1024
tass picotcp@tass.be 149:5f4cb161cec3 1025 static int pico_socket_xmit_one(struct pico_socket *s, const void *buf, const int len, void *src, struct pico_remote_endpoint *ep)
tass picotcp@tass.be 149:5f4cb161cec3 1026 {
tass picotcp@tass.be 149:5f4cb161cec3 1027 struct pico_frame *f;
tass picotcp@tass.be 149:5f4cb161cec3 1028 uint16_t hdr_offset = (uint16_t)pico_socket_sendto_transport_offset(s);
tass picotcp@tass.be 149:5f4cb161cec3 1029 int ret = 0;
tass picotcp@tass.be 149:5f4cb161cec3 1030 (void)src;
TASS Belgium NV 131:4758606c9316 1031
tass picotcp@tass.be 149:5f4cb161cec3 1032 f = pico_socket_frame_alloc(s, (uint16_t)(len + hdr_offset));
tass 68:0847e35d08a6 1033 if (!f) {
TASS Belgium NV 131:4758606c9316 1034 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1035 return -1;
tass 68:0847e35d08a6 1036 }
TASS Belgium NV 131:4758606c9316 1037
tass picotcp@tass.be 149:5f4cb161cec3 1038 f->payload += hdr_offset;
tass picotcp@tass.be 149:5f4cb161cec3 1039 f->payload_len = (uint16_t)(len);
tass 68:0847e35d08a6 1040 f->sock = s;
TASS Belgium NV 131:4758606c9316 1041 transport_flags_update(f, s);
tass picotcp@tass.be 149:5f4cb161cec3 1042 pico_xmit_frame_set_nofrag(f);
tass picotcp@tass.be 149:5f4cb161cec3 1043 if (ep) {
tass picotcp@tass.be 149:5f4cb161cec3 1044 f->info = pico_socket_set_info(ep);
tass picotcp@tass.be 149:5f4cb161cec3 1045 if (!f->info) {
tass picotcp@tass.be 149:5f4cb161cec3 1046 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 1047 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1048 }
tass picotcp@tass.be 149:5f4cb161cec3 1049 }
tass picotcp@tass.be 149:5f4cb161cec3 1050
tass picotcp@tass.be 149:5f4cb161cec3 1051 memcpy(f->payload, (const uint8_t *)buf, f->payload_len);
tass picotcp@tass.be 149:5f4cb161cec3 1052 /* dbg("Pushing segment, hdr len: %d, payload_len: %d\n", header_offset, f->payload_len); */
tass picotcp@tass.be 149:5f4cb161cec3 1053 ret = pico_socket_final_xmit(s, f);
tass picotcp@tass.be 149:5f4cb161cec3 1054 return ret;
tass picotcp@tass.be 149:5f4cb161cec3 1055 }
tass picotcp@tass.be 149:5f4cb161cec3 1056
tass picotcp@tass.be 149:5f4cb161cec3 1057 static int pico_socket_xmit_avail_space(struct pico_socket *s);
tass picotcp@tass.be 149:5f4cb161cec3 1058
tass picotcp@tass.be 149:5f4cb161cec3 1059 static void pico_socket_xmit_first_fragment_setup(struct pico_frame *f, int space, int hdr_offset)
tass picotcp@tass.be 149:5f4cb161cec3 1060 {
tass picotcp@tass.be 149:5f4cb161cec3 1061 frag_dbg("FRAG: first fragmented frame %p | len = %u offset = 0\n", f, f->payload_len);
tass picotcp@tass.be 149:5f4cb161cec3 1062 /* transport header length field contains total length + header length */
tass picotcp@tass.be 149:5f4cb161cec3 1063 f->transport_len = (uint16_t)(space);
tass picotcp@tass.be 149:5f4cb161cec3 1064 #ifdef PICO_SUPPORT_IPFRAG
tass picotcp@tass.be 149:5f4cb161cec3 1065 f->frag = short_be(PICO_IPV4_MOREFRAG);
tass picotcp@tass.be 149:5f4cb161cec3 1066 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1067 f->payload += hdr_offset;
tass picotcp@tass.be 149:5f4cb161cec3 1068 f->payload_len = (uint16_t) space;
tass picotcp@tass.be 149:5f4cb161cec3 1069 }
tass picotcp@tass.be 149:5f4cb161cec3 1070
tass picotcp@tass.be 149:5f4cb161cec3 1071 static void pico_socket_xmit_next_fragment_setup(struct pico_frame *f, int hdr_offset, int total_payload_written, int len)
tass picotcp@tass.be 149:5f4cb161cec3 1072 {
tass picotcp@tass.be 149:5f4cb161cec3 1073 /* no transport header in fragmented IP */
tass picotcp@tass.be 149:5f4cb161cec3 1074 f->payload = f->transport_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 1075 f->payload_len = (uint16_t)(f->payload_len + hdr_offset);
tass picotcp@tass.be 149:5f4cb161cec3 1076 /* set offset in octets */
tass picotcp@tass.be 149:5f4cb161cec3 1077 #ifdef PICO_SUPPORT_IPFRAG
tass picotcp@tass.be 149:5f4cb161cec3 1078 f->frag = short_be((uint16_t)((uint16_t)(total_payload_written + (uint16_t)hdr_offset) >> 3u));
tass picotcp@tass.be 149:5f4cb161cec3 1079 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1080 if (total_payload_written + f->payload_len < len) {
tass picotcp@tass.be 149:5f4cb161cec3 1081 frag_dbg("FRAG: intermediate fragmented frame %p | len = %u offset = %u\n", f, f->payload_len, short_be(f->frag));
tass picotcp@tass.be 149:5f4cb161cec3 1082 #ifdef PICO_SUPPORT_IPFRAG
tass picotcp@tass.be 149:5f4cb161cec3 1083 f->frag |= short_be(PICO_IPV4_MOREFRAG);
tass picotcp@tass.be 149:5f4cb161cec3 1084 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1085 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1086 frag_dbg("FRAG: last fragmented frame %p | len = %u offset = %u\n", f, f->payload_len, short_be(f->frag));
tass picotcp@tass.be 149:5f4cb161cec3 1087 #ifdef PICO_SUPPORT_IPFRAG
tass picotcp@tass.be 149:5f4cb161cec3 1088 f->frag &= short_be(PICO_IPV4_FRAG_MASK);
tass picotcp@tass.be 149:5f4cb161cec3 1089 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1090 }
tass picotcp@tass.be 149:5f4cb161cec3 1091 }
tass picotcp@tass.be 149:5f4cb161cec3 1092
tass picotcp@tass.be 149:5f4cb161cec3 1093 static int pico_socket_xmit_fragments(struct pico_socket *s, const void *buf, const int len, void *src, struct pico_remote_endpoint *ep)
tass picotcp@tass.be 149:5f4cb161cec3 1094 {
tass picotcp@tass.be 149:5f4cb161cec3 1095 int space = pico_socket_xmit_avail_space(s);
tass picotcp@tass.be 149:5f4cb161cec3 1096 int hdr_offset = pico_socket_sendto_transport_offset(s);
tass picotcp@tass.be 149:5f4cb161cec3 1097 int total_payload_written = 0;
tass picotcp@tass.be 149:5f4cb161cec3 1098 struct pico_frame *f = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 1099
tass picotcp@tass.be 149:5f4cb161cec3 1100 if (space > len) {
tass picotcp@tass.be 149:5f4cb161cec3 1101 return pico_socket_xmit_one(s, buf, len, src, ep);
tass 68:0847e35d08a6 1102 }
tass 68:0847e35d08a6 1103
tass picotcp@tass.be 149:5f4cb161cec3 1104 #ifdef PICO_SUPPORT_IPFRAG
tass picotcp@tass.be 149:5f4cb161cec3 1105 while(total_payload_written < len) {
tass picotcp@tass.be 149:5f4cb161cec3 1106 /* Always allocate the max space available: space + offset */
tass picotcp@tass.be 149:5f4cb161cec3 1107 if (len < space)
tass picotcp@tass.be 149:5f4cb161cec3 1108 space = len;
tass picotcp@tass.be 149:5f4cb161cec3 1109
tass picotcp@tass.be 149:5f4cb161cec3 1110 f = pico_socket_frame_alloc(s, (uint16_t)(space + hdr_offset));
tass picotcp@tass.be 149:5f4cb161cec3 1111 if (!f) {
tass picotcp@tass.be 149:5f4cb161cec3 1112 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 1113 pico_endpoint_free(ep);
tass picotcp@tass.be 149:5f4cb161cec3 1114 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1115 }
tass picotcp@tass.be 149:5f4cb161cec3 1116
tass picotcp@tass.be 149:5f4cb161cec3 1117 f->sock = s;
tass picotcp@tass.be 149:5f4cb161cec3 1118 if (ep) {
tass picotcp@tass.be 149:5f4cb161cec3 1119 f->info = pico_socket_set_info(ep);
tass picotcp@tass.be 149:5f4cb161cec3 1120 if (!f->info) {
tass picotcp@tass.be 149:5f4cb161cec3 1121 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 1122 pico_endpoint_free(ep);
tass picotcp@tass.be 149:5f4cb161cec3 1123 return -1;
TASS Belgium NV 131:4758606c9316 1124 }
tass 68:0847e35d08a6 1125 }
tass picotcp@tass.be 149:5f4cb161cec3 1126
tass picotcp@tass.be 149:5f4cb161cec3 1127 if (!total_payload_written == 0) {
tass picotcp@tass.be 149:5f4cb161cec3 1128 /* First fragment: no payload written yet! */
tass picotcp@tass.be 149:5f4cb161cec3 1129 pico_socket_xmit_first_fragment_setup(f, space, hdr_offset);
tass picotcp@tass.be 149:5f4cb161cec3 1130 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1131 /* Next fragment */
tass picotcp@tass.be 149:5f4cb161cec3 1132 pico_socket_xmit_next_fragment_setup(f, hdr_offset, total_payload_written, len);
tass picotcp@tass.be 149:5f4cb161cec3 1133 }
tass picotcp@tass.be 149:5f4cb161cec3 1134
tass picotcp@tass.be 149:5f4cb161cec3 1135 memcpy(f->payload, (const uint8_t *)buf + total_payload_written, f->payload_len);
tass picotcp@tass.be 149:5f4cb161cec3 1136 transport_flags_update(f, s);
tass picotcp@tass.be 149:5f4cb161cec3 1137 if (s->proto->push(s->proto, f) > 0) {
tass picotcp@tass.be 149:5f4cb161cec3 1138 total_payload_written += f->payload_len;
tass picotcp@tass.be 149:5f4cb161cec3 1139 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1140 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 1141 break;
tass picotcp@tass.be 149:5f4cb161cec3 1142 }
tass picotcp@tass.be 149:5f4cb161cec3 1143 } /* while() */
tass picotcp@tass.be 149:5f4cb161cec3 1144 pico_endpoint_free(ep);
tass picotcp@tass.be 149:5f4cb161cec3 1145 return total_payload_written;
tass picotcp@tass.be 149:5f4cb161cec3 1146
tass picotcp@tass.be 149:5f4cb161cec3 1147 #else
tass picotcp@tass.be 149:5f4cb161cec3 1148 /* Careful with that axe, Eugene!
tass picotcp@tass.be 149:5f4cb161cec3 1149 *
tass picotcp@tass.be 149:5f4cb161cec3 1150 * cropping down datagrams to the MTU value.
tass picotcp@tass.be 149:5f4cb161cec3 1151 */
tass picotcp@tass.be 149:5f4cb161cec3 1152 (void) f;
tass picotcp@tass.be 149:5f4cb161cec3 1153 (void) hdr_offset;
tass picotcp@tass.be 149:5f4cb161cec3 1154 (void) total_payload_written;
tass picotcp@tass.be 149:5f4cb161cec3 1155 return pico_socket_xmit_one(s, buf, space, src, ep);
tass picotcp@tass.be 149:5f4cb161cec3 1156
tass picotcp@tass.be 149:5f4cb161cec3 1157 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1158 }
tass picotcp@tass.be 149:5f4cb161cec3 1159
tass picotcp@tass.be 149:5f4cb161cec3 1160 uint16_t pico_socket_get_mtu(struct pico_socket *s)
tass picotcp@tass.be 149:5f4cb161cec3 1161 {
tass picotcp@tass.be 149:5f4cb161cec3 1162 (void)s;
tass picotcp@tass.be 149:5f4cb161cec3 1163 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 1164 if (is_sock_ipv6(s))
tass picotcp@tass.be 149:5f4cb161cec3 1165 return PICO_SOCKET6_MTU;
tass picotcp@tass.be 149:5f4cb161cec3 1166
tass picotcp@tass.be 149:5f4cb161cec3 1167 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1168 return PICO_SOCKET4_MTU;
tass picotcp@tass.be 149:5f4cb161cec3 1169 }
tass picotcp@tass.be 149:5f4cb161cec3 1170
tass picotcp@tass.be 149:5f4cb161cec3 1171
tass picotcp@tass.be 149:5f4cb161cec3 1172 static int pico_socket_xmit_avail_space(struct pico_socket *s)
tass picotcp@tass.be 149:5f4cb161cec3 1173 {
tass picotcp@tass.be 149:5f4cb161cec3 1174 int transport_len;
tass picotcp@tass.be 149:5f4cb161cec3 1175 int header_offset;
tass picotcp@tass.be 149:5f4cb161cec3 1176
tass picotcp@tass.be 149:5f4cb161cec3 1177 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 1178 if (PROTO(s) == PICO_PROTO_TCP) {
tass picotcp@tass.be 149:5f4cb161cec3 1179 transport_len = pico_tcp_get_socket_mtu(s);
tass picotcp@tass.be 149:5f4cb161cec3 1180 } else
tass picotcp@tass.be 149:5f4cb161cec3 1181 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1182 transport_len = pico_socket_get_mtu(s);
tass picotcp@tass.be 149:5f4cb161cec3 1183 header_offset = pico_socket_sendto_transport_offset(s);
tass picotcp@tass.be 149:5f4cb161cec3 1184 if (header_offset < 0) {
tass picotcp@tass.be 149:5f4cb161cec3 1185 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass picotcp@tass.be 149:5f4cb161cec3 1186 return -1;
tass 68:0847e35d08a6 1187 }
TASS Belgium NV 131:4758606c9316 1188
tass picotcp@tass.be 149:5f4cb161cec3 1189 transport_len -= pico_socket_sendto_transport_offset(s);
tass picotcp@tass.be 149:5f4cb161cec3 1190 return transport_len;
tass picotcp@tass.be 149:5f4cb161cec3 1191 }
tass picotcp@tass.be 149:5f4cb161cec3 1192
tass 68:0847e35d08a6 1193
tass picotcp@tass.be 149:5f4cb161cec3 1194 static int pico_socket_xmit(struct pico_socket *s, const void *buf, const int len, void *src, struct pico_remote_endpoint *ep)
tass picotcp@tass.be 149:5f4cb161cec3 1195 {
tass picotcp@tass.be 149:5f4cb161cec3 1196 int space = pico_socket_xmit_avail_space(s);
tass picotcp@tass.be 149:5f4cb161cec3 1197 int total_payload_written = 0;
TASS Belgium NV 131:4758606c9316 1198
tass picotcp@tass.be 149:5f4cb161cec3 1199 if (space < 0) {
tass picotcp@tass.be 149:5f4cb161cec3 1200 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass picotcp@tass.be 149:5f4cb161cec3 1201 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1202 }
tass picotcp@tass.be 149:5f4cb161cec3 1203
tass picotcp@tass.be 149:5f4cb161cec3 1204 if ((PROTO(s) == PICO_PROTO_UDP) && (len > space)) {
tass picotcp@tass.be 149:5f4cb161cec3 1205 return pico_socket_xmit_fragments(s, buf, len, src, ep);
tass 68:0847e35d08a6 1206 }
tass 68:0847e35d08a6 1207
tass picotcp@tass.be 149:5f4cb161cec3 1208 while (total_payload_written < len) {
tass picotcp@tass.be 149:5f4cb161cec3 1209 int w, chunk_len = len - total_payload_written;
tass picotcp@tass.be 149:5f4cb161cec3 1210 if (chunk_len > space)
tass picotcp@tass.be 149:5f4cb161cec3 1211 chunk_len = space;
tass picotcp@tass.be 149:5f4cb161cec3 1212
tass picotcp@tass.be 149:5f4cb161cec3 1213 w = pico_socket_xmit_one(s, (const void *)((const uint8_t *)buf + total_payload_written), chunk_len, src, ep);
tass picotcp@tass.be 149:5f4cb161cec3 1214 if (w <= 0) {
tass picotcp@tass.be 149:5f4cb161cec3 1215 break;
tass picotcp@tass.be 149:5f4cb161cec3 1216 }
tass 68:0847e35d08a6 1217
tass picotcp@tass.be 149:5f4cb161cec3 1218 total_payload_written += w;
tass picotcp@tass.be 149:5f4cb161cec3 1219 if (PROTO(s) == PICO_PROTO_UDP) {
tass picotcp@tass.be 149:5f4cb161cec3 1220 /* Break after the first datagram sent with at most MTU bytes. */
tass picotcp@tass.be 149:5f4cb161cec3 1221 break;
tass picotcp@tass.be 149:5f4cb161cec3 1222 }
tass picotcp@tass.be 149:5f4cb161cec3 1223 }
tass picotcp@tass.be 149:5f4cb161cec3 1224 pico_endpoint_free(ep);
tass picotcp@tass.be 149:5f4cb161cec3 1225 return total_payload_written;
tass picotcp@tass.be 149:5f4cb161cec3 1226 }
tass picotcp@tass.be 149:5f4cb161cec3 1227
tass picotcp@tass.be 149:5f4cb161cec3 1228 static void pico_socket_sendto_set_dport(struct pico_socket *s, uint16_t port)
tass picotcp@tass.be 149:5f4cb161cec3 1229 {
tass picotcp@tass.be 149:5f4cb161cec3 1230 if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) {
tass picotcp@tass.be 149:5f4cb161cec3 1231 s->remote_port = port;
tass 68:0847e35d08a6 1232 }
TASS Belgium NV 131:4758606c9316 1233 }
tass picotcp@tass.be 149:5f4cb161cec3 1234
tass picotcp@tass.be 149:5f4cb161cec3 1235
tass picotcp@tass.be 149:5f4cb161cec3 1236 int pico_socket_sendto(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port)
tass picotcp@tass.be 149:5f4cb161cec3 1237 {
tass picotcp@tass.be 149:5f4cb161cec3 1238 struct pico_remote_endpoint *remote_endpoint = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 1239 void *src = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 1240
tass picotcp@tass.be 149:5f4cb161cec3 1241
tass picotcp@tass.be 149:5f4cb161cec3 1242 if (pico_socket_sendto_initial_checks(s, buf, len, dst, remote_port) < 0)
tass picotcp@tass.be 149:5f4cb161cec3 1243 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1244
TASS Belgium NV 131:4758606c9316 1245
tass picotcp@tass.be 149:5f4cb161cec3 1246 src = pico_socket_sendto_get_src(s, dst);
tass picotcp@tass.be 149:5f4cb161cec3 1247 if (!src) {
tass picotcp@tass.be 149:5f4cb161cec3 1248 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1249 }
tass picotcp@tass.be 149:5f4cb161cec3 1250
tass picotcp@tass.be 149:5f4cb161cec3 1251 remote_endpoint = pico_socket_sendto_destination(s, dst, remote_port);
tass picotcp@tass.be 149:5f4cb161cec3 1252 if (pico_socket_sendto_set_localport(s) < 0)
tass picotcp@tass.be 149:5f4cb161cec3 1253 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1254
tass picotcp@tass.be 149:5f4cb161cec3 1255 pico_socket_sendto_set_dport(s, remote_port);
tass picotcp@tass.be 149:5f4cb161cec3 1256
tass picotcp@tass.be 149:5f4cb161cec3 1257 return pico_socket_xmit(s, buf, len, src, remote_endpoint);
tass 68:0847e35d08a6 1258 }
tass 68:0847e35d08a6 1259
tass 68:0847e35d08a6 1260 int pico_socket_send(struct pico_socket *s, const void *buf, int len)
tass 68:0847e35d08a6 1261 {
TASS Belgium NV 131:4758606c9316 1262 if (!s || buf == NULL) {
TASS Belgium NV 131:4758606c9316 1263 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1264 return -1;
TASS Belgium NV 131:4758606c9316 1265 } else {
TASS Belgium NV 131:4758606c9316 1266 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1267 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1268 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1269 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1270 return -1;
TASS Belgium NV 131:4758606c9316 1271 }
tass 68:0847e35d08a6 1272 }
tass 68:0847e35d08a6 1273
TASS Belgium NV 131:4758606c9316 1274 if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) {
TASS Belgium NV 131:4758606c9316 1275 pico_err = PICO_ERR_ENOTCONN;
TASS Belgium NV 131:4758606c9316 1276 return -1;
TASS Belgium NV 131:4758606c9316 1277 }
TASS Belgium NV 131:4758606c9316 1278
TASS Belgium NV 131:4758606c9316 1279 return pico_socket_sendto(s, buf, len, &s->remote_addr, s->remote_port);
tass 68:0847e35d08a6 1280 }
tass 68:0847e35d08a6 1281
tass 68:0847e35d08a6 1282 int pico_socket_recvfrom(struct pico_socket *s, void *buf, int len, void *orig, uint16_t *remote_port)
tass 68:0847e35d08a6 1283 {
TASS Belgium NV 131:4758606c9316 1284 if (!s || buf == NULL) { /* / || orig == NULL || remote_port == NULL) { */
TASS Belgium NV 131:4758606c9316 1285 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1286 return -1;
TASS Belgium NV 131:4758606c9316 1287 } else {
TASS Belgium NV 131:4758606c9316 1288 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1289 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1290 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1291 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1292 return -1;
TASS Belgium NV 131:4758606c9316 1293 }
tass 68:0847e35d08a6 1294 }
TASS Belgium NV 131:4758606c9316 1295
TASS Belgium NV 131:4758606c9316 1296 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1297 pico_err = PICO_ERR_EADDRNOTAVAIL;
TASS Belgium NV 131:4758606c9316 1298 return -1;
TASS Belgium NV 131:4758606c9316 1299 }
tass 68:0847e35d08a6 1300
TASS Belgium NV 131:4758606c9316 1301 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1302 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1303 return pico_udp_recv(s, buf, (uint16_t)len, orig, remote_port);
TASS Belgium NV 131:4758606c9316 1304 }
TASS Belgium NV 131:4758606c9316 1305
tass 68:0847e35d08a6 1306 #endif
tass 68:0847e35d08a6 1307 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1308 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 1309 /* check if in shutdown state and if tcpq_in empty */
TASS Belgium NV 131:4758606c9316 1310 if ((s->state & PICO_SOCKET_STATE_SHUT_REMOTE) && pico_tcp_queue_in_is_empty(s)) {
TASS Belgium NV 131:4758606c9316 1311 pico_err = PICO_ERR_ESHUTDOWN;
TASS Belgium NV 131:4758606c9316 1312 return -1;
TASS Belgium NV 131:4758606c9316 1313 } else {
TASS Belgium NV 131:4758606c9316 1314 /* dbg("socket tcp recv\n"); */
TASS Belgium NV 131:4758606c9316 1315 return (int)pico_tcp_read(s, buf, (uint32_t)len);
TASS Belgium NV 131:4758606c9316 1316 }
tass 68:0847e35d08a6 1317 }
TASS Belgium NV 131:4758606c9316 1318
tass 68:0847e35d08a6 1319 #endif
TASS Belgium NV 131:4758606c9316 1320 /* dbg("socket return 0\n"); */
TASS Belgium NV 131:4758606c9316 1321 return 0;
tass 68:0847e35d08a6 1322 }
tass 68:0847e35d08a6 1323
tass 68:0847e35d08a6 1324 int pico_socket_recv(struct pico_socket *s, void *buf, int len)
tass 68:0847e35d08a6 1325 {
TASS Belgium NV 131:4758606c9316 1326 return pico_socket_recvfrom(s, buf, len, NULL, NULL);
tass 68:0847e35d08a6 1327 }
tass 68:0847e35d08a6 1328
tass 68:0847e35d08a6 1329
tass picotcp@tass.be 149:5f4cb161cec3 1330 int pico_socket_getname(struct pico_socket *s, void *local_addr, uint16_t *port, uint16_t *proto)
tass picotcp@tass.be 149:5f4cb161cec3 1331 {
tass picotcp@tass.be 149:5f4cb161cec3 1332
tass picotcp@tass.be 149:5f4cb161cec3 1333 if (!s || !local_addr || !port || !proto) {
tass picotcp@tass.be 149:5f4cb161cec3 1334 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 1335 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1336 }
tass picotcp@tass.be 149:5f4cb161cec3 1337
tass picotcp@tass.be 149:5f4cb161cec3 1338 if (is_sock_ipv4(s)) {
tass picotcp@tass.be 149:5f4cb161cec3 1339 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 1340 struct pico_ip4 *ip = (struct pico_ip4 *)local_addr;
tass picotcp@tass.be 149:5f4cb161cec3 1341 ip->addr = s->local_addr.ip4.addr;
tass picotcp@tass.be 149:5f4cb161cec3 1342 *proto = PICO_PROTO_IPV4;
tass picotcp@tass.be 149:5f4cb161cec3 1343 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1344 } else if (is_sock_ipv6(s)) {
tass picotcp@tass.be 149:5f4cb161cec3 1345 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 1346 struct pico_ip6 *ip = (struct pico_ip6 *)local_addr;
tass picotcp@tass.be 149:5f4cb161cec3 1347 memcpy(ip->addr, s->local_addr.ip6.addr, PICO_SIZE_IP6);
tass picotcp@tass.be 149:5f4cb161cec3 1348 *proto = PICO_PROTO_IPV6;
tass picotcp@tass.be 149:5f4cb161cec3 1349 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1350 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1351 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 1352 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1353 }
tass picotcp@tass.be 149:5f4cb161cec3 1354 *port = s->local_port;
tass picotcp@tass.be 149:5f4cb161cec3 1355 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 1356 }
tass picotcp@tass.be 149:5f4cb161cec3 1357
tass 68:0847e35d08a6 1358 int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
tass 68:0847e35d08a6 1359 {
TASS Belgium NV 131:4758606c9316 1360 if (!s || !local_addr || !port) {
tass 68:0847e35d08a6 1361 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1362 return -1;
tass 68:0847e35d08a6 1363 }
TASS Belgium NV 131:4758606c9316 1364
tass picotcp@tass.be 149:5f4cb161cec3 1365 if (is_sock_ipv4(s)) {
tass picotcp@tass.be 149:5f4cb161cec3 1366 #ifdef PICO_SUPPORT_IPV4
TASS Belgium NV 131:4758606c9316 1367 struct pico_ip4 *ip = (struct pico_ip4 *)local_addr;
TASS Belgium NV 131:4758606c9316 1368 if (ip->addr != PICO_IPV4_INADDR_ANY) {
TASS Belgium NV 131:4758606c9316 1369 if (!pico_ipv4_link_find(local_addr)) {
TASS Belgium NV 131:4758606c9316 1370 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1371 return -1;
TASS Belgium NV 131:4758606c9316 1372 }
TASS Belgium NV 131:4758606c9316 1373 }
tass picotcp@tass.be 149:5f4cb161cec3 1374
tass picotcp@tass.be 149:5f4cb161cec3 1375 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1376 } else if (is_sock_ipv6(s)) {
tass picotcp@tass.be 149:5f4cb161cec3 1377 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 1378 struct pico_ip6 *ip = (struct pico_ip6 *)local_addr;
tass picotcp@tass.be 149:5f4cb161cec3 1379 if (!pico_ipv6_is_unspecified(ip->addr)) {
tass picotcp@tass.be 149:5f4cb161cec3 1380 if (!pico_ipv6_link_find(local_addr)) {
tass picotcp@tass.be 149:5f4cb161cec3 1381 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 1382 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1383 }
tass picotcp@tass.be 149:5f4cb161cec3 1384 }
tass picotcp@tass.be 149:5f4cb161cec3 1385
tass picotcp@tass.be 149:5f4cb161cec3 1386 #endif
TASS Belgium NV 131:4758606c9316 1387 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1388 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 1389 return -1;
TASS Belgium NV 131:4758606c9316 1390 }
tass 68:0847e35d08a6 1391
tass 68:0847e35d08a6 1392
TASS Belgium NV 131:4758606c9316 1393 /* When given port = 0, get a random high port to bind to. */
tass 68:0847e35d08a6 1394 if (*port == 0) {
TASS Belgium NV 131:4758606c9316 1395 *port = pico_socket_high_port(PROTO(s));
TASS Belgium NV 131:4758606c9316 1396 if (*port == 0) {
TASS Belgium NV 131:4758606c9316 1397 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1398 return -1;
TASS Belgium NV 131:4758606c9316 1399 }
tass 68:0847e35d08a6 1400 }
tass 68:0847e35d08a6 1401
TASS Belgium NV 131:4758606c9316 1402 if (pico_is_port_free(PROTO(s), *port, local_addr, s->net) == 0) {
TASS Belgium NV 131:4758606c9316 1403 pico_err = PICO_ERR_EADDRINUSE;
TASS Belgium NV 131:4758606c9316 1404 return -1;
TASS Belgium NV 131:4758606c9316 1405 }
TASS Belgium NV 131:4758606c9316 1406
TASS Belgium NV 131:4758606c9316 1407 s->local_port = *port;
tass 68:0847e35d08a6 1408
tass picotcp@tass.be 149:5f4cb161cec3 1409 if (is_sock_ipv4(s)) {
tass picotcp@tass.be 149:5f4cb161cec3 1410 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 1411 struct pico_ip4 *ip = (struct pico_ip4 *)local_addr;
tass picotcp@tass.be 149:5f4cb161cec3 1412 s->local_addr.ip4 = *ip;
tass picotcp@tass.be 149:5f4cb161cec3 1413 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1414 } else if (is_sock_ipv6(s)) {
tass picotcp@tass.be 149:5f4cb161cec3 1415 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 1416 struct pico_ip6 *ip = (struct pico_ip6 *)local_addr;
tass picotcp@tass.be 149:5f4cb161cec3 1417 s->local_addr.ip6 = *ip;
tass picotcp@tass.be 149:5f4cb161cec3 1418 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1419 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1420 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 1421 return -1;
tass 68:0847e35d08a6 1422 }
TASS Belgium NV 131:4758606c9316 1423
TASS Belgium NV 131:4758606c9316 1424 return pico_socket_alter_state(s, PICO_SOCKET_STATE_BOUND, 0, 0);
tass 68:0847e35d08a6 1425 }
tass 68:0847e35d08a6 1426
tass picotcp@tass.be 149:5f4cb161cec3 1427
tass 68:0847e35d08a6 1428 int pico_socket_connect(struct pico_socket *s, const void *remote_addr, uint16_t remote_port)
tass 68:0847e35d08a6 1429 {
TASS Belgium NV 131:4758606c9316 1430 int ret = -1;
TASS Belgium NV 131:4758606c9316 1431 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 1432 if (!s || remote_addr == NULL || remote_port == 0) {
TASS Belgium NV 131:4758606c9316 1433 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1434 return -1;
TASS Belgium NV 131:4758606c9316 1435 }
tass 68:0847e35d08a6 1436
TASS Belgium NV 131:4758606c9316 1437 s->remote_port = remote_port;
tass 68:0847e35d08a6 1438
TASS Belgium NV 131:4758606c9316 1439 if (s->local_port == 0) {
TASS Belgium NV 131:4758606c9316 1440 s->local_port = pico_socket_high_port(PROTO(s));
TASS Belgium NV 131:4758606c9316 1441 if (!s->local_port) {
TASS Belgium NV 131:4758606c9316 1442 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1443 return -1;
TASS Belgium NV 131:4758606c9316 1444 }
tass 68:0847e35d08a6 1445 }
tass 68:0847e35d08a6 1446
tass picotcp@tass.be 149:5f4cb161cec3 1447 if (is_sock_ipv4(s)) {
tass picotcp@tass.be 149:5f4cb161cec3 1448 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 1449 struct pico_ip4 *local = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 1450 const struct pico_ip4 *ip = (const struct pico_ip4 *)remote_addr;
tass picotcp@tass.be 149:5f4cb161cec3 1451 s->remote_addr.ip4 = *ip;
TASS Belgium NV 131:4758606c9316 1452 local = pico_ipv4_source_find(ip);
TASS Belgium NV 131:4758606c9316 1453 if (local) {
tass picotcp@tass.be 149:5f4cb161cec3 1454 s->local_addr.ip4 = *local;
TASS Belgium NV 131:4758606c9316 1455 } else {
TASS Belgium NV 131:4758606c9316 1456 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1457 return -1;
TASS Belgium NV 131:4758606c9316 1458 }
tass picotcp@tass.be 149:5f4cb161cec3 1459
tass picotcp@tass.be 149:5f4cb161cec3 1460 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1461 } else if (is_sock_ipv6(s)) {
tass picotcp@tass.be 149:5f4cb161cec3 1462 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 1463 struct pico_ip6 *local = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 1464 const struct pico_ip6 *ip = (const struct pico_ip6 *)remote_addr;
tass picotcp@tass.be 149:5f4cb161cec3 1465 s->remote_addr.ip6 = *ip;
tass picotcp@tass.be 149:5f4cb161cec3 1466 local = pico_ipv6_source_find(ip);
tass picotcp@tass.be 149:5f4cb161cec3 1467 if (local) {
tass picotcp@tass.be 149:5f4cb161cec3 1468 s->local_addr.ip6 = *local;
tass picotcp@tass.be 149:5f4cb161cec3 1469 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1470 pico_err = PICO_ERR_EHOSTUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 1471 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1472 }
tass picotcp@tass.be 149:5f4cb161cec3 1473
tass picotcp@tass.be 149:5f4cb161cec3 1474 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1475 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1476 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 1477 return -1;
tass 68:0847e35d08a6 1478 }
tass 68:0847e35d08a6 1479
TASS Belgium NV 131:4758606c9316 1480 pico_socket_alter_state(s, PICO_SOCKET_STATE_BOUND, 0, 0);
tass 68:0847e35d08a6 1481
tass 68:0847e35d08a6 1482 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1483 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1484 pico_socket_alter_state(s, PICO_SOCKET_STATE_CONNECTED, 0, 0);
TASS Belgium NV 131:4758606c9316 1485 pico_err = PICO_ERR_NOERR;
TASS Belgium NV 131:4758606c9316 1486 ret = 0;
TASS Belgium NV 131:4758606c9316 1487 }
TASS Belgium NV 131:4758606c9316 1488
tass 68:0847e35d08a6 1489 #endif
tass 68:0847e35d08a6 1490
tass 68:0847e35d08a6 1491 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1492 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 1493 if (pico_tcp_initconn(s) == 0) {
TASS Belgium NV 131:4758606c9316 1494 pico_socket_alter_state(s, PICO_SOCKET_STATE_CONNECTED | PICO_SOCKET_STATE_TCP_SYN_SENT, 0, 0);
TASS Belgium NV 131:4758606c9316 1495 pico_err = PICO_ERR_NOERR;
TASS Belgium NV 131:4758606c9316 1496 ret = 0;
TASS Belgium NV 131:4758606c9316 1497 } else {
TASS Belgium NV 131:4758606c9316 1498 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 1499 }
tass 68:0847e35d08a6 1500 }
TASS Belgium NV 131:4758606c9316 1501
tass 68:0847e35d08a6 1502 #endif
tass 68:0847e35d08a6 1503
TASS Belgium NV 131:4758606c9316 1504 return ret;
tass 68:0847e35d08a6 1505 }
tass 68:0847e35d08a6 1506
tass picotcp@tass.be 149:5f4cb161cec3 1507
tass 68:0847e35d08a6 1508 #ifdef PICO_SUPPORT_TCP
tass 68:0847e35d08a6 1509
tass 68:0847e35d08a6 1510 int pico_socket_listen(struct pico_socket *s, int backlog)
tass 68:0847e35d08a6 1511 {
TASS Belgium NV 131:4758606c9316 1512 if (!s || backlog < 1) {
TASS Belgium NV 131:4758606c9316 1513 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1514 return -1;
TASS Belgium NV 131:4758606c9316 1515 } else {
TASS Belgium NV 131:4758606c9316 1516 /* check if exists in tree */
TASS Belgium NV 131:4758606c9316 1517 /* See task #178 */
TASS Belgium NV 131:4758606c9316 1518 if (pico_check_socket(s) != 0) {
TASS Belgium NV 131:4758606c9316 1519 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1520 return -1;
TASS Belgium NV 131:4758606c9316 1521 }
tass 68:0847e35d08a6 1522 }
TASS Belgium NV 131:4758606c9316 1523
TASS Belgium NV 131:4758606c9316 1524 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1525 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1526 return -1;
TASS Belgium NV 131:4758606c9316 1527 }
tass 68:0847e35d08a6 1528
TASS Belgium NV 131:4758606c9316 1529 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1530 pico_err = PICO_ERR_EISCONN;
TASS Belgium NV 131:4758606c9316 1531 return -1;
TASS Belgium NV 131:4758606c9316 1532 }
tass 68:0847e35d08a6 1533
TASS Belgium NV 131:4758606c9316 1534 if (PROTO(s) == PICO_PROTO_TCP)
TASS Belgium NV 131:4758606c9316 1535 pico_socket_alter_state(s, PICO_SOCKET_STATE_TCP_SYN_SENT, 0, PICO_SOCKET_STATE_TCP_LISTEN);
tass 68:0847e35d08a6 1536
tass picotcp@tass.be 149:5f4cb161cec3 1537 s->max_backlog = (uint16_t)backlog;
TASS Belgium NV 131:4758606c9316 1538
TASS Belgium NV 131:4758606c9316 1539 return 0;
tass 68:0847e35d08a6 1540 }
tass 68:0847e35d08a6 1541
tass 68:0847e35d08a6 1542 struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *port)
tass 68:0847e35d08a6 1543 {
TASS Belgium NV 131:4758606c9316 1544 if (!s || !orig || !port) {
TASS Belgium NV 131:4758606c9316 1545 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1546 return NULL;
TASS Belgium NV 131:4758606c9316 1547 }
TASS Belgium NV 131:4758606c9316 1548
tass 68:0847e35d08a6 1549 pico_err = PICO_ERR_EINVAL;
tass 68:0847e35d08a6 1550
TASS Belgium NV 131:4758606c9316 1551 if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) {
TASS Belgium NV 131:4758606c9316 1552 return NULL;
TASS Belgium NV 131:4758606c9316 1553 }
tass 68:0847e35d08a6 1554
TASS Belgium NV 131:4758606c9316 1555 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1556 return NULL;
TASS Belgium NV 131:4758606c9316 1557 }
tass 68:0847e35d08a6 1558
TASS Belgium NV 131:4758606c9316 1559 if (TCPSTATE(s) == PICO_SOCKET_STATE_TCP_LISTEN) {
TASS Belgium NV 131:4758606c9316 1560 struct pico_sockport *sp = pico_get_sockport(PICO_PROTO_TCP, s->local_port);
TASS Belgium NV 131:4758606c9316 1561 struct pico_socket *found;
tass picotcp@tass.be 149:5f4cb161cec3 1562 uint32_t socklen = sizeof(struct pico_ip4);
TASS Belgium NV 131:4758606c9316 1563 /* If at this point no incoming connection socket is found,
TASS Belgium NV 131:4758606c9316 1564 * the accept call is valid, but no connection is established yet.
TASS Belgium NV 131:4758606c9316 1565 */
TASS Belgium NV 131:4758606c9316 1566 pico_err = PICO_ERR_EAGAIN;
TASS Belgium NV 131:4758606c9316 1567 if (sp) {
TASS Belgium NV 131:4758606c9316 1568 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 1569 /* RB_FOREACH(found, socket_tree, &sp->socks) { */
TASS Belgium NV 131:4758606c9316 1570 pico_tree_foreach(index, &sp->socks){
TASS Belgium NV 131:4758606c9316 1571 found = index->keyValue;
TASS Belgium NV 131:4758606c9316 1572 if ((s == found->parent) && ((found->state & PICO_SOCKET_STATE_TCP) == PICO_SOCKET_STATE_TCP_ESTABLISHED)) {
TASS Belgium NV 131:4758606c9316 1573 found->parent = NULL;
TASS Belgium NV 131:4758606c9316 1574 pico_err = PICO_ERR_NOERR;
tass picotcp@tass.be 149:5f4cb161cec3 1575 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 1576 if (is_sock_ipv6(s))
tass picotcp@tass.be 149:5f4cb161cec3 1577 socklen = sizeof(struct pico_ip6);
tass picotcp@tass.be 149:5f4cb161cec3 1578
tass picotcp@tass.be 149:5f4cb161cec3 1579 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1580 memcpy(orig, &found->remote_addr, socklen);
TASS Belgium NV 131:4758606c9316 1581 *port = found->remote_port;
TASS Belgium NV 131:4758606c9316 1582 s->number_of_pending_conn--;
TASS Belgium NV 131:4758606c9316 1583 return found;
TASS Belgium NV 131:4758606c9316 1584 }
TASS Belgium NV 131:4758606c9316 1585 }
tass 68:0847e35d08a6 1586 }
tass 68:0847e35d08a6 1587 }
TASS Belgium NV 131:4758606c9316 1588
TASS Belgium NV 131:4758606c9316 1589 return NULL;
tass 68:0847e35d08a6 1590 }
tass 68:0847e35d08a6 1591
tass 68:0847e35d08a6 1592 #else
tass 68:0847e35d08a6 1593
tass 68:0847e35d08a6 1594 int pico_socket_listen(struct pico_socket *s, int backlog)
tass 68:0847e35d08a6 1595 {
TASS Belgium NV 131:4758606c9316 1596 IGNORE_PARAMETER(s);
TASS Belgium NV 131:4758606c9316 1597 IGNORE_PARAMETER(backlog);
TASS Belgium NV 131:4758606c9316 1598 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1599 return -1;
tass 68:0847e35d08a6 1600 }
tass 68:0847e35d08a6 1601
tass 68:0847e35d08a6 1602 struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *local_port)
tass 68:0847e35d08a6 1603 {
TASS Belgium NV 131:4758606c9316 1604 IGNORE_PARAMETER(s);
TASS Belgium NV 131:4758606c9316 1605 IGNORE_PARAMETER(orig);
TASS Belgium NV 131:4758606c9316 1606 IGNORE_PARAMETER(local_port);
TASS Belgium NV 131:4758606c9316 1607 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1608 return NULL;
tass 68:0847e35d08a6 1609 }
tass 68:0847e35d08a6 1610
tass 68:0847e35d08a6 1611 #endif
tass 68:0847e35d08a6 1612
tass 68:0847e35d08a6 1613
tass picotcp@tass.be 149:5f4cb161cec3 1614 int pico_socket_setoption(struct pico_socket *s, int option, void *value)
tass 74:c146c4e346c4 1615 {
tass 74:c146c4e346c4 1616
tass picotcp@tass.be 149:5f4cb161cec3 1617 if (s == NULL) {
TASS Belgium NV 131:4758606c9316 1618 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 1619 return -1;
tass 74:c146c4e346c4 1620 }
TASS Belgium NV 131:4758606c9316 1621
TASS Belgium NV 131:4758606c9316 1622
tass picotcp@tass.be 149:5f4cb161cec3 1623 if (PROTO(s) == PICO_PROTO_TCP)
tass picotcp@tass.be 149:5f4cb161cec3 1624 return pico_setsockopt_tcp(s, option, value);
tass picotcp@tass.be 149:5f4cb161cec3 1625
tass picotcp@tass.be 149:5f4cb161cec3 1626 if (PROTO(s) == PICO_PROTO_UDP)
tass picotcp@tass.be 149:5f4cb161cec3 1627 return pico_setsockopt_udp(s, option, value);
tass 74:c146c4e346c4 1628
tass picotcp@tass.be 149:5f4cb161cec3 1629 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass picotcp@tass.be 149:5f4cb161cec3 1630 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1631 }
TASS Belgium NV 131:4758606c9316 1632
TASS Belgium NV 131:4758606c9316 1633
tass picotcp@tass.be 149:5f4cb161cec3 1634 int pico_socket_getoption(struct pico_socket *s, int option, void *value)
tass 68:0847e35d08a6 1635 {
TASS Belgium NV 131:4758606c9316 1636 if (s == NULL) {
TASS Belgium NV 131:4758606c9316 1637 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1638 return -1;
TASS Belgium NV 131:4758606c9316 1639 }
tass 68:0847e35d08a6 1640
tass 68:0847e35d08a6 1641
tass picotcp@tass.be 149:5f4cb161cec3 1642 if (PROTO(s) == PICO_PROTO_TCP)
tass picotcp@tass.be 149:5f4cb161cec3 1643 return pico_getsockopt_tcp(s, option, value);
TASS Belgium NV 131:4758606c9316 1644
tass picotcp@tass.be 149:5f4cb161cec3 1645 if (PROTO(s) == PICO_PROTO_UDP)
tass picotcp@tass.be 149:5f4cb161cec3 1646 return pico_getsockopt_udp(s, option, value);
TASS Belgium NV 131:4758606c9316 1647
tass picotcp@tass.be 149:5f4cb161cec3 1648 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass picotcp@tass.be 149:5f4cb161cec3 1649 return -1;
tass 68:0847e35d08a6 1650 }
tass 68:0847e35d08a6 1651
tass 68:0847e35d08a6 1652
tass 68:0847e35d08a6 1653 int pico_socket_shutdown(struct pico_socket *s, int mode)
tass 68:0847e35d08a6 1654 {
TASS Belgium NV 131:4758606c9316 1655 if (!s) {
TASS Belgium NV 131:4758606c9316 1656 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1657 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1658 }
tass picotcp@tass.be 149:5f4cb161cec3 1659
tass picotcp@tass.be 149:5f4cb161cec3 1660 /* Check if the socket has already been closed */
tass picotcp@tass.be 149:5f4cb161cec3 1661 if (s->state & PICO_SOCKET_STATE_CLOSED) {
tass picotcp@tass.be 149:5f4cb161cec3 1662 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 1663 return -1;
tass 68:0847e35d08a6 1664 }
tass 68:0847e35d08a6 1665
tass 68:0847e35d08a6 1666 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1667 if (PROTO(s) == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1668 if (mode & PICO_SHUT_RDWR)
TASS Belgium NV 131:4758606c9316 1669 pico_socket_alter_state(s, PICO_SOCKET_STATE_CLOSED, PICO_SOCKET_STATE_CLOSING | PICO_SOCKET_STATE_BOUND | PICO_SOCKET_STATE_CONNECTED, 0);
TASS Belgium NV 131:4758606c9316 1670 else if (mode & PICO_SHUT_RD)
TASS Belgium NV 131:4758606c9316 1671 pico_socket_alter_state(s, 0, PICO_SOCKET_STATE_BOUND, 0);
TASS Belgium NV 131:4758606c9316 1672 }
TASS Belgium NV 131:4758606c9316 1673
tass 68:0847e35d08a6 1674 #endif
tass 68:0847e35d08a6 1675 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 1676 if (PROTO(s) == PICO_PROTO_TCP) {
TASS Belgium NV 131:4758606c9316 1677 if(mode & PICO_SHUT_RDWR)
TASS Belgium NV 131:4758606c9316 1678 {
TASS Belgium NV 131:4758606c9316 1679 pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_LOCAL | PICO_SOCKET_STATE_SHUT_REMOTE, 0, 0);
TASS Belgium NV 131:4758606c9316 1680 pico_tcp_notify_closing(s);
TASS Belgium NV 131:4758606c9316 1681 }
TASS Belgium NV 131:4758606c9316 1682 else if (mode & PICO_SHUT_WR)
TASS Belgium NV 131:4758606c9316 1683 pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_LOCAL, 0, 0);
TASS Belgium NV 131:4758606c9316 1684 else if (mode & PICO_SHUT_RD)
TASS Belgium NV 131:4758606c9316 1685 pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_REMOTE, 0, 0);
tass 68:0847e35d08a6 1686
TASS Belgium NV 131:4758606c9316 1687 }
TASS Belgium NV 131:4758606c9316 1688
tass 68:0847e35d08a6 1689 #endif
TASS Belgium NV 131:4758606c9316 1690 return 0;
tass 68:0847e35d08a6 1691 }
tass 68:0847e35d08a6 1692
tass 68:0847e35d08a6 1693 int pico_socket_close(struct pico_socket *s)
tass 68:0847e35d08a6 1694 {
tass picotcp@tass.be 149:5f4cb161cec3 1695 if (!s)
tass picotcp@tass.be 149:5f4cb161cec3 1696 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1697 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 1698 if (PROTO(s) == PICO_PROTO_TCP) {
tass picotcp@tass.be 149:5f4cb161cec3 1699 if (pico_tcp_check_listen_close(s) == 0)
tass picotcp@tass.be 149:5f4cb161cec3 1700 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 1701 }
tass picotcp@tass.be 149:5f4cb161cec3 1702 #endif
TASS Belgium NV 131:4758606c9316 1703 return pico_socket_shutdown(s, PICO_SHUT_RDWR);
tass 68:0847e35d08a6 1704 }
tass 68:0847e35d08a6 1705
tass 68:0847e35d08a6 1706 #ifdef PICO_SUPPORT_CRC
tass 68:0847e35d08a6 1707 static inline int pico_transport_crc_check(struct pico_frame *f)
tass 68:0847e35d08a6 1708 {
TASS Belgium NV 131:4758606c9316 1709 struct pico_ipv4_hdr *net_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 1710 struct pico_udp_hdr *udp_hdr = NULL;
TASS Belgium NV 131:4758606c9316 1711 uint16_t checksum_invalid = 1;
tass 68:0847e35d08a6 1712
TASS Belgium NV 131:4758606c9316 1713 switch (net_hdr->proto)
TASS Belgium NV 131:4758606c9316 1714 {
tass 68:0847e35d08a6 1715 case PICO_PROTO_TCP:
tass picotcp@tass.be 149:5f4cb161cec3 1716 checksum_invalid = short_be(pico_tcp_checksum(f));
TASS Belgium NV 131:4758606c9316 1717 /* dbg("TCP CRC validation == %u\n", checksum_invalid); */
TASS Belgium NV 131:4758606c9316 1718 if (checksum_invalid) {
tass picotcp@tass.be 149:5f4cb161cec3 1719 dbg("TCP CRC: validation failed!\n");
TASS Belgium NV 131:4758606c9316 1720 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 1721 return 0;
TASS Belgium NV 131:4758606c9316 1722 }
TASS Belgium NV 131:4758606c9316 1723
TASS Belgium NV 131:4758606c9316 1724 break;
tass 68:0847e35d08a6 1725
tass 68:0847e35d08a6 1726 case PICO_PROTO_UDP:
TASS Belgium NV 131:4758606c9316 1727 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 1728 if (short_be(udp_hdr->crc)) {
tass picotcp@tass.be 149:5f4cb161cec3 1729 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 1730 if (IS_IPV4(f))
tass picotcp@tass.be 149:5f4cb161cec3 1731 checksum_invalid = short_be(pico_udp_checksum_ipv4(f));
tass picotcp@tass.be 149:5f4cb161cec3 1732
tass picotcp@tass.be 149:5f4cb161cec3 1733 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1734 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 1735 if (IS_IPV6(f))
tass picotcp@tass.be 149:5f4cb161cec3 1736 checksum_invalid = short_be(pico_udp_checksum_ipv6(f));
tass picotcp@tass.be 149:5f4cb161cec3 1737
tass picotcp@tass.be 149:5f4cb161cec3 1738 #endif
TASS Belgium NV 131:4758606c9316 1739 /* dbg("UDP CRC validation == %u\n", checksum_invalid); */
TASS Belgium NV 131:4758606c9316 1740 if (checksum_invalid) {
TASS Belgium NV 131:4758606c9316 1741 /* dbg("UDP CRC: validation failed!\n"); */
TASS Belgium NV 131:4758606c9316 1742 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 1743 return 0;
TASS Belgium NV 131:4758606c9316 1744 }
tass 68:0847e35d08a6 1745 }
TASS Belgium NV 131:4758606c9316 1746
TASS Belgium NV 131:4758606c9316 1747 break;
tass 68:0847e35d08a6 1748
tass 68:0847e35d08a6 1749 default:
TASS Belgium NV 131:4758606c9316 1750 /* Do nothing */
TASS Belgium NV 131:4758606c9316 1751 break;
TASS Belgium NV 131:4758606c9316 1752 }
TASS Belgium NV 131:4758606c9316 1753 return 1;
tass 68:0847e35d08a6 1754 }
tass 68:0847e35d08a6 1755 #else
tass 68:0847e35d08a6 1756 static inline int pico_transport_crc_check(struct pico_frame *f)
tass 68:0847e35d08a6 1757 {
TASS Belgium NV 131:4758606c9316 1758 IGNORE_PARAMETER(f);
TASS Belgium NV 131:4758606c9316 1759 return 1;
tass 68:0847e35d08a6 1760 }
tass 68:0847e35d08a6 1761 #endif /* PICO_SUPPORT_CRC */
tass 68:0847e35d08a6 1762
tass 68:0847e35d08a6 1763 int pico_transport_process_in(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 1764 {
TASS Belgium NV 131:4758606c9316 1765 struct pico_trans *hdr = (struct pico_trans *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 1766 int ret = 0;
tass 68:0847e35d08a6 1767
TASS Belgium NV 131:4758606c9316 1768 if (!hdr) {
TASS Belgium NV 131:4758606c9316 1769 pico_err = PICO_ERR_EFAULT;
TASS Belgium NV 131:4758606c9316 1770 return -1;
TASS Belgium NV 131:4758606c9316 1771 }
tass 68:0847e35d08a6 1772
TASS Belgium NV 131:4758606c9316 1773 ret = pico_transport_crc_check(f);
TASS Belgium NV 131:4758606c9316 1774 if (ret < 1)
TASS Belgium NV 131:4758606c9316 1775 return ret;
TASS Belgium NV 131:4758606c9316 1776 else
TASS Belgium NV 131:4758606c9316 1777 ret = 0;
tass 68:0847e35d08a6 1778
TASS Belgium NV 131:4758606c9316 1779 if ((hdr) && (pico_socket_deliver(self, f, hdr->dport) == 0))
TASS Belgium NV 131:4758606c9316 1780 return ret;
tass 68:0847e35d08a6 1781
TASS Belgium NV 131:4758606c9316 1782 if (!IS_BCAST(f)) {
TASS Belgium NV 131:4758606c9316 1783 dbg("Socket not found... \n");
TASS Belgium NV 131:4758606c9316 1784 pico_notify_socket_unreachable(f);
TASS Belgium NV 131:4758606c9316 1785 ret = -1;
TASS Belgium NV 131:4758606c9316 1786 pico_err = PICO_ERR_ENOENT;
TASS Belgium NV 131:4758606c9316 1787 }
TASS Belgium NV 131:4758606c9316 1788
TASS Belgium NV 131:4758606c9316 1789 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 1790 return ret;
tass 68:0847e35d08a6 1791 }
tass 68:0847e35d08a6 1792
tass 68:0847e35d08a6 1793 #define SL_LOOP_MIN 1
tass 68:0847e35d08a6 1794
tass 125:96003ae6f1d8 1795 #ifdef PICO_SUPPORT_TCP
tass 95:f4ca916a26fe 1796 static int checkSocketSanity(struct pico_socket *s)
tass 95:f4ca916a26fe 1797 {
tass 95:f4ca916a26fe 1798
tass picotcp@tass.be 149:5f4cb161cec3 1799 /* checking for pending connections */
tass picotcp@tass.be 133:5b075f5e141a 1800 if(TCP_STATE(s) == PICO_SOCKET_STATE_TCP_SYN_RECV) {
tass picotcp@tass.be 149:5f4cb161cec3 1801 if((PICO_TIME_MS() - s->timestamp) >= PICO_SOCKET_BOUND_TIMEOUT)
TASS Belgium NV 131:4758606c9316 1802 return -1;
tass picotcp@tass.be 133:5b075f5e141a 1803 }
TASS Belgium NV 131:4758606c9316 1804
tass picotcp@tass.be 149:5f4cb161cec3 1805 if((PICO_TIME_MS() - s->timestamp) >= PICO_SOCKET_TIMEOUT) {
TASS Belgium NV 131:4758606c9316 1806 /* checking for hanging sockets */
TASS Belgium NV 131:4758606c9316 1807 if((TCP_STATE(s) != PICO_SOCKET_STATE_TCP_LISTEN) && (TCP_STATE(s) != PICO_SOCKET_STATE_TCP_ESTABLISHED))
TASS Belgium NV 131:4758606c9316 1808 return -1;
TASS Belgium NV 131:4758606c9316 1809 }
TASS Belgium NV 131:4758606c9316 1810
TASS Belgium NV 131:4758606c9316 1811 return 0;
tass 95:f4ca916a26fe 1812 }
tass 125:96003ae6f1d8 1813 #endif
tass 95:f4ca916a26fe 1814
tass picotcp@tass.be 149:5f4cb161cec3 1815
tass picotcp@tass.be 149:5f4cb161cec3 1816 static int pico_sockets_loop_udp(int loop_score)
tass 68:0847e35d08a6 1817 {
tass picotcp@tass.be 149:5f4cb161cec3 1818
tass 125:96003ae6f1d8 1819 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1820 static struct pico_tree_node *index_udp;
TASS Belgium NV 131:4758606c9316 1821 struct pico_sockport *start;
TASS Belgium NV 131:4758606c9316 1822 struct pico_socket *s;
TASS Belgium NV 131:4758606c9316 1823 struct pico_frame *f;
tass 68:0847e35d08a6 1824
tass 68:0847e35d08a6 1825 if (sp_udp == NULL)
tass 68:0847e35d08a6 1826 {
TASS Belgium NV 131:4758606c9316 1827 index_udp = pico_tree_firstNode(UDPTable.root);
TASS Belgium NV 131:4758606c9316 1828 sp_udp = index_udp->keyValue;
tass 68:0847e35d08a6 1829 }
TASS Belgium NV 131:4758606c9316 1830
TASS Belgium NV 131:4758606c9316 1831 /* init start node */
TASS Belgium NV 131:4758606c9316 1832 start = sp_udp;
TASS Belgium NV 131:4758606c9316 1833
TASS Belgium NV 131:4758606c9316 1834 /* round-robin all transport protocols, break if traversed all protocols */
TASS Belgium NV 131:4758606c9316 1835 while (loop_score > SL_LOOP_MIN && sp_udp != NULL) {
TASS Belgium NV 131:4758606c9316 1836 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 1837
TASS Belgium NV 131:4758606c9316 1838 pico_tree_foreach(index, &sp_udp->socks){
TASS Belgium NV 131:4758606c9316 1839 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 1840 f = pico_dequeue(&s->q_out);
TASS Belgium NV 131:4758606c9316 1841 while (f && (loop_score > 0)) {
TASS Belgium NV 131:4758606c9316 1842 pico_proto_udp.push(&pico_proto_udp, f);
TASS Belgium NV 131:4758606c9316 1843 loop_score -= 1;
TASS Belgium NV 131:4758606c9316 1844 f = pico_dequeue(&s->q_out);
TASS Belgium NV 131:4758606c9316 1845 }
TASS Belgium NV 131:4758606c9316 1846 }
TASS Belgium NV 131:4758606c9316 1847
TASS Belgium NV 131:4758606c9316 1848 index_udp = pico_tree_next(index_udp);
TASS Belgium NV 131:4758606c9316 1849 sp_udp = index_udp->keyValue;
TASS Belgium NV 131:4758606c9316 1850
TASS Belgium NV 131:4758606c9316 1851 if (sp_udp == NULL)
TASS Belgium NV 131:4758606c9316 1852 {
TASS Belgium NV 131:4758606c9316 1853 index_udp = pico_tree_firstNode(UDPTable.root);
TASS Belgium NV 131:4758606c9316 1854 sp_udp = index_udp->keyValue;
TASS Belgium NV 131:4758606c9316 1855 }
TASS Belgium NV 131:4758606c9316 1856
TASS Belgium NV 131:4758606c9316 1857 if (sp_udp == start)
TASS Belgium NV 131:4758606c9316 1858 break;
TASS Belgium NV 131:4758606c9316 1859 }
tass 68:0847e35d08a6 1860 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1861 return loop_score;
tass picotcp@tass.be 149:5f4cb161cec3 1862 }
tass 68:0847e35d08a6 1863
tass picotcp@tass.be 149:5f4cb161cec3 1864 static int pico_sockets_loop_tcp(int loop_score)
tass picotcp@tass.be 149:5f4cb161cec3 1865 {
tass 68:0847e35d08a6 1866 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 1867 struct pico_sockport *start;
tass picotcp@tass.be 149:5f4cb161cec3 1868 struct pico_socket *s;
tass picotcp@tass.be 149:5f4cb161cec3 1869 static struct pico_tree_node *index_tcp;
TASS Belgium NV 131:4758606c9316 1870 if (sp_tcp == NULL)
TASS Belgium NV 131:4758606c9316 1871 {
TASS Belgium NV 131:4758606c9316 1872 index_tcp = pico_tree_firstNode(TCPTable.root);
TASS Belgium NV 131:4758606c9316 1873 sp_tcp = index_tcp->keyValue;
tass 95:f4ca916a26fe 1874 }
tass 68:0847e35d08a6 1875
TASS Belgium NV 131:4758606c9316 1876 /* init start node */
TASS Belgium NV 131:4758606c9316 1877 start = sp_tcp;
tass 68:0847e35d08a6 1878
TASS Belgium NV 131:4758606c9316 1879 while (loop_score > SL_LOOP_MIN && sp_tcp != NULL) {
TASS Belgium NV 131:4758606c9316 1880 struct pico_tree_node *index = NULL, *safe_index = NULL;
TASS Belgium NV 131:4758606c9316 1881 pico_tree_foreach_safe(index, &sp_tcp->socks, safe_index){
TASS Belgium NV 131:4758606c9316 1882 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 1883 loop_score = pico_tcp_output(s, loop_score);
TASS Belgium NV 131:4758606c9316 1884 if ((s->ev_pending) && s->wakeup) {
TASS Belgium NV 131:4758606c9316 1885 s->wakeup(s->ev_pending, s);
TASS Belgium NV 131:4758606c9316 1886 if(!s->parent)
TASS Belgium NV 131:4758606c9316 1887 s->ev_pending = 0;
TASS Belgium NV 131:4758606c9316 1888 }
TASS Belgium NV 131:4758606c9316 1889
TASS Belgium NV 131:4758606c9316 1890 if (loop_score <= 0) {
TASS Belgium NV 131:4758606c9316 1891 loop_score = 0;
TASS Belgium NV 131:4758606c9316 1892 break;
TASS Belgium NV 131:4758606c9316 1893 }
tass 68:0847e35d08a6 1894
TASS Belgium NV 131:4758606c9316 1895 if(checkSocketSanity(s) < 0)
TASS Belgium NV 131:4758606c9316 1896 {
TASS Belgium NV 131:4758606c9316 1897 pico_socket_del(s);
TASS Belgium NV 131:4758606c9316 1898 index_tcp = NULL; /* forcing the restart of loop */
TASS Belgium NV 131:4758606c9316 1899 sp_tcp = NULL;
TASS Belgium NV 131:4758606c9316 1900 break;
TASS Belgium NV 131:4758606c9316 1901 }
TASS Belgium NV 131:4758606c9316 1902 }
TASS Belgium NV 131:4758606c9316 1903
TASS Belgium NV 131:4758606c9316 1904 /* check if RB_FOREACH ended, if not, break to keep the cur sp_tcp */
TASS Belgium NV 131:4758606c9316 1905 if (!index_tcp || (index && index->keyValue))
TASS Belgium NV 131:4758606c9316 1906 break;
TASS Belgium NV 131:4758606c9316 1907
TASS Belgium NV 131:4758606c9316 1908 index_tcp = pico_tree_next(index_tcp);
TASS Belgium NV 131:4758606c9316 1909 sp_tcp = index_tcp->keyValue;
TASS Belgium NV 131:4758606c9316 1910
TASS Belgium NV 131:4758606c9316 1911 if (sp_tcp == NULL)
TASS Belgium NV 131:4758606c9316 1912 {
TASS Belgium NV 131:4758606c9316 1913 index_tcp = pico_tree_firstNode(TCPTable.root);
TASS Belgium NV 131:4758606c9316 1914 sp_tcp = index_tcp->keyValue;
TASS Belgium NV 131:4758606c9316 1915 }
TASS Belgium NV 131:4758606c9316 1916
TASS Belgium NV 131:4758606c9316 1917 if (sp_tcp == start)
TASS Belgium NV 131:4758606c9316 1918 break;
tass 68:0847e35d08a6 1919 }
tass 68:0847e35d08a6 1920 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1921 return loop_score;
tass 68:0847e35d08a6 1922
tass picotcp@tass.be 149:5f4cb161cec3 1923
tass picotcp@tass.be 149:5f4cb161cec3 1924 }
tass picotcp@tass.be 149:5f4cb161cec3 1925
tass picotcp@tass.be 149:5f4cb161cec3 1926 int pico_sockets_loop(int loop_score)
tass picotcp@tass.be 149:5f4cb161cec3 1927 {
tass picotcp@tass.be 149:5f4cb161cec3 1928 loop_score = pico_sockets_loop_udp(loop_score);
tass picotcp@tass.be 149:5f4cb161cec3 1929 loop_score = pico_sockets_loop_tcp(loop_score);
TASS Belgium NV 131:4758606c9316 1930 return loop_score;
tass 68:0847e35d08a6 1931 }
tass 68:0847e35d08a6 1932
tass 68:0847e35d08a6 1933
tass 70:cd218dd180e5 1934 struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, uint16_t len)
tass 68:0847e35d08a6 1935 {
TASS Belgium NV 131:4758606c9316 1936 struct pico_frame *f = NULL;
tass 68:0847e35d08a6 1937
tass 68:0847e35d08a6 1938 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 1939 if (is_sock_ipv6(s))
TASS Belgium NV 131:4758606c9316 1940 f = pico_proto_ipv6.alloc(&pico_proto_ipv6, len);
TASS Belgium NV 131:4758606c9316 1941
tass 68:0847e35d08a6 1942 #endif
tass 68:0847e35d08a6 1943
tass 68:0847e35d08a6 1944 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 1945 if (is_sock_ipv4(s))
tass picotcp@tass.be 149:5f4cb161cec3 1946 f = pico_proto_ipv4.alloc(&pico_proto_ipv4, len);
TASS Belgium NV 131:4758606c9316 1947
tass 68:0847e35d08a6 1948 #endif
TASS Belgium NV 131:4758606c9316 1949 if (!f) {
TASS Belgium NV 131:4758606c9316 1950 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1951 return f;
TASS Belgium NV 131:4758606c9316 1952 }
TASS Belgium NV 131:4758606c9316 1953
TASS Belgium NV 131:4758606c9316 1954 f->payload = f->transport_hdr;
TASS Belgium NV 131:4758606c9316 1955 f->payload_len = len;
TASS Belgium NV 131:4758606c9316 1956 f->sock = s;
tass 68:0847e35d08a6 1957 return f;
tass 68:0847e35d08a6 1958 }
tass 68:0847e35d08a6 1959
tass picotcp@tass.be 149:5f4cb161cec3 1960 static void pico_transport_error_set_picoerr(int code)
tass picotcp@tass.be 149:5f4cb161cec3 1961 {
tass picotcp@tass.be 149:5f4cb161cec3 1962 /* dbg("SOCKET ERROR FROM ICMP NOTIFICATION. (icmp code= %d)\n\n", code); */
tass picotcp@tass.be 149:5f4cb161cec3 1963 switch(code) {
tass picotcp@tass.be 149:5f4cb161cec3 1964 case PICO_ICMP_UNREACH_NET:
tass picotcp@tass.be 149:5f4cb161cec3 1965 pico_err = PICO_ERR_ENETUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 1966 break;
tass picotcp@tass.be 149:5f4cb161cec3 1967
tass picotcp@tass.be 149:5f4cb161cec3 1968 case PICO_ICMP_UNREACH_HOST:
tass picotcp@tass.be 149:5f4cb161cec3 1969 pico_err = PICO_ERR_EHOSTUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 1970 break;
tass picotcp@tass.be 149:5f4cb161cec3 1971
tass picotcp@tass.be 149:5f4cb161cec3 1972 case PICO_ICMP_UNREACH_PROTOCOL:
tass picotcp@tass.be 149:5f4cb161cec3 1973 pico_err = PICO_ERR_ENOPROTOOPT;
tass picotcp@tass.be 149:5f4cb161cec3 1974 break;
tass picotcp@tass.be 149:5f4cb161cec3 1975
tass picotcp@tass.be 149:5f4cb161cec3 1976 case PICO_ICMP_UNREACH_PORT:
tass picotcp@tass.be 149:5f4cb161cec3 1977 pico_err = PICO_ERR_ECONNREFUSED;
tass picotcp@tass.be 149:5f4cb161cec3 1978 break;
tass picotcp@tass.be 149:5f4cb161cec3 1979
tass picotcp@tass.be 149:5f4cb161cec3 1980 case PICO_ICMP_UNREACH_NET_UNKNOWN:
tass picotcp@tass.be 149:5f4cb161cec3 1981 pico_err = PICO_ERR_ENETUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 1982 break;
tass picotcp@tass.be 149:5f4cb161cec3 1983
tass picotcp@tass.be 149:5f4cb161cec3 1984 case PICO_ICMP_UNREACH_HOST_UNKNOWN:
tass picotcp@tass.be 149:5f4cb161cec3 1985 pico_err = PICO_ERR_EHOSTDOWN;
tass picotcp@tass.be 149:5f4cb161cec3 1986 break;
tass picotcp@tass.be 149:5f4cb161cec3 1987
tass picotcp@tass.be 149:5f4cb161cec3 1988 case PICO_ICMP_UNREACH_ISOLATED:
tass picotcp@tass.be 149:5f4cb161cec3 1989 pico_err = PICO_ERR_ENONET;
tass picotcp@tass.be 149:5f4cb161cec3 1990 break;
tass picotcp@tass.be 149:5f4cb161cec3 1991
tass picotcp@tass.be 149:5f4cb161cec3 1992 case PICO_ICMP_UNREACH_NET_PROHIB:
tass picotcp@tass.be 149:5f4cb161cec3 1993 case PICO_ICMP_UNREACH_HOST_PROHIB:
tass picotcp@tass.be 149:5f4cb161cec3 1994 pico_err = PICO_ERR_EHOSTUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 1995 break;
tass picotcp@tass.be 149:5f4cb161cec3 1996
tass picotcp@tass.be 149:5f4cb161cec3 1997 default:
tass picotcp@tass.be 149:5f4cb161cec3 1998 pico_err = PICO_ERR_EOPNOTSUPP;
tass picotcp@tass.be 149:5f4cb161cec3 1999 }
tass picotcp@tass.be 149:5f4cb161cec3 2000 }
tass picotcp@tass.be 149:5f4cb161cec3 2001
tass 68:0847e35d08a6 2002 int pico_transport_error(struct pico_frame *f, uint8_t proto, int code)
tass 68:0847e35d08a6 2003 {
TASS Belgium NV 131:4758606c9316 2004 int ret = -1;
TASS Belgium NV 131:4758606c9316 2005 struct pico_trans *trans = (struct pico_trans*) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 2006 struct pico_sockport *port = NULL;
TASS Belgium NV 131:4758606c9316 2007 struct pico_socket *s = NULL;
TASS Belgium NV 131:4758606c9316 2008 switch (proto) {
tass 68:0847e35d08a6 2009
tass 68:0847e35d08a6 2010
tass 68:0847e35d08a6 2011 #ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 2012 case PICO_PROTO_UDP:
TASS Belgium NV 131:4758606c9316 2013 port = pico_get_sockport(proto, trans->sport);
TASS Belgium NV 131:4758606c9316 2014 break;
tass 68:0847e35d08a6 2015 #endif
tass 68:0847e35d08a6 2016
tass 68:0847e35d08a6 2017 #ifdef PICO_SUPPORT_TCP
TASS Belgium NV 131:4758606c9316 2018 case PICO_PROTO_TCP:
TASS Belgium NV 131:4758606c9316 2019 port = pico_get_sockport(proto, trans->sport);
TASS Belgium NV 131:4758606c9316 2020 break;
tass 68:0847e35d08a6 2021 #endif
tass 68:0847e35d08a6 2022
TASS Belgium NV 131:4758606c9316 2023 default:
TASS Belgium NV 131:4758606c9316 2024 /* Protocol not available */
TASS Belgium NV 131:4758606c9316 2025 ret = -1;
TASS Belgium NV 131:4758606c9316 2026 }
TASS Belgium NV 131:4758606c9316 2027 if (port) {
TASS Belgium NV 131:4758606c9316 2028 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 2029 ret = 0;
tass 68:0847e35d08a6 2030
TASS Belgium NV 131:4758606c9316 2031 pico_tree_foreach(index, &port->socks) {
TASS Belgium NV 131:4758606c9316 2032 s = index->keyValue;
TASS Belgium NV 131:4758606c9316 2033 if (trans->dport == s->remote_port) {
TASS Belgium NV 131:4758606c9316 2034 if (s->wakeup) {
tass picotcp@tass.be 149:5f4cb161cec3 2035 pico_transport_error_set_picoerr(code);
TASS Belgium NV 131:4758606c9316 2036 s->state |= PICO_SOCKET_STATE_SHUT_REMOTE;
TASS Belgium NV 131:4758606c9316 2037 s->wakeup(PICO_SOCK_EV_ERR, s);
TASS Belgium NV 131:4758606c9316 2038 }
TASS Belgium NV 131:4758606c9316 2039
TASS Belgium NV 131:4758606c9316 2040 break;
TASS Belgium NV 131:4758606c9316 2041 }
tass 68:0847e35d08a6 2042 }
tass 68:0847e35d08a6 2043 }
TASS Belgium NV 131:4758606c9316 2044
TASS Belgium NV 131:4758606c9316 2045 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 2046 return ret;
tass 68:0847e35d08a6 2047 }
tass 68:0847e35d08a6 2048 #endif
tass 68:0847e35d08a6 2049 #endif