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
pico_socket_tcp.c
00001 #include "pico_config.h" 00002 #include "pico_socket.h" 00003 #include "pico_ipv4.h" 00004 #include "pico_ipv6.h" 00005 #include "pico_tcp.h" 00006 #include "pico_socket_tcp.h" 00007 00008 00009 static int sockopt_validate_args(struct pico_socket *s, void *value) 00010 { 00011 if (!value) { 00012 pico_err = PICO_ERR_EINVAL; 00013 return -1; 00014 } 00015 00016 if (s->proto->proto_number != PICO_PROTO_TCP) { 00017 pico_err = PICO_ERR_EPROTONOSUPPORT; 00018 return -1; 00019 } 00020 00021 return 0; 00022 } 00023 00024 int pico_getsockopt_tcp(struct pico_socket *s, int option, void *value) 00025 { 00026 if (sockopt_validate_args(s, value) < 0) 00027 return -1; 00028 00029 #ifdef PICO_SUPPORT_TCP 00030 if (option == PICO_TCP_NODELAY) { 00031 /* state of the NODELAY option */ 00032 *(int *)value = PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_TCPNODELAY); 00033 return 0; 00034 } 00035 else if (option == PICO_SOCKET_OPT_RCVBUF) { 00036 return pico_tcp_get_bufsize_in(s, (uint32_t *)value); 00037 } 00038 00039 else if (option == PICO_SOCKET_OPT_SNDBUF) { 00040 return pico_tcp_get_bufsize_out(s, (uint32_t *)value); 00041 } 00042 00043 #endif 00044 return -1; 00045 } 00046 00047 static void tcp_set_nagle_option(struct pico_socket *s, void *value) 00048 { 00049 int *val = (int*)value; 00050 if (*val > 0) { 00051 dbg("setsockopt: Nagle algorithm disabled.\n"); 00052 PICO_SOCKET_SETOPT_EN(s, PICO_SOCKET_OPT_TCPNODELAY); 00053 } else { 00054 dbg("setsockopt: Nagle algorithm enabled.\n"); 00055 PICO_SOCKET_SETOPT_DIS(s, PICO_SOCKET_OPT_TCPNODELAY); 00056 } 00057 } 00058 00059 int pico_setsockopt_tcp(struct pico_socket *s, int option, void *value) 00060 { 00061 if (sockopt_validate_args(s, value) < 0) 00062 return -1; 00063 00064 #ifdef PICO_SUPPORT_TCP 00065 if (option == PICO_TCP_NODELAY) { 00066 tcp_set_nagle_option(s, value); 00067 return 0; 00068 } 00069 else if (option == PICO_SOCKET_OPT_RCVBUF) { 00070 uint32_t *val = (uint32_t*)value; 00071 pico_tcp_set_bufsize_in(s, *val); 00072 return 0; 00073 } 00074 else if (option == PICO_SOCKET_OPT_SNDBUF) { 00075 uint32_t *val = (uint32_t*)value; 00076 pico_tcp_set_bufsize_out(s, *val); 00077 return 0; 00078 } 00079 else if (option == PICO_SOCKET_OPT_KEEPCNT) { 00080 uint32_t *val = (uint32_t*)value; 00081 pico_tcp_set_keepalive_probes(s, *val); 00082 return 0; 00083 } 00084 else if (option == PICO_SOCKET_OPT_KEEPIDLE) { 00085 uint32_t *val = (uint32_t*)value; 00086 pico_tcp_set_keepalive_time(s, *val); 00087 return 0; 00088 } 00089 else if (option == PICO_SOCKET_OPT_KEEPINTVL) { 00090 uint32_t *val = (uint32_t*)value; 00091 pico_tcp_set_keepalive_intvl(s, *val); 00092 return 0; 00093 } 00094 else if (option == PICO_SOCKET_OPT_LINGER) { 00095 uint32_t *val = (uint32_t*)value; 00096 pico_tcp_set_linger(s, *val); 00097 return 0; 00098 } 00099 00100 #endif 00101 pico_err = PICO_ERR_EINVAL; 00102 return -1; 00103 } 00104 00105 void pico_socket_tcp_cleanup(struct pico_socket *sock) 00106 { 00107 #ifdef PICO_SUPPORT_TCP 00108 /* for tcp sockets go further and clean the sockets inside queue */ 00109 if(is_sock_tcp(sock)) 00110 pico_tcp_cleanup_queues(sock); 00111 00112 #endif 00113 } 00114 00115 00116 void pico_socket_tcp_delete(struct pico_socket *s) 00117 { 00118 #ifdef PICO_SUPPORT_TCP 00119 if(s->parent) 00120 s->parent->number_of_pending_conn--; 00121 00122 #endif 00123 } 00124 00125 static struct pico_socket *socket_tcp_deliver_ipv4(struct pico_socket *s, struct pico_frame *f) 00126 { 00127 struct pico_socket *found = NULL; 00128 #ifdef PICO_SUPPORT_IPV4 00129 struct pico_ip4 s_local, s_remote, p_src, p_dst; 00130 struct pico_ipv4_hdr *ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr); 00131 struct pico_trans *tr = (struct pico_trans *) f->transport_hdr; 00132 s_local.addr = s->local_addr.ip4.addr; 00133 s_remote.addr = s->remote_addr.ip4.addr; 00134 p_src.addr = ip4hdr->src.addr; 00135 p_dst.addr = ip4hdr->dst.addr; 00136 if ((s->remote_port == tr->sport) && /* remote port check */ 00137 (s_remote.addr == p_src.addr) && /* remote addr check */ 00138 ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))) { /* Either local socket is ANY, or matches dst */ 00139 found = s; 00140 return found; 00141 } else if ((s->remote_port == 0) && /* not connected... listening */ 00142 ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr))) { /* Either local socket is ANY, or matches dst */ 00143 /* listen socket */ 00144 found = s; 00145 } 00146 00147 #endif 00148 return found; 00149 } 00150 00151 static struct pico_socket *socket_tcp_deliver_ipv6(struct pico_socket *s, struct pico_frame *f) 00152 { 00153 struct pico_socket *found = NULL; 00154 #ifdef PICO_SUPPORT_IPV6 00155 struct pico_trans *tr = (struct pico_trans *) f->transport_hdr; 00156 struct pico_ip6 s_local = {{0}}, s_remote = {{0}}, p_src = {{0}}, p_dst = {{0}}; 00157 struct pico_ipv6_hdr *ip6hdr = (struct pico_ipv6_hdr *)(f->net_hdr); 00158 s_local = s->local_addr.ip6; 00159 s_remote = s->remote_addr.ip6; 00160 p_src = ip6hdr->src; 00161 p_dst = ip6hdr->dst; 00162 if ((s->remote_port == tr->sport) && 00163 (!memcmp(s_remote.addr, p_src.addr, PICO_SIZE_IP6)) && 00164 ((!memcmp(s_local.addr, PICO_IP6_ANY, PICO_SIZE_IP6)) || (!memcmp(s_local.addr, p_dst.addr, PICO_SIZE_IP6)))) { 00165 found = s; 00166 return found; 00167 } else if ((s->remote_port == 0) && /* not connected... listening */ 00168 ((!memcmp(s_local.addr, PICO_IP6_ANY, PICO_SIZE_IP6)) || (!memcmp(s_local.addr, p_dst.addr, PICO_SIZE_IP6)))) { 00169 /* listen socket */ 00170 found = s; 00171 } 00172 00173 #else 00174 (void) s; 00175 (void) f; 00176 #endif 00177 return found; 00178 } 00179 00180 static int socket_tcp_do_deliver(struct pico_socket *s, struct pico_frame *f) 00181 { 00182 if (s != NULL) { 00183 pico_tcp_input(s, f); 00184 if ((s->ev_pending) && s->wakeup) { 00185 s->wakeup(s->ev_pending, s); 00186 if(!s->parent) 00187 s->ev_pending = 0; 00188 } 00189 00190 return 0; 00191 } 00192 00193 dbg("TCP SOCKET> Not s.\n"); 00194 return -1; 00195 } 00196 00197 int pico_socket_tcp_deliver(struct pico_sockport *sp, struct pico_frame *f) 00198 { 00199 struct pico_socket *found = NULL; 00200 struct pico_tree_node *index = NULL; 00201 struct pico_tree_node *_tmp; 00202 struct pico_socket *s = NULL; 00203 00204 00205 pico_tree_foreach_safe(index, &sp->socks, _tmp){ 00206 s = index->keyValue; 00207 /* 4-tuple identification of socket (port-IP) */ 00208 if (IS_IPV4(f)) { 00209 found = socket_tcp_deliver_ipv4(s, f); 00210 } 00211 00212 if (IS_IPV6(f)) { 00213 found = socket_tcp_deliver_ipv6(s, f); 00214 } 00215 00216 if (found) 00217 break; 00218 } /* FOREACH */ 00219 00220 return socket_tcp_do_deliver(found, f); 00221 } 00222 00223 struct pico_socket *pico_socket_tcp_open(uint16_t family) 00224 { 00225 struct pico_socket *s = NULL; 00226 (void) family; 00227 #ifdef PICO_SUPPORT_TCP 00228 s = pico_tcp_open(family); 00229 if (!s) { 00230 pico_err = PICO_ERR_ENOMEM; 00231 return NULL; 00232 } 00233 00234 s->proto = &pico_proto_tcp; 00235 /*check if Nagle enabled */ 00236 /* 00237 if (!IS_NAGLE_ENABLED(s)) 00238 dbg("ERROR Nagle should be enabled here\n\n"); 00239 */ 00240 #endif 00241 return s; 00242 } 00243 00244 int pico_socket_tcp_read(struct pico_socket *s, void *buf, uint32_t len) 00245 { 00246 #ifdef PICO_SUPPORT_TCP 00247 /* check if in shutdown state and if no more data in tcpq_in */ 00248 if ((s->state & PICO_SOCKET_STATE_SHUT_REMOTE) && pico_tcp_queue_in_is_empty(s)) { 00249 pico_err = PICO_ERR_ESHUTDOWN; 00250 return -1; 00251 } else { 00252 return (int)(pico_tcp_read(s, buf, (uint32_t)len)); 00253 } 00254 00255 #else 00256 return 0; 00257 #endif 00258 } 00259 00260 void transport_flags_update(struct pico_frame *f, struct pico_socket *s) 00261 { 00262 #ifdef PICO_SUPPORT_TCP 00263 if(is_sock_tcp(s)) 00264 pico_tcp_flags_update(f, s); 00265 00266 #endif 00267 }
Generated on Tue Jul 12 2022 15:59:22 by 1.7.2