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 RTOSgeneric mbed Ethernet driverhigh performance NXP LPC1768 specific Ethernet driverMulti-threading support for mbed RTOSBerkeley sockets and integration with the New Socket APIFork of the apps running on top of the New Socket APIScheduling 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.
stack/pico_socket.c@155:a70f34550c34, 2016-01-28 (annotated)
- 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?
User | Revision | Line number | New 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 |