Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

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

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

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

Development steps:

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

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

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

Committer:
tass picotcp@tass.be
Date:
Wed Apr 09 15:43:37 2014 +0200
Revision:
150:551effcf6a39
Parent:
149:5f4cb161cec3
Child:
152:a3d286bf94e5
Fixed some warnings

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass picotcp@tass.be 149:5f4cb161cec3 1 #include <stdint.h>
tass picotcp@tass.be 149:5f4cb161cec3 2 #include "pico_socket.h"
tass picotcp@tass.be 149:5f4cb161cec3 3 #include "pico_ipv4.h"
tass picotcp@tass.be 149:5f4cb161cec3 4 #include "pico_ipv6.h"
tass picotcp@tass.be 149:5f4cb161cec3 5 #include "pico_tcp.h"
tass picotcp@tass.be 149:5f4cb161cec3 6
tass picotcp@tass.be 149:5f4cb161cec3 7 int pico_getsockopt_tcp(struct pico_socket *s, int option, void *value)
tass picotcp@tass.be 149:5f4cb161cec3 8 {
tass picotcp@tass.be 149:5f4cb161cec3 9 if (!value) {
tass picotcp@tass.be 149:5f4cb161cec3 10 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 11 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 12 }
tass picotcp@tass.be 149:5f4cb161cec3 13
tass picotcp@tass.be 149:5f4cb161cec3 14 if (s->proto->proto_number != PICO_PROTO_TCP) {
tass picotcp@tass.be 149:5f4cb161cec3 15 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass picotcp@tass.be 149:5f4cb161cec3 16 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 17 }
tass picotcp@tass.be 149:5f4cb161cec3 18
tass picotcp@tass.be 149:5f4cb161cec3 19 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 20 if (option == PICO_TCP_NODELAY) {
tass picotcp@tass.be 149:5f4cb161cec3 21 /* state of the NODELAY option */
tass picotcp@tass.be 149:5f4cb161cec3 22 *(int *)value = PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_TCPNODELAY);
tass picotcp@tass.be 149:5f4cb161cec3 23 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 24 }
tass picotcp@tass.be 149:5f4cb161cec3 25 else if (option == PICO_SOCKET_OPT_RCVBUF) {
tass picotcp@tass.be 149:5f4cb161cec3 26 return pico_tcp_get_bufsize_in(s, (uint32_t *)value);
tass picotcp@tass.be 149:5f4cb161cec3 27 }
tass picotcp@tass.be 149:5f4cb161cec3 28
tass picotcp@tass.be 149:5f4cb161cec3 29 if (option == PICO_SOCKET_OPT_SNDBUF) {
tass picotcp@tass.be 149:5f4cb161cec3 30 return pico_tcp_get_bufsize_out(s, (uint32_t *)value);
tass picotcp@tass.be 149:5f4cb161cec3 31 }
tass picotcp@tass.be 149:5f4cb161cec3 32
tass picotcp@tass.be 149:5f4cb161cec3 33 #endif
tass picotcp@tass.be 149:5f4cb161cec3 34 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 35 }
tass picotcp@tass.be 149:5f4cb161cec3 36
tass picotcp@tass.be 149:5f4cb161cec3 37 int pico_setsockopt_tcp(struct pico_socket *s, int option, void *value)
tass picotcp@tass.be 149:5f4cb161cec3 38 {
tass picotcp@tass.be 149:5f4cb161cec3 39 if (!value) {
tass picotcp@tass.be 149:5f4cb161cec3 40 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 41 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 42 }
tass picotcp@tass.be 149:5f4cb161cec3 43
tass picotcp@tass.be 149:5f4cb161cec3 44 if (s->proto->proto_number != PICO_PROTO_TCP) {
tass picotcp@tass.be 149:5f4cb161cec3 45 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass picotcp@tass.be 149:5f4cb161cec3 46 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 47 }
tass picotcp@tass.be 149:5f4cb161cec3 48
tass picotcp@tass.be 149:5f4cb161cec3 49 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 50 if (option == PICO_TCP_NODELAY) {
tass picotcp@tass.be 149:5f4cb161cec3 51 int *val = (int*)value;
tass picotcp@tass.be 149:5f4cb161cec3 52 if (*val > 0) {
tass picotcp@tass.be 149:5f4cb161cec3 53 dbg("setsockopt: Nagle algorithm disabled.\n");
tass picotcp@tass.be 149:5f4cb161cec3 54 PICO_SOCKET_SETOPT_EN(s, PICO_SOCKET_OPT_TCPNODELAY);
tass picotcp@tass.be 149:5f4cb161cec3 55 } else {
tass picotcp@tass.be 149:5f4cb161cec3 56 dbg("setsockopt: Nagle algorithm enabled.\n");
tass picotcp@tass.be 149:5f4cb161cec3 57 PICO_SOCKET_SETOPT_DIS(s, PICO_SOCKET_OPT_TCPNODELAY);
tass picotcp@tass.be 149:5f4cb161cec3 58 }
tass picotcp@tass.be 149:5f4cb161cec3 59
tass picotcp@tass.be 149:5f4cb161cec3 60 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 61 }
tass picotcp@tass.be 149:5f4cb161cec3 62
tass picotcp@tass.be 149:5f4cb161cec3 63 if (option == PICO_SOCKET_OPT_RCVBUF) {
tass picotcp@tass.be 149:5f4cb161cec3 64 uint32_t *val = (uint32_t*)value;
tass picotcp@tass.be 149:5f4cb161cec3 65 pico_tcp_set_bufsize_in(s, *val);
tass picotcp@tass.be 149:5f4cb161cec3 66 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 67 }
tass picotcp@tass.be 149:5f4cb161cec3 68
tass picotcp@tass.be 149:5f4cb161cec3 69 if (option == PICO_SOCKET_OPT_SNDBUF) {
tass picotcp@tass.be 149:5f4cb161cec3 70 uint32_t *val = (uint32_t*)value;
tass picotcp@tass.be 149:5f4cb161cec3 71 pico_tcp_set_bufsize_out(s, *val);
tass picotcp@tass.be 149:5f4cb161cec3 72 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 73 }
tass picotcp@tass.be 149:5f4cb161cec3 74
tass picotcp@tass.be 149:5f4cb161cec3 75 #endif
tass picotcp@tass.be 149:5f4cb161cec3 76 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 77 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 78 }
tass picotcp@tass.be 149:5f4cb161cec3 79
tass picotcp@tass.be 149:5f4cb161cec3 80 void pico_socket_tcp_cleanup(struct pico_socket *sock)
tass picotcp@tass.be 149:5f4cb161cec3 81 {
tass picotcp@tass.be 149:5f4cb161cec3 82 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 83 /* for tcp sockets go further and clean the sockets inside queue */
tass picotcp@tass.be 149:5f4cb161cec3 84 if(sock->proto == &pico_proto_tcp)
tass picotcp@tass.be 149:5f4cb161cec3 85 pico_tcp_cleanup_queues(sock);
tass picotcp@tass.be 149:5f4cb161cec3 86
tass picotcp@tass.be 149:5f4cb161cec3 87 #endif
tass picotcp@tass.be 149:5f4cb161cec3 88 }
tass picotcp@tass.be 149:5f4cb161cec3 89
tass picotcp@tass.be 149:5f4cb161cec3 90
tass picotcp@tass.be 149:5f4cb161cec3 91 void pico_socket_tcp_delete(struct pico_socket *s)
tass picotcp@tass.be 149:5f4cb161cec3 92 {
tass picotcp@tass.be 149:5f4cb161cec3 93 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 94 if(s->parent)
tass picotcp@tass.be 149:5f4cb161cec3 95 s->parent->number_of_pending_conn--;
tass picotcp@tass.be 149:5f4cb161cec3 96
tass picotcp@tass.be 149:5f4cb161cec3 97 #endif
tass picotcp@tass.be 149:5f4cb161cec3 98 }
tass picotcp@tass.be 149:5f4cb161cec3 99
tass picotcp@tass.be 149:5f4cb161cec3 100 int pico_socket_tcp_deliver(struct pico_sockport *sp, struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 101 {
tass picotcp@tass.be 149:5f4cb161cec3 102 struct pico_socket *found = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 103 struct pico_tree_node *index = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 104 struct pico_tree_node *_tmp;
tass picotcp@tass.be 149:5f4cb161cec3 105 struct pico_trans *tr = (struct pico_trans *) f->transport_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 106 struct pico_socket *s = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 107
tass picotcp@tass.be 149:5f4cb161cec3 108
tass picotcp@tass.be 149:5f4cb161cec3 109 pico_tree_foreach_safe(index, &sp->socks, _tmp){
tass picotcp@tass.be 149:5f4cb161cec3 110 s = index->keyValue;
tass picotcp@tass.be 149:5f4cb161cec3 111 /* 4-tuple identification of socket (port-IP) */
tass picotcp@tass.be 149:5f4cb161cec3 112 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 113 if (IS_IPV4(f)) {
tass picotcp@tass.be 149:5f4cb161cec3 114 struct pico_ip4 s_local, s_remote, p_src, p_dst;
tass picotcp@tass.be 149:5f4cb161cec3 115 struct pico_ipv4_hdr *ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr);
tass picotcp@tass.be 149:5f4cb161cec3 116 s_local.addr = s->local_addr.ip4.addr;
tass picotcp@tass.be 149:5f4cb161cec3 117 s_remote.addr = s->remote_addr.ip4.addr;
tass picotcp@tass.be 149:5f4cb161cec3 118 p_src.addr = ip4hdr->src.addr;
tass picotcp@tass.be 149:5f4cb161cec3 119 p_dst.addr = ip4hdr->dst.addr;
tass picotcp@tass.be 149:5f4cb161cec3 120 if ((s->remote_port == tr->sport) && /* remote port check */
tass picotcp@tass.be 149:5f4cb161cec3 121 (s_remote.addr == p_src.addr) && /* remote addr check */
tass picotcp@tass.be 149:5f4cb161cec3 122 ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))) { /* Either local socket is ANY, or matches dst */
tass picotcp@tass.be 149:5f4cb161cec3 123 found = s;
tass picotcp@tass.be 149:5f4cb161cec3 124 break;
tass picotcp@tass.be 149:5f4cb161cec3 125 } else if ((s->remote_port == 0) && /* not connected... listening */
tass picotcp@tass.be 149:5f4cb161cec3 126 ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))) { /* Either local socket is ANY, or matches dst */
tass picotcp@tass.be 149:5f4cb161cec3 127 /* listen socket */
tass picotcp@tass.be 149:5f4cb161cec3 128 found = s;
tass picotcp@tass.be 149:5f4cb161cec3 129 }
tass picotcp@tass.be 149:5f4cb161cec3 130 }
tass picotcp@tass.be 149:5f4cb161cec3 131
tass picotcp@tass.be 149:5f4cb161cec3 132 #endif
tass picotcp@tass.be 149:5f4cb161cec3 133 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 134 if (IS_IPV6(f)) {
tass picotcp@tass.be 149:5f4cb161cec3 135 struct pico_ip6 s_local = {{0}}, s_remote = {{0}}, p_src = {{0}}, p_dst = {{0}};
tass picotcp@tass.be 149:5f4cb161cec3 136 struct pico_ipv6_hdr *ip6hdr = (struct pico_ipv6_hdr *)(f->net_hdr);
tass picotcp@tass.be 149:5f4cb161cec3 137 s_local = s->local_addr.ip6;
tass picotcp@tass.be 149:5f4cb161cec3 138 s_remote = s->remote_addr.ip6;
tass picotcp@tass.be 149:5f4cb161cec3 139 p_src = ip6hdr->src;
tass picotcp@tass.be 149:5f4cb161cec3 140 p_dst = ip6hdr->dst;
tass picotcp@tass.be 149:5f4cb161cec3 141 if ((s->remote_port == tr->sport) &&
tass picotcp@tass.be 149:5f4cb161cec3 142 (!memcmp(s_remote.addr, p_src.addr, PICO_SIZE_IP6)) &&
tass picotcp@tass.be 149:5f4cb161cec3 143 ((!memcmp(s_local.addr, PICO_IP6_ANY, PICO_SIZE_IP6)) || (!memcmp(s_local.addr, p_dst.addr, PICO_SIZE_IP6)))) {
tass picotcp@tass.be 149:5f4cb161cec3 144 found = s;
tass picotcp@tass.be 149:5f4cb161cec3 145 break;
tass picotcp@tass.be 149:5f4cb161cec3 146 } else if ((s->remote_port == 0) && /* not connected... listening */
tass picotcp@tass.be 149:5f4cb161cec3 147 ((!memcmp(s_local.addr, PICO_IP6_ANY, PICO_SIZE_IP6)) || (!memcmp(s_local.addr, p_dst.addr, PICO_SIZE_IP6)))) {
tass picotcp@tass.be 149:5f4cb161cec3 148 /* listen socket */
tass picotcp@tass.be 149:5f4cb161cec3 149 found = s;
tass picotcp@tass.be 149:5f4cb161cec3 150 }
tass picotcp@tass.be 149:5f4cb161cec3 151 }
tass picotcp@tass.be 149:5f4cb161cec3 152
tass picotcp@tass.be 149:5f4cb161cec3 153 #endif
tass picotcp@tass.be 149:5f4cb161cec3 154 } /* FOREACH */
tass picotcp@tass.be 149:5f4cb161cec3 155 if (found != NULL) {
tass picotcp@tass.be 149:5f4cb161cec3 156 pico_tcp_input(found, f);
tass picotcp@tass.be 149:5f4cb161cec3 157 if ((found->ev_pending) && found->wakeup) {
tass picotcp@tass.be 149:5f4cb161cec3 158 found->wakeup(found->ev_pending, found);
tass picotcp@tass.be 149:5f4cb161cec3 159 if(!found->parent)
tass picotcp@tass.be 149:5f4cb161cec3 160 found->ev_pending = 0;
tass picotcp@tass.be 149:5f4cb161cec3 161 }
tass picotcp@tass.be 149:5f4cb161cec3 162
tass picotcp@tass.be 149:5f4cb161cec3 163 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 164 } else {
tass picotcp@tass.be 149:5f4cb161cec3 165 dbg("TCP SOCKET> Not found.\n");
tass picotcp@tass.be 149:5f4cb161cec3 166 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 167 }
tass picotcp@tass.be 149:5f4cb161cec3 168 }
tass picotcp@tass.be 149:5f4cb161cec3 169
tass picotcp@tass.be 149:5f4cb161cec3 170 struct pico_socket *pico_socket_tcp_open(uint16_t family)
tass picotcp@tass.be 149:5f4cb161cec3 171 {
tass picotcp@tass.be 149:5f4cb161cec3 172 struct pico_socket *s = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 173 (void) family;
tass picotcp@tass.be 149:5f4cb161cec3 174 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 175 s = pico_tcp_open(family);
tass picotcp@tass.be 149:5f4cb161cec3 176 if (!s) {
tass picotcp@tass.be 149:5f4cb161cec3 177 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 178 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 179 }
tass picotcp@tass.be 149:5f4cb161cec3 180
tass picotcp@tass.be 149:5f4cb161cec3 181 s->proto = &pico_proto_tcp;
tass picotcp@tass.be 149:5f4cb161cec3 182 /*check if Nagle enabled */
tass picotcp@tass.be 149:5f4cb161cec3 183 /*
tass picotcp@tass.be 149:5f4cb161cec3 184 if (!IS_NAGLE_ENABLED(s))
tass picotcp@tass.be 149:5f4cb161cec3 185 dbg("ERROR Nagle should be enabled here\n\n");
tass picotcp@tass.be 149:5f4cb161cec3 186 */
tass picotcp@tass.be 149:5f4cb161cec3 187 #endif
tass picotcp@tass.be 149:5f4cb161cec3 188 return s;
tass picotcp@tass.be 149:5f4cb161cec3 189 }
tass picotcp@tass.be 149:5f4cb161cec3 190
tass picotcp@tass.be 149:5f4cb161cec3 191 int pico_socket_tcp_read(struct pico_socket *s, void *buf, uint32_t len)
tass picotcp@tass.be 149:5f4cb161cec3 192 {
tass picotcp@tass.be 149:5f4cb161cec3 193 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 194 /* check if in shutdown state and if no more data in tcpq_in */
tass picotcp@tass.be 149:5f4cb161cec3 195 if ((s->state & PICO_SOCKET_STATE_SHUT_REMOTE) && pico_tcp_queue_in_is_empty(s)) {
tass picotcp@tass.be 149:5f4cb161cec3 196 pico_err = PICO_ERR_ESHUTDOWN;
tass picotcp@tass.be 149:5f4cb161cec3 197 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 198 } else {
tass picotcp@tass.be 149:5f4cb161cec3 199 return (int)(pico_tcp_read(s, buf, (uint32_t)len));
tass picotcp@tass.be 149:5f4cb161cec3 200 }
tass picotcp@tass.be 149:5f4cb161cec3 201
tass picotcp@tass.be 150:551effcf6a39 202 #else
tass picotcp@tass.be 150:551effcf6a39 203 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 204 #endif
tass picotcp@tass.be 149:5f4cb161cec3 205 }
tass picotcp@tass.be 149:5f4cb161cec3 206
tass picotcp@tass.be 149:5f4cb161cec3 207 void transport_flags_update(struct pico_frame *f, struct pico_socket *s)
tass picotcp@tass.be 149:5f4cb161cec3 208 {
tass picotcp@tass.be 149:5f4cb161cec3 209 #ifdef PICO_SUPPORT_TCP
tass picotcp@tass.be 149:5f4cb161cec3 210 pico_tcp_flags_update(f, s);
tass picotcp@tass.be 149:5f4cb161cec3 211 #endif
tass picotcp@tass.be 149:5f4cb161cec3 212 }