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@134:cc4e6d2654d9, 2014-01-16 (annotated)
- Committer:
- tass picotcp@tass.be
- Date:
- Thu Jan 16 14:46:07 2014 +0100
- Revision:
- 134:cc4e6d2654d9
- Parent:
- 133:5b075f5e141a
- Child:
- 137:a1c8bfa9d691
Update from masterbranch
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tass | 68:0847e35d08a6 | 1 | /********************************************************************* |
TASS Belgium NV |
131:4758606c9316 | 2 | PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. |
TASS Belgium NV |
131:4758606c9316 | 3 | See LICENSE and COPYING for usage. |
tass | 68:0847e35d08a6 | 4 | |
tass | 68:0847e35d08a6 | 5 | |
TASS Belgium NV |
131:4758606c9316 | 6 | Authors: Daniele Lacamera |
TASS Belgium NV |
131:4758606c9316 | 7 | *********************************************************************/ |
tass | 68:0847e35d08a6 | 8 | |
tass | 68:0847e35d08a6 | 9 | |
tass | 68:0847e35d08a6 | 10 | #include "pico_config.h" |
tass | 68:0847e35d08a6 | 11 | #include "pico_queue.h" |
tass | 68:0847e35d08a6 | 12 | #include "pico_socket.h" |
tass | 68:0847e35d08a6 | 13 | #include "pico_ipv4.h" |
tass | 68:0847e35d08a6 | 14 | #include "pico_ipv6.h" |
tass | 68:0847e35d08a6 | 15 | #include "pico_udp.h" |
tass | 68:0847e35d08a6 | 16 | #include "pico_tcp.h" |
tass | 68:0847e35d08a6 | 17 | #include "pico_stack.h" |
tass | 68:0847e35d08a6 | 18 | #include "pico_icmp4.h" |
tass | 68:0847e35d08a6 | 19 | #include "pico_nat.h" |
tass | 68:0847e35d08a6 | 20 | #include "pico_tree.h" |
tass | 68:0847e35d08a6 | 21 | #include "pico_device.h" |
tass | 68:0847e35d08a6 | 22 | |
tass | 68:0847e35d08a6 | 23 | #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6) |
tass | 68:0847e35d08a6 | 24 | #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP) |
tass | 68:0847e35d08a6 | 25 | |
tass | 110:0ece1bbbd36e | 26 | #define UDP_FRAME_OVERHEAD (sizeof(struct pico_frame)) |
tass | 68:0847e35d08a6 | 27 | |
tass | 68:0847e35d08a6 | 28 | #define PROTO(s) ((s)->proto->proto_number) |
tass | 68:0847e35d08a6 | 29 | #define PICO_SOCKET4_MTU 1480 /* Ethernet MTU(1500) - IP header size(20) */ |
tass | 68:0847e35d08a6 | 30 | #define PICO_SOCKET6_MTU 1460 /* Ethernet MTU(1500) - IP header size(40) */ |
tass | 68:0847e35d08a6 | 31 | #define TCP_STATE(s) (s->state & PICO_SOCKET_STATE_TCP) |
tass | 68:0847e35d08a6 | 32 | |
tass | 68:0847e35d08a6 | 33 | #ifdef PICO_SUPPORT_MUTEX |
TASS Belgium NV |
131:4758606c9316 | 34 | static void *Mutex = NULL; |
TASS Belgium NV |
131:4758606c9316 | 35 | #define LOCK(x) { \ |
TASS Belgium NV |
131:4758606c9316 | 36 | if (x == NULL) \ |
TASS Belgium NV |
131:4758606c9316 | 37 | x = pico_mutex_init(); \ |
TASS Belgium NV |
131:4758606c9316 | 38 | pico_mutex_lock(x); \ |
tass | 68:0847e35d08a6 | 39 | } |
TASS Belgium NV |
131:4758606c9316 | 40 | #define UNLOCK(x) pico_mutex_unlock(x) |
tass | 68:0847e35d08a6 | 41 | |
tass | 68:0847e35d08a6 | 42 | #else |
TASS Belgium NV |
131:4758606c9316 | 43 | #define LOCK(x) do {} while(0) |
TASS Belgium NV |
131:4758606c9316 | 44 | #define UNLOCK(x) do {} while(0) |
tass | 68:0847e35d08a6 | 45 | #endif |
tass | 68:0847e35d08a6 | 46 | |
tass | 68:0847e35d08a6 | 47 | |
tass | 68:0847e35d08a6 | 48 | #define PROTO(s) ((s)->proto->proto_number) |
tass | 68:0847e35d08a6 | 49 | |
tass | 68:0847e35d08a6 | 50 | #ifdef PICO_SUPPORT_TCP |
tass | 68:0847e35d08a6 | 51 | # define IS_NAGLE_ENABLED(s) (!(!(!(s->opt_flags & (1 << PICO_SOCKET_OPT_TCPNODELAY))))) |
tass | 68:0847e35d08a6 | 52 | #endif |
tass | 68:0847e35d08a6 | 53 | |
tass | 68:0847e35d08a6 | 54 | #define PICO_SOCKET_MTU 1480 /* Ethernet MTU(1500) - IP header size(20) */ |
tass | 68:0847e35d08a6 | 55 | |
tass | 68:0847e35d08a6 | 56 | #ifdef PICO_SUPPORT_IPV4 |
tass | 68:0847e35d08a6 | 57 | # define IS_SOCK_IPV4(s) ((s->net == &pico_proto_ipv4)) |
tass | 68:0847e35d08a6 | 58 | #else |
tass | 68:0847e35d08a6 | 59 | # define IS_SOCK_IPV4(s) (0) |
tass | 68:0847e35d08a6 | 60 | #endif |
tass | 68:0847e35d08a6 | 61 | |
tass | 68:0847e35d08a6 | 62 | #ifdef PICO_SUPPORT_IPV6 |
tass | 68:0847e35d08a6 | 63 | # define IS_SOCK_IPV6(s) ((s->net == &pico_proto_ipv6)) |
tass | 68:0847e35d08a6 | 64 | #else |
tass | 68:0847e35d08a6 | 65 | # define IS_SOCK_IPV6(s) (0) |
tass | 68:0847e35d08a6 | 66 | #endif |
tass | 68:0847e35d08a6 | 67 | |
tass | 68:0847e35d08a6 | 68 | #ifdef PICO_SUPPORT_IPFRAG |
TASS Belgium NV |
131:4758606c9316 | 69 | # define frag_dbg(...) do {} while(0) |
tass | 68:0847e35d08a6 | 70 | #endif |
tass | 68:0847e35d08a6 | 71 | |
TASS Belgium NV |
131:4758606c9316 | 72 | #ifdef PICO_SUPPORT_MCAST |
TASS Belgium NV |
131:4758606c9316 | 73 | # define so_mcast_dbg(...) do {} while(0) /* ip_mcast_dbg in pico_ipv4.c */ |
tass | 68:0847e35d08a6 | 74 | #endif |
tass | 68:0847e35d08a6 | 75 | |
TASS Belgium NV |
131:4758606c9316 | 76 | static struct pico_sockport *sp_udp = NULL, *sp_tcp = NULL; |
tass | 68:0847e35d08a6 | 77 | |
tass | 70:cd218dd180e5 | 78 | struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, uint16_t len); |
tass | 68:0847e35d08a6 | 79 | |
TASS Belgium NV |
131:4758606c9316 | 80 | static int32_t socket_cmp(void *ka, void *kb) |
tass | 68:0847e35d08a6 | 81 | { |
TASS Belgium NV |
131:4758606c9316 | 82 | struct pico_socket *a = ka, *b = kb; |
TASS Belgium NV |
131:4758606c9316 | 83 | uint32_t a_is_ip6 = is_sock_ipv6(a); |
TASS Belgium NV |
131:4758606c9316 | 84 | uint32_t b_is_ip6 = is_sock_ipv6(b); |
tass | 68:0847e35d08a6 | 85 | |
TASS Belgium NV |
131:4758606c9316 | 86 | int32_t diff; |
tass | 68:0847e35d08a6 | 87 | |
TASS Belgium NV |
131:4758606c9316 | 88 | /* First, order by network ver */ |
TASS Belgium NV |
131:4758606c9316 | 89 | if (a_is_ip6 < b_is_ip6) |
TASS Belgium NV |
131:4758606c9316 | 90 | return -1; |
tass | 68:0847e35d08a6 | 91 | |
TASS Belgium NV |
131:4758606c9316 | 92 | if (a_is_ip6 > b_is_ip6) |
TASS Belgium NV |
131:4758606c9316 | 93 | return 1; |
tass | 68:0847e35d08a6 | 94 | |
TASS Belgium NV |
131:4758606c9316 | 95 | /* If either socket is PICO_IPV4_INADDR_ANY mode, skip local address comparison */ |
TASS Belgium NV |
131:4758606c9316 | 96 | |
TASS Belgium NV |
131:4758606c9316 | 97 | /* At this point, sort by local host */ |
tass | 68:0847e35d08a6 | 98 | |
TASS Belgium NV |
131:4758606c9316 | 99 | if (0) { |
tass | 68:0847e35d08a6 | 100 | #ifdef PICO_SUPPORT_IPV6 |
TASS Belgium NV |
131:4758606c9316 | 101 | } else if (a_is_ip6) { |
TASS Belgium NV |
131:4758606c9316 | 102 | 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 Belgium NV |
131:4758606c9316 | 103 | diff = 0; |
TASS Belgium NV |
131:4758606c9316 | 104 | else |
TASS Belgium NV |
131:4758606c9316 | 105 | diff = memcmp(a->local_addr.ip6.addr, b->local_addr.ip6.addr, PICO_SIZE_IP6); |
TASS Belgium NV |
131:4758606c9316 | 106 | |
tass | 68:0847e35d08a6 | 107 | #endif |
TASS Belgium NV |
131:4758606c9316 | 108 | } else { |
TASS Belgium NV |
131:4758606c9316 | 109 | if ((a->local_addr.ip4.addr == PICO_IP4_ANY) || (b->local_addr.ip4.addr == PICO_IP4_ANY)) |
TASS Belgium NV |
131:4758606c9316 | 110 | diff = 0; |
TASS Belgium NV |
131:4758606c9316 | 111 | else |
TASS Belgium NV |
131:4758606c9316 | 112 | diff = (int32_t)(a->local_addr.ip4.addr - b->local_addr.ip4.addr); |
TASS Belgium NV |
131:4758606c9316 | 113 | } |
tass | 68:0847e35d08a6 | 114 | |
TASS Belgium NV |
131:4758606c9316 | 115 | if (diff) |
TASS Belgium NV |
131:4758606c9316 | 116 | return diff; |
tass | 68:0847e35d08a6 | 117 | |
tass | 68:0847e35d08a6 | 118 | |
TASS Belgium NV |
131:4758606c9316 | 119 | /* Sort by remote host */ |
TASS Belgium NV |
131:4758606c9316 | 120 | if (a_is_ip6) |
TASS Belgium NV |
131:4758606c9316 | 121 | diff = memcmp(a->remote_addr.ip6.addr, b->remote_addr.ip6.addr, PICO_SIZE_IP6); |
TASS Belgium NV |
131:4758606c9316 | 122 | else |
TASS Belgium NV |
131:4758606c9316 | 123 | diff = (int32_t)(a->remote_addr.ip4.addr - b->remote_addr.ip4.addr); |
tass | 68:0847e35d08a6 | 124 | |
TASS Belgium NV |
131:4758606c9316 | 125 | if (diff) |
TASS Belgium NV |
131:4758606c9316 | 126 | return diff; |
tass | 68:0847e35d08a6 | 127 | |
TASS Belgium NV |
131:4758606c9316 | 128 | /* And finally by remote port. The two sockets are coincident if the quad is the same. */ |
TASS Belgium NV |
131:4758606c9316 | 129 | return b->remote_port - a->remote_port; |
tass | 68:0847e35d08a6 | 130 | } |
tass | 68:0847e35d08a6 | 131 | |
tass | 68:0847e35d08a6 | 132 | struct pico_sockport |
tass | 68:0847e35d08a6 | 133 | { |
TASS Belgium NV |
131:4758606c9316 | 134 | struct pico_tree socks; /* how you make the connection ? */ |
TASS Belgium NV |
131:4758606c9316 | 135 | uint16_t number; |
TASS Belgium NV |
131:4758606c9316 | 136 | uint16_t proto; |
tass | 68:0847e35d08a6 | 137 | }; |
tass | 68:0847e35d08a6 | 138 | |
TASS Belgium NV |
131:4758606c9316 | 139 | #define INIT_SOCKPORT { {&LEAF, socket_cmp}, 0, 0 } |
tass | 68:0847e35d08a6 | 140 | |
TASS Belgium NV |
131:4758606c9316 | 141 | int sockport_cmp(void *ka, void *kb) |
tass | 68:0847e35d08a6 | 142 | { |
TASS Belgium NV |
131:4758606c9316 | 143 | struct pico_sockport *a = ka, *b = kb; |
TASS Belgium NV |
131:4758606c9316 | 144 | if (a->number < b->number) |
TASS Belgium NV |
131:4758606c9316 | 145 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 146 | |
TASS Belgium NV |
131:4758606c9316 | 147 | if (a->number > b->number) |
TASS Belgium NV |
131:4758606c9316 | 148 | return 1; |
TASS Belgium NV |
131:4758606c9316 | 149 | |
TASS Belgium NV |
131:4758606c9316 | 150 | return 0; |
tass | 68:0847e35d08a6 | 151 | } |
tass | 68:0847e35d08a6 | 152 | |
TASS Belgium NV |
131:4758606c9316 | 153 | PICO_TREE_DECLARE(UDPTable, sockport_cmp); |
TASS Belgium NV |
131:4758606c9316 | 154 | PICO_TREE_DECLARE(TCPTable, sockport_cmp); |
tass | 68:0847e35d08a6 | 155 | |
tass | 68:0847e35d08a6 | 156 | #ifdef PICO_SUPPORT_MCAST |
tass | 68:0847e35d08a6 | 157 | /* socket |
TASS Belgium NV |
131:4758606c9316 | 158 | * | |
tass | 68:0847e35d08a6 | 159 | * MCASTListen |
tass | 68:0847e35d08a6 | 160 | * | | | |
tass | 68:0847e35d08a6 | 161 | * ------------ | ------------ |
tass | 68:0847e35d08a6 | 162 | * | | | |
TASS Belgium NV |
131:4758606c9316 | 163 | * MCASTSources MCASTSources MCASTSources |
tass | 68:0847e35d08a6 | 164 | * | | | | | | | | | | | | |
tass | 68:0847e35d08a6 | 165 | * S S S S S S S S S S S S |
tass | 68:0847e35d08a6 | 166 | * |
tass | 68:0847e35d08a6 | 167 | * MCASTListen: RBTree(mcast_link, mcast_group) |
tass | 68:0847e35d08a6 | 168 | * MCASTSources: RBTree(source) |
tass | 68:0847e35d08a6 | 169 | */ |
tass | 68:0847e35d08a6 | 170 | struct pico_mcast_listen |
tass | 68:0847e35d08a6 | 171 | { |
TASS Belgium NV |
131:4758606c9316 | 172 | uint8_t filter_mode; |
TASS Belgium NV |
131:4758606c9316 | 173 | struct pico_ip4 mcast_link; |
TASS Belgium NV |
131:4758606c9316 | 174 | struct pico_ip4 mcast_group; |
TASS Belgium NV |
131:4758606c9316 | 175 | struct pico_tree MCASTSources; |
tass | 68:0847e35d08a6 | 176 | }; |
tass | 68:0847e35d08a6 | 177 | |
tass | 68:0847e35d08a6 | 178 | static int mcast_listen_cmp(void *ka, void *kb) |
tass | 68:0847e35d08a6 | 179 | { |
TASS Belgium NV |
131:4758606c9316 | 180 | struct pico_mcast_listen *a = ka, *b = kb; |
TASS Belgium NV |
131:4758606c9316 | 181 | if (a->mcast_group.addr < b->mcast_group.addr) |
TASS Belgium NV |
131:4758606c9316 | 182 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 183 | |
TASS Belgium NV |
131:4758606c9316 | 184 | if (a->mcast_group.addr > b->mcast_group.addr) |
TASS Belgium NV |
131:4758606c9316 | 185 | return 1; |
tass | 68:0847e35d08a6 | 186 | |
TASS Belgium NV |
131:4758606c9316 | 187 | if (a->mcast_link.addr < b->mcast_link.addr) |
TASS Belgium NV |
131:4758606c9316 | 188 | return -1; |
tass | 68:0847e35d08a6 | 189 | |
TASS Belgium NV |
131:4758606c9316 | 190 | if (a->mcast_link.addr > b->mcast_link.addr) |
TASS Belgium NV |
131:4758606c9316 | 191 | return 1; |
TASS Belgium NV |
131:4758606c9316 | 192 | |
TASS Belgium NV |
131:4758606c9316 | 193 | return 0; |
tass | 68:0847e35d08a6 | 194 | } |
tass | 68:0847e35d08a6 | 195 | |
tass | 68:0847e35d08a6 | 196 | static int mcast_sources_cmp(void *ka, void *kb) |
tass | 68:0847e35d08a6 | 197 | { |
TASS Belgium NV |
131:4758606c9316 | 198 | struct pico_ip4 *a = ka, *b = kb; |
TASS Belgium NV |
131:4758606c9316 | 199 | if (a->addr < b->addr) |
TASS Belgium NV |
131:4758606c9316 | 200 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 201 | |
TASS Belgium NV |
131:4758606c9316 | 202 | if (a->addr > b->addr) |
TASS Belgium NV |
131:4758606c9316 | 203 | return 1; |
TASS Belgium NV |
131:4758606c9316 | 204 | |
TASS Belgium NV |
131:4758606c9316 | 205 | return 0; |
tass | 68:0847e35d08a6 | 206 | } |
tass | 68:0847e35d08a6 | 207 | |
tass | 68:0847e35d08a6 | 208 | static int mcast_socket_cmp(void *ka, void *kb) |
tass | 68:0847e35d08a6 | 209 | { |
TASS Belgium NV |
131:4758606c9316 | 210 | struct pico_socket *a = ka, *b = kb; |
TASS Belgium NV |
131:4758606c9316 | 211 | if (a < b) |
TASS Belgium NV |
131:4758606c9316 | 212 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 213 | |
TASS Belgium NV |
131:4758606c9316 | 214 | if (a > b) |
TASS Belgium NV |
131:4758606c9316 | 215 | return 1; |
TASS Belgium NV |
131:4758606c9316 | 216 | |
TASS Belgium NV |
131:4758606c9316 | 217 | return 0; |
tass | 68:0847e35d08a6 | 218 | } |
tass | 68:0847e35d08a6 | 219 | /* gather all multicast sockets to hasten filter aggregation */ |
tass | 68:0847e35d08a6 | 220 | PICO_TREE_DECLARE(MCASTSockets, mcast_socket_cmp); |
tass | 68:0847e35d08a6 | 221 | |
tass | 68:0847e35d08a6 | 222 | static int mcast_filter_cmp(void *ka, void *kb) |
tass | 68:0847e35d08a6 | 223 | { |
TASS Belgium NV |
131:4758606c9316 | 224 | struct pico_ip4 *a = ka, *b = kb; |
TASS Belgium NV |
131:4758606c9316 | 225 | if (a->addr < b->addr) |
TASS Belgium NV |
131:4758606c9316 | 226 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 227 | |
TASS Belgium NV |
131:4758606c9316 | 228 | if (a->addr > b->addr) |
TASS Belgium NV |
131:4758606c9316 | 229 | return 1; |
TASS Belgium NV |
131:4758606c9316 | 230 | |
TASS Belgium NV |
131:4758606c9316 | 231 | return 0; |
tass | 68:0847e35d08a6 | 232 | } |
tass | 68:0847e35d08a6 | 233 | /* gather sources to be filtered */ |
tass | 68:0847e35d08a6 | 234 | PICO_TREE_DECLARE(MCASTFilter, mcast_filter_cmp); |
tass | 68:0847e35d08a6 | 235 | |
tass | 74:c146c4e346c4 | 236 | static struct pico_mcast_listen *listen_find(struct pico_socket *s, struct pico_ip4 *lnk, struct pico_ip4 *grp) |
tass | 74:c146c4e346c4 | 237 | { |
TASS Belgium NV |
131:4758606c9316 | 238 | struct pico_mcast_listen ltest = { |
TASS Belgium NV |
131:4758606c9316 | 239 | 0 |
TASS Belgium NV |
131:4758606c9316 | 240 | }; |
TASS Belgium NV |
131:4758606c9316 | 241 | ltest.mcast_link.addr = lnk->addr; |
TASS Belgium NV |
131:4758606c9316 | 242 | ltest.mcast_group.addr = grp->addr; |
TASS Belgium NV |
131:4758606c9316 | 243 | return pico_tree_findKey(s->MCASTListen, <est); |
tass | 74:c146c4e346c4 | 244 | } |
tass | 74:c146c4e346c4 | 245 | |
tass | 68:0847e35d08a6 | 246 | /* MCASTFilter will be empty if no socket is listening on mcast_group on mcast_link anymore */ |
tass | 68:0847e35d08a6 | 247 | static int pico_socket_aggregate_mcastfilters(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group) |
tass | 68:0847e35d08a6 | 248 | { |
TASS Belgium NV |
131:4758606c9316 | 249 | uint8_t filter_mode = PICO_IP_MULTICAST_INCLUDE; |
TASS Belgium NV |
131:4758606c9316 | 250 | struct pico_mcast_listen *listen = NULL; |
TASS Belgium NV |
131:4758606c9316 | 251 | struct pico_ip4 *source = NULL; |
TASS Belgium NV |
131:4758606c9316 | 252 | struct pico_socket *mcast_sock = NULL; |
TASS Belgium NV |
131:4758606c9316 | 253 | struct pico_tree_node *index = NULL, *_tmp = NULL, *index2 = NULL, *_tmp2 = NULL; |
tass | 68:0847e35d08a6 | 254 | |
tass | 68:0847e35d08a6 | 255 | |
TASS Belgium NV |
131:4758606c9316 | 256 | /* cleanup old filter */ |
TASS Belgium NV |
131:4758606c9316 | 257 | pico_tree_foreach_safe(index, &MCASTFilter, _tmp) |
TASS Belgium NV |
131:4758606c9316 | 258 | { |
TASS Belgium NV |
131:4758606c9316 | 259 | pico_tree_delete(&MCASTFilter, index->keyValue); |
TASS Belgium NV |
131:4758606c9316 | 260 | } |
tass | 68:0847e35d08a6 | 261 | |
TASS Belgium NV |
131:4758606c9316 | 262 | /* construct new filter */ |
TASS Belgium NV |
131:4758606c9316 | 263 | pico_tree_foreach(index, &MCASTSockets) |
TASS Belgium NV |
131:4758606c9316 | 264 | { |
TASS Belgium NV |
131:4758606c9316 | 265 | mcast_sock = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 266 | listen = listen_find(mcast_sock, mcast_link, mcast_group); |
TASS Belgium NV |
131:4758606c9316 | 267 | if (listen) { |
TASS Belgium NV |
131:4758606c9316 | 268 | /* aggregate filter */ |
TASS Belgium NV |
131:4758606c9316 | 269 | switch(filter_mode) |
TASS Belgium NV |
131:4758606c9316 | 270 | { |
tass | 68:0847e35d08a6 | 271 | case PICO_IP_MULTICAST_INCLUDE: |
TASS Belgium NV |
131:4758606c9316 | 272 | switch (listen->filter_mode) |
TASS Belgium NV |
131:4758606c9316 | 273 | { |
TASS Belgium NV |
131:4758606c9316 | 274 | case PICO_IP_MULTICAST_INCLUDE: |
TASS Belgium NV |
131:4758606c9316 | 275 | /* filter = summation of INCLUDEs */ |
TASS Belgium NV |
131:4758606c9316 | 276 | /* mode stays INCLUDE, add all sources to filter */ |
TASS Belgium NV |
131:4758606c9316 | 277 | pico_tree_foreach(index2, &listen->MCASTSources) |
TASS Belgium NV |
131:4758606c9316 | 278 | { |
TASS Belgium NV |
131:4758606c9316 | 279 | source = index2->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 280 | pico_tree_insert(&MCASTFilter, source); |
TASS Belgium NV |
131:4758606c9316 | 281 | } |
TASS Belgium NV |
131:4758606c9316 | 282 | break; |
TASS Belgium NV |
131:4758606c9316 | 283 | |
TASS Belgium NV |
131:4758606c9316 | 284 | case PICO_IP_MULTICAST_EXCLUDE: |
TASS Belgium NV |
131:4758606c9316 | 285 | /* filter = EXCLUDE - INCLUDE */ |
TASS Belgium NV |
131:4758606c9316 | 286 | /* delete from the interface INCLUDE filter any source NOT in the socket EXCLUDE filter */ |
TASS Belgium NV |
131:4758606c9316 | 287 | pico_tree_foreach_safe(index2, &MCASTFilter, _tmp2) |
TASS Belgium NV |
131:4758606c9316 | 288 | { |
TASS Belgium NV |
131:4758606c9316 | 289 | source = pico_tree_findKey(&listen->MCASTSources, index2->keyValue); |
TASS Belgium NV |
131:4758606c9316 | 290 | if (!source) |
TASS Belgium NV |
131:4758606c9316 | 291 | pico_tree_delete(&MCASTFilter, index2->keyValue); |
TASS Belgium NV |
131:4758606c9316 | 292 | } |
TASS Belgium NV |
131:4758606c9316 | 293 | /* any record with filter mode EXCLUDE, causes the interface mode to be EXCLUDE */ |
TASS Belgium NV |
131:4758606c9316 | 294 | filter_mode = PICO_IP_MULTICAST_EXCLUDE; |
TASS Belgium NV |
131:4758606c9316 | 295 | /* add to the interface EXCLUDE filter any socket source NOT in the former interface INCLUDE filter */ |
TASS Belgium NV |
131:4758606c9316 | 296 | pico_tree_foreach(index2, &listen->MCASTSources) |
TASS Belgium NV |
131:4758606c9316 | 297 | { |
TASS Belgium NV |
131:4758606c9316 | 298 | source = pico_tree_insert(&MCASTFilter, index2->keyValue); |
TASS Belgium NV |
131:4758606c9316 | 299 | if (source) |
TASS Belgium NV |
131:4758606c9316 | 300 | pico_tree_delete(&MCASTFilter, source); |
TASS Belgium NV |
131:4758606c9316 | 301 | } |
TASS Belgium NV |
131:4758606c9316 | 302 | break; |
TASS Belgium NV |
131:4758606c9316 | 303 | |
TASS Belgium NV |
131:4758606c9316 | 304 | default: |
TASS Belgium NV |
131:4758606c9316 | 305 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 306 | } |
TASS Belgium NV |
131:4758606c9316 | 307 | break; |
tass | 68:0847e35d08a6 | 308 | |
tass | 68:0847e35d08a6 | 309 | case PICO_IP_MULTICAST_EXCLUDE: |
TASS Belgium NV |
131:4758606c9316 | 310 | switch (listen->filter_mode) |
TASS Belgium NV |
131:4758606c9316 | 311 | { |
TASS Belgium NV |
131:4758606c9316 | 312 | case PICO_IP_MULTICAST_INCLUDE: |
TASS Belgium NV |
131:4758606c9316 | 313 | /* filter = EXCLUDE - INCLUDE */ |
TASS Belgium NV |
131:4758606c9316 | 314 | /* any record with filter mode EXCLUDE, causes the interface mode to be EXCLUDE */ |
TASS Belgium NV |
131:4758606c9316 | 315 | /* remove from the interface EXCLUDE filter any source in the socket INCLUDE filter */ |
TASS Belgium NV |
131:4758606c9316 | 316 | pico_tree_foreach(index2, &listen->MCASTSources) |
TASS Belgium NV |
131:4758606c9316 | 317 | { |
TASS Belgium NV |
131:4758606c9316 | 318 | source = pico_tree_findKey(&MCASTFilter, index2->keyValue); |
TASS Belgium NV |
131:4758606c9316 | 319 | if (source) |
TASS Belgium NV |
131:4758606c9316 | 320 | pico_tree_delete(&MCASTFilter, source); |
TASS Belgium NV |
131:4758606c9316 | 321 | } |
TASS Belgium NV |
131:4758606c9316 | 322 | break; |
TASS Belgium NV |
131:4758606c9316 | 323 | |
TASS Belgium NV |
131:4758606c9316 | 324 | case PICO_IP_MULTICAST_EXCLUDE: |
TASS Belgium NV |
131:4758606c9316 | 325 | /* filter = intersection of EXCLUDEs */ |
TASS Belgium NV |
131:4758606c9316 | 326 | /* any record with filter mode EXCLUDE, causes the interface mode to be EXCLUDE */ |
TASS Belgium NV |
131:4758606c9316 | 327 | /* remove from the interface EXCLUDE filter any source not in the socket EXCLUDE filter */ |
TASS Belgium NV |
131:4758606c9316 | 328 | pico_tree_foreach_safe(index2, &MCASTFilter, _tmp2) |
TASS Belgium NV |
131:4758606c9316 | 329 | { |
TASS Belgium NV |
131:4758606c9316 | 330 | source = pico_tree_findKey(&listen->MCASTSources, index2->keyValue); |
TASS Belgium NV |
131:4758606c9316 | 331 | if (!source) |
TASS Belgium NV |
131:4758606c9316 | 332 | pico_tree_delete(&MCASTFilter, index2->keyValue); |
TASS Belgium NV |
131:4758606c9316 | 333 | } |
TASS Belgium NV |
131:4758606c9316 | 334 | break; |
TASS Belgium NV |
131:4758606c9316 | 335 | |
TASS Belgium NV |
131:4758606c9316 | 336 | default: |
TASS Belgium NV |
131:4758606c9316 | 337 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 338 | } |
TASS Belgium NV |
131:4758606c9316 | 339 | break; |
tass | 68:0847e35d08a6 | 340 | |
tass | 68:0847e35d08a6 | 341 | default: |
TASS Belgium NV |
131:4758606c9316 | 342 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 343 | } |
TASS Belgium NV |
131:4758606c9316 | 344 | } |
tass | 68:0847e35d08a6 | 345 | } |
TASS Belgium NV |
131:4758606c9316 | 346 | return filter_mode; |
tass | 68:0847e35d08a6 | 347 | } |
tass | 68:0847e35d08a6 | 348 | |
tass | 68:0847e35d08a6 | 349 | static int pico_socket_mcast_filter(struct pico_socket *s, struct pico_ip4 *mcast_group, struct pico_ip4 *src) |
tass | 68:0847e35d08a6 | 350 | { |
TASS Belgium NV |
131:4758606c9316 | 351 | struct pico_ipv4_link *mcast_link = NULL; |
TASS Belgium NV |
131:4758606c9316 | 352 | struct pico_mcast_listen *listen = NULL; |
TASS Belgium NV |
131:4758606c9316 | 353 | struct pico_tree_node *index = NULL; |
tass | 68:0847e35d08a6 | 354 | |
TASS Belgium NV |
131:4758606c9316 | 355 | /* no multicast enabled on socket */ |
TASS Belgium NV |
131:4758606c9316 | 356 | if (!s->MCASTListen) |
TASS Belgium NV |
131:4758606c9316 | 357 | return 0; |
tass | 68:0847e35d08a6 | 358 | |
TASS Belgium NV |
131:4758606c9316 | 359 | mcast_link = pico_ipv4_link_get(&s->local_addr.ip4); |
TASS Belgium NV |
131:4758606c9316 | 360 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 361 | return -1; |
tass | 68:0847e35d08a6 | 362 | |
TASS Belgium NV |
131:4758606c9316 | 363 | listen = listen_find(s, &mcast_link->address, mcast_group); |
TASS Belgium NV |
131:4758606c9316 | 364 | if (!listen) |
TASS Belgium NV |
131:4758606c9316 | 365 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 366 | |
TASS Belgium NV |
131:4758606c9316 | 367 | /* perform source filtering */ |
TASS Belgium NV |
131:4758606c9316 | 368 | switch (listen->filter_mode) |
TASS Belgium NV |
131:4758606c9316 | 369 | { |
tass | 68:0847e35d08a6 | 370 | case PICO_IP_MULTICAST_INCLUDE: |
TASS Belgium NV |
131:4758606c9316 | 371 | pico_tree_foreach(index, &listen->MCASTSources) |
TASS Belgium NV |
131:4758606c9316 | 372 | { |
TASS Belgium NV |
131:4758606c9316 | 373 | if (src->addr == ((struct pico_ip4 *)index->keyValue)->addr) { |
TASS Belgium NV |
131:4758606c9316 | 374 | so_mcast_dbg("MCAST: IP %08X in included socket source list\n", src->addr); |
TASS Belgium NV |
131:4758606c9316 | 375 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 376 | } |
tass | 68:0847e35d08a6 | 377 | } |
TASS Belgium NV |
131:4758606c9316 | 378 | so_mcast_dbg("MCAST: IP %08X NOT in included socket source list\n", src->addr); |
TASS Belgium NV |
131:4758606c9316 | 379 | return -1; |
tass | 68:0847e35d08a6 | 380 | |
tass | 68:0847e35d08a6 | 381 | case PICO_IP_MULTICAST_EXCLUDE: |
TASS Belgium NV |
131:4758606c9316 | 382 | pico_tree_foreach(index, &listen->MCASTSources) |
TASS Belgium NV |
131:4758606c9316 | 383 | { |
TASS Belgium NV |
131:4758606c9316 | 384 | if (src->addr == ((struct pico_ip4 *)index->keyValue)->addr) { |
TASS Belgium NV |
131:4758606c9316 | 385 | so_mcast_dbg("MCAST: IP %08X in excluded socket source list\n", src->addr); |
TASS Belgium NV |
131:4758606c9316 | 386 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 387 | } |
tass | 68:0847e35d08a6 | 388 | } |
TASS Belgium NV |
131:4758606c9316 | 389 | so_mcast_dbg("MCAST: IP %08X NOT in excluded socket source list\n", src->addr); |
TASS Belgium NV |
131:4758606c9316 | 390 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 391 | } |
TASS Belgium NV |
131:4758606c9316 | 392 | return -1; |
tass | 68:0847e35d08a6 | 393 | } |
tass | 68:0847e35d08a6 | 394 | |
tass | 68:0847e35d08a6 | 395 | static inline struct pico_ipv4_link *pico_socket_setoption_mcastargs_validation(struct pico_ip_mreq *mreq, struct pico_ip_mreq_source *mreq_source) |
tass | 68:0847e35d08a6 | 396 | { |
TASS Belgium NV |
131:4758606c9316 | 397 | struct pico_ipv4_link *mcast_link = NULL; |
tass | 68:0847e35d08a6 | 398 | |
TASS Belgium NV |
131:4758606c9316 | 399 | if (!mreq && !mreq_source) |
TASS Belgium NV |
131:4758606c9316 | 400 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 401 | |
TASS Belgium NV |
131:4758606c9316 | 402 | if (mreq) { |
TASS Belgium NV |
131:4758606c9316 | 403 | if (!mreq->mcast_group_addr.addr) |
TASS Belgium NV |
131:4758606c9316 | 404 | return NULL; |
tass | 68:0847e35d08a6 | 405 | |
TASS Belgium NV |
131:4758606c9316 | 406 | if (pico_ipv4_is_unicast(mreq->mcast_group_addr.addr)) |
TASS Belgium NV |
131:4758606c9316 | 407 | return NULL; |
tass | 68:0847e35d08a6 | 408 | |
TASS Belgium NV |
131:4758606c9316 | 409 | if (!mreq->mcast_link_addr.addr) { |
TASS Belgium NV |
131:4758606c9316 | 410 | mcast_link = pico_ipv4_get_default_mcastlink(); |
TASS Belgium NV |
131:4758606c9316 | 411 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 412 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 413 | } else { |
TASS Belgium NV |
131:4758606c9316 | 414 | mcast_link = pico_ipv4_link_get(&mreq->mcast_link_addr); |
TASS Belgium NV |
131:4758606c9316 | 415 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 416 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 417 | } |
tass | 68:0847e35d08a6 | 418 | } |
TASS Belgium NV |
131:4758606c9316 | 419 | |
TASS Belgium NV |
131:4758606c9316 | 420 | if (mreq_source) { |
TASS Belgium NV |
131:4758606c9316 | 421 | if (!mreq_source->mcast_group_addr.addr) |
TASS Belgium NV |
131:4758606c9316 | 422 | return NULL; |
tass | 68:0847e35d08a6 | 423 | |
TASS Belgium NV |
131:4758606c9316 | 424 | if (pico_ipv4_is_unicast(mreq_source->mcast_group_addr.addr)) |
TASS Belgium NV |
131:4758606c9316 | 425 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 426 | |
TASS Belgium NV |
131:4758606c9316 | 427 | if (!mreq_source->mcast_source_addr.addr) |
TASS Belgium NV |
131:4758606c9316 | 428 | return NULL; |
tass | 68:0847e35d08a6 | 429 | |
TASS Belgium NV |
131:4758606c9316 | 430 | if (!pico_ipv4_is_unicast(mreq_source->mcast_source_addr.addr)) |
TASS Belgium NV |
131:4758606c9316 | 431 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 432 | |
TASS Belgium NV |
131:4758606c9316 | 433 | if (!mreq_source->mcast_link_addr.addr) { |
TASS Belgium NV |
131:4758606c9316 | 434 | mcast_link = pico_ipv4_get_default_mcastlink(); |
TASS Belgium NV |
131:4758606c9316 | 435 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 436 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 437 | } else { |
TASS Belgium NV |
131:4758606c9316 | 438 | mcast_link = pico_ipv4_link_get(&mreq_source->mcast_link_addr); |
TASS Belgium NV |
131:4758606c9316 | 439 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 440 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 441 | } |
tass | 68:0847e35d08a6 | 442 | } |
TASS Belgium NV |
131:4758606c9316 | 443 | |
TASS Belgium NV |
131:4758606c9316 | 444 | return mcast_link; |
tass | 68:0847e35d08a6 | 445 | } |
tass | 68:0847e35d08a6 | 446 | #else |
TASS Belgium NV |
131:4758606c9316 | 447 | static int pico_socket_mcast_filter(struct pico_socket *s, struct pico_ip4 *mcast_group, struct pico_ip4 *src) |
TASS Belgium NV |
131:4758606c9316 | 448 | { |
TASS Belgium NV |
131:4758606c9316 | 449 | return 0; |
tass | 68:0847e35d08a6 | 450 | } |
tass | 68:0847e35d08a6 | 451 | #endif /* PICO_SUPPORT_MCAST */ |
tass | 68:0847e35d08a6 | 452 | |
tass | 68:0847e35d08a6 | 453 | static struct pico_sockport *pico_get_sockport(uint16_t proto, uint16_t port) |
tass | 68:0847e35d08a6 | 454 | { |
TASS Belgium NV |
131:4758606c9316 | 455 | struct pico_sockport test = INIT_SOCKPORT; |
TASS Belgium NV |
131:4758606c9316 | 456 | test.number = port; |
tass | 68:0847e35d08a6 | 457 | |
TASS Belgium NV |
131:4758606c9316 | 458 | if (proto == PICO_PROTO_UDP) |
TASS Belgium NV |
131:4758606c9316 | 459 | return pico_tree_findKey(&UDPTable, &test); |
tass | 68:0847e35d08a6 | 460 | |
TASS Belgium NV |
131:4758606c9316 | 461 | else if (proto == PICO_PROTO_TCP) |
TASS Belgium NV |
131:4758606c9316 | 462 | return pico_tree_findKey(&TCPTable, &test); |
tass | 68:0847e35d08a6 | 463 | |
TASS Belgium NV |
131:4758606c9316 | 464 | else return NULL; |
tass | 68:0847e35d08a6 | 465 | } |
tass | 68:0847e35d08a6 | 466 | |
tass | 68:0847e35d08a6 | 467 | int pico_is_port_free(uint16_t proto, uint16_t port, void *addr, void *net) |
tass | 68:0847e35d08a6 | 468 | { |
TASS Belgium NV |
131:4758606c9316 | 469 | struct pico_sockport *sp; |
TASS Belgium NV |
131:4758606c9316 | 470 | struct pico_ip4 ip; |
TASS Belgium NV |
131:4758606c9316 | 471 | sp = pico_get_sockport(proto, port); |
tass | 68:0847e35d08a6 | 472 | |
TASS Belgium NV |
131:4758606c9316 | 473 | if (!net) |
TASS Belgium NV |
131:4758606c9316 | 474 | net = &pico_proto_ipv4; |
tass | 68:0847e35d08a6 | 475 | |
TASS Belgium NV |
131:4758606c9316 | 476 | /** IPv6 (wip) ***/ |
TASS Belgium NV |
131:4758606c9316 | 477 | if (net != &pico_proto_ipv4) { |
TASS Belgium NV |
131:4758606c9316 | 478 | dbg("IPV6!!!!!\n"); |
TASS Belgium NV |
131:4758606c9316 | 479 | return (!sp); |
TASS Belgium NV |
131:4758606c9316 | 480 | } |
tass | 68:0847e35d08a6 | 481 | |
TASS Belgium NV |
131:4758606c9316 | 482 | /* IPv4 */ |
tass | 68:0847e35d08a6 | 483 | #ifdef PICO_SUPPORT_NAT |
TASS Belgium NV |
131:4758606c9316 | 484 | if (pico_ipv4_nat_find(port, NULL, 0, (uint8_t)proto)) { |
TASS Belgium NV |
131:4758606c9316 | 485 | dbg("In use by nat....\n"); |
TASS Belgium NV |
131:4758606c9316 | 486 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 487 | } |
TASS Belgium NV |
131:4758606c9316 | 488 | |
tass | 68:0847e35d08a6 | 489 | #endif |
TASS Belgium NV |
131:4758606c9316 | 490 | if (addr) |
TASS Belgium NV |
131:4758606c9316 | 491 | ip.addr = ((struct pico_ip4 *)addr)->addr; |
TASS Belgium NV |
131:4758606c9316 | 492 | else |
TASS Belgium NV |
131:4758606c9316 | 493 | ip.addr = PICO_IPV4_INADDR_ANY; |
TASS Belgium NV |
131:4758606c9316 | 494 | |
TASS Belgium NV |
131:4758606c9316 | 495 | if (ip.addr == PICO_IPV4_INADDR_ANY) { |
TASS Belgium NV |
131:4758606c9316 | 496 | if (!sp) return 1; |
TASS Belgium NV |
131:4758606c9316 | 497 | else { |
TASS Belgium NV |
131:4758606c9316 | 498 | dbg("In use, and asked for ANY\n"); |
TASS Belgium NV |
131:4758606c9316 | 499 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 500 | } |
TASS Belgium NV |
131:4758606c9316 | 501 | } |
tass | 68:0847e35d08a6 | 502 | |
TASS Belgium NV |
131:4758606c9316 | 503 | if (sp) { |
TASS Belgium NV |
131:4758606c9316 | 504 | struct pico_ip4 *s_local; |
TASS Belgium NV |
131:4758606c9316 | 505 | struct pico_tree_node *idx; |
TASS Belgium NV |
131:4758606c9316 | 506 | struct pico_socket *s; |
TASS Belgium NV |
131:4758606c9316 | 507 | pico_tree_foreach(idx, &sp->socks) { |
TASS Belgium NV |
131:4758606c9316 | 508 | s = idx->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 509 | if (s->net == &pico_proto_ipv4) { |
TASS Belgium NV |
131:4758606c9316 | 510 | s_local = (struct pico_ip4*) &s->local_addr; |
TASS Belgium NV |
131:4758606c9316 | 511 | if ((s_local->addr == PICO_IPV4_INADDR_ANY) || (s_local->addr == ip.addr)) |
TASS Belgium NV |
131:4758606c9316 | 512 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 513 | } |
TASS Belgium NV |
131:4758606c9316 | 514 | } |
tass | 68:0847e35d08a6 | 515 | } |
TASS Belgium NV |
131:4758606c9316 | 516 | |
TASS Belgium NV |
131:4758606c9316 | 517 | return 1; |
tass | 68:0847e35d08a6 | 518 | } |
tass | 68:0847e35d08a6 | 519 | |
tass | 68:0847e35d08a6 | 520 | static int pico_check_socket(struct pico_socket *s) |
tass | 68:0847e35d08a6 | 521 | { |
TASS Belgium NV |
131:4758606c9316 | 522 | struct pico_sockport *test; |
TASS Belgium NV |
131:4758606c9316 | 523 | struct pico_socket *found; |
TASS Belgium NV |
131:4758606c9316 | 524 | struct pico_tree_node *index; |
TASS Belgium NV |
131:4758606c9316 | 525 | |
TASS Belgium NV |
131:4758606c9316 | 526 | test = pico_get_sockport(PROTO(s), s->local_port); |
tass | 68:0847e35d08a6 | 527 | |
TASS Belgium NV |
131:4758606c9316 | 528 | if (!test) { |
TASS Belgium NV |
131:4758606c9316 | 529 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 530 | } |
TASS Belgium NV |
131:4758606c9316 | 531 | |
TASS Belgium NV |
131:4758606c9316 | 532 | pico_tree_foreach(index, &test->socks){ |
TASS Belgium NV |
131:4758606c9316 | 533 | found = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 534 | if (s == found) { |
TASS Belgium NV |
131:4758606c9316 | 535 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 536 | } |
TASS Belgium NV |
131:4758606c9316 | 537 | } |
TASS Belgium NV |
131:4758606c9316 | 538 | |
tass | 68:0847e35d08a6 | 539 | return -1; |
tass | 68:0847e35d08a6 | 540 | } |
tass | 68:0847e35d08a6 | 541 | |
TASS Belgium NV |
131:4758606c9316 | 542 | struct pico_socket*pico_sockets_find(uint16_t local, uint16_t remote) |
tass | 68:0847e35d08a6 | 543 | { |
TASS Belgium NV |
131:4758606c9316 | 544 | struct pico_socket *sock = NULL; |
TASS Belgium NV |
131:4758606c9316 | 545 | struct pico_tree_node *index = NULL; |
TASS Belgium NV |
131:4758606c9316 | 546 | struct pico_sockport *sp = NULL; |
tass | 68:0847e35d08a6 | 547 | |
TASS Belgium NV |
131:4758606c9316 | 548 | sp = pico_get_sockport(PICO_PROTO_TCP, local); |
TASS Belgium NV |
131:4758606c9316 | 549 | if(sp) |
TASS Belgium NV |
131:4758606c9316 | 550 | { |
TASS Belgium NV |
131:4758606c9316 | 551 | pico_tree_foreach(index, &sp->socks) |
TASS Belgium NV |
131:4758606c9316 | 552 | { |
TASS Belgium NV |
131:4758606c9316 | 553 | if(((struct pico_socket *)index->keyValue)->remote_port == remote) |
TASS Belgium NV |
131:4758606c9316 | 554 | { |
TASS Belgium NV |
131:4758606c9316 | 555 | sock = (struct pico_socket *)index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 556 | break; |
TASS Belgium NV |
131:4758606c9316 | 557 | } |
TASS Belgium NV |
131:4758606c9316 | 558 | } |
TASS Belgium NV |
131:4758606c9316 | 559 | } |
tass | 68:0847e35d08a6 | 560 | |
TASS Belgium NV |
131:4758606c9316 | 561 | return sock; |
tass | 68:0847e35d08a6 | 562 | } |
tass | 68:0847e35d08a6 | 563 | |
tass | 68:0847e35d08a6 | 564 | |
tass | 70:cd218dd180e5 | 565 | int8_t pico_socket_add(struct pico_socket *s) |
tass | 68:0847e35d08a6 | 566 | { |
TASS Belgium NV |
131:4758606c9316 | 567 | struct pico_sockport *sp = pico_get_sockport(PROTO(s), s->local_port); |
TASS Belgium NV |
131:4758606c9316 | 568 | LOCK(Mutex); |
tass | 68:0847e35d08a6 | 569 | if (!sp) { |
TASS Belgium NV |
131:4758606c9316 | 570 | /* dbg("Creating sockport..%04x\n", s->local_port); / * In comment due to spam during test * / */ |
TASS Belgium NV |
131:4758606c9316 | 571 | sp = pico_zalloc(sizeof(struct pico_sockport)); |
TASS Belgium NV |
131:4758606c9316 | 572 | |
TASS Belgium NV |
131:4758606c9316 | 573 | if (!sp) { |
TASS Belgium NV |
131:4758606c9316 | 574 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 575 | UNLOCK(Mutex); |
TASS Belgium NV |
131:4758606c9316 | 576 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 577 | } |
tass | 68:0847e35d08a6 | 578 | |
TASS Belgium NV |
131:4758606c9316 | 579 | sp->proto = PROTO(s); |
TASS Belgium NV |
131:4758606c9316 | 580 | sp->number = s->local_port; |
TASS Belgium NV |
131:4758606c9316 | 581 | sp->socks.root = &LEAF; |
TASS Belgium NV |
131:4758606c9316 | 582 | sp->socks.compare = socket_cmp; |
tass | 68:0847e35d08a6 | 583 | |
TASS Belgium NV |
131:4758606c9316 | 584 | if (PROTO(s) == PICO_PROTO_UDP) |
TASS Belgium NV |
131:4758606c9316 | 585 | { |
TASS Belgium NV |
131:4758606c9316 | 586 | pico_tree_insert(&UDPTable, sp); |
TASS Belgium NV |
131:4758606c9316 | 587 | } |
TASS Belgium NV |
131:4758606c9316 | 588 | else if (PROTO(s) == PICO_PROTO_TCP) |
TASS Belgium NV |
131:4758606c9316 | 589 | { |
TASS Belgium NV |
131:4758606c9316 | 590 | pico_tree_insert(&TCPTable, sp); |
TASS Belgium NV |
131:4758606c9316 | 591 | } |
tass | 68:0847e35d08a6 | 592 | } |
tass | 68:0847e35d08a6 | 593 | |
TASS Belgium NV |
131:4758606c9316 | 594 | pico_tree_insert(&sp->socks, s); |
TASS Belgium NV |
131:4758606c9316 | 595 | s->state |= PICO_SOCKET_STATE_BOUND; |
TASS Belgium NV |
131:4758606c9316 | 596 | UNLOCK(Mutex); |
TASS Belgium NV |
131:4758606c9316 | 597 | #if DEBUG_SOCKET_TREE |
TASS Belgium NV |
131:4758606c9316 | 598 | { |
TASS Belgium NV |
131:4758606c9316 | 599 | struct pico_tree_node *index; |
TASS Belgium NV |
131:4758606c9316 | 600 | /* RB_FOREACH(s, socket_tree, &sp->socks) { */ |
TASS Belgium NV |
131:4758606c9316 | 601 | pico_tree_foreach(index, &sp->socks){ |
TASS Belgium NV |
131:4758606c9316 | 602 | s = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 603 | dbg(">>>> List Socket lc=%hu rm=%hu\n", short_be(s->local_port), short_be(s->remote_port)); |
TASS Belgium NV |
131:4758606c9316 | 604 | } |
TASS Belgium NV |
131:4758606c9316 | 605 | |
TASS Belgium NV |
131:4758606c9316 | 606 | } |
tass | 68:0847e35d08a6 | 607 | #endif |
TASS Belgium NV |
131:4758606c9316 | 608 | return 0; |
tass | 68:0847e35d08a6 | 609 | } |
tass | 68:0847e35d08a6 | 610 | |
tass | 68:0847e35d08a6 | 611 | static void socket_clean_queues(struct pico_socket *sock) |
tass | 68:0847e35d08a6 | 612 | { |
TASS Belgium NV |
131:4758606c9316 | 613 | struct pico_frame *f_in = pico_dequeue(&sock->q_in); |
TASS Belgium NV |
131:4758606c9316 | 614 | struct pico_frame *f_out = pico_dequeue(&sock->q_out); |
TASS Belgium NV |
131:4758606c9316 | 615 | while(f_in || f_out) |
tass | 68:0847e35d08a6 | 616 | { |
TASS Belgium NV |
131:4758606c9316 | 617 | if(f_in) |
TASS Belgium NV |
131:4758606c9316 | 618 | { |
TASS Belgium NV |
131:4758606c9316 | 619 | pico_frame_discard(f_in); |
TASS Belgium NV |
131:4758606c9316 | 620 | f_in = pico_dequeue(&sock->q_in); |
TASS Belgium NV |
131:4758606c9316 | 621 | } |
tass | 68:0847e35d08a6 | 622 | |
TASS Belgium NV |
131:4758606c9316 | 623 | if(f_out) |
TASS Belgium NV |
131:4758606c9316 | 624 | { |
TASS Belgium NV |
131:4758606c9316 | 625 | pico_frame_discard(f_out); |
TASS Belgium NV |
131:4758606c9316 | 626 | f_out = pico_dequeue(&sock->q_out); |
TASS Belgium NV |
131:4758606c9316 | 627 | } |
tass | 68:0847e35d08a6 | 628 | } |
TASS Belgium NV |
131:4758606c9316 | 629 | /* for tcp sockets go further and clean the sockets inside queue */ |
TASS Belgium NV |
131:4758606c9316 | 630 | if(sock->proto == &pico_proto_tcp) |
TASS Belgium NV |
131:4758606c9316 | 631 | pico_tcp_cleanup_queues(sock); |
tass | 68:0847e35d08a6 | 632 | } |
tass | 68:0847e35d08a6 | 633 | |
tass | 128:ae39e6e81531 | 634 | static void socket_garbage_collect(pico_time now, void *arg) |
tass | 68:0847e35d08a6 | 635 | { |
TASS Belgium NV |
131:4758606c9316 | 636 | struct pico_socket *s = (struct pico_socket *) arg; |
TASS Belgium NV |
131:4758606c9316 | 637 | IGNORE_PARAMETER(now); |
tass | 128:ae39e6e81531 | 638 | |
TASS Belgium NV |
131:4758606c9316 | 639 | socket_clean_queues(s); |
TASS Belgium NV |
131:4758606c9316 | 640 | pico_free(s); |
tass | 68:0847e35d08a6 | 641 | } |
tass | 68:0847e35d08a6 | 642 | |
tass | 70:cd218dd180e5 | 643 | int8_t pico_socket_del(struct pico_socket *s) |
tass | 68:0847e35d08a6 | 644 | { |
TASS Belgium NV |
131:4758606c9316 | 645 | struct pico_sockport *sp = pico_get_sockport(PROTO(s), s->local_port); |
tass | 68:0847e35d08a6 | 646 | |
TASS Belgium NV |
131:4758606c9316 | 647 | if (!sp) { |
TASS Belgium NV |
131:4758606c9316 | 648 | pico_err = PICO_ERR_ENXIO; |
TASS Belgium NV |
131:4758606c9316 | 649 | return -1; |
tass | 68:0847e35d08a6 | 650 | } |
tass | 68:0847e35d08a6 | 651 | |
TASS Belgium NV |
131:4758606c9316 | 652 | LOCK(Mutex); |
TASS Belgium NV |
131:4758606c9316 | 653 | pico_tree_delete(&sp->socks, s); |
TASS Belgium NV |
131:4758606c9316 | 654 | s->net = NULL; |
TASS Belgium NV |
131:4758606c9316 | 655 | if(pico_tree_empty(&sp->socks)) { |
TASS Belgium NV |
131:4758606c9316 | 656 | if (PROTO(s) == PICO_PROTO_UDP) |
TASS Belgium NV |
131:4758606c9316 | 657 | { |
TASS Belgium NV |
131:4758606c9316 | 658 | pico_tree_delete(&UDPTable, sp); |
TASS Belgium NV |
131:4758606c9316 | 659 | } |
TASS Belgium NV |
131:4758606c9316 | 660 | else if (PROTO(s) == PICO_PROTO_TCP) |
TASS Belgium NV |
131:4758606c9316 | 661 | { |
TASS Belgium NV |
131:4758606c9316 | 662 | pico_tree_delete(&TCPTable, sp); |
TASS Belgium NV |
131:4758606c9316 | 663 | } |
tass | 68:0847e35d08a6 | 664 | |
TASS Belgium NV |
131:4758606c9316 | 665 | if(sp_tcp == sp) sp_tcp = NULL; |
TASS Belgium NV |
131:4758606c9316 | 666 | |
TASS Belgium NV |
131:4758606c9316 | 667 | if(sp_udp == sp) sp_udp = NULL; |
tass | 68:0847e35d08a6 | 668 | |
TASS Belgium NV |
131:4758606c9316 | 669 | pico_free(sp); |
TASS Belgium NV |
131:4758606c9316 | 670 | |
TASS Belgium NV |
131:4758606c9316 | 671 | } |
tass | 68:0847e35d08a6 | 672 | |
tass | 68:0847e35d08a6 | 673 | #ifdef PICO_SUPPORT_MCAST |
TASS Belgium NV |
131:4758606c9316 | 674 | do { |
TASS Belgium NV |
131:4758606c9316 | 675 | int filter_mode; |
TASS Belgium NV |
131:4758606c9316 | 676 | struct pico_tree_node *index = NULL, *_tmp = NULL, *index2 = NULL, *_tmp2 = NULL; |
TASS Belgium NV |
131:4758606c9316 | 677 | struct pico_mcast_listen *listen = NULL; |
TASS Belgium NV |
131:4758606c9316 | 678 | struct pico_ip4 *source = NULL; |
TASS Belgium NV |
131:4758606c9316 | 679 | if (s->MCASTListen) { |
TASS Belgium NV |
131:4758606c9316 | 680 | pico_tree_delete(&MCASTSockets, s); |
TASS Belgium NV |
131:4758606c9316 | 681 | pico_tree_foreach_safe(index, s->MCASTListen, _tmp) |
TASS Belgium NV |
131:4758606c9316 | 682 | { |
TASS Belgium NV |
131:4758606c9316 | 683 | listen = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 684 | pico_tree_foreach_safe(index2, &listen->MCASTSources, _tmp2) |
TASS Belgium NV |
131:4758606c9316 | 685 | { |
TASS Belgium NV |
131:4758606c9316 | 686 | source = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 687 | pico_tree_delete(&listen->MCASTSources, source); |
TASS Belgium NV |
131:4758606c9316 | 688 | pico_free(source); |
TASS Belgium NV |
131:4758606c9316 | 689 | } |
TASS Belgium NV |
131:4758606c9316 | 690 | filter_mode = pico_socket_aggregate_mcastfilters(&listen->mcast_link, &listen->mcast_group); |
TASS Belgium NV |
131:4758606c9316 | 691 | if (filter_mode >= 0) |
TASS Belgium NV |
131:4758606c9316 | 692 | pico_ipv4_mcast_leave(&listen->mcast_link, &listen->mcast_group, 1, (uint8_t)filter_mode, &MCASTFilter); |
TASS Belgium NV |
131:4758606c9316 | 693 | |
TASS Belgium NV |
131:4758606c9316 | 694 | pico_tree_delete(s->MCASTListen, listen); |
TASS Belgium NV |
131:4758606c9316 | 695 | pico_free(listen); |
TASS Belgium NV |
131:4758606c9316 | 696 | } |
TASS Belgium NV |
131:4758606c9316 | 697 | pico_free(s->MCASTListen); |
tass | 68:0847e35d08a6 | 698 | } |
TASS Belgium NV |
131:4758606c9316 | 699 | } while (0); |
tass | 68:0847e35d08a6 | 700 | #endif |
tass | 68:0847e35d08a6 | 701 | |
tass picotcp@tass.be | 133:5b075f5e141a | 702 | #ifdef PICO_SUPPORT_TCP |
tass picotcp@tass.be | 133:5b075f5e141a | 703 | if(s->parent) |
tass picotcp@tass.be | 133:5b075f5e141a | 704 | s->parent->number_of_pending_conn--; |
tass picotcp@tass.be | 133:5b075f5e141a | 705 | #endif |
tass picotcp@tass.be | 133:5b075f5e141a | 706 | |
TASS Belgium NV |
131:4758606c9316 | 707 | s->state = PICO_SOCKET_STATE_CLOSED; |
TASS Belgium NV |
131:4758606c9316 | 708 | pico_timer_add(3000, socket_garbage_collect, s); |
TASS Belgium NV |
131:4758606c9316 | 709 | UNLOCK(Mutex); |
TASS Belgium NV |
131:4758606c9316 | 710 | return 0; |
tass | 68:0847e35d08a6 | 711 | } |
tass | 68:0847e35d08a6 | 712 | |
tass | 70:cd218dd180e5 | 713 | 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 | 714 | { |
TASS Belgium NV |
131:4758606c9316 | 715 | struct pico_sockport *sp; |
TASS Belgium NV |
131:4758606c9316 | 716 | if (more_states & PICO_SOCKET_STATE_BOUND) |
TASS Belgium NV |
131:4758606c9316 | 717 | return pico_socket_add(s); |
tass | 68:0847e35d08a6 | 718 | |
TASS Belgium NV |
131:4758606c9316 | 719 | if (less_states & PICO_SOCKET_STATE_BOUND) |
TASS Belgium NV |
131:4758606c9316 | 720 | return pico_socket_del(s); |
tass | 68:0847e35d08a6 | 721 | |
TASS Belgium NV |
131:4758606c9316 | 722 | sp = pico_get_sockport(PROTO(s), s->local_port); |
TASS Belgium NV |
131:4758606c9316 | 723 | if (!sp) { |
TASS Belgium NV |
131:4758606c9316 | 724 | pico_err = PICO_ERR_ENXIO; |
TASS Belgium NV |
131:4758606c9316 | 725 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 726 | } |
tass | 68:0847e35d08a6 | 727 | |
TASS Belgium NV |
131:4758606c9316 | 728 | s->state |= more_states; |
TASS Belgium NV |
131:4758606c9316 | 729 | s->state = (uint16_t)(s->state & (~less_states)); |
TASS Belgium NV |
131:4758606c9316 | 730 | if (tcp_state) { |
TASS Belgium NV |
131:4758606c9316 | 731 | s->state &= 0x00FF; |
TASS Belgium NV |
131:4758606c9316 | 732 | s->state |= tcp_state; |
TASS Belgium NV |
131:4758606c9316 | 733 | } |
tass | 68:0847e35d08a6 | 734 | |
TASS Belgium NV |
131:4758606c9316 | 735 | return 0; |
tass | 68:0847e35d08a6 | 736 | } |
tass | 68:0847e35d08a6 | 737 | |
tass | 68:0847e35d08a6 | 738 | static int pico_socket_deliver(struct pico_protocol *p, struct pico_frame *f, uint16_t localport) |
tass | 68:0847e35d08a6 | 739 | { |
TASS Belgium NV |
131:4758606c9316 | 740 | struct pico_frame *cpy = NULL; |
TASS Belgium NV |
131:4758606c9316 | 741 | struct pico_sockport *sp = NULL; |
TASS Belgium NV |
131:4758606c9316 | 742 | struct pico_socket *s = NULL; |
TASS Belgium NV |
131:4758606c9316 | 743 | struct pico_tree_node *index = NULL; |
TASS Belgium NV |
131:4758606c9316 | 744 | struct pico_tree_node *_tmp; |
TASS Belgium NV |
131:4758606c9316 | 745 | struct pico_trans *tr = (struct pico_trans *) f->transport_hdr; |
tass | 68:0847e35d08a6 | 746 | #ifdef PICO_SUPPORT_IPV4 |
TASS Belgium NV |
131:4758606c9316 | 747 | struct pico_ipv4_hdr *ip4hdr; |
tass | 68:0847e35d08a6 | 748 | #endif |
tass | 68:0847e35d08a6 | 749 | #ifdef PICO_SUPPORT_IPV6 |
TASS Belgium NV |
131:4758606c9316 | 750 | struct pico_ipv6_hdr *ip6hdr; |
tass | 68:0847e35d08a6 | 751 | #endif |
tass | 68:0847e35d08a6 | 752 | |
tass | 125:96003ae6f1d8 | 753 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 754 | struct pico_socket *found = NULL; |
tass | 125:96003ae6f1d8 | 755 | #endif |
tass | 125:96003ae6f1d8 | 756 | |
TASS Belgium NV |
131:4758606c9316 | 757 | if (!tr) |
TASS Belgium NV |
131:4758606c9316 | 758 | return -1; |
tass | 68:0847e35d08a6 | 759 | |
TASS Belgium NV |
131:4758606c9316 | 760 | sp = pico_get_sockport(p->proto_number, localport); |
tass | 68:0847e35d08a6 | 761 | |
TASS Belgium NV |
131:4758606c9316 | 762 | if (!sp) { |
TASS Belgium NV |
131:4758606c9316 | 763 | dbg("No such port %d\n", short_be(localport)); |
TASS Belgium NV |
131:4758606c9316 | 764 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 765 | } |
tass | 68:0847e35d08a6 | 766 | |
tass | 68:0847e35d08a6 | 767 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 768 | if (p->proto_number == PICO_PROTO_TCP) { |
TASS Belgium NV |
131:4758606c9316 | 769 | pico_tree_foreach_safe(index, &sp->socks, _tmp){ |
TASS Belgium NV |
131:4758606c9316 | 770 | s = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 771 | /* 4-tuple identification of socket (port-IP) */ |
tass | 68:0847e35d08a6 | 772 | #ifdef PICO_SUPPORT_IPV4 |
TASS Belgium NV |
131:4758606c9316 | 773 | if (IS_IPV4(f)) { |
TASS Belgium NV |
131:4758606c9316 | 774 | struct pico_ip4 s_local, s_remote, p_src, p_dst; |
TASS Belgium NV |
131:4758606c9316 | 775 | ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr); |
TASS Belgium NV |
131:4758606c9316 | 776 | s_local.addr = s->local_addr.ip4.addr; |
TASS Belgium NV |
131:4758606c9316 | 777 | s_remote.addr = s->remote_addr.ip4.addr; |
TASS Belgium NV |
131:4758606c9316 | 778 | p_src.addr = ip4hdr->src.addr; |
TASS Belgium NV |
131:4758606c9316 | 779 | p_dst.addr = ip4hdr->dst.addr; |
TASS Belgium NV |
131:4758606c9316 | 780 | if ((s->remote_port == tr->sport) && /* remote port check */ |
TASS Belgium NV |
131:4758606c9316 | 781 | (s_remote.addr == p_src.addr) && /* remote addr check */ |
TASS Belgium NV |
131:4758606c9316 | 782 | ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))) { /* Either local socket is ANY, or matches dst */ |
TASS Belgium NV |
131:4758606c9316 | 783 | found = s; |
TASS Belgium NV |
131:4758606c9316 | 784 | break; |
TASS Belgium NV |
131:4758606c9316 | 785 | } else if ((s->remote_port == 0) && /* not connected... listening */ |
TASS Belgium NV |
131:4758606c9316 | 786 | ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))) { /* Either local socket is ANY, or matches dst */ |
TASS Belgium NV |
131:4758606c9316 | 787 | /* listen socket */ |
TASS Belgium NV |
131:4758606c9316 | 788 | found = s; |
TASS Belgium NV |
131:4758606c9316 | 789 | } |
TASS Belgium NV |
131:4758606c9316 | 790 | } |
TASS Belgium NV |
131:4758606c9316 | 791 | |
tass | 68:0847e35d08a6 | 792 | #endif |
tass | 68:0847e35d08a6 | 793 | #ifdef PICO_SUPPORT_IPV6 /* XXX TODO make compare for ipv6 addresses */ |
TASS Belgium NV |
131:4758606c9316 | 794 | if (IS_IPV6(f)) { |
TASS Belgium NV |
131:4758606c9316 | 795 | ip6hdr = (struct pico_ipv6_hdr*)(f->net_hdr); |
TASS Belgium NV |
131:4758606c9316 | 796 | if ((s->remote_port == localport)) { /* && (((struct pico_ip6) s->remote_addr.ip6).addr == ((struct pico_ip6)(ip6hdr->src)).addr) ) { */ |
TASS Belgium NV |
131:4758606c9316 | 797 | found = s; |
TASS Belgium NV |
131:4758606c9316 | 798 | break; |
TASS Belgium NV |
131:4758606c9316 | 799 | } else if (s->remote_port == 0) { |
TASS Belgium NV |
131:4758606c9316 | 800 | /* listen socket */ |
TASS Belgium NV |
131:4758606c9316 | 801 | found = s; |
TASS Belgium NV |
131:4758606c9316 | 802 | } |
TASS Belgium NV |
131:4758606c9316 | 803 | } |
TASS Belgium NV |
131:4758606c9316 | 804 | |
TASS Belgium NV |
131:4758606c9316 | 805 | #endif |
TASS Belgium NV |
131:4758606c9316 | 806 | } /* FOREACH */ |
TASS Belgium NV |
131:4758606c9316 | 807 | if (found != NULL) { |
TASS Belgium NV |
131:4758606c9316 | 808 | pico_tcp_input(found, f); |
TASS Belgium NV |
131:4758606c9316 | 809 | if ((found->ev_pending) && found->wakeup) { |
TASS Belgium NV |
131:4758606c9316 | 810 | found->wakeup(found->ev_pending, found); |
TASS Belgium NV |
131:4758606c9316 | 811 | if(!found->parent) |
TASS Belgium NV |
131:4758606c9316 | 812 | found->ev_pending = 0; |
TASS Belgium NV |
131:4758606c9316 | 813 | } |
TASS Belgium NV |
131:4758606c9316 | 814 | |
TASS Belgium NV |
131:4758606c9316 | 815 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 816 | } else { |
TASS Belgium NV |
131:4758606c9316 | 817 | dbg("SOCKET> mmm something wrong (prob sockport)\n"); |
TASS Belgium NV |
131:4758606c9316 | 818 | return -1; |
tass | 68:0847e35d08a6 | 819 | } |
TASS Belgium NV |
131:4758606c9316 | 820 | } /* TCP CASE */ |
TASS Belgium NV |
131:4758606c9316 | 821 | |
tass | 68:0847e35d08a6 | 822 | #endif |
tass | 68:0847e35d08a6 | 823 | |
tass | 68:0847e35d08a6 | 824 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 825 | if (p->proto_number == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 826 | pico_tree_foreach_safe(index, &sp->socks, _tmp){ |
TASS Belgium NV |
131:4758606c9316 | 827 | s = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 828 | if (IS_IPV4(f)) { /* IPV4 */ |
TASS Belgium NV |
131:4758606c9316 | 829 | struct pico_ip4 s_local, p_dst; |
TASS Belgium NV |
131:4758606c9316 | 830 | ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr); |
TASS Belgium NV |
131:4758606c9316 | 831 | s_local.addr = s->local_addr.ip4.addr; |
TASS Belgium NV |
131:4758606c9316 | 832 | p_dst.addr = ip4hdr->dst.addr; |
TASS Belgium NV |
131:4758606c9316 | 833 | if ((pico_ipv4_is_broadcast(p_dst.addr)) || pico_ipv4_is_multicast(p_dst.addr)) { |
TASS Belgium NV |
131:4758606c9316 | 834 | struct pico_device *dev = pico_ipv4_link_find(&s->local_addr.ip4); |
TASS Belgium NV |
131:4758606c9316 | 835 | if (pico_ipv4_is_multicast(p_dst.addr) && (pico_socket_mcast_filter(s, &ip4hdr->dst, &ip4hdr->src) < 0)) |
TASS Belgium NV |
131:4758606c9316 | 836 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 837 | |
TASS Belgium NV |
131:4758606c9316 | 838 | if ((s_local.addr == PICO_IPV4_INADDR_ANY) || /* If our local ip is ANY, or.. */ |
TASS Belgium NV |
131:4758606c9316 | 839 | (dev == f->dev)) { /* the source of the bcast packet is a neighbor... */ |
TASS Belgium NV |
131:4758606c9316 | 840 | cpy = pico_frame_copy(f); |
TASS Belgium NV |
131:4758606c9316 | 841 | if (!cpy) |
TASS Belgium NV |
131:4758606c9316 | 842 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 843 | |
TASS Belgium NV |
131:4758606c9316 | 844 | if (pico_enqueue(&s->q_in, cpy) > 0) { |
TASS Belgium NV |
131:4758606c9316 | 845 | if (s->wakeup) |
TASS Belgium NV |
131:4758606c9316 | 846 | s->wakeup(PICO_SOCK_EV_RD, s); |
TASS Belgium NV |
131:4758606c9316 | 847 | } |
TASS Belgium NV |
131:4758606c9316 | 848 | else |
TASS Belgium NV |
131:4758606c9316 | 849 | pico_frame_discard(cpy); |
tass | 110:0ece1bbbd36e | 850 | |
TASS Belgium NV |
131:4758606c9316 | 851 | } |
TASS Belgium NV |
131:4758606c9316 | 852 | } else if ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr)) |
TASS Belgium NV |
131:4758606c9316 | 853 | { /* Either local socket is ANY, or matches dst */ |
TASS Belgium NV |
131:4758606c9316 | 854 | cpy = pico_frame_copy(f); |
TASS Belgium NV |
131:4758606c9316 | 855 | if (!cpy) |
TASS Belgium NV |
131:4758606c9316 | 856 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 857 | |
TASS Belgium NV |
131:4758606c9316 | 858 | if (pico_enqueue(&s->q_in, cpy) > 0) { |
TASS Belgium NV |
131:4758606c9316 | 859 | if (s->wakeup) |
TASS Belgium NV |
131:4758606c9316 | 860 | s->wakeup(PICO_SOCK_EV_RD, s); |
TASS Belgium NV |
131:4758606c9316 | 861 | } |
TASS Belgium NV |
131:4758606c9316 | 862 | else |
TASS Belgium NV |
131:4758606c9316 | 863 | pico_frame_discard(cpy); |
TASS Belgium NV |
131:4758606c9316 | 864 | } |
TASS Belgium NV |
131:4758606c9316 | 865 | } else { |
TASS Belgium NV |
131:4758606c9316 | 866 | /*... IPv6 */ |
TASS Belgium NV |
131:4758606c9316 | 867 | } |
TASS Belgium NV |
131:4758606c9316 | 868 | } /* FOREACH */ |
TASS Belgium NV |
131:4758606c9316 | 869 | pico_frame_discard(f); |
TASS Belgium NV |
131:4758606c9316 | 870 | if (s) |
TASS Belgium NV |
131:4758606c9316 | 871 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 872 | else |
tass | 68:0847e35d08a6 | 873 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 874 | } |
TASS Belgium NV |
131:4758606c9316 | 875 | |
tass | 68:0847e35d08a6 | 876 | #endif |
TASS Belgium NV |
131:4758606c9316 | 877 | return -1; |
tass | 68:0847e35d08a6 | 878 | } |
tass | 68:0847e35d08a6 | 879 | |
tass | 68:0847e35d08a6 | 880 | struct pico_socket *pico_socket_open(uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *)) |
tass | 68:0847e35d08a6 | 881 | { |
tass | 68:0847e35d08a6 | 882 | |
TASS Belgium NV |
131:4758606c9316 | 883 | struct pico_socket *s = NULL; |
tass | 68:0847e35d08a6 | 884 | |
tass | 68:0847e35d08a6 | 885 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 886 | if (proto == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 887 | s = pico_udp_open(); |
TASS Belgium NV |
131:4758606c9316 | 888 | s->proto = &pico_proto_udp; |
TASS Belgium NV |
131:4758606c9316 | 889 | s->q_in.overhead = s->q_out.overhead = UDP_FRAME_OVERHEAD; |
TASS Belgium NV |
131:4758606c9316 | 890 | } |
TASS Belgium NV |
131:4758606c9316 | 891 | |
tass | 68:0847e35d08a6 | 892 | #endif |
tass | 68:0847e35d08a6 | 893 | |
tass | 68:0847e35d08a6 | 894 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 895 | if (proto == PICO_PROTO_TCP) { |
TASS Belgium NV |
131:4758606c9316 | 896 | s = pico_tcp_open(); |
TASS Belgium NV |
131:4758606c9316 | 897 | s->proto = &pico_proto_tcp; |
TASS Belgium NV |
131:4758606c9316 | 898 | /*check if Nagle enabled */ |
TASS Belgium NV |
131:4758606c9316 | 899 | if (!IS_NAGLE_ENABLED(s)) |
TASS Belgium NV |
131:4758606c9316 | 900 | dbg("ERROR Nagle should be enabled here\n\n"); |
TASS Belgium NV |
131:4758606c9316 | 901 | } |
TASS Belgium NV |
131:4758606c9316 | 902 | |
tass | 68:0847e35d08a6 | 903 | #endif |
tass | 68:0847e35d08a6 | 904 | |
TASS Belgium NV |
131:4758606c9316 | 905 | if (!s) { |
TASS Belgium NV |
131:4758606c9316 | 906 | pico_err = PICO_ERR_EPROTONOSUPPORT; |
TASS Belgium NV |
131:4758606c9316 | 907 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 908 | } |
tass | 68:0847e35d08a6 | 909 | |
tass | 68:0847e35d08a6 | 910 | #ifdef PICO_SUPPORT_IPV4 |
TASS Belgium NV |
131:4758606c9316 | 911 | if (net == PICO_PROTO_IPV4) |
TASS Belgium NV |
131:4758606c9316 | 912 | s->net = &pico_proto_ipv4; |
TASS Belgium NV |
131:4758606c9316 | 913 | |
tass | 68:0847e35d08a6 | 914 | #endif |
tass | 68:0847e35d08a6 | 915 | |
tass | 68:0847e35d08a6 | 916 | #ifdef PICO_SUPPORT_IPV6 |
TASS Belgium NV |
131:4758606c9316 | 917 | if (net == PICO_PROTO_IPV6) |
TASS Belgium NV |
131:4758606c9316 | 918 | s->net = &pico_proto_ipv6; |
TASS Belgium NV |
131:4758606c9316 | 919 | |
tass | 68:0847e35d08a6 | 920 | #endif |
tass | 68:0847e35d08a6 | 921 | |
TASS Belgium NV |
131:4758606c9316 | 922 | s->q_in.max_size = PICO_DEFAULT_SOCKETQ; |
TASS Belgium NV |
131:4758606c9316 | 923 | s->q_out.max_size = PICO_DEFAULT_SOCKETQ; |
tass | 110:0ece1bbbd36e | 924 | |
TASS Belgium NV |
131:4758606c9316 | 925 | s->wakeup = wakeup; |
tass | 68:0847e35d08a6 | 926 | |
TASS Belgium NV |
131:4758606c9316 | 927 | if (!s->net) { |
TASS Belgium NV |
131:4758606c9316 | 928 | pico_free(s); |
TASS Belgium NV |
131:4758606c9316 | 929 | pico_err = PICO_ERR_ENETUNREACH; |
TASS Belgium NV |
131:4758606c9316 | 930 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 931 | } |
TASS Belgium NV |
131:4758606c9316 | 932 | |
TASS Belgium NV |
131:4758606c9316 | 933 | return s; |
tass | 68:0847e35d08a6 | 934 | } |
tass | 68:0847e35d08a6 | 935 | |
tass | 68:0847e35d08a6 | 936 | |
tass | 68:0847e35d08a6 | 937 | struct pico_socket *pico_socket_clone(struct pico_socket *facsimile) |
tass | 68:0847e35d08a6 | 938 | { |
TASS Belgium NV |
131:4758606c9316 | 939 | struct pico_socket *s = NULL; |
tass | 68:0847e35d08a6 | 940 | |
tass | 68:0847e35d08a6 | 941 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 942 | if (facsimile->proto->proto_number == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 943 | s = pico_udp_open(); |
TASS Belgium NV |
131:4758606c9316 | 944 | s->proto = &pico_proto_udp; |
TASS Belgium NV |
131:4758606c9316 | 945 | s->q_in.overhead = s->q_out.overhead = UDP_FRAME_OVERHEAD; |
TASS Belgium NV |
131:4758606c9316 | 946 | } |
TASS Belgium NV |
131:4758606c9316 | 947 | |
tass | 68:0847e35d08a6 | 948 | #endif |
tass | 68:0847e35d08a6 | 949 | |
tass | 68:0847e35d08a6 | 950 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 951 | if (facsimile->proto->proto_number == PICO_PROTO_TCP) { |
TASS Belgium NV |
131:4758606c9316 | 952 | s = pico_tcp_open(); |
TASS Belgium NV |
131:4758606c9316 | 953 | s->proto = &pico_proto_tcp; |
TASS Belgium NV |
131:4758606c9316 | 954 | } |
TASS Belgium NV |
131:4758606c9316 | 955 | |
tass | 68:0847e35d08a6 | 956 | #endif |
tass | 68:0847e35d08a6 | 957 | |
TASS Belgium NV |
131:4758606c9316 | 958 | if (!s) { |
TASS Belgium NV |
131:4758606c9316 | 959 | pico_err = PICO_ERR_EPROTONOSUPPORT; |
TASS Belgium NV |
131:4758606c9316 | 960 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 961 | } |
TASS Belgium NV |
131:4758606c9316 | 962 | |
TASS Belgium NV |
131:4758606c9316 | 963 | s->local_port = facsimile->local_port; |
TASS Belgium NV |
131:4758606c9316 | 964 | s->remote_port = facsimile->remote_port; |
TASS Belgium NV |
131:4758606c9316 | 965 | s->state = facsimile->state; |
tass | 68:0847e35d08a6 | 966 | |
tass | 68:0847e35d08a6 | 967 | #ifdef PICO_SUPPORT_IPV4 |
TASS Belgium NV |
131:4758606c9316 | 968 | if (facsimile->net == &pico_proto_ipv4) { |
TASS Belgium NV |
131:4758606c9316 | 969 | s->net = &pico_proto_ipv4; |
TASS Belgium NV |
131:4758606c9316 | 970 | memcpy(&s->local_addr, &facsimile->local_addr, sizeof(struct pico_ip4)); |
TASS Belgium NV |
131:4758606c9316 | 971 | memcpy(&s->remote_addr, &facsimile->remote_addr, sizeof(struct pico_ip4)); |
TASS Belgium NV |
131:4758606c9316 | 972 | } |
TASS Belgium NV |
131:4758606c9316 | 973 | |
tass | 68:0847e35d08a6 | 974 | #endif |
tass | 68:0847e35d08a6 | 975 | |
tass | 68:0847e35d08a6 | 976 | #ifdef PICO_SUPPORT_IPV6 |
TASS Belgium NV |
131:4758606c9316 | 977 | if (net == &pico_proto_ipv6) { |
TASS Belgium NV |
131:4758606c9316 | 978 | s->net = &pico_proto_ipv6; |
TASS Belgium NV |
131:4758606c9316 | 979 | memcpy(&s->local_addr, &facsimile->local_addr, sizeof(struct pico_ip6)); |
TASS Belgium NV |
131:4758606c9316 | 980 | memcpy(&s->remote_addr, &facsimile->remote_addr, sizeof(struct pico_ip6)); |
TASS Belgium NV |
131:4758606c9316 | 981 | } |
TASS Belgium NV |
131:4758606c9316 | 982 | |
tass | 68:0847e35d08a6 | 983 | #endif |
TASS Belgium NV |
131:4758606c9316 | 984 | s->q_in.max_size = PICO_DEFAULT_SOCKETQ; |
TASS Belgium NV |
131:4758606c9316 | 985 | s->q_out.max_size = PICO_DEFAULT_SOCKETQ; |
TASS Belgium NV |
131:4758606c9316 | 986 | s->wakeup = NULL; |
TASS Belgium NV |
131:4758606c9316 | 987 | if (!s->net) { |
TASS Belgium NV |
131:4758606c9316 | 988 | pico_free(s); |
TASS Belgium NV |
131:4758606c9316 | 989 | pico_err = PICO_ERR_ENETUNREACH; |
TASS Belgium NV |
131:4758606c9316 | 990 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 991 | } |
TASS Belgium NV |
131:4758606c9316 | 992 | |
TASS Belgium NV |
131:4758606c9316 | 993 | return s; |
tass | 68:0847e35d08a6 | 994 | } |
tass | 68:0847e35d08a6 | 995 | |
tass | 68:0847e35d08a6 | 996 | int pico_socket_read(struct pico_socket *s, void *buf, int len) |
tass | 68:0847e35d08a6 | 997 | { |
TASS Belgium NV |
131:4758606c9316 | 998 | if (!s || buf == NULL) { |
TASS Belgium NV |
131:4758606c9316 | 999 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1000 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1001 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1002 | /* check if exists in tree */ |
TASS Belgium NV |
131:4758606c9316 | 1003 | /* See task #178 */ |
TASS Belgium NV |
131:4758606c9316 | 1004 | if (pico_check_socket(s) != 0) { |
TASS Belgium NV |
131:4758606c9316 | 1005 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1006 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1007 | } |
tass | 68:0847e35d08a6 | 1008 | } |
tass | 68:0847e35d08a6 | 1009 | |
TASS Belgium NV |
131:4758606c9316 | 1010 | if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1011 | pico_err = PICO_ERR_EIO; |
TASS Belgium NV |
131:4758606c9316 | 1012 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1013 | } |
TASS Belgium NV |
131:4758606c9316 | 1014 | |
TASS Belgium NV |
131:4758606c9316 | 1015 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 1016 | if (PROTO(s) == PICO_PROTO_UDP) |
TASS Belgium NV |
131:4758606c9316 | 1017 | return pico_udp_recv(s, buf, (uint16_t)len, NULL, NULL); |
TASS Belgium NV |
131:4758606c9316 | 1018 | |
tass | 68:0847e35d08a6 | 1019 | #endif |
tass | 68:0847e35d08a6 | 1020 | |
tass | 68:0847e35d08a6 | 1021 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 1022 | if (PROTO(s) == PICO_PROTO_TCP) { |
TASS Belgium NV |
131:4758606c9316 | 1023 | /* check if in shutdown state and if no more data in tcpq_in */ |
TASS Belgium NV |
131:4758606c9316 | 1024 | if ((s->state & PICO_SOCKET_STATE_SHUT_REMOTE) && pico_tcp_queue_in_is_empty(s)) { |
TASS Belgium NV |
131:4758606c9316 | 1025 | pico_err = PICO_ERR_ESHUTDOWN; |
TASS Belgium NV |
131:4758606c9316 | 1026 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1027 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1028 | return (int)pico_tcp_read(s, buf, (uint32_t)len); |
TASS Belgium NV |
131:4758606c9316 | 1029 | } |
tass | 68:0847e35d08a6 | 1030 | } |
TASS Belgium NV |
131:4758606c9316 | 1031 | |
tass | 68:0847e35d08a6 | 1032 | #endif |
TASS Belgium NV |
131:4758606c9316 | 1033 | return 0; |
tass | 68:0847e35d08a6 | 1034 | } |
tass | 68:0847e35d08a6 | 1035 | |
tass | 68:0847e35d08a6 | 1036 | int pico_socket_write(struct pico_socket *s, const void *buf, int len) |
tass | 68:0847e35d08a6 | 1037 | { |
TASS Belgium NV |
131:4758606c9316 | 1038 | if (!s || buf == NULL) { |
TASS Belgium NV |
131:4758606c9316 | 1039 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1040 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1041 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1042 | /* check if exists in tree */ |
TASS Belgium NV |
131:4758606c9316 | 1043 | /* See task #178 */ |
TASS Belgium NV |
131:4758606c9316 | 1044 | if (pico_check_socket(s) != 0) { |
TASS Belgium NV |
131:4758606c9316 | 1045 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1046 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1047 | } |
tass | 68:0847e35d08a6 | 1048 | } |
tass | 68:0847e35d08a6 | 1049 | |
TASS Belgium NV |
131:4758606c9316 | 1050 | if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1051 | pico_err = PICO_ERR_EIO; |
TASS Belgium NV |
131:4758606c9316 | 1052 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1053 | } |
TASS Belgium NV |
131:4758606c9316 | 1054 | |
TASS Belgium NV |
131:4758606c9316 | 1055 | if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1056 | pico_err = PICO_ERR_ENOTCONN; |
TASS Belgium NV |
131:4758606c9316 | 1057 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1058 | } else if (s->state & PICO_SOCKET_STATE_SHUT_LOCAL) { /* check if in shutdown state */ |
TASS Belgium NV |
131:4758606c9316 | 1059 | pico_err = PICO_ERR_ESHUTDOWN; |
TASS Belgium NV |
131:4758606c9316 | 1060 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1061 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1062 | return pico_socket_sendto(s, buf, len, &s->remote_addr, s->remote_port); |
TASS Belgium NV |
131:4758606c9316 | 1063 | } |
tass | 68:0847e35d08a6 | 1064 | } |
tass | 68:0847e35d08a6 | 1065 | |
tass | 68:0847e35d08a6 | 1066 | uint16_t pico_socket_high_port(uint16_t proto) |
tass | 68:0847e35d08a6 | 1067 | { |
TASS Belgium NV |
131:4758606c9316 | 1068 | uint16_t port; |
TASS Belgium NV |
131:4758606c9316 | 1069 | if (0 || |
tass | 68:0847e35d08a6 | 1070 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 1071 | (proto == PICO_PROTO_TCP) || |
tass | 68:0847e35d08a6 | 1072 | #endif |
tass | 68:0847e35d08a6 | 1073 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 1074 | (proto == PICO_PROTO_UDP) || |
tass | 68:0847e35d08a6 | 1075 | #endif |
TASS Belgium NV |
131:4758606c9316 | 1076 | 0) { |
TASS Belgium NV |
131:4758606c9316 | 1077 | do { |
TASS Belgium NV |
131:4758606c9316 | 1078 | uint32_t rand = pico_rand(); |
TASS Belgium NV |
131:4758606c9316 | 1079 | port = (uint16_t) (rand & 0xFFFFU); |
TASS Belgium NV |
131:4758606c9316 | 1080 | port = (uint16_t)((port % (65535 - 1024)) + 1024U); |
TASS Belgium NV |
131:4758606c9316 | 1081 | if (pico_is_port_free(proto, port, NULL, NULL)) { |
TASS Belgium NV |
131:4758606c9316 | 1082 | return short_be(port); |
TASS Belgium NV |
131:4758606c9316 | 1083 | } |
TASS Belgium NV |
131:4758606c9316 | 1084 | } while(1); |
TASS Belgium NV |
131:4758606c9316 | 1085 | } |
TASS Belgium NV |
131:4758606c9316 | 1086 | else return 0U; |
tass | 68:0847e35d08a6 | 1087 | } |
tass | 68:0847e35d08a6 | 1088 | |
tass | 68:0847e35d08a6 | 1089 | |
tass | 68:0847e35d08a6 | 1090 | int pico_socket_sendto(struct pico_socket *s, const void *buf, const int len, void *dst, uint16_t remote_port) |
tass | 68:0847e35d08a6 | 1091 | { |
TASS Belgium NV |
131:4758606c9316 | 1092 | struct pico_frame *f; |
TASS Belgium NV |
131:4758606c9316 | 1093 | struct pico_remote_duple *remote_duple = NULL; |
TASS Belgium NV |
131:4758606c9316 | 1094 | int socket_mtu = PICO_SOCKET4_MTU; |
TASS Belgium NV |
131:4758606c9316 | 1095 | int header_offset = 0; |
TASS Belgium NV |
131:4758606c9316 | 1096 | int total_payload_written = 0; |
tass picotcp@tass.be | 134:cc4e6d2654d9 | 1097 | |
tass | 68:0847e35d08a6 | 1098 | #ifdef PICO_SUPPORT_IPV4 |
TASS Belgium NV |
131:4758606c9316 | 1099 | struct pico_ip4 *src4; |
tass | 68:0847e35d08a6 | 1100 | #endif |
tass | 68:0847e35d08a6 | 1101 | |
tass | 68:0847e35d08a6 | 1102 | #ifdef PICO_SUPPORT_IPV6 |
TASS Belgium NV |
131:4758606c9316 | 1103 | struct pico_ip6 *src6; |
tass | 68:0847e35d08a6 | 1104 | #endif |
TASS Belgium NV |
131:4758606c9316 | 1105 | if (len == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1106 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 1107 | } else if (len < 0) { |
TASS Belgium NV |
131:4758606c9316 | 1108 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1109 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1110 | } |
tass | 68:0847e35d08a6 | 1111 | |
TASS Belgium NV |
131:4758606c9316 | 1112 | if (buf == NULL || s == NULL) { |
TASS Belgium NV |
131:4758606c9316 | 1113 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1114 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1115 | } |
tass | 68:0847e35d08a6 | 1116 | |
TASS Belgium NV |
131:4758606c9316 | 1117 | if (!dst || !remote_port) { |
TASS Belgium NV |
131:4758606c9316 | 1118 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 1119 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1120 | } |
tass | 68:0847e35d08a6 | 1121 | |
TASS Belgium NV |
131:4758606c9316 | 1122 | if ((s->state & PICO_SOCKET_STATE_CONNECTED) != 0) { |
TASS Belgium NV |
131:4758606c9316 | 1123 | if (remote_port != s->remote_port) { |
TASS Belgium NV |
131:4758606c9316 | 1124 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1125 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1126 | } |
tass | 68:0847e35d08a6 | 1127 | } |
tass | 68:0847e35d08a6 | 1128 | |
tass | 68:0847e35d08a6 | 1129 | #ifdef PICO_SUPPORT_IPV4 |
TASS Belgium NV |
131:4758606c9316 | 1130 | if (IS_SOCK_IPV4(s)) { |
TASS Belgium NV |
131:4758606c9316 | 1131 | socket_mtu = PICO_SOCKET4_MTU; |
TASS Belgium NV |
131:4758606c9316 | 1132 | if ((s->state & PICO_SOCKET_STATE_CONNECTED)) { |
TASS Belgium NV |
131:4758606c9316 | 1133 | if (s->remote_addr.ip4.addr != ((struct pico_ip4 *)dst)->addr ) { |
TASS Belgium NV |
131:4758606c9316 | 1134 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 1135 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1136 | } |
TASS Belgium NV |
131:4758606c9316 | 1137 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1138 | src4 = pico_ipv4_source_find(dst); |
TASS Belgium NV |
131:4758606c9316 | 1139 | if (!src4) { |
TASS Belgium NV |
131:4758606c9316 | 1140 | pico_err = PICO_ERR_EHOSTUNREACH; |
TASS Belgium NV |
131:4758606c9316 | 1141 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1142 | } |
TASS Belgium NV |
131:4758606c9316 | 1143 | |
TASS Belgium NV |
131:4758606c9316 | 1144 | if (src4->addr != PICO_IPV4_INADDR_ANY) |
TASS Belgium NV |
131:4758606c9316 | 1145 | s->local_addr.ip4.addr = src4->addr; |
TASS Belgium NV |
131:4758606c9316 | 1146 | |
tass | 68:0847e35d08a6 | 1147 | # ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 1148 | /* socket remote info could change in a consecutive call, make persistent */ |
TASS Belgium NV |
131:4758606c9316 | 1149 | if (PROTO(s) == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1150 | remote_duple = pico_zalloc(sizeof(struct pico_remote_duple)); |
TASS Belgium NV |
131:4758606c9316 | 1151 | remote_duple->remote_addr.ip4.addr = ((struct pico_ip4 *)dst)->addr; |
TASS Belgium NV |
131:4758606c9316 | 1152 | remote_duple->remote_port = remote_port; |
TASS Belgium NV |
131:4758606c9316 | 1153 | } |
TASS Belgium NV |
131:4758606c9316 | 1154 | |
tass | 68:0847e35d08a6 | 1155 | # endif |
TASS Belgium NV |
131:4758606c9316 | 1156 | } |
TASS Belgium NV |
131:4758606c9316 | 1157 | |
tass | 68:0847e35d08a6 | 1158 | #endif |
TASS Belgium NV |
131:4758606c9316 | 1159 | } |
TASS Belgium NV |
131:4758606c9316 | 1160 | else if (IS_SOCK_IPV6(s)) { |
tass | 68:0847e35d08a6 | 1161 | socket_mtu = PICO_SOCKET6_MTU; |
tass | 68:0847e35d08a6 | 1162 | #ifdef PICO_SUPPORT_IPV6 |
tass | 68:0847e35d08a6 | 1163 | if (s->state & PICO_SOCKET_STATE_CONNECTED) { |
TASS Belgium NV |
131:4758606c9316 | 1164 | if (memcmp(&s->remote_addr, dst, PICO_SIZE_IP6)) |
TASS Belgium NV |
131:4758606c9316 | 1165 | return -1; |
tass | 68:0847e35d08a6 | 1166 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1167 | src6 = pico_ipv6_source_find(dst); |
TASS Belgium NV |
131:4758606c9316 | 1168 | if (!src6) { |
TASS Belgium NV |
131:4758606c9316 | 1169 | pico_err = PICO_ERR_EHOSTUNREACH; |
TASS Belgium NV |
131:4758606c9316 | 1170 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1171 | } |
TASS Belgium NV |
131:4758606c9316 | 1172 | |
TASS Belgium NV |
131:4758606c9316 | 1173 | memcpy(&s->local_addr, src6, PICO_SIZE_IP6); |
TASS Belgium NV |
131:4758606c9316 | 1174 | memcpy(&s->remote_addr, dst, PICO_SIZE_IP6); |
tass | 68:0847e35d08a6 | 1175 | # ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 1176 | if (PROTO(s) == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1177 | remote_duple = pico_zalloc(sizeof(struct pico_remote_duple)); |
TASS Belgium NV |
131:4758606c9316 | 1178 | remote_duple->remote_addr.ip6.addr = ((struct pico_ip6 *)dst)->addr; |
TASS Belgium NV |
131:4758606c9316 | 1179 | remote_duple->remote_port = remote_port; |
TASS Belgium NV |
131:4758606c9316 | 1180 | } |
TASS Belgium NV |
131:4758606c9316 | 1181 | |
tass | 68:0847e35d08a6 | 1182 | # endif |
tass | 68:0847e35d08a6 | 1183 | } |
TASS Belgium NV |
131:4758606c9316 | 1184 | |
tass | 68:0847e35d08a6 | 1185 | #endif |
TASS Belgium NV |
131:4758606c9316 | 1186 | } |
tass | 68:0847e35d08a6 | 1187 | |
TASS Belgium NV |
131:4758606c9316 | 1188 | if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) { |
tass | 68:0847e35d08a6 | 1189 | s->local_port = pico_socket_high_port(s->proto->proto_number); |
tass | 68:0847e35d08a6 | 1190 | if (s->local_port == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1191 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1192 | return -1; |
tass | 68:0847e35d08a6 | 1193 | } |
TASS Belgium NV |
131:4758606c9316 | 1194 | } |
TASS Belgium NV |
131:4758606c9316 | 1195 | |
TASS Belgium NV |
131:4758606c9316 | 1196 | if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) { |
tass | 68:0847e35d08a6 | 1197 | s->remote_port = remote_port; |
TASS Belgium NV |
131:4758606c9316 | 1198 | } |
tass | 68:0847e35d08a6 | 1199 | |
tass | 68:0847e35d08a6 | 1200 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 1201 | if (PROTO(s) == PICO_PROTO_TCP) |
tass | 68:0847e35d08a6 | 1202 | header_offset = pico_tcp_overhead(s); |
TASS Belgium NV |
131:4758606c9316 | 1203 | |
tass | 68:0847e35d08a6 | 1204 | #endif |
tass | 68:0847e35d08a6 | 1205 | |
tass | 68:0847e35d08a6 | 1206 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 1207 | if (PROTO(s) == PICO_PROTO_UDP) |
tass | 68:0847e35d08a6 | 1208 | header_offset = sizeof(struct pico_udp_hdr); |
TASS Belgium NV |
131:4758606c9316 | 1209 | |
tass | 68:0847e35d08a6 | 1210 | #endif |
tass | 68:0847e35d08a6 | 1211 | |
TASS Belgium NV |
131:4758606c9316 | 1212 | while (total_payload_written < len) { |
TASS Belgium NV |
131:4758606c9316 | 1213 | int transport_len = (len - total_payload_written) + header_offset; |
tass | 68:0847e35d08a6 | 1214 | if (transport_len > socket_mtu) |
TASS Belgium NV |
131:4758606c9316 | 1215 | transport_len = socket_mtu; |
TASS Belgium NV |
131:4758606c9316 | 1216 | |
tass | 68:0847e35d08a6 | 1217 | #ifdef PICO_SUPPORT_IPFRAG |
tass | 68:0847e35d08a6 | 1218 | else { |
TASS Belgium NV |
131:4758606c9316 | 1219 | if (total_payload_written) |
TASS Belgium NV |
131:4758606c9316 | 1220 | transport_len -= header_offset; /* last fragment, do not allocate memory for transport header */ |
TASS Belgium NV |
131:4758606c9316 | 1221 | |
tass | 68:0847e35d08a6 | 1222 | } |
tass | 68:0847e35d08a6 | 1223 | #endif /* PICO_SUPPORT_IPFRAG */ |
tass | 68:0847e35d08a6 | 1224 | |
tass | 70:cd218dd180e5 | 1225 | f = pico_socket_frame_alloc(s, (uint16_t)transport_len); |
tass | 68:0847e35d08a6 | 1226 | if (!f) { |
TASS Belgium NV |
131:4758606c9316 | 1227 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 1228 | return -1; |
tass | 68:0847e35d08a6 | 1229 | } |
TASS Belgium NV |
131:4758606c9316 | 1230 | |
tass | 68:0847e35d08a6 | 1231 | f->payload += header_offset; |
tass | 73:dfb737147f6e | 1232 | f->payload_len = (uint16_t)(f->payload_len - header_offset); |
tass | 68:0847e35d08a6 | 1233 | f->sock = s; |
TASS Belgium NV |
131:4758606c9316 | 1234 | transport_flags_update(f, s); |
tass | 68:0847e35d08a6 | 1235 | if (remote_duple) { |
TASS Belgium NV |
131:4758606c9316 | 1236 | f->info = pico_zalloc(sizeof(struct pico_remote_duple)); |
TASS Belgium NV |
131:4758606c9316 | 1237 | memcpy(f->info, remote_duple, sizeof(struct pico_remote_duple)); |
tass | 68:0847e35d08a6 | 1238 | } |
tass | 68:0847e35d08a6 | 1239 | |
tass | 68:0847e35d08a6 | 1240 | #ifdef PICO_SUPPORT_IPFRAG |
tass | 68:0847e35d08a6 | 1241 | #ifdef PICO_SUPPORT_UDP |
tass | 68:0847e35d08a6 | 1242 | if (PROTO(s) == PICO_PROTO_UDP && ((len + header_offset) > socket_mtu)) { |
TASS Belgium NV |
131:4758606c9316 | 1243 | /* hacking way to identify fragmentation frames: payload != transport_hdr -> first frame */ |
TASS Belgium NV |
131:4758606c9316 | 1244 | if (!total_payload_written) { |
TASS Belgium NV |
131:4758606c9316 | 1245 | frag_dbg("FRAG: first fragmented frame %p | len = %u offset = 0\n", f, f->payload_len); |
TASS Belgium NV |
131:4758606c9316 | 1246 | /* transport header length field contains total length + header length */ |
TASS Belgium NV |
131:4758606c9316 | 1247 | f->transport_len = (uint16_t)(len + header_offset); |
TASS Belgium NV |
131:4758606c9316 | 1248 | f->frag = short_be(PICO_IPV4_MOREFRAG); |
tass | 68:0847e35d08a6 | 1249 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1250 | /* no transport header in fragmented IP */ |
TASS Belgium NV |
131:4758606c9316 | 1251 | f->payload = f->transport_hdr; |
TASS Belgium NV |
131:4758606c9316 | 1252 | f->payload_len = (uint16_t)(f->payload_len + header_offset); |
TASS Belgium NV |
131:4758606c9316 | 1253 | /* set offset in octets */ |
TASS Belgium NV |
131:4758606c9316 | 1254 | f->frag = short_be((uint16_t)((total_payload_written + header_offset) / 8)); |
TASS Belgium NV |
131:4758606c9316 | 1255 | if (total_payload_written + f->payload_len < len) { |
TASS Belgium NV |
131:4758606c9316 | 1256 | frag_dbg("FRAG: intermediate fragmented frame %p | len = %u offset = %u\n", f, f->payload_len, short_be(f->frag)); |
TASS Belgium NV |
131:4758606c9316 | 1257 | f->frag |= short_be(PICO_IPV4_MOREFRAG); |
TASS Belgium NV |
131:4758606c9316 | 1258 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1259 | frag_dbg("FRAG: last fragmented frame %p | len = %u offset = %u\n", f, f->payload_len, short_be(f->frag)); |
TASS Belgium NV |
131:4758606c9316 | 1260 | f->frag &= short_be(PICO_IPV4_FRAG_MASK); |
TASS Belgium NV |
131:4758606c9316 | 1261 | } |
tass | 68:0847e35d08a6 | 1262 | } |
tass | 68:0847e35d08a6 | 1263 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1264 | f->frag = short_be(PICO_IPV4_DONTFRAG); |
tass | 68:0847e35d08a6 | 1265 | } |
TASS Belgium NV |
131:4758606c9316 | 1266 | |
tass | 68:0847e35d08a6 | 1267 | # endif /* PICO_SUPPORT_UDP */ |
tass | 68:0847e35d08a6 | 1268 | #endif /* PICO_SUPPORT_IPFRAG */ |
tass | 68:0847e35d08a6 | 1269 | |
tass | 68:0847e35d08a6 | 1270 | if (f->payload_len <= 0) { |
TASS Belgium NV |
131:4758606c9316 | 1271 | pico_frame_discard(f); |
TASS Belgium NV |
131:4758606c9316 | 1272 | if (remote_duple) |
TASS Belgium NV |
131:4758606c9316 | 1273 | pico_free(remote_duple); |
TASS Belgium NV |
131:4758606c9316 | 1274 | |
TASS Belgium NV |
131:4758606c9316 | 1275 | return total_payload_written; |
tass | 68:0847e35d08a6 | 1276 | } |
tass | 68:0847e35d08a6 | 1277 | |
tass picotcp@tass.be | 134:cc4e6d2654d9 | 1278 | memcpy(f->payload, (const uint8_t *)buf + total_payload_written, f->payload_len); |
TASS Belgium NV |
131:4758606c9316 | 1279 | /* dbg("Pushing segment, hdr len: %d, payload_len: %d\n", header_offset, f->payload_len); */ |
tass | 68:0847e35d08a6 | 1280 | |
tass | 68:0847e35d08a6 | 1281 | if (s->proto->push(s->proto, f) > 0) { |
TASS Belgium NV |
131:4758606c9316 | 1282 | total_payload_written += (int)f->payload_len; |
tass | 68:0847e35d08a6 | 1283 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1284 | pico_frame_discard(f); |
TASS Belgium NV |
131:4758606c9316 | 1285 | pico_err = PICO_ERR_EAGAIN; |
TASS Belgium NV |
131:4758606c9316 | 1286 | break; |
tass | 68:0847e35d08a6 | 1287 | } |
TASS Belgium NV |
131:4758606c9316 | 1288 | } |
TASS Belgium NV |
131:4758606c9316 | 1289 | if (remote_duple) |
tass | 68:0847e35d08a6 | 1290 | pico_free(remote_duple); |
TASS Belgium NV |
131:4758606c9316 | 1291 | |
TASS Belgium NV |
131:4758606c9316 | 1292 | return total_payload_written; |
tass | 68:0847e35d08a6 | 1293 | } |
tass | 68:0847e35d08a6 | 1294 | |
tass | 68:0847e35d08a6 | 1295 | int pico_socket_send(struct pico_socket *s, const void *buf, int len) |
tass | 68:0847e35d08a6 | 1296 | { |
TASS Belgium NV |
131:4758606c9316 | 1297 | if (!s || buf == NULL) { |
TASS Belgium NV |
131:4758606c9316 | 1298 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1299 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1300 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1301 | /* check if exists in tree */ |
TASS Belgium NV |
131:4758606c9316 | 1302 | /* See task #178 */ |
TASS Belgium NV |
131:4758606c9316 | 1303 | if (pico_check_socket(s) != 0) { |
TASS Belgium NV |
131:4758606c9316 | 1304 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1305 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1306 | } |
tass | 68:0847e35d08a6 | 1307 | } |
tass | 68:0847e35d08a6 | 1308 | |
TASS Belgium NV |
131:4758606c9316 | 1309 | if ((s->state & PICO_SOCKET_STATE_CONNECTED) == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1310 | pico_err = PICO_ERR_ENOTCONN; |
TASS Belgium NV |
131:4758606c9316 | 1311 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1312 | } |
TASS Belgium NV |
131:4758606c9316 | 1313 | |
TASS Belgium NV |
131:4758606c9316 | 1314 | return pico_socket_sendto(s, buf, len, &s->remote_addr, s->remote_port); |
tass | 68:0847e35d08a6 | 1315 | } |
tass | 68:0847e35d08a6 | 1316 | |
tass | 68:0847e35d08a6 | 1317 | int pico_socket_recvfrom(struct pico_socket *s, void *buf, int len, void *orig, uint16_t *remote_port) |
tass | 68:0847e35d08a6 | 1318 | { |
TASS Belgium NV |
131:4758606c9316 | 1319 | if (!s || buf == NULL) { /* / || orig == NULL || remote_port == NULL) { */ |
TASS Belgium NV |
131:4758606c9316 | 1320 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1321 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1322 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1323 | /* check if exists in tree */ |
TASS Belgium NV |
131:4758606c9316 | 1324 | if (pico_check_socket(s) != 0) { |
TASS Belgium NV |
131:4758606c9316 | 1325 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1326 | /* See task #178 */ |
TASS Belgium NV |
131:4758606c9316 | 1327 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1328 | } |
tass | 68:0847e35d08a6 | 1329 | } |
TASS Belgium NV |
131:4758606c9316 | 1330 | |
TASS Belgium NV |
131:4758606c9316 | 1331 | if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1332 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 1333 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1334 | } |
tass | 68:0847e35d08a6 | 1335 | |
TASS Belgium NV |
131:4758606c9316 | 1336 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 1337 | if (PROTO(s) == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1338 | return pico_udp_recv(s, buf, (uint16_t)len, orig, remote_port); |
TASS Belgium NV |
131:4758606c9316 | 1339 | } |
TASS Belgium NV |
131:4758606c9316 | 1340 | |
tass | 68:0847e35d08a6 | 1341 | #endif |
tass | 68:0847e35d08a6 | 1342 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 1343 | if (PROTO(s) == PICO_PROTO_TCP) { |
TASS Belgium NV |
131:4758606c9316 | 1344 | /* check if in shutdown state and if tcpq_in empty */ |
TASS Belgium NV |
131:4758606c9316 | 1345 | if ((s->state & PICO_SOCKET_STATE_SHUT_REMOTE) && pico_tcp_queue_in_is_empty(s)) { |
TASS Belgium NV |
131:4758606c9316 | 1346 | pico_err = PICO_ERR_ESHUTDOWN; |
TASS Belgium NV |
131:4758606c9316 | 1347 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1348 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1349 | /* dbg("socket tcp recv\n"); */ |
TASS Belgium NV |
131:4758606c9316 | 1350 | return (int)pico_tcp_read(s, buf, (uint32_t)len); |
TASS Belgium NV |
131:4758606c9316 | 1351 | } |
tass | 68:0847e35d08a6 | 1352 | } |
TASS Belgium NV |
131:4758606c9316 | 1353 | |
tass | 68:0847e35d08a6 | 1354 | #endif |
TASS Belgium NV |
131:4758606c9316 | 1355 | /* dbg("socket return 0\n"); */ |
TASS Belgium NV |
131:4758606c9316 | 1356 | return 0; |
tass | 68:0847e35d08a6 | 1357 | } |
tass | 68:0847e35d08a6 | 1358 | |
tass | 68:0847e35d08a6 | 1359 | int pico_socket_recv(struct pico_socket *s, void *buf, int len) |
tass | 68:0847e35d08a6 | 1360 | { |
TASS Belgium NV |
131:4758606c9316 | 1361 | return pico_socket_recvfrom(s, buf, len, NULL, NULL); |
tass | 68:0847e35d08a6 | 1362 | } |
tass | 68:0847e35d08a6 | 1363 | |
tass | 68:0847e35d08a6 | 1364 | |
tass | 68:0847e35d08a6 | 1365 | int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port) |
tass | 68:0847e35d08a6 | 1366 | { |
TASS Belgium NV |
131:4758606c9316 | 1367 | if (!s || !local_addr || !port) { |
tass | 68:0847e35d08a6 | 1368 | pico_err = PICO_ERR_EINVAL; |
tass | 68:0847e35d08a6 | 1369 | return -1; |
tass | 68:0847e35d08a6 | 1370 | } |
TASS Belgium NV |
131:4758606c9316 | 1371 | |
TASS Belgium NV |
131:4758606c9316 | 1372 | if (!is_sock_ipv6(s)) { |
TASS Belgium NV |
131:4758606c9316 | 1373 | struct pico_ip4 *ip = (struct pico_ip4 *)local_addr; |
TASS Belgium NV |
131:4758606c9316 | 1374 | if (ip->addr != PICO_IPV4_INADDR_ANY) { |
TASS Belgium NV |
131:4758606c9316 | 1375 | if (!pico_ipv4_link_find(local_addr)) { |
TASS Belgium NV |
131:4758606c9316 | 1376 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1377 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1378 | } |
TASS Belgium NV |
131:4758606c9316 | 1379 | } |
TASS Belgium NV |
131:4758606c9316 | 1380 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1381 | /*... IPv6 */ |
TASS Belgium NV |
131:4758606c9316 | 1382 | } |
tass | 68:0847e35d08a6 | 1383 | |
tass | 68:0847e35d08a6 | 1384 | |
TASS Belgium NV |
131:4758606c9316 | 1385 | /* When given port = 0, get a random high port to bind to. */ |
tass | 68:0847e35d08a6 | 1386 | if (*port == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1387 | *port = pico_socket_high_port(PROTO(s)); |
TASS Belgium NV |
131:4758606c9316 | 1388 | if (*port == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1389 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1390 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1391 | } |
tass | 68:0847e35d08a6 | 1392 | } |
tass | 68:0847e35d08a6 | 1393 | |
TASS Belgium NV |
131:4758606c9316 | 1394 | if (pico_is_port_free(PROTO(s), *port, local_addr, s->net) == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1395 | pico_err = PICO_ERR_EADDRINUSE; |
TASS Belgium NV |
131:4758606c9316 | 1396 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1397 | } |
TASS Belgium NV |
131:4758606c9316 | 1398 | |
TASS Belgium NV |
131:4758606c9316 | 1399 | s->local_port = *port; |
tass | 68:0847e35d08a6 | 1400 | |
TASS Belgium NV |
131:4758606c9316 | 1401 | if (is_sock_ipv6(s)) { |
TASS Belgium NV |
131:4758606c9316 | 1402 | struct pico_ip6 *ip = (struct pico_ip6 *) local_addr; |
TASS Belgium NV |
131:4758606c9316 | 1403 | memcpy(s->local_addr.ip6.addr, ip, PICO_SIZE_IP6); |
TASS Belgium NV |
131:4758606c9316 | 1404 | /* XXX: port ipv4 functionality to ipv6 */ |
TASS Belgium NV |
131:4758606c9316 | 1405 | /* Check for port already in use */ |
TASS Belgium NV |
131:4758606c9316 | 1406 | if (pico_is_port_free(PROTO(s), *port, &local_addr, s->net)) { |
TASS Belgium NV |
131:4758606c9316 | 1407 | pico_err = PICO_ERR_EADDRINUSE; |
TASS Belgium NV |
131:4758606c9316 | 1408 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1409 | } |
TASS Belgium NV |
131:4758606c9316 | 1410 | } else if (is_sock_ipv4(s)) { |
TASS Belgium NV |
131:4758606c9316 | 1411 | struct pico_ip4 *ip = (struct pico_ip4 *) local_addr; |
TASS Belgium NV |
131:4758606c9316 | 1412 | s->local_addr.ip4.addr = ip->addr; |
tass | 68:0847e35d08a6 | 1413 | } |
TASS Belgium NV |
131:4758606c9316 | 1414 | |
TASS Belgium NV |
131:4758606c9316 | 1415 | return pico_socket_alter_state(s, PICO_SOCKET_STATE_BOUND, 0, 0); |
tass | 68:0847e35d08a6 | 1416 | } |
tass | 68:0847e35d08a6 | 1417 | |
tass | 68:0847e35d08a6 | 1418 | int pico_socket_connect(struct pico_socket *s, const void *remote_addr, uint16_t remote_port) |
tass | 68:0847e35d08a6 | 1419 | { |
TASS Belgium NV |
131:4758606c9316 | 1420 | int ret = -1; |
TASS Belgium NV |
131:4758606c9316 | 1421 | pico_err = PICO_ERR_EPROTONOSUPPORT; |
TASS Belgium NV |
131:4758606c9316 | 1422 | if (!s || remote_addr == NULL || remote_port == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1423 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1424 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1425 | } |
tass | 68:0847e35d08a6 | 1426 | |
TASS Belgium NV |
131:4758606c9316 | 1427 | s->remote_port = remote_port; |
tass | 68:0847e35d08a6 | 1428 | |
TASS Belgium NV |
131:4758606c9316 | 1429 | if (s->local_port == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1430 | s->local_port = pico_socket_high_port(PROTO(s)); |
TASS Belgium NV |
131:4758606c9316 | 1431 | if (!s->local_port) { |
TASS Belgium NV |
131:4758606c9316 | 1432 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1433 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1434 | } |
tass | 68:0847e35d08a6 | 1435 | } |
tass | 68:0847e35d08a6 | 1436 | |
TASS Belgium NV |
131:4758606c9316 | 1437 | if (is_sock_ipv6(s)) { |
TASS Belgium NV |
131:4758606c9316 | 1438 | const struct pico_ip6 *ip = (const struct pico_ip6 *) remote_addr; |
TASS Belgium NV |
131:4758606c9316 | 1439 | memcpy(s->remote_addr.ip6.addr, ip, PICO_SIZE_IP6); |
TASS Belgium NV |
131:4758606c9316 | 1440 | } else if (is_sock_ipv4(s)) { |
TASS Belgium NV |
131:4758606c9316 | 1441 | const struct pico_ip4 *local, *ip = (const struct pico_ip4 *) remote_addr; |
TASS Belgium NV |
131:4758606c9316 | 1442 | s->remote_addr.ip4.addr = ip->addr; |
TASS Belgium NV |
131:4758606c9316 | 1443 | local = pico_ipv4_source_find(ip); |
TASS Belgium NV |
131:4758606c9316 | 1444 | if (local) { |
TASS Belgium NV |
131:4758606c9316 | 1445 | s->local_addr.ip4.addr = local->addr; |
TASS Belgium NV |
131:4758606c9316 | 1446 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1447 | pico_err = PICO_ERR_EHOSTUNREACH; |
TASS Belgium NV |
131:4758606c9316 | 1448 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1449 | } |
tass | 68:0847e35d08a6 | 1450 | } |
tass | 68:0847e35d08a6 | 1451 | |
TASS Belgium NV |
131:4758606c9316 | 1452 | pico_socket_alter_state(s, PICO_SOCKET_STATE_BOUND, 0, 0); |
tass | 68:0847e35d08a6 | 1453 | |
tass | 68:0847e35d08a6 | 1454 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 1455 | if (PROTO(s) == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1456 | pico_socket_alter_state(s, PICO_SOCKET_STATE_CONNECTED, 0, 0); |
TASS Belgium NV |
131:4758606c9316 | 1457 | pico_err = PICO_ERR_NOERR; |
TASS Belgium NV |
131:4758606c9316 | 1458 | ret = 0; |
TASS Belgium NV |
131:4758606c9316 | 1459 | } |
TASS Belgium NV |
131:4758606c9316 | 1460 | |
tass | 68:0847e35d08a6 | 1461 | #endif |
tass | 68:0847e35d08a6 | 1462 | |
tass | 68:0847e35d08a6 | 1463 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 1464 | if (PROTO(s) == PICO_PROTO_TCP) { |
TASS Belgium NV |
131:4758606c9316 | 1465 | if (pico_tcp_initconn(s) == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1466 | pico_socket_alter_state(s, PICO_SOCKET_STATE_CONNECTED | PICO_SOCKET_STATE_TCP_SYN_SENT, 0, 0); |
TASS Belgium NV |
131:4758606c9316 | 1467 | pico_err = PICO_ERR_NOERR; |
TASS Belgium NV |
131:4758606c9316 | 1468 | ret = 0; |
TASS Belgium NV |
131:4758606c9316 | 1469 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1470 | pico_err = PICO_ERR_EHOSTUNREACH; |
TASS Belgium NV |
131:4758606c9316 | 1471 | } |
tass | 68:0847e35d08a6 | 1472 | } |
TASS Belgium NV |
131:4758606c9316 | 1473 | |
tass | 68:0847e35d08a6 | 1474 | #endif |
tass | 68:0847e35d08a6 | 1475 | |
TASS Belgium NV |
131:4758606c9316 | 1476 | return ret; |
tass | 68:0847e35d08a6 | 1477 | } |
tass | 68:0847e35d08a6 | 1478 | |
tass | 68:0847e35d08a6 | 1479 | #ifdef PICO_SUPPORT_TCP |
tass | 68:0847e35d08a6 | 1480 | |
tass | 68:0847e35d08a6 | 1481 | int pico_socket_listen(struct pico_socket *s, int backlog) |
tass | 68:0847e35d08a6 | 1482 | { |
TASS Belgium NV |
131:4758606c9316 | 1483 | if (!s || backlog < 1) { |
TASS Belgium NV |
131:4758606c9316 | 1484 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1485 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1486 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1487 | /* check if exists in tree */ |
TASS Belgium NV |
131:4758606c9316 | 1488 | /* See task #178 */ |
TASS Belgium NV |
131:4758606c9316 | 1489 | if (pico_check_socket(s) != 0) { |
TASS Belgium NV |
131:4758606c9316 | 1490 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1491 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1492 | } |
tass | 68:0847e35d08a6 | 1493 | } |
TASS Belgium NV |
131:4758606c9316 | 1494 | |
TASS Belgium NV |
131:4758606c9316 | 1495 | if (PROTO(s) == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1496 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1497 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1498 | } |
tass | 68:0847e35d08a6 | 1499 | |
TASS Belgium NV |
131:4758606c9316 | 1500 | if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1501 | pico_err = PICO_ERR_EISCONN; |
TASS Belgium NV |
131:4758606c9316 | 1502 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1503 | } |
tass | 68:0847e35d08a6 | 1504 | |
TASS Belgium NV |
131:4758606c9316 | 1505 | if (backlog < 1) { |
TASS Belgium NV |
131:4758606c9316 | 1506 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1507 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1508 | } |
tass | 68:0847e35d08a6 | 1509 | |
TASS Belgium NV |
131:4758606c9316 | 1510 | if (PROTO(s) == PICO_PROTO_TCP) |
TASS Belgium NV |
131:4758606c9316 | 1511 | pico_socket_alter_state(s, PICO_SOCKET_STATE_TCP_SYN_SENT, 0, PICO_SOCKET_STATE_TCP_LISTEN); |
tass | 68:0847e35d08a6 | 1512 | |
TASS Belgium NV |
131:4758606c9316 | 1513 | s->max_backlog = backlog; |
TASS Belgium NV |
131:4758606c9316 | 1514 | |
TASS Belgium NV |
131:4758606c9316 | 1515 | return 0; |
tass | 68:0847e35d08a6 | 1516 | } |
tass | 68:0847e35d08a6 | 1517 | |
tass | 68:0847e35d08a6 | 1518 | struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *port) |
tass | 68:0847e35d08a6 | 1519 | { |
TASS Belgium NV |
131:4758606c9316 | 1520 | if (!s || !orig || !port) { |
TASS Belgium NV |
131:4758606c9316 | 1521 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1522 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 1523 | } |
TASS Belgium NV |
131:4758606c9316 | 1524 | |
tass | 68:0847e35d08a6 | 1525 | pico_err = PICO_ERR_EINVAL; |
tass | 68:0847e35d08a6 | 1526 | |
TASS Belgium NV |
131:4758606c9316 | 1527 | if ((s->state & PICO_SOCKET_STATE_BOUND) == 0) { |
TASS Belgium NV |
131:4758606c9316 | 1528 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 1529 | } |
tass | 68:0847e35d08a6 | 1530 | |
TASS Belgium NV |
131:4758606c9316 | 1531 | if (PROTO(s) == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1532 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 1533 | } |
tass | 68:0847e35d08a6 | 1534 | |
TASS Belgium NV |
131:4758606c9316 | 1535 | if (TCPSTATE(s) == PICO_SOCKET_STATE_TCP_LISTEN) { |
TASS Belgium NV |
131:4758606c9316 | 1536 | struct pico_sockport *sp = pico_get_sockport(PICO_PROTO_TCP, s->local_port); |
TASS Belgium NV |
131:4758606c9316 | 1537 | struct pico_socket *found; |
TASS Belgium NV |
131:4758606c9316 | 1538 | /* If at this point no incoming connection socket is found, |
TASS Belgium NV |
131:4758606c9316 | 1539 | * the accept call is valid, but no connection is established yet. |
TASS Belgium NV |
131:4758606c9316 | 1540 | */ |
TASS Belgium NV |
131:4758606c9316 | 1541 | pico_err = PICO_ERR_EAGAIN; |
TASS Belgium NV |
131:4758606c9316 | 1542 | if (sp) { |
TASS Belgium NV |
131:4758606c9316 | 1543 | struct pico_tree_node *index; |
TASS Belgium NV |
131:4758606c9316 | 1544 | /* RB_FOREACH(found, socket_tree, &sp->socks) { */ |
TASS Belgium NV |
131:4758606c9316 | 1545 | pico_tree_foreach(index, &sp->socks){ |
TASS Belgium NV |
131:4758606c9316 | 1546 | found = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 1547 | if ((s == found->parent) && ((found->state & PICO_SOCKET_STATE_TCP) == PICO_SOCKET_STATE_TCP_ESTABLISHED)) { |
TASS Belgium NV |
131:4758606c9316 | 1548 | found->parent = NULL; |
TASS Belgium NV |
131:4758606c9316 | 1549 | pico_err = PICO_ERR_NOERR; |
TASS Belgium NV |
131:4758606c9316 | 1550 | memcpy(orig, &found->remote_addr, sizeof(struct pico_ip4)); |
TASS Belgium NV |
131:4758606c9316 | 1551 | *port = found->remote_port; |
TASS Belgium NV |
131:4758606c9316 | 1552 | s->number_of_pending_conn--; |
TASS Belgium NV |
131:4758606c9316 | 1553 | return found; |
TASS Belgium NV |
131:4758606c9316 | 1554 | } |
TASS Belgium NV |
131:4758606c9316 | 1555 | } |
tass | 68:0847e35d08a6 | 1556 | } |
tass | 68:0847e35d08a6 | 1557 | } |
TASS Belgium NV |
131:4758606c9316 | 1558 | |
TASS Belgium NV |
131:4758606c9316 | 1559 | return NULL; |
tass | 68:0847e35d08a6 | 1560 | } |
tass | 68:0847e35d08a6 | 1561 | |
tass | 68:0847e35d08a6 | 1562 | #else |
tass | 68:0847e35d08a6 | 1563 | |
tass | 68:0847e35d08a6 | 1564 | int pico_socket_listen(struct pico_socket *s, int backlog) |
tass | 68:0847e35d08a6 | 1565 | { |
TASS Belgium NV |
131:4758606c9316 | 1566 | IGNORE_PARAMETER(s); |
TASS Belgium NV |
131:4758606c9316 | 1567 | IGNORE_PARAMETER(backlog); |
TASS Belgium NV |
131:4758606c9316 | 1568 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1569 | return -1; |
tass | 68:0847e35d08a6 | 1570 | } |
tass | 68:0847e35d08a6 | 1571 | |
tass | 68:0847e35d08a6 | 1572 | struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *local_port) |
tass | 68:0847e35d08a6 | 1573 | { |
TASS Belgium NV |
131:4758606c9316 | 1574 | IGNORE_PARAMETER(s); |
TASS Belgium NV |
131:4758606c9316 | 1575 | IGNORE_PARAMETER(orig); |
TASS Belgium NV |
131:4758606c9316 | 1576 | IGNORE_PARAMETER(local_port); |
TASS Belgium NV |
131:4758606c9316 | 1577 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1578 | return NULL; |
tass | 68:0847e35d08a6 | 1579 | } |
tass | 68:0847e35d08a6 | 1580 | |
tass | 68:0847e35d08a6 | 1581 | #endif |
tass | 68:0847e35d08a6 | 1582 | |
TASS Belgium NV |
131:4758606c9316 | 1583 | #define PICO_SOCKET_SETOPT_EN(socket, index) (socket->opt_flags |= (1 << index)) |
TASS Belgium NV |
131:4758606c9316 | 1584 | #define PICO_SOCKET_SETOPT_DIS(socket, index) (socket->opt_flags &= (uint16_t) ~(1 << index)) |
tass | 68:0847e35d08a6 | 1585 | |
tass | 74:c146c4e346c4 | 1586 | #ifdef PICO_SUPPORT_MCAST |
tass | 74:c146c4e346c4 | 1587 | static struct pico_ipv4_link *setopt_multicast_check(struct pico_socket *s, void *value, int alloc, int bysource) |
tass | 74:c146c4e346c4 | 1588 | { |
tass | 74:c146c4e346c4 | 1589 | struct pico_ip_mreq *mreq = NULL; |
tass | 74:c146c4e346c4 | 1590 | struct pico_ipv4_link *mcast_link = NULL; |
tass | 74:c146c4e346c4 | 1591 | struct pico_ip_mreq_source *mreq_src = NULL; |
tass | 74:c146c4e346c4 | 1592 | |
tass | 74:c146c4e346c4 | 1593 | if (!value) { |
TASS Belgium NV |
131:4758606c9316 | 1594 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1595 | return NULL; |
tass | 74:c146c4e346c4 | 1596 | } |
TASS Belgium NV |
131:4758606c9316 | 1597 | |
tass | 74:c146c4e346c4 | 1598 | if (!bysource) { |
TASS Belgium NV |
131:4758606c9316 | 1599 | mreq = (struct pico_ip_mreq *) value; |
TASS Belgium NV |
131:4758606c9316 | 1600 | mcast_link = pico_socket_setoption_mcastargs_validation(mreq, NULL); |
TASS Belgium NV |
131:4758606c9316 | 1601 | if (!mreq->mcast_link_addr.addr) |
TASS Belgium NV |
131:4758606c9316 | 1602 | mreq->mcast_link_addr.addr = mcast_link->address.addr; |
tass | 74:c146c4e346c4 | 1603 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1604 | mreq_src = (struct pico_ip_mreq_source *) value; |
TASS Belgium NV |
131:4758606c9316 | 1605 | mcast_link = pico_socket_setoption_mcastargs_validation(NULL, mreq_src); |
TASS Belgium NV |
131:4758606c9316 | 1606 | if (!mreq_src->mcast_link_addr.addr) |
TASS Belgium NV |
131:4758606c9316 | 1607 | mreq_src->mcast_link_addr.addr = mcast_link->address.addr; |
tass | 74:c146c4e346c4 | 1608 | } |
TASS Belgium NV |
131:4758606c9316 | 1609 | |
tass | 74:c146c4e346c4 | 1610 | if (!mcast_link) { |
TASS Belgium NV |
131:4758606c9316 | 1611 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1612 | return NULL; |
tass | 74:c146c4e346c4 | 1613 | } |
tass | 74:c146c4e346c4 | 1614 | |
tass | 74:c146c4e346c4 | 1615 | if (!s->MCASTListen) { /* No RBTree allocated yet */ |
TASS Belgium NV |
131:4758606c9316 | 1616 | if (alloc) { |
TASS Belgium NV |
131:4758606c9316 | 1617 | s->MCASTListen = pico_zalloc(sizeof(struct pico_tree)); |
TASS Belgium NV |
131:4758606c9316 | 1618 | if (!s->MCASTListen) { |
TASS Belgium NV |
131:4758606c9316 | 1619 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 1620 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 1621 | } |
TASS Belgium NV |
131:4758606c9316 | 1622 | |
TASS Belgium NV |
131:4758606c9316 | 1623 | s->MCASTListen->root = &LEAF; |
TASS Belgium NV |
131:4758606c9316 | 1624 | s->MCASTListen->compare = mcast_listen_cmp; |
TASS Belgium NV |
131:4758606c9316 | 1625 | } else return NULL; |
tass | 74:c146c4e346c4 | 1626 | } |
TASS Belgium NV |
131:4758606c9316 | 1627 | |
tass | 74:c146c4e346c4 | 1628 | return mcast_link; |
tass | 74:c146c4e346c4 | 1629 | } |
tass | 74:c146c4e346c4 | 1630 | #endif |
tass | 74:c146c4e346c4 | 1631 | |
TASS Belgium NV |
131:4758606c9316 | 1632 | int pico_socket_setoption(struct pico_socket *s, int option, void *value) /* XXX no check against proto (vs setsockopt) or implicit by socket? */ |
tass | 68:0847e35d08a6 | 1633 | { |
TASS Belgium NV |
131:4758606c9316 | 1634 | if (s == NULL) { |
TASS Belgium NV |
131:4758606c9316 | 1635 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1636 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1637 | } |
tass | 68:0847e35d08a6 | 1638 | |
TASS Belgium NV |
131:4758606c9316 | 1639 | pico_err = PICO_ERR_NOERR; |
tass | 68:0847e35d08a6 | 1640 | |
TASS Belgium NV |
131:4758606c9316 | 1641 | switch (option) |
TASS Belgium NV |
131:4758606c9316 | 1642 | { |
tass | 68:0847e35d08a6 | 1643 | #ifdef PICO_SUPPORT_TCP |
tass | 68:0847e35d08a6 | 1644 | case PICO_TCP_NODELAY: |
TASS Belgium NV |
131:4758606c9316 | 1645 | if (!value) { |
tass | 68:0847e35d08a6 | 1646 | pico_err = PICO_ERR_EINVAL; |
tass | 68:0847e35d08a6 | 1647 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1648 | } |
TASS Belgium NV |
131:4758606c9316 | 1649 | |
TASS Belgium NV |
131:4758606c9316 | 1650 | if (s->proto->proto_number == PICO_PROTO_TCP) { |
tass | 68:0847e35d08a6 | 1651 | int *val = (int*)value; |
tass | 68:0847e35d08a6 | 1652 | if (*val > 0) { |
TASS Belgium NV |
131:4758606c9316 | 1653 | dbg("setsockopt: Nagle algorithm disabled.\n"); |
TASS Belgium NV |
131:4758606c9316 | 1654 | PICO_SOCKET_SETOPT_EN(s, PICO_SOCKET_OPT_TCPNODELAY); |
tass | 68:0847e35d08a6 | 1655 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1656 | dbg("setsockopt: Nagle algorithm enabled.\n"); |
TASS Belgium NV |
131:4758606c9316 | 1657 | PICO_SOCKET_SETOPT_DIS(s, PICO_SOCKET_OPT_TCPNODELAY); |
tass | 68:0847e35d08a6 | 1658 | } |
TASS Belgium NV |
131:4758606c9316 | 1659 | } else { |
tass | 68:0847e35d08a6 | 1660 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1661 | } |
TASS Belgium NV |
131:4758606c9316 | 1662 | |
TASS Belgium NV |
131:4758606c9316 | 1663 | break; |
tass | 68:0847e35d08a6 | 1664 | #endif |
tass | 68:0847e35d08a6 | 1665 | |
tass | 68:0847e35d08a6 | 1666 | |
tass | 68:0847e35d08a6 | 1667 | #ifdef PICO_SUPPORT_MCAST |
tass | 68:0847e35d08a6 | 1668 | case PICO_IP_MULTICAST_IF: |
TASS Belgium NV |
131:4758606c9316 | 1669 | pico_err = PICO_ERR_EOPNOTSUPP; |
TASS Belgium NV |
131:4758606c9316 | 1670 | return -1; |
tass | 68:0847e35d08a6 | 1671 | |
tass | 68:0847e35d08a6 | 1672 | case PICO_IP_MULTICAST_TTL: |
TASS Belgium NV |
131:4758606c9316 | 1673 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
tass | 68:0847e35d08a6 | 1674 | return pico_udp_set_mc_ttl(s, *((uint8_t *) value)); |
TASS Belgium NV |
131:4758606c9316 | 1675 | } |
TASS Belgium NV |
131:4758606c9316 | 1676 | |
TASS Belgium NV |
131:4758606c9316 | 1677 | break; |
tass | 68:0847e35d08a6 | 1678 | |
tass | 68:0847e35d08a6 | 1679 | case PICO_IP_MULTICAST_LOOP: |
TASS Belgium NV |
131:4758606c9316 | 1680 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
tass | 68:0847e35d08a6 | 1681 | switch (*(uint8_t *) value) |
tass | 68:0847e35d08a6 | 1682 | { |
TASS Belgium NV |
131:4758606c9316 | 1683 | case 0: |
tass | 68:0847e35d08a6 | 1684 | /* do not loop back multicast datagram */ |
TASS Belgium NV |
131:4758606c9316 | 1685 | PICO_SOCKET_SETOPT_DIS(s, PICO_SOCKET_OPT_MULTICAST_LOOP); |
tass | 68:0847e35d08a6 | 1686 | break; |
tass | 68:0847e35d08a6 | 1687 | |
TASS Belgium NV |
131:4758606c9316 | 1688 | case 1: |
tass | 68:0847e35d08a6 | 1689 | /* do loop back multicast datagram */ |
TASS Belgium NV |
131:4758606c9316 | 1690 | PICO_SOCKET_SETOPT_EN(s, PICO_SOCKET_OPT_MULTICAST_LOOP); |
TASS Belgium NV |
131:4758606c9316 | 1691 | break; |
tass | 68:0847e35d08a6 | 1692 | |
TASS Belgium NV |
131:4758606c9316 | 1693 | default: |
tass | 68:0847e35d08a6 | 1694 | pico_err = PICO_ERR_EINVAL; |
tass | 68:0847e35d08a6 | 1695 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1696 | } |
TASS Belgium NV |
131:4758606c9316 | 1697 | } |
TASS Belgium NV |
131:4758606c9316 | 1698 | |
TASS Belgium NV |
131:4758606c9316 | 1699 | break; |
tass | 68:0847e35d08a6 | 1700 | |
tass | 68:0847e35d08a6 | 1701 | case PICO_IP_ADD_MEMBERSHIP: |
TASS Belgium NV |
131:4758606c9316 | 1702 | /* EXCLUDE mode */ |
TASS Belgium NV |
131:4758606c9316 | 1703 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1704 | int filter_mode; |
TASS Belgium NV |
131:4758606c9316 | 1705 | struct pico_mcast_listen *listen; |
TASS Belgium NV |
131:4758606c9316 | 1706 | struct pico_ip_mreq *mreq = (struct pico_ip_mreq *)value; |
TASS Belgium NV |
131:4758606c9316 | 1707 | struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 1, 0); |
TASS Belgium NV |
131:4758606c9316 | 1708 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 1709 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1710 | |
TASS Belgium NV |
131:4758606c9316 | 1711 | listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1712 | if (listen) { |
TASS Belgium NV |
131:4758606c9316 | 1713 | if (listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) { |
TASS Belgium NV |
131:4758606c9316 | 1714 | so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n"); |
TASS Belgium NV |
131:4758606c9316 | 1715 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1716 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1717 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1718 | so_mcast_dbg("pico_socket_setoption: ERROR duplicate PICO_IP_ADD_MEMBERSHIP\n"); |
TASS Belgium NV |
131:4758606c9316 | 1719 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1720 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1721 | } |
TASS Belgium NV |
131:4758606c9316 | 1722 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1723 | listen = pico_zalloc(sizeof(struct pico_mcast_listen)); |
TASS Belgium NV |
131:4758606c9316 | 1724 | if (!listen) { |
TASS Belgium NV |
131:4758606c9316 | 1725 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 1726 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1727 | } |
TASS Belgium NV |
131:4758606c9316 | 1728 | |
TASS Belgium NV |
131:4758606c9316 | 1729 | listen->filter_mode = PICO_IP_MULTICAST_EXCLUDE; |
TASS Belgium NV |
131:4758606c9316 | 1730 | listen->mcast_link = mreq->mcast_link_addr; |
TASS Belgium NV |
131:4758606c9316 | 1731 | listen->mcast_group = mreq->mcast_group_addr; |
TASS Belgium NV |
131:4758606c9316 | 1732 | listen->MCASTSources.root = &LEAF; |
TASS Belgium NV |
131:4758606c9316 | 1733 | listen->MCASTSources.compare = mcast_sources_cmp; |
TASS Belgium NV |
131:4758606c9316 | 1734 | pico_tree_insert(s->MCASTListen, listen); |
TASS Belgium NV |
131:4758606c9316 | 1735 | } |
TASS Belgium NV |
131:4758606c9316 | 1736 | |
TASS Belgium NV |
131:4758606c9316 | 1737 | pico_tree_insert(&MCASTSockets, s); |
TASS Belgium NV |
131:4758606c9316 | 1738 | filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1739 | if (filter_mode < 0) |
TASS Belgium NV |
131:4758606c9316 | 1740 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1741 | |
TASS Belgium NV |
131:4758606c9316 | 1742 | return pico_ipv4_mcast_join(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter); |
tass | 68:0847e35d08a6 | 1743 | } |
tass | 68:0847e35d08a6 | 1744 | |
TASS Belgium NV |
131:4758606c9316 | 1745 | break; |
tass | 68:0847e35d08a6 | 1746 | |
tass | 68:0847e35d08a6 | 1747 | case PICO_IP_DROP_MEMBERSHIP: |
TASS Belgium NV |
131:4758606c9316 | 1748 | /* EXCLUDE mode */ |
TASS Belgium NV |
131:4758606c9316 | 1749 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1750 | int filter_mode = 0; |
TASS Belgium NV |
131:4758606c9316 | 1751 | struct pico_mcast_listen *listen; |
TASS Belgium NV |
131:4758606c9316 | 1752 | struct pico_ip_mreq *mreq = (struct pico_ip_mreq *)value; |
TASS Belgium NV |
131:4758606c9316 | 1753 | struct pico_ip4 *source = NULL; |
TASS Belgium NV |
131:4758606c9316 | 1754 | struct pico_tree_node *index, *_tmp; |
TASS Belgium NV |
131:4758606c9316 | 1755 | struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 0); |
TASS Belgium NV |
131:4758606c9316 | 1756 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 1757 | return -1; |
tass | 68:0847e35d08a6 | 1758 | |
TASS Belgium NV |
131:4758606c9316 | 1759 | listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1760 | if (!listen) { |
TASS Belgium NV |
131:4758606c9316 | 1761 | so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_DROP_MEMBERSHIP before PICO_IP_ADD_MEMBERSHIP/SOURCE_MEMBERSHIP\n"); |
TASS Belgium NV |
131:4758606c9316 | 1762 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 1763 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1764 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1765 | pico_tree_foreach_safe(index, &listen->MCASTSources, _tmp) |
TASS Belgium NV |
131:4758606c9316 | 1766 | { |
TASS Belgium NV |
131:4758606c9316 | 1767 | source = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 1768 | pico_tree_delete(&listen->MCASTSources, source); |
TASS Belgium NV |
131:4758606c9316 | 1769 | pico_free(source); |
TASS Belgium NV |
131:4758606c9316 | 1770 | } |
TASS Belgium NV |
131:4758606c9316 | 1771 | pico_tree_delete(s->MCASTListen, listen); |
TASS Belgium NV |
131:4758606c9316 | 1772 | pico_free(listen); |
TASS Belgium NV |
131:4758606c9316 | 1773 | if (pico_tree_empty(s->MCASTListen)) { |
TASS Belgium NV |
131:4758606c9316 | 1774 | pico_free(s->MCASTListen); |
TASS Belgium NV |
131:4758606c9316 | 1775 | s->MCASTListen = NULL; |
TASS Belgium NV |
131:4758606c9316 | 1776 | pico_tree_delete(&MCASTSockets, s); |
TASS Belgium NV |
131:4758606c9316 | 1777 | } |
TASS Belgium NV |
131:4758606c9316 | 1778 | } |
TASS Belgium NV |
131:4758606c9316 | 1779 | |
TASS Belgium NV |
131:4758606c9316 | 1780 | filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1781 | if (filter_mode < 0) |
TASS Belgium NV |
131:4758606c9316 | 1782 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1783 | |
TASS Belgium NV |
131:4758606c9316 | 1784 | return pico_ipv4_mcast_leave(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter); |
tass | 68:0847e35d08a6 | 1785 | } |
tass | 68:0847e35d08a6 | 1786 | |
TASS Belgium NV |
131:4758606c9316 | 1787 | break; |
tass | 68:0847e35d08a6 | 1788 | |
tass | 68:0847e35d08a6 | 1789 | case PICO_IP_UNBLOCK_SOURCE: |
TASS Belgium NV |
131:4758606c9316 | 1790 | /* EXCLUDE mode */ |
TASS Belgium NV |
131:4758606c9316 | 1791 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1792 | int filter_mode = 0; |
TASS Belgium NV |
131:4758606c9316 | 1793 | struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value; |
TASS Belgium NV |
131:4758606c9316 | 1794 | struct pico_mcast_listen *listen = NULL; |
TASS Belgium NV |
131:4758606c9316 | 1795 | struct pico_ip4 *source = NULL, stest = { |
TASS Belgium NV |
131:4758606c9316 | 1796 | 0 |
TASS Belgium NV |
131:4758606c9316 | 1797 | }; |
TASS Belgium NV |
131:4758606c9316 | 1798 | struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 1); |
TASS Belgium NV |
131:4758606c9316 | 1799 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 1800 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1801 | |
TASS Belgium NV |
131:4758606c9316 | 1802 | listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1803 | if (!listen) { |
TASS Belgium NV |
131:4758606c9316 | 1804 | so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_UNBLOCK_SOURCE before PICO_IP_ADD_MEMBERSHIP\n"); |
TASS Belgium NV |
131:4758606c9316 | 1805 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1806 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1807 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1808 | if (listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) { |
TASS Belgium NV |
131:4758606c9316 | 1809 | so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n"); |
TASS Belgium NV |
131:4758606c9316 | 1810 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1811 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1812 | } |
TASS Belgium NV |
131:4758606c9316 | 1813 | |
TASS Belgium NV |
131:4758606c9316 | 1814 | stest.addr = mreq->mcast_source_addr.addr; |
TASS Belgium NV |
131:4758606c9316 | 1815 | source = pico_tree_findKey(&listen->MCASTSources, &stest); |
TASS Belgium NV |
131:4758606c9316 | 1816 | if (!source) { |
TASS Belgium NV |
131:4758606c9316 | 1817 | so_mcast_dbg("pico_socket_setoption: ERROR address to unblock not in source list\n"); |
TASS Belgium NV |
131:4758606c9316 | 1818 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 1819 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1820 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1821 | pico_tree_delete(&listen->MCASTSources, source); |
TASS Belgium NV |
131:4758606c9316 | 1822 | pico_free(source); |
TASS Belgium NV |
131:4758606c9316 | 1823 | } |
TASS Belgium NV |
131:4758606c9316 | 1824 | } |
TASS Belgium NV |
131:4758606c9316 | 1825 | |
TASS Belgium NV |
131:4758606c9316 | 1826 | filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1827 | if (filter_mode < 0) |
TASS Belgium NV |
131:4758606c9316 | 1828 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1829 | |
TASS Belgium NV |
131:4758606c9316 | 1830 | return pico_ipv4_mcast_leave(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter); |
tass | 68:0847e35d08a6 | 1831 | } |
tass | 68:0847e35d08a6 | 1832 | |
TASS Belgium NV |
131:4758606c9316 | 1833 | break; |
tass | 68:0847e35d08a6 | 1834 | |
tass | 68:0847e35d08a6 | 1835 | case PICO_IP_BLOCK_SOURCE: |
TASS Belgium NV |
131:4758606c9316 | 1836 | /* EXCLUDE mode */ |
TASS Belgium NV |
131:4758606c9316 | 1837 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1838 | int filter_mode = 0; |
TASS Belgium NV |
131:4758606c9316 | 1839 | struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value; |
TASS Belgium NV |
131:4758606c9316 | 1840 | struct pico_mcast_listen *listen = NULL; |
TASS Belgium NV |
131:4758606c9316 | 1841 | struct pico_ip4 *source = NULL, stest = { |
TASS Belgium NV |
131:4758606c9316 | 1842 | 0 |
TASS Belgium NV |
131:4758606c9316 | 1843 | }; |
TASS Belgium NV |
131:4758606c9316 | 1844 | struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 1); |
TASS Belgium NV |
131:4758606c9316 | 1845 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 1846 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1847 | |
TASS Belgium NV |
131:4758606c9316 | 1848 | listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1849 | if (!listen) { |
TASS Belgium NV |
131:4758606c9316 | 1850 | dbg("pico_socket_setoption: ERROR PICO_IP_BLOCK_SOURCE before PICO_IP_ADD_MEMBERSHIP\n"); |
TASS Belgium NV |
131:4758606c9316 | 1851 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1852 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1853 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1854 | if (listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) { |
TASS Belgium NV |
131:4758606c9316 | 1855 | so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n"); |
TASS Belgium NV |
131:4758606c9316 | 1856 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1857 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1858 | } |
TASS Belgium NV |
131:4758606c9316 | 1859 | |
TASS Belgium NV |
131:4758606c9316 | 1860 | stest.addr = mreq->mcast_source_addr.addr; |
TASS Belgium NV |
131:4758606c9316 | 1861 | source = pico_tree_findKey(&listen->MCASTSources, &stest); |
TASS Belgium NV |
131:4758606c9316 | 1862 | if (source) { |
TASS Belgium NV |
131:4758606c9316 | 1863 | so_mcast_dbg("pico_socket_setoption: ERROR address to block already in source list\n"); |
TASS Belgium NV |
131:4758606c9316 | 1864 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 1865 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1866 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1867 | source = pico_zalloc(sizeof(struct pico_ip4)); |
TASS Belgium NV |
131:4758606c9316 | 1868 | if (!source) { |
TASS Belgium NV |
131:4758606c9316 | 1869 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 1870 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1871 | } |
TASS Belgium NV |
131:4758606c9316 | 1872 | |
TASS Belgium NV |
131:4758606c9316 | 1873 | source->addr = mreq->mcast_source_addr.addr; |
TASS Belgium NV |
131:4758606c9316 | 1874 | pico_tree_insert(&listen->MCASTSources, source); |
TASS Belgium NV |
131:4758606c9316 | 1875 | } |
tass | 68:0847e35d08a6 | 1876 | } |
TASS Belgium NV |
131:4758606c9316 | 1877 | |
TASS Belgium NV |
131:4758606c9316 | 1878 | filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1879 | if (filter_mode < 0) |
TASS Belgium NV |
131:4758606c9316 | 1880 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1881 | |
TASS Belgium NV |
131:4758606c9316 | 1882 | return pico_ipv4_mcast_join(&mreq->mcast_link_addr, &mreq->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter); |
tass | 68:0847e35d08a6 | 1883 | } |
tass | 68:0847e35d08a6 | 1884 | |
TASS Belgium NV |
131:4758606c9316 | 1885 | break; |
tass | 68:0847e35d08a6 | 1886 | |
tass | 68:0847e35d08a6 | 1887 | case PICO_IP_ADD_SOURCE_MEMBERSHIP: |
TASS Belgium NV |
131:4758606c9316 | 1888 | /* INCLUDE mode */ |
TASS Belgium NV |
131:4758606c9316 | 1889 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1890 | int filter_mode = 0, reference_count = 0; |
TASS Belgium NV |
131:4758606c9316 | 1891 | struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value; |
TASS Belgium NV |
131:4758606c9316 | 1892 | struct pico_mcast_listen *listen = NULL; |
TASS Belgium NV |
131:4758606c9316 | 1893 | struct pico_ip4 *source = NULL, stest = { |
TASS Belgium NV |
131:4758606c9316 | 1894 | 0 |
TASS Belgium NV |
131:4758606c9316 | 1895 | }; |
TASS Belgium NV |
131:4758606c9316 | 1896 | struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 1, 1); |
TASS Belgium NV |
131:4758606c9316 | 1897 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 1898 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1899 | |
TASS Belgium NV |
131:4758606c9316 | 1900 | listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1901 | if (listen) { |
TASS Belgium NV |
131:4758606c9316 | 1902 | if (listen->filter_mode != PICO_IP_MULTICAST_INCLUDE) { |
TASS Belgium NV |
131:4758606c9316 | 1903 | so_mcast_dbg("pico_socket_setoption: ERROR source-specific multicast (include) on any-source multicast (exclude)\n"); |
TASS Belgium NV |
131:4758606c9316 | 1904 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1905 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1906 | } |
TASS Belgium NV |
131:4758606c9316 | 1907 | |
TASS Belgium NV |
131:4758606c9316 | 1908 | stest.addr = mreq->mcast_source_addr.addr; |
TASS Belgium NV |
131:4758606c9316 | 1909 | source = pico_tree_findKey(&listen->MCASTSources, &stest); |
TASS Belgium NV |
131:4758606c9316 | 1910 | if (source) { |
TASS Belgium NV |
131:4758606c9316 | 1911 | so_mcast_dbg("pico_socket_setoption: ERROR source address to allow already in source list\n"); |
TASS Belgium NV |
131:4758606c9316 | 1912 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 1913 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1914 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1915 | source = pico_zalloc(sizeof(struct pico_ip4)); |
TASS Belgium NV |
131:4758606c9316 | 1916 | if (!source) { |
TASS Belgium NV |
131:4758606c9316 | 1917 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 1918 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1919 | } |
TASS Belgium NV |
131:4758606c9316 | 1920 | |
TASS Belgium NV |
131:4758606c9316 | 1921 | source->addr = mreq->mcast_source_addr.addr; |
TASS Belgium NV |
131:4758606c9316 | 1922 | pico_tree_insert(&listen->MCASTSources, source); |
TASS Belgium NV |
131:4758606c9316 | 1923 | } |
TASS Belgium NV |
131:4758606c9316 | 1924 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1925 | listen = pico_zalloc(sizeof(struct pico_mcast_listen)); |
TASS Belgium NV |
131:4758606c9316 | 1926 | if (!listen) { |
TASS Belgium NV |
131:4758606c9316 | 1927 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 1928 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1929 | } |
TASS Belgium NV |
131:4758606c9316 | 1930 | |
TASS Belgium NV |
131:4758606c9316 | 1931 | listen->filter_mode = PICO_IP_MULTICAST_INCLUDE; |
TASS Belgium NV |
131:4758606c9316 | 1932 | listen->mcast_link = mreq->mcast_link_addr; |
TASS Belgium NV |
131:4758606c9316 | 1933 | listen->mcast_group = mreq->mcast_group_addr; |
TASS Belgium NV |
131:4758606c9316 | 1934 | listen->MCASTSources.root = &LEAF; |
TASS Belgium NV |
131:4758606c9316 | 1935 | listen->MCASTSources.compare = mcast_sources_cmp; |
TASS Belgium NV |
131:4758606c9316 | 1936 | source = pico_zalloc(sizeof(struct pico_ip4)); |
TASS Belgium NV |
131:4758606c9316 | 1937 | if (!source) { |
TASS Belgium NV |
131:4758606c9316 | 1938 | pico_free(listen); |
TASS Belgium NV |
131:4758606c9316 | 1939 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 1940 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1941 | } |
TASS Belgium NV |
131:4758606c9316 | 1942 | |
TASS Belgium NV |
131:4758606c9316 | 1943 | source->addr = mreq->mcast_source_addr.addr; |
TASS Belgium NV |
131:4758606c9316 | 1944 | pico_tree_insert(&listen->MCASTSources, source); |
TASS Belgium NV |
131:4758606c9316 | 1945 | pico_tree_insert(s->MCASTListen, listen); |
TASS Belgium NV |
131:4758606c9316 | 1946 | reference_count = 1; |
tass | 68:0847e35d08a6 | 1947 | } |
TASS Belgium NV |
131:4758606c9316 | 1948 | |
TASS Belgium NV |
131:4758606c9316 | 1949 | pico_tree_insert(&MCASTSockets, s); |
TASS Belgium NV |
131:4758606c9316 | 1950 | filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1951 | if (filter_mode < 0) |
TASS Belgium NV |
131:4758606c9316 | 1952 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1953 | |
TASS Belgium NV |
131:4758606c9316 | 1954 | return pico_ipv4_mcast_join(&mreq->mcast_link_addr, &mreq->mcast_group_addr, (uint8_t)reference_count, (uint8_t)filter_mode, &MCASTFilter); |
tass | 68:0847e35d08a6 | 1955 | } |
tass | 68:0847e35d08a6 | 1956 | |
TASS Belgium NV |
131:4758606c9316 | 1957 | break; |
tass | 68:0847e35d08a6 | 1958 | |
tass | 68:0847e35d08a6 | 1959 | case PICO_IP_DROP_SOURCE_MEMBERSHIP: |
TASS Belgium NV |
131:4758606c9316 | 1960 | /* INCLUDE mode */ |
TASS Belgium NV |
131:4758606c9316 | 1961 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 1962 | int filter_mode = 0, reference_count = 0; |
TASS Belgium NV |
131:4758606c9316 | 1963 | struct pico_ip_mreq_source *mreq = (struct pico_ip_mreq_source *)value; |
TASS Belgium NV |
131:4758606c9316 | 1964 | struct pico_mcast_listen *listen = NULL; |
TASS Belgium NV |
131:4758606c9316 | 1965 | struct pico_ip4 *source = NULL, stest = { |
TASS Belgium NV |
131:4758606c9316 | 1966 | 0 |
TASS Belgium NV |
131:4758606c9316 | 1967 | }; |
TASS Belgium NV |
131:4758606c9316 | 1968 | struct pico_ipv4_link *mcast_link = setopt_multicast_check(s, value, 0, 1); |
TASS Belgium NV |
131:4758606c9316 | 1969 | if (!mcast_link) |
TASS Belgium NV |
131:4758606c9316 | 1970 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1971 | |
TASS Belgium NV |
131:4758606c9316 | 1972 | listen = listen_find(s, &mreq->mcast_link_addr, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 1973 | if (!listen) { |
TASS Belgium NV |
131:4758606c9316 | 1974 | so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_DROP_SOURCE_MEMBERSHIP before PICO_IP_ADD_SOURCE_MEMBERSHIP\n"); |
TASS Belgium NV |
131:4758606c9316 | 1975 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 1976 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1977 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1978 | if (listen->filter_mode != PICO_IP_MULTICAST_INCLUDE) { |
TASS Belgium NV |
131:4758606c9316 | 1979 | so_mcast_dbg("pico_socket_setoption: ERROR source-specific multicast (include) on any-source multicast (exclude)\n"); |
TASS Belgium NV |
131:4758606c9316 | 1980 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 1981 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1982 | } |
TASS Belgium NV |
131:4758606c9316 | 1983 | |
TASS Belgium NV |
131:4758606c9316 | 1984 | stest.addr = mreq->mcast_source_addr.addr; |
TASS Belgium NV |
131:4758606c9316 | 1985 | source = pico_tree_findKey(&listen->MCASTSources, &stest); |
TASS Belgium NV |
131:4758606c9316 | 1986 | if (!source) { |
TASS Belgium NV |
131:4758606c9316 | 1987 | so_mcast_dbg("pico_socket_setoption: ERROR address to drop not in source list\n"); |
TASS Belgium NV |
131:4758606c9316 | 1988 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 1989 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 1990 | } else { |
TASS Belgium NV |
131:4758606c9316 | 1991 | pico_tree_delete(&listen->MCASTSources, source); |
TASS Belgium NV |
131:4758606c9316 | 1992 | pico_free(source); |
TASS Belgium NV |
131:4758606c9316 | 1993 | if (pico_tree_empty(&listen->MCASTSources)) { /* 1 if empty, 0 otherwise */ |
TASS Belgium NV |
131:4758606c9316 | 1994 | reference_count = 1; |
TASS Belgium NV |
131:4758606c9316 | 1995 | pico_tree_delete(s->MCASTListen, listen); |
TASS Belgium NV |
131:4758606c9316 | 1996 | pico_free(listen); |
TASS Belgium NV |
131:4758606c9316 | 1997 | if (pico_tree_empty(s->MCASTListen)) { |
TASS Belgium NV |
131:4758606c9316 | 1998 | pico_free(s->MCASTListen); |
TASS Belgium NV |
131:4758606c9316 | 1999 | s->MCASTListen = NULL; |
TASS Belgium NV |
131:4758606c9316 | 2000 | pico_tree_delete(&MCASTSockets, s); |
TASS Belgium NV |
131:4758606c9316 | 2001 | } |
TASS Belgium NV |
131:4758606c9316 | 2002 | } |
TASS Belgium NV |
131:4758606c9316 | 2003 | } |
tass | 68:0847e35d08a6 | 2004 | } |
TASS Belgium NV |
131:4758606c9316 | 2005 | |
TASS Belgium NV |
131:4758606c9316 | 2006 | filter_mode = pico_socket_aggregate_mcastfilters(&mcast_link->address, &mreq->mcast_group_addr); |
TASS Belgium NV |
131:4758606c9316 | 2007 | if (filter_mode < 0) |
TASS Belgium NV |
131:4758606c9316 | 2008 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2009 | |
TASS Belgium NV |
131:4758606c9316 | 2010 | return pico_ipv4_mcast_leave(&mreq->mcast_link_addr, &mreq->mcast_group_addr, (uint8_t)reference_count, (uint8_t)filter_mode, &MCASTFilter); |
tass | 68:0847e35d08a6 | 2011 | } |
tass | 68:0847e35d08a6 | 2012 | |
TASS Belgium NV |
131:4758606c9316 | 2013 | break; |
tass | 68:0847e35d08a6 | 2014 | #endif /* PICO_SUPPORT_MCAST */ |
tass | 68:0847e35d08a6 | 2015 | |
tass | 68:0847e35d08a6 | 2016 | default: |
TASS Belgium NV |
131:4758606c9316 | 2017 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 2018 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2019 | } |
tass | 68:0847e35d08a6 | 2020 | |
TASS Belgium NV |
131:4758606c9316 | 2021 | if (pico_err != PICO_ERR_NOERR) |
TASS Belgium NV |
131:4758606c9316 | 2022 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2023 | else |
TASS Belgium NV |
131:4758606c9316 | 2024 | return 0; |
tass | 68:0847e35d08a6 | 2025 | } |
tass | 68:0847e35d08a6 | 2026 | |
TASS Belgium NV |
131:4758606c9316 | 2027 | #define PICO_SOCKET_GETOPT(socket, index) ((socket->opt_flags & (1 << index)) != 0) |
tass | 68:0847e35d08a6 | 2028 | |
tass | 68:0847e35d08a6 | 2029 | int pico_socket_getoption(struct pico_socket *s, int option, void *value) |
TASS Belgium NV |
131:4758606c9316 | 2030 | { |
TASS Belgium NV |
131:4758606c9316 | 2031 | if (!s || !value) { |
TASS Belgium NV |
131:4758606c9316 | 2032 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 2033 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2034 | } |
tass | 68:0847e35d08a6 | 2035 | |
TASS Belgium NV |
131:4758606c9316 | 2036 | switch (option) |
TASS Belgium NV |
131:4758606c9316 | 2037 | { |
tass | 68:0847e35d08a6 | 2038 | #ifdef PICO_SUPPORT_TCP |
tass | 68:0847e35d08a6 | 2039 | case PICO_TCP_NODELAY: |
TASS Belgium NV |
131:4758606c9316 | 2040 | if (s->proto->proto_number == PICO_PROTO_TCP) |
tass | 68:0847e35d08a6 | 2041 | /* state of the NODELAY option */ |
TASS Belgium NV |
131:4758606c9316 | 2042 | *(int *)value = PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_TCPNODELAY); |
TASS Belgium NV |
131:4758606c9316 | 2043 | else |
tass | 68:0847e35d08a6 | 2044 | *(int *)value = 0; |
TASS Belgium NV |
131:4758606c9316 | 2045 | |
TASS Belgium NV |
131:4758606c9316 | 2046 | break; |
tass | 68:0847e35d08a6 | 2047 | #endif |
tass | 68:0847e35d08a6 | 2048 | |
tass | 68:0847e35d08a6 | 2049 | #ifdef PICO_SUPPORT_MCAST |
tass | 68:0847e35d08a6 | 2050 | case PICO_IP_MULTICAST_IF: |
TASS Belgium NV |
131:4758606c9316 | 2051 | pico_err = PICO_ERR_EOPNOTSUPP; |
TASS Belgium NV |
131:4758606c9316 | 2052 | return -1; |
tass | 68:0847e35d08a6 | 2053 | |
tass | 68:0847e35d08a6 | 2054 | case PICO_IP_MULTICAST_TTL: |
TASS Belgium NV |
131:4758606c9316 | 2055 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
tass | 68:0847e35d08a6 | 2056 | pico_udp_get_mc_ttl(s, (uint8_t *) value); |
TASS Belgium NV |
131:4758606c9316 | 2057 | } else { |
tass | 68:0847e35d08a6 | 2058 | *(uint8_t *)value = 0; |
tass | 68:0847e35d08a6 | 2059 | pico_err = PICO_ERR_EINVAL; |
tass | 68:0847e35d08a6 | 2060 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2061 | } |
TASS Belgium NV |
131:4758606c9316 | 2062 | |
TASS Belgium NV |
131:4758606c9316 | 2063 | break; |
tass | 68:0847e35d08a6 | 2064 | |
tass | 68:0847e35d08a6 | 2065 | case PICO_IP_MULTICAST_LOOP: |
TASS Belgium NV |
131:4758606c9316 | 2066 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 2067 | *(uint8_t *)value = PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_MULTICAST_LOOP); |
TASS Belgium NV |
131:4758606c9316 | 2068 | } else { |
tass | 68:0847e35d08a6 | 2069 | *(uint8_t *)value = 0; |
tass | 68:0847e35d08a6 | 2070 | pico_err = PICO_ERR_EINVAL; |
tass | 68:0847e35d08a6 | 2071 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2072 | } |
TASS Belgium NV |
131:4758606c9316 | 2073 | |
TASS Belgium NV |
131:4758606c9316 | 2074 | break; |
tass | 68:0847e35d08a6 | 2075 | #endif /* PICO_SUPPORT_MCAST */ |
tass | 68:0847e35d08a6 | 2076 | |
tass | 68:0847e35d08a6 | 2077 | default: |
TASS Belgium NV |
131:4758606c9316 | 2078 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 2079 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2080 | } |
tass | 68:0847e35d08a6 | 2081 | |
TASS Belgium NV |
131:4758606c9316 | 2082 | return 0; |
tass | 68:0847e35d08a6 | 2083 | } |
tass | 68:0847e35d08a6 | 2084 | |
tass | 68:0847e35d08a6 | 2085 | |
tass | 68:0847e35d08a6 | 2086 | int pico_socket_shutdown(struct pico_socket *s, int mode) |
tass | 68:0847e35d08a6 | 2087 | { |
TASS Belgium NV |
131:4758606c9316 | 2088 | if (!s) { |
TASS Belgium NV |
131:4758606c9316 | 2089 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 2090 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2091 | } else { |
TASS Belgium NV |
131:4758606c9316 | 2092 | /* check if exists in tree */ |
TASS Belgium NV |
131:4758606c9316 | 2093 | /* See task #178 */ |
TASS Belgium NV |
131:4758606c9316 | 2094 | if (pico_check_socket(s) != 0) { |
TASS Belgium NV |
131:4758606c9316 | 2095 | pico_free(s); /* close socket after bind or connect failed */ |
TASS Belgium NV |
131:4758606c9316 | 2096 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 2097 | } |
tass | 68:0847e35d08a6 | 2098 | } |
tass | 68:0847e35d08a6 | 2099 | |
tass | 68:0847e35d08a6 | 2100 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 2101 | if (PROTO(s) == PICO_PROTO_UDP) { |
TASS Belgium NV |
131:4758606c9316 | 2102 | if (mode & PICO_SHUT_RDWR) |
TASS Belgium NV |
131:4758606c9316 | 2103 | 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 | 2104 | else if (mode & PICO_SHUT_RD) |
TASS Belgium NV |
131:4758606c9316 | 2105 | pico_socket_alter_state(s, 0, PICO_SOCKET_STATE_BOUND, 0); |
TASS Belgium NV |
131:4758606c9316 | 2106 | } |
TASS Belgium NV |
131:4758606c9316 | 2107 | |
tass | 68:0847e35d08a6 | 2108 | #endif |
tass | 68:0847e35d08a6 | 2109 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 2110 | if (PROTO(s) == PICO_PROTO_TCP) { |
TASS Belgium NV |
131:4758606c9316 | 2111 | if(mode & PICO_SHUT_RDWR) |
TASS Belgium NV |
131:4758606c9316 | 2112 | { |
TASS Belgium NV |
131:4758606c9316 | 2113 | pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_LOCAL | PICO_SOCKET_STATE_SHUT_REMOTE, 0, 0); |
TASS Belgium NV |
131:4758606c9316 | 2114 | pico_tcp_notify_closing(s); |
TASS Belgium NV |
131:4758606c9316 | 2115 | } |
TASS Belgium NV |
131:4758606c9316 | 2116 | else if (mode & PICO_SHUT_WR) |
TASS Belgium NV |
131:4758606c9316 | 2117 | pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_LOCAL, 0, 0); |
TASS Belgium NV |
131:4758606c9316 | 2118 | else if (mode & PICO_SHUT_RD) |
TASS Belgium NV |
131:4758606c9316 | 2119 | pico_socket_alter_state(s, PICO_SOCKET_STATE_SHUT_REMOTE, 0, 0); |
tass | 68:0847e35d08a6 | 2120 | |
TASS Belgium NV |
131:4758606c9316 | 2121 | } |
TASS Belgium NV |
131:4758606c9316 | 2122 | |
tass | 68:0847e35d08a6 | 2123 | #endif |
TASS Belgium NV |
131:4758606c9316 | 2124 | return 0; |
tass | 68:0847e35d08a6 | 2125 | } |
tass | 68:0847e35d08a6 | 2126 | |
tass | 68:0847e35d08a6 | 2127 | int pico_socket_close(struct pico_socket *s) |
tass | 68:0847e35d08a6 | 2128 | { |
TASS Belgium NV |
131:4758606c9316 | 2129 | return pico_socket_shutdown(s, PICO_SHUT_RDWR); |
tass | 68:0847e35d08a6 | 2130 | } |
tass | 68:0847e35d08a6 | 2131 | |
tass | 68:0847e35d08a6 | 2132 | #ifdef PICO_SUPPORT_CRC |
tass | 68:0847e35d08a6 | 2133 | static inline int pico_transport_crc_check(struct pico_frame *f) |
tass | 68:0847e35d08a6 | 2134 | { |
TASS Belgium NV |
131:4758606c9316 | 2135 | struct pico_ipv4_hdr *net_hdr = (struct pico_ipv4_hdr *) f->net_hdr; |
TASS Belgium NV |
131:4758606c9316 | 2136 | struct pico_udp_hdr *udp_hdr = NULL; |
TASS Belgium NV |
131:4758606c9316 | 2137 | uint16_t checksum_invalid = 1; |
tass | 68:0847e35d08a6 | 2138 | |
TASS Belgium NV |
131:4758606c9316 | 2139 | switch (net_hdr->proto) |
TASS Belgium NV |
131:4758606c9316 | 2140 | { |
tass | 68:0847e35d08a6 | 2141 | case PICO_PROTO_TCP: |
TASS Belgium NV |
131:4758606c9316 | 2142 | checksum_invalid = short_be(pico_tcp_checksum_ipv4(f)); |
TASS Belgium NV |
131:4758606c9316 | 2143 | /* dbg("TCP CRC validation == %u\n", checksum_invalid); */ |
TASS Belgium NV |
131:4758606c9316 | 2144 | if (checksum_invalid) { |
TASS Belgium NV |
131:4758606c9316 | 2145 | /* dbg("TCP CRC: validation failed!\n"); */ |
TASS Belgium NV |
131:4758606c9316 | 2146 | pico_frame_discard(f); |
TASS Belgium NV |
131:4758606c9316 | 2147 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 2148 | } |
TASS Belgium NV |
131:4758606c9316 | 2149 | |
TASS Belgium NV |
131:4758606c9316 | 2150 | break; |
tass | 68:0847e35d08a6 | 2151 | |
tass | 68:0847e35d08a6 | 2152 | case PICO_PROTO_UDP: |
TASS Belgium NV |
131:4758606c9316 | 2153 | udp_hdr = (struct pico_udp_hdr *) f->transport_hdr; |
TASS Belgium NV |
131:4758606c9316 | 2154 | if (short_be(udp_hdr->crc)) { |
TASS Belgium NV |
131:4758606c9316 | 2155 | checksum_invalid = short_be(pico_udp_checksum_ipv4(f)); |
TASS Belgium NV |
131:4758606c9316 | 2156 | /* dbg("UDP CRC validation == %u\n", checksum_invalid); */ |
TASS Belgium NV |
131:4758606c9316 | 2157 | if (checksum_invalid) { |
TASS Belgium NV |
131:4758606c9316 | 2158 | /* dbg("UDP CRC: validation failed!\n"); */ |
TASS Belgium NV |
131:4758606c9316 | 2159 | pico_frame_discard(f); |
TASS Belgium NV |
131:4758606c9316 | 2160 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 2161 | } |
tass | 68:0847e35d08a6 | 2162 | } |
TASS Belgium NV |
131:4758606c9316 | 2163 | |
TASS Belgium NV |
131:4758606c9316 | 2164 | break; |
tass | 68:0847e35d08a6 | 2165 | |
tass | 68:0847e35d08a6 | 2166 | default: |
TASS Belgium NV |
131:4758606c9316 | 2167 | /* Do nothing */ |
TASS Belgium NV |
131:4758606c9316 | 2168 | break; |
TASS Belgium NV |
131:4758606c9316 | 2169 | } |
TASS Belgium NV |
131:4758606c9316 | 2170 | return 1; |
tass | 68:0847e35d08a6 | 2171 | } |
tass | 68:0847e35d08a6 | 2172 | #else |
tass | 68:0847e35d08a6 | 2173 | static inline int pico_transport_crc_check(struct pico_frame *f) |
tass | 68:0847e35d08a6 | 2174 | { |
TASS Belgium NV |
131:4758606c9316 | 2175 | IGNORE_PARAMETER(f); |
TASS Belgium NV |
131:4758606c9316 | 2176 | return 1; |
tass | 68:0847e35d08a6 | 2177 | } |
tass | 68:0847e35d08a6 | 2178 | #endif /* PICO_SUPPORT_CRC */ |
tass | 68:0847e35d08a6 | 2179 | |
tass | 68:0847e35d08a6 | 2180 | int pico_transport_process_in(struct pico_protocol *self, struct pico_frame *f) |
tass | 68:0847e35d08a6 | 2181 | { |
TASS Belgium NV |
131:4758606c9316 | 2182 | struct pico_trans *hdr = (struct pico_trans *) f->transport_hdr; |
TASS Belgium NV |
131:4758606c9316 | 2183 | int ret = 0; |
tass | 68:0847e35d08a6 | 2184 | |
TASS Belgium NV |
131:4758606c9316 | 2185 | if (!hdr) { |
TASS Belgium NV |
131:4758606c9316 | 2186 | pico_err = PICO_ERR_EFAULT; |
TASS Belgium NV |
131:4758606c9316 | 2187 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2188 | } |
tass | 68:0847e35d08a6 | 2189 | |
TASS Belgium NV |
131:4758606c9316 | 2190 | ret = pico_transport_crc_check(f); |
TASS Belgium NV |
131:4758606c9316 | 2191 | if (ret < 1) |
TASS Belgium NV |
131:4758606c9316 | 2192 | return ret; |
TASS Belgium NV |
131:4758606c9316 | 2193 | else |
TASS Belgium NV |
131:4758606c9316 | 2194 | ret = 0; |
tass | 68:0847e35d08a6 | 2195 | |
TASS Belgium NV |
131:4758606c9316 | 2196 | if ((hdr) && (pico_socket_deliver(self, f, hdr->dport) == 0)) |
TASS Belgium NV |
131:4758606c9316 | 2197 | return ret; |
tass | 68:0847e35d08a6 | 2198 | |
TASS Belgium NV |
131:4758606c9316 | 2199 | if (!IS_BCAST(f)) { |
TASS Belgium NV |
131:4758606c9316 | 2200 | dbg("Socket not found... \n"); |
TASS Belgium NV |
131:4758606c9316 | 2201 | pico_notify_socket_unreachable(f); |
tass | 68:0847e35d08a6 | 2202 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 2203 | /* if tcp protocol send RST segment */ |
TASS Belgium NV |
131:4758606c9316 | 2204 | /* if (self->proto_number == PICO_PROTO_TCP) */ |
TASS Belgium NV |
131:4758606c9316 | 2205 | /* pico_tcp_reply_rst(f); */ |
tass | 68:0847e35d08a6 | 2206 | #endif |
TASS Belgium NV |
131:4758606c9316 | 2207 | ret = -1; |
TASS Belgium NV |
131:4758606c9316 | 2208 | pico_err = PICO_ERR_ENOENT; |
TASS Belgium NV |
131:4758606c9316 | 2209 | } |
TASS Belgium NV |
131:4758606c9316 | 2210 | |
TASS Belgium NV |
131:4758606c9316 | 2211 | pico_frame_discard(f); |
TASS Belgium NV |
131:4758606c9316 | 2212 | return ret; |
tass | 68:0847e35d08a6 | 2213 | } |
tass | 68:0847e35d08a6 | 2214 | |
tass | 68:0847e35d08a6 | 2215 | #define SL_LOOP_MIN 1 |
tass | 68:0847e35d08a6 | 2216 | |
tass | 125:96003ae6f1d8 | 2217 | #ifdef PICO_SUPPORT_TCP |
tass | 95:f4ca916a26fe | 2218 | static int checkSocketSanity(struct pico_socket *s) |
tass | 95:f4ca916a26fe | 2219 | { |
tass | 95:f4ca916a26fe | 2220 | |
TASS Belgium NV |
131:4758606c9316 | 2221 | /* checking for pending connections */ |
tass picotcp@tass.be | 133:5b075f5e141a | 2222 | if(TCP_STATE(s) == PICO_SOCKET_STATE_TCP_SYN_RECV) { |
tass picotcp@tass.be | 133:5b075f5e141a | 2223 | if((pico_time)(PICO_TIME_MS() - s->timestamp) >= PICO_SOCKET_BOUND_TIMEOUT) |
TASS Belgium NV |
131:4758606c9316 | 2224 | return -1; |
tass picotcp@tass.be | 133:5b075f5e141a | 2225 | } |
TASS Belgium NV |
131:4758606c9316 | 2226 | |
TASS Belgium NV |
131:4758606c9316 | 2227 | if((pico_time)(PICO_TIME_MS() - s->timestamp) >= PICO_SOCKET_TIMEOUT) { |
TASS Belgium NV |
131:4758606c9316 | 2228 | /* checking for hanging sockets */ |
TASS Belgium NV |
131:4758606c9316 | 2229 | if((TCP_STATE(s) != PICO_SOCKET_STATE_TCP_LISTEN) && (TCP_STATE(s) != PICO_SOCKET_STATE_TCP_ESTABLISHED)) |
TASS Belgium NV |
131:4758606c9316 | 2230 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 2231 | |
TASS Belgium NV |
131:4758606c9316 | 2232 | /* if no activity, force the socket into closing state */ |
TASS Belgium NV |
131:4758606c9316 | 2233 | if( TCP_STATE(s) == PICO_SOCKET_STATE_TCP_ESTABLISHED ) |
TASS Belgium NV |
131:4758606c9316 | 2234 | { |
TASS Belgium NV |
131:4758606c9316 | 2235 | s->wakeup(PICO_SOCK_EV_CLOSE, s); |
TASS Belgium NV |
131:4758606c9316 | 2236 | pico_socket_close(s); |
TASS Belgium NV |
131:4758606c9316 | 2237 | s->timestamp = PICO_TIME_MS(); |
TASS Belgium NV |
131:4758606c9316 | 2238 | } |
TASS Belgium NV |
131:4758606c9316 | 2239 | } |
TASS Belgium NV |
131:4758606c9316 | 2240 | |
TASS Belgium NV |
131:4758606c9316 | 2241 | return 0; |
tass | 95:f4ca916a26fe | 2242 | } |
tass | 125:96003ae6f1d8 | 2243 | #endif |
tass | 95:f4ca916a26fe | 2244 | |
tass | 68:0847e35d08a6 | 2245 | int pico_sockets_loop(int loop_score) |
tass | 68:0847e35d08a6 | 2246 | { |
tass | 125:96003ae6f1d8 | 2247 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 2248 | static struct pico_tree_node *index_udp; |
tass | 125:96003ae6f1d8 | 2249 | #endif |
tass | 125:96003ae6f1d8 | 2250 | |
tass | 125:96003ae6f1d8 | 2251 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 2252 | static struct pico_tree_node*index_tcp; |
tass | 125:96003ae6f1d8 | 2253 | #endif |
tass | 68:0847e35d08a6 | 2254 | |
TASS Belgium NV |
131:4758606c9316 | 2255 | struct pico_sockport *start; |
TASS Belgium NV |
131:4758606c9316 | 2256 | struct pico_socket *s; |
tass | 68:0847e35d08a6 | 2257 | |
tass | 68:0847e35d08a6 | 2258 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 2259 | struct pico_frame *f; |
tass | 68:0847e35d08a6 | 2260 | |
tass | 68:0847e35d08a6 | 2261 | if (sp_udp == NULL) |
tass | 68:0847e35d08a6 | 2262 | { |
TASS Belgium NV |
131:4758606c9316 | 2263 | index_udp = pico_tree_firstNode(UDPTable.root); |
TASS Belgium NV |
131:4758606c9316 | 2264 | sp_udp = index_udp->keyValue; |
tass | 68:0847e35d08a6 | 2265 | } |
TASS Belgium NV |
131:4758606c9316 | 2266 | |
TASS Belgium NV |
131:4758606c9316 | 2267 | /* init start node */ |
TASS Belgium NV |
131:4758606c9316 | 2268 | start = sp_udp; |
TASS Belgium NV |
131:4758606c9316 | 2269 | |
TASS Belgium NV |
131:4758606c9316 | 2270 | /* round-robin all transport protocols, break if traversed all protocols */ |
TASS Belgium NV |
131:4758606c9316 | 2271 | while (loop_score > SL_LOOP_MIN && sp_udp != NULL) { |
TASS Belgium NV |
131:4758606c9316 | 2272 | struct pico_tree_node *index; |
TASS Belgium NV |
131:4758606c9316 | 2273 | |
TASS Belgium NV |
131:4758606c9316 | 2274 | pico_tree_foreach(index, &sp_udp->socks){ |
TASS Belgium NV |
131:4758606c9316 | 2275 | s = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 2276 | f = pico_dequeue(&s->q_out); |
TASS Belgium NV |
131:4758606c9316 | 2277 | while (f && (loop_score > 0)) { |
TASS Belgium NV |
131:4758606c9316 | 2278 | pico_proto_udp.push(&pico_proto_udp, f); |
TASS Belgium NV |
131:4758606c9316 | 2279 | loop_score -= 1; |
TASS Belgium NV |
131:4758606c9316 | 2280 | f = pico_dequeue(&s->q_out); |
TASS Belgium NV |
131:4758606c9316 | 2281 | } |
TASS Belgium NV |
131:4758606c9316 | 2282 | } |
TASS Belgium NV |
131:4758606c9316 | 2283 | |
TASS Belgium NV |
131:4758606c9316 | 2284 | index_udp = pico_tree_next(index_udp); |
TASS Belgium NV |
131:4758606c9316 | 2285 | sp_udp = index_udp->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 2286 | |
TASS Belgium NV |
131:4758606c9316 | 2287 | if (sp_udp == NULL) |
TASS Belgium NV |
131:4758606c9316 | 2288 | { |
TASS Belgium NV |
131:4758606c9316 | 2289 | index_udp = pico_tree_firstNode(UDPTable.root); |
TASS Belgium NV |
131:4758606c9316 | 2290 | sp_udp = index_udp->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 2291 | } |
TASS Belgium NV |
131:4758606c9316 | 2292 | |
TASS Belgium NV |
131:4758606c9316 | 2293 | if (sp_udp == start) |
TASS Belgium NV |
131:4758606c9316 | 2294 | break; |
TASS Belgium NV |
131:4758606c9316 | 2295 | } |
tass | 68:0847e35d08a6 | 2296 | #endif |
tass | 68:0847e35d08a6 | 2297 | |
tass | 68:0847e35d08a6 | 2298 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 2299 | if (sp_tcp == NULL) |
TASS Belgium NV |
131:4758606c9316 | 2300 | { |
TASS Belgium NV |
131:4758606c9316 | 2301 | index_tcp = pico_tree_firstNode(TCPTable.root); |
TASS Belgium NV |
131:4758606c9316 | 2302 | sp_tcp = index_tcp->keyValue; |
tass | 95:f4ca916a26fe | 2303 | } |
tass | 68:0847e35d08a6 | 2304 | |
TASS Belgium NV |
131:4758606c9316 | 2305 | /* init start node */ |
TASS Belgium NV |
131:4758606c9316 | 2306 | start = sp_tcp; |
tass | 68:0847e35d08a6 | 2307 | |
TASS Belgium NV |
131:4758606c9316 | 2308 | while (loop_score > SL_LOOP_MIN && sp_tcp != NULL) { |
TASS Belgium NV |
131:4758606c9316 | 2309 | struct pico_tree_node *index = NULL, *safe_index = NULL; |
TASS Belgium NV |
131:4758606c9316 | 2310 | pico_tree_foreach_safe(index, &sp_tcp->socks, safe_index){ |
TASS Belgium NV |
131:4758606c9316 | 2311 | s = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 2312 | loop_score = pico_tcp_output(s, loop_score); |
TASS Belgium NV |
131:4758606c9316 | 2313 | if ((s->ev_pending) && s->wakeup) { |
TASS Belgium NV |
131:4758606c9316 | 2314 | s->wakeup(s->ev_pending, s); |
TASS Belgium NV |
131:4758606c9316 | 2315 | if(!s->parent) |
TASS Belgium NV |
131:4758606c9316 | 2316 | s->ev_pending = 0; |
TASS Belgium NV |
131:4758606c9316 | 2317 | } |
TASS Belgium NV |
131:4758606c9316 | 2318 | |
TASS Belgium NV |
131:4758606c9316 | 2319 | if (loop_score <= 0) { |
TASS Belgium NV |
131:4758606c9316 | 2320 | loop_score = 0; |
TASS Belgium NV |
131:4758606c9316 | 2321 | break; |
TASS Belgium NV |
131:4758606c9316 | 2322 | } |
tass | 68:0847e35d08a6 | 2323 | |
TASS Belgium NV |
131:4758606c9316 | 2324 | if(checkSocketSanity(s) < 0) |
TASS Belgium NV |
131:4758606c9316 | 2325 | { |
TASS Belgium NV |
131:4758606c9316 | 2326 | pico_socket_del(s); |
TASS Belgium NV |
131:4758606c9316 | 2327 | index_tcp = NULL; /* forcing the restart of loop */ |
TASS Belgium NV |
131:4758606c9316 | 2328 | sp_tcp = NULL; |
TASS Belgium NV |
131:4758606c9316 | 2329 | break; |
TASS Belgium NV |
131:4758606c9316 | 2330 | } |
TASS Belgium NV |
131:4758606c9316 | 2331 | } |
TASS Belgium NV |
131:4758606c9316 | 2332 | |
TASS Belgium NV |
131:4758606c9316 | 2333 | /* check if RB_FOREACH ended, if not, break to keep the cur sp_tcp */ |
TASS Belgium NV |
131:4758606c9316 | 2334 | if (!index_tcp || (index && index->keyValue)) |
TASS Belgium NV |
131:4758606c9316 | 2335 | break; |
TASS Belgium NV |
131:4758606c9316 | 2336 | |
TASS Belgium NV |
131:4758606c9316 | 2337 | index_tcp = pico_tree_next(index_tcp); |
TASS Belgium NV |
131:4758606c9316 | 2338 | sp_tcp = index_tcp->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 2339 | |
TASS Belgium NV |
131:4758606c9316 | 2340 | if (sp_tcp == NULL) |
TASS Belgium NV |
131:4758606c9316 | 2341 | { |
TASS Belgium NV |
131:4758606c9316 | 2342 | index_tcp = pico_tree_firstNode(TCPTable.root); |
TASS Belgium NV |
131:4758606c9316 | 2343 | sp_tcp = index_tcp->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 2344 | } |
TASS Belgium NV |
131:4758606c9316 | 2345 | |
TASS Belgium NV |
131:4758606c9316 | 2346 | if (sp_tcp == start) |
TASS Belgium NV |
131:4758606c9316 | 2347 | break; |
tass | 68:0847e35d08a6 | 2348 | } |
tass | 68:0847e35d08a6 | 2349 | #endif |
tass | 68:0847e35d08a6 | 2350 | |
TASS Belgium NV |
131:4758606c9316 | 2351 | return loop_score; |
tass | 68:0847e35d08a6 | 2352 | } |
tass | 68:0847e35d08a6 | 2353 | |
tass | 68:0847e35d08a6 | 2354 | |
tass | 70:cd218dd180e5 | 2355 | struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, uint16_t len) |
tass | 68:0847e35d08a6 | 2356 | { |
TASS Belgium NV |
131:4758606c9316 | 2357 | struct pico_frame *f = NULL; |
tass | 68:0847e35d08a6 | 2358 | |
tass | 68:0847e35d08a6 | 2359 | #ifdef PICO_SUPPORT_IPV6 |
TASS Belgium NV |
131:4758606c9316 | 2360 | if (IS_SOCK_IPV6(s)) |
TASS Belgium NV |
131:4758606c9316 | 2361 | f = pico_proto_ipv6.alloc(&pico_proto_ipv6, len); |
TASS Belgium NV |
131:4758606c9316 | 2362 | |
tass | 68:0847e35d08a6 | 2363 | #endif |
tass | 68:0847e35d08a6 | 2364 | |
tass | 68:0847e35d08a6 | 2365 | #ifdef PICO_SUPPORT_IPV4 |
TASS Belgium NV |
131:4758606c9316 | 2366 | if (IS_SOCK_IPV4(s)) |
TASS Belgium NV |
131:4758606c9316 | 2367 | f = pico_proto_ipv4.alloc(&pico_proto_ipv4, (uint16_t)len); |
TASS Belgium NV |
131:4758606c9316 | 2368 | |
tass | 68:0847e35d08a6 | 2369 | #endif |
TASS Belgium NV |
131:4758606c9316 | 2370 | if (!f) { |
TASS Belgium NV |
131:4758606c9316 | 2371 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 2372 | return f; |
TASS Belgium NV |
131:4758606c9316 | 2373 | } |
TASS Belgium NV |
131:4758606c9316 | 2374 | |
TASS Belgium NV |
131:4758606c9316 | 2375 | f->payload = f->transport_hdr; |
TASS Belgium NV |
131:4758606c9316 | 2376 | f->payload_len = len; |
TASS Belgium NV |
131:4758606c9316 | 2377 | f->sock = s; |
tass | 68:0847e35d08a6 | 2378 | return f; |
tass | 68:0847e35d08a6 | 2379 | } |
tass | 68:0847e35d08a6 | 2380 | |
tass | 68:0847e35d08a6 | 2381 | int pico_transport_error(struct pico_frame *f, uint8_t proto, int code) |
tass | 68:0847e35d08a6 | 2382 | { |
TASS Belgium NV |
131:4758606c9316 | 2383 | int ret = -1; |
TASS Belgium NV |
131:4758606c9316 | 2384 | struct pico_trans *trans = (struct pico_trans*) f->transport_hdr; |
TASS Belgium NV |
131:4758606c9316 | 2385 | struct pico_sockport *port = NULL; |
TASS Belgium NV |
131:4758606c9316 | 2386 | struct pico_socket *s = NULL; |
TASS Belgium NV |
131:4758606c9316 | 2387 | switch (proto) { |
tass | 68:0847e35d08a6 | 2388 | |
tass | 68:0847e35d08a6 | 2389 | |
tass | 68:0847e35d08a6 | 2390 | #ifdef PICO_SUPPORT_UDP |
TASS Belgium NV |
131:4758606c9316 | 2391 | case PICO_PROTO_UDP: |
TASS Belgium NV |
131:4758606c9316 | 2392 | port = pico_get_sockport(proto, trans->sport); |
TASS Belgium NV |
131:4758606c9316 | 2393 | break; |
tass | 68:0847e35d08a6 | 2394 | #endif |
tass | 68:0847e35d08a6 | 2395 | |
tass | 68:0847e35d08a6 | 2396 | #ifdef PICO_SUPPORT_TCP |
TASS Belgium NV |
131:4758606c9316 | 2397 | case PICO_PROTO_TCP: |
TASS Belgium NV |
131:4758606c9316 | 2398 | port = pico_get_sockport(proto, trans->sport); |
TASS Belgium NV |
131:4758606c9316 | 2399 | break; |
tass | 68:0847e35d08a6 | 2400 | #endif |
tass | 68:0847e35d08a6 | 2401 | |
TASS Belgium NV |
131:4758606c9316 | 2402 | default: |
TASS Belgium NV |
131:4758606c9316 | 2403 | /* Protocol not available */ |
TASS Belgium NV |
131:4758606c9316 | 2404 | ret = -1; |
TASS Belgium NV |
131:4758606c9316 | 2405 | } |
TASS Belgium NV |
131:4758606c9316 | 2406 | if (port) { |
TASS Belgium NV |
131:4758606c9316 | 2407 | struct pico_tree_node *index; |
TASS Belgium NV |
131:4758606c9316 | 2408 | ret = 0; |
tass | 68:0847e35d08a6 | 2409 | |
TASS Belgium NV |
131:4758606c9316 | 2410 | pico_tree_foreach(index, &port->socks) { |
TASS Belgium NV |
131:4758606c9316 | 2411 | s = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 2412 | if (trans->dport == s->remote_port) { |
TASS Belgium NV |
131:4758606c9316 | 2413 | if (s->wakeup) { |
TASS Belgium NV |
131:4758606c9316 | 2414 | /* dbg("SOCKET ERROR FROM ICMP NOTIFICATION. (icmp code= %d)\n\n", code); */ |
TASS Belgium NV |
131:4758606c9316 | 2415 | switch(code) { |
TASS Belgium NV |
131:4758606c9316 | 2416 | case PICO_ICMP_UNREACH_PROTOCOL: |
TASS Belgium NV |
131:4758606c9316 | 2417 | pico_err = PICO_ERR_EPROTO; |
TASS Belgium NV |
131:4758606c9316 | 2418 | break; |
TASS Belgium NV |
131:4758606c9316 | 2419 | |
TASS Belgium NV |
131:4758606c9316 | 2420 | case PICO_ICMP_UNREACH_PORT: |
TASS Belgium NV |
131:4758606c9316 | 2421 | pico_err = PICO_ERR_ECONNREFUSED; |
TASS Belgium NV |
131:4758606c9316 | 2422 | break; |
tass | 68:0847e35d08a6 | 2423 | |
TASS Belgium NV |
131:4758606c9316 | 2424 | case PICO_ICMP_UNREACH_NET: |
TASS Belgium NV |
131:4758606c9316 | 2425 | case PICO_ICMP_UNREACH_NET_PROHIB: |
TASS Belgium NV |
131:4758606c9316 | 2426 | case PICO_ICMP_UNREACH_NET_UNKNOWN: |
TASS Belgium NV |
131:4758606c9316 | 2427 | pico_err = PICO_ERR_ENETUNREACH; |
TASS Belgium NV |
131:4758606c9316 | 2428 | break; |
tass | 68:0847e35d08a6 | 2429 | |
TASS Belgium NV |
131:4758606c9316 | 2430 | default: |
TASS Belgium NV |
131:4758606c9316 | 2431 | pico_err = PICO_ERR_EHOSTUNREACH; |
TASS Belgium NV |
131:4758606c9316 | 2432 | } |
TASS Belgium NV |
131:4758606c9316 | 2433 | s->state |= PICO_SOCKET_STATE_SHUT_REMOTE; |
TASS Belgium NV |
131:4758606c9316 | 2434 | s->wakeup(PICO_SOCK_EV_ERR, s); |
tass | 122:5b1e9de8bf7f | 2435 | |
TASS Belgium NV |
131:4758606c9316 | 2436 | } |
TASS Belgium NV |
131:4758606c9316 | 2437 | |
TASS Belgium NV |
131:4758606c9316 | 2438 | break; |
TASS Belgium NV |
131:4758606c9316 | 2439 | } |
tass | 68:0847e35d08a6 | 2440 | } |
tass | 68:0847e35d08a6 | 2441 | } |
TASS Belgium NV |
131:4758606c9316 | 2442 | |
TASS Belgium NV |
131:4758606c9316 | 2443 | pico_frame_discard(f); |
TASS Belgium NV |
131:4758606c9316 | 2444 | return ret; |
tass | 68:0847e35d08a6 | 2445 | } |
tass | 68:0847e35d08a6 | 2446 | #endif |
tass | 68:0847e35d08a6 | 2447 | #endif |