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
Date:
Thu Jan 28 15:12:00 2016 +0100
Revision:
155:a70f34550c34
Parent:
152:a3d286bf94e5
Adding TCP flag for FIN.

Who changed what in which revision?

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