/****************************************************************************** * FunctionName : espconn_set_opt * Description : set the option for connections so that we don't end up bouncing * all connections at the same time . * Parameters : espconn -- the espconn used to set the connection * opt -- the option for set * Returns : the result *******************************************************************************/ sint8 ICACHE_FLASH_ATTR espconn_set_opt(struct espconn *espconn, uint8 opt) { espconn_msg *pnode = NULL; struct tcp_pcb *tpcb; bool value = false; if (espconn == NULL) { return ESPCONN_ARG;; } else if (espconn->type != ESPCONN_TCP) return ESPCONN_ARG; /*Find the node depend on the espconn message*/ value = espconn_find_connection(espconn, &pnode); if (value) { pnode->pcommon.espconn_opt |= opt; tpcb = pnode->pcommon.pcb; if (espconn_delay_disabled(pnode)) tcp_nagle_disable(tpcb); if (espconn_keepalive_disabled(pnode)) espconn_keepalive_enable(tpcb); return ESPCONN_OK; } else return ESPCONN_ARG; }
socket_error_t lwipv4_socket_set_option(struct socket *socket, const socket_proto_level_t level, const socket_option_type_t type, const void *option, const size_t optionSize) { (void) level; (void) optionSize; socket_error_t err = SOCKET_ERROR_UNIMPLEMENTED; switch (type) { case SOCKET_OPT_NAGLE: { if (socket->family != SOCKET_STREAM) return SOCKET_ERROR_UNIMPLEMENTED; /* Check the pointer. If it is NULL, disable Nagle's Algorithm. If not, enable Nagle's Algorithm. * This approach is used because configuration data could be passed via a structure */ if(option == NULL) { tcp_nagle_disable((struct tcp_pcb *) socket->impl); } else { tcp_nagle_enable((struct tcp_pcb *) socket->impl); } err = SOCKET_ERROR_NONE; break; } default: break; } return err; }
static int tcp_do_accept(struct socket * listen_sock, message * m, struct tcp_pcb * newpcb) { struct socket * newsock; unsigned sock_num; int ret; debug_tcp_print("socket num %ld", get_sock_num(listen_sock)); if ((ret = copy_from_user(m->m_source, &sock_num, sizeof(sock_num), (cp_grant_id_t) m->IO_GRANT, 0)) != OK) return EFAULT; if (!is_valid_sock_num(sock_num)) return EBADF; newsock = get_sock(sock_num); assert(newsock->pcb); /* because of previous open() */ /* we really want to forget about this socket */ tcp_err((struct tcp_pcb *)newsock->pcb, NULL); tcp_abandon((struct tcp_pcb *)newsock->pcb, 0); tcp_arg(newpcb, newsock); tcp_err(newpcb, tcp_error_callback); tcp_sent(newpcb, tcp_sent_callback); tcp_recv(newpcb, tcp_recv_callback); tcp_nagle_disable(newpcb); tcp_accepted(((struct tcp_pcb *)(listen_sock->pcb))); newsock->pcb = newpcb; debug_tcp_print("Accepted new connection using socket %d\n", sock_num); return OK; }
int8_t AsyncServer::_accept(tcp_pcb* pcb, int8_t err){ tcp_accepted(_pcb); if(_connect_cb){ if (_noDelay) tcp_nagle_disable(pcb); else tcp_nagle_enable(pcb); AsyncClient *c = new AsyncClient(pcb); if(c){ _in_lwip_thread = true; c->_in_lwip_thread = true; _connect_cb(_connect_cb_arg, c); c->_in_lwip_thread = false; _in_lwip_thread = false; return ERR_OK; } } if(tcp_close(pcb) != ERR_OK){ tcp_abort(pcb); } log_e("FAIL"); return ERR_OK; }
void AsyncServer::setNoDelay(bool nodelay){ if (!_pcb) return; if (nodelay) tcp_nagle_disable(_pcb); else tcp_nagle_enable(_pcb); }
static void altcp_tcp_nagle_disable(struct altcp_pcb *conn) { if (conn && conn->state) { struct tcp_pcb *pcb = (struct tcp_pcb *)conn->state; ALTCP_TCP_ASSERT_CONN(conn); tcp_nagle_disable(pcb); } }
void TcpConnection::initialize(tcp_pcb* pcb) { tcp = pcb; sleep = 0; canSend = true; tcp_nagle_disable(tcp); tcp_arg(tcp, (void*)this); tcp_sent(tcp, staticOnSent); tcp_recv(tcp, staticOnReceive); tcp_err(tcp, staticOnError); tcp_poll(tcp, staticOnPoll, 4); #ifdef NETWORK_DEBUG debugf("+TCP connection"); #endif }
static int tcp_fill_new_socket(struct socket * sock, struct tcp_pcb * pcb) { struct wbuf_chain * wc; if (!(wc = malloc(sizeof(struct wbuf_chain)))) return ENOMEM; wc-> head = wc->tail = wc->unsent = NULL; sock->buf = wc; sock->buf_size = 0; sock->pcb = pcb; tcp_arg(pcb, sock); tcp_err(pcb, tcp_error_callback); tcp_nagle_disable(pcb); return OK; }
/****************************************************************************** * FunctionName : espconn_client_connect * Description : A new incoming connection has been connected. * Parameters : arg -- Additional argument to pass to the callback function * tpcb -- The connection pcb which is connected * err -- An unused error code, always ERR_OK currently * Returns : connection result *******************************************************************************/ static err_t ICACHE_FLASH_ATTR espconn_client_connect(void *arg, struct tcp_pcb *tpcb, err_t err) { espconn_msg *pcon = arg; espconn_printf("espconn_client_connect pcon %p tpcb %p\n", pcon, tpcb); if (err == ERR_OK){ /*Reserve the remote information for current active connection*/ pcon->pespconn->state = ESPCONN_CONNECT; pcon->pcommon.err = err; pcon->pcommon.pcb = tpcb; pcon->pcommon.local_port = tpcb->local_port; pcon->pcommon.local_ip = tpcb->local_ip.u_addr.ip4.addr; pcon->pcommon.remote_port = tpcb->remote_port; pcon->pcommon.remote_ip[0] = ip4_addr1_16(&tpcb->remote_ip.u_addr.ip4); pcon->pcommon.remote_ip[1] = ip4_addr2_16(&tpcb->remote_ip.u_addr.ip4); pcon->pcommon.remote_ip[2] = ip4_addr3_16(&tpcb->remote_ip.u_addr.ip4); pcon->pcommon.remote_ip[3] = ip4_addr4_16(&tpcb->remote_ip.u_addr.ip4); pcon->pcommon.write_flag = true; tcp_arg(tpcb, (void *) pcon); /*Set the specify function that should be called * when TCP data has been successfully delivered, * when active connection receives data*/ tcp_sent(tpcb, espconn_client_sent); tcp_recv(tpcb, espconn_client_recv); /*Disable Nagle algorithm default*/ tcp_nagle_disable(tpcb); /*Default set the total number of espconn_buf on the unsent lists for one*/ espconn_tcp_set_buf_count(pcon->pespconn, 1); if (pcon->pespconn->proto.tcp->connect_callback != NULL) { pcon->pespconn->proto.tcp->connect_callback(pcon->pespconn); } /*Enable keep alive option*/ if (espconn_keepalive_disabled(pcon)) espconn_keepalive_enable(tpcb); } else{ printf("err in host connected (%s)\n",lwip_strerr(err)); } return err; }
/****************************************************************************** * FunctionName : espconn_tcp_accept * Description : A new incoming connection has been accepted. * Parameters : arg -- Additional argument to pass to the callback function * pcb -- The connection pcb which is accepted * err -- An unused error code, always ERR_OK currently * Returns : acception result *******************************************************************************/ static err_t ICACHE_FLASH_ATTR espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) { struct espconn *espconn = arg; espconn_msg *paccept = NULL; remot_info *pinfo = NULL; LWIP_UNUSED_ARG(err); if (!espconn || !espconn->proto.tcp) { return ERR_ARG; } tcp_arg(pcb, paccept); tcp_err(pcb, esponn_server_err); /*Ensure the active connection is less than the count of active connections on the server*/ espconn_get_connection_info(espconn, &pinfo , 0); espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt); if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn)) return ERR_ISCONN; /*Creates a new active connect control message*/ paccept = (espconn_msg *)malloc(sizeof(espconn_msg)); memset(paccept, 0, sizeof(espconn_msg)); tcp_arg(pcb, paccept); if (paccept == NULL) return ERR_MEM; /*Insert the node to the active connection list*/ espconn_list_creat(&plink_active, paccept); paccept->preverse = espconn; paccept->pespconn = (struct espconn *)malloc(sizeof(struct espconn)); if (paccept->pespconn == NULL) return ERR_MEM; paccept->pespconn->proto.tcp = (esp_tcp *)malloc(sizeof(esp_tcp)); if (paccept->pespconn->proto.tcp == NULL) return ERR_MEM; /*Reserve the remote information for current active connection*/ paccept->pcommon.pcb = pcb; paccept->pcommon.remote_port = pcb->remote_port; paccept->pcommon.remote_ip[0] = ip4_addr1_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip.u_addr.ip4); paccept->pcommon.write_flag = true; memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4); espconn->proto.tcp->remote_port = pcb->remote_port; espconn->state = ESPCONN_CONNECT; espconn_copy_partial(paccept->pespconn, espconn); /*Set the specify function that should be called * when TCP data has been successfully delivered, * when active connection receives data, * or periodically from active connection*/ tcp_sent(pcb, espconn_server_sent); tcp_recv(pcb, espconn_server_recv); tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */ /*Disable Nagle algorithm default*/ tcp_nagle_disable(pcb); /*Default set the total number of espconn_buf on the unsent lists for one*/ espconn_tcp_set_buf_count(paccept->pespconn, 1); if (paccept->pespconn->proto.tcp->connect_callback != NULL) { paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn); } /*Enable keep alive option*/ if (espconn_keepalive_disabled(paccept)) espconn_keepalive_enable(pcb); return ERR_OK; }
static int ol_tcp_set_opts(outlet_t *ol, uint8_t *data, int dlen) { uint8_t *p = data; int left = dlen; int saved_active = ol->active; while (left > 0) { int opt = *p++; left--; if (left < 4) return -BAD_ARG; uint32_t val = GET_UINT_32(p); p += 4; left -= 4; switch (opt) { case INET_OPT_RCVBUF: if (val >= 0x80000000) return -BAD_ARG; if (val > ol->max_recv_bufsize) { memnode_t *node = nalloc_N(val); if (node == 0) { // We may return -NO_MEMORY here; a more conservative // approach is to ignore the option and continue printk("ol_tcp_set_opts: cannot expand recv_buffer to %d byte(s)\n", val); continue; } ol->recv_bufsize = val; assert(ol->recv_buf_off <= ol->recv_bufsize); // no truncation memcpy(node->starts, ol->recv_buffer, ol->recv_buf_off); ol->max_recv_bufsize = (void *)node->ends -(void *)node->starts; ol->recv_buffer = (uint8_t *)node->starts; nfree(ol->recv_buf_node); ol->recv_buf_node = node; // ol->recv_buf_off stays the same } else ol->recv_bufsize = val; break; case INET_OPT_PRIORITY: // // There is a priority setting in a PCB. It is always set to high // value to avoid closing of open connections when the stack runs // out of memory. Thus the option is ignored. // //printk("tcp_set_opts: unsupported option SO_PRIORITY ignored\n"); break; case INET_OPT_TOS: ol->tcp->tos = (uint8_t)val; break; case TCP_OPT_NODELAY: // // Nagle's algo fights silly window syndrome. What is its // relationship to not delaying send? // if (val) tcp_nagle_disable(ol->tcp); else tcp_nagle_enable(ol->tcp); break; default: if (inet_set_opt(ol, opt, val) < 0) return -BAD_ARG; } } // // If 'active' option was set among other options, then act immediately to // deliver a buffered packet, if any. // if (saved_active == INET_PASSIVE && ol->active != INET_PASSIVE) { proc_t *cont_proc = scheduler_lookup(ol->owner); assert(cont_proc != 0); recv_bake_packets(ol, cont_proc); } return 0; }
int main() { sys_sem_t sem; sys_init(); if(sys_sem_new(&sem, 0) != ERR_OK) { LWIP_ASSERT("failed to create semaphore", 0); } tcpip_init(tcpip_init_done, &sem); sys_sem_wait(&sem); sys_sem_free(&sem); /////////////////////////////////////////////////////////////////////////////////////////////////// struct netconn *conn, *newconn; err_t err; /* Create a new connection identifier. */ conn = netconn_new(NETCONN_TCP); netconn_set_noautorecved(conn, 0); tcp_nagle_disable(conn->pcb.tcp); /* Bind connection to well known port number 7. */ netconn_bind(conn, NULL, 80); /* Tell connection to go into listening mode. */ netconn_listen(conn); while (1) { /* Grab new connection. */ err = netconn_accept(conn, &newconn); printf("accepted new connection %p\n", newconn); /* Process the new connection. */ if (err == ERR_OK) { struct netbuf *buf; void *data; u16_t len; u64_t total_rcvd = 0; u64_t eal_tsc_resolution_hz = rte_get_timer_hz(); u64_t end = rte_get_timer_cycles() + eal_tsc_resolution_hz; while ((err = netconn_recv(newconn, &buf)) == ERR_OK) { netbuf_data(buf, &data, &len); if (len > 0) { total_rcvd += len; } if (rte_get_timer_cycles() >= end) { printf("%llu \n", (unsigned long long)total_rcvd); total_rcvd = 0; end = rte_get_timer_cycles() + eal_tsc_resolution_hz; } #if 0 if (err != ERR_OK) { printf("tcpecho: netconn_write: error \"%s\"\n", lwip_strerr(err)); } #endif //} while (netbuf_next(buf) >= 0); netbuf_delete(buf); } /*printf("Got EOF, looping\n");*/ /* Close connection and discard connection identifier. */ netconn_close(newconn); netconn_delete(newconn); } } while (1); }