int mg_lwip_tcp_write(struct mg_connection *nc, const void *data, uint16_t len) { struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; struct tcp_pcb *tpcb = cs->pcb.tcp; len = MIN(tpcb->mss, MIN(len, tpcb->snd_buf)); if (len == 0) { DBG(("%p no buf avail %u %u %u %p %p", tpcb, tpcb->acked, tpcb->snd_buf, tpcb->snd_queuelen, tpcb->unsent, tpcb->unacked)); tcp_output(tpcb); return 0; } err_t err = tcp_write(tpcb, data, len, TCP_WRITE_FLAG_COPY); tcp_output(tpcb); DBG(("%p tcp_write %u = %d", tpcb, len, err)); if (err != ERR_OK) { /* * We ignore ERR_MEM because memory will be freed up when the data is sent * and we'll retry. */ return (err == ERR_MEM ? 0 : -1); } cs->bytes_written += len; if (cs->send_started_bytes == 0) { cs->send_started_bytes = cs->bytes_written; cs->send_started_micros = system_get_time(); cs->rexmit_timeout_micros = cs->next_rexmit_ts_micros = 0; mg_lwip_sched_rexmit(nc); } return len; }
size_t EthernetClient::write(const uint8_t *buf, size_t size) { uint32_t i = 0, inc = 0; boolean stuffed_buffer = false; // Attempt to write in 1024-byte increments. while (i < size) { inc = (size-i) < 1024 ? size-i : 1024; err_t err = tcp_write(cpcb, buf+i, inc, TCP_WRITE_FLAG_COPY); if (err != ERR_MEM) { // Keep enqueueing the lwIP buffer until it's full... i += inc; stuffed_buffer = false; } else { if (!stuffed_buffer) { // Buffer full; force output if (cs->mode) tcp_output(cpcb); stuffed_buffer = true; } else { delay(1); // else wait a little bit for lwIP to flush its buffers } } } // flush any remaining queue contents if (!stuffed_buffer) { if (cs->mode) tcp_output(cpcb); } return i; }
static void mg_lwip_tcp_write(struct mg_connection *nc) { struct tcp_pcb *tpcb = (struct tcp_pcb *) nc->sock; size_t len; if (nc->sock == INVALID_SOCKET) { DBG(("%p tcp_write invalid socket %d", nc, nc->err)); return; } len = MIN(tpcb->mss, MIN(nc->send_mbuf.len, tpcb->snd_buf)); if (len == 0) { DBG(("%p no buf avail %u %u %u %p %p", nc, tpcb->acked, tpcb->snd_buf, tpcb->snd_queuelen, tpcb->unsent, tpcb->unacked)); tcp_output(tpcb); return; } nc->err = tcp_write(tpcb, nc->send_mbuf.buf, len, TCP_WRITE_FLAG_COPY); tcp_output(tpcb); DBG(("%p tcp_write %u = %d", nc, len, nc->err)); if (nc->err != ERR_OK) { if (nc->err != ERR_MEM) { system_os_post(MG_TASK_PRIORITY, MG_SIG_CLOSE_CONN, (uint32_t) nc); } /* * We ignore ERR_MEM because memory will be freed up when the data is sent * and we'll retry. */ } else { mbuf_remove(&nc->send_mbuf, len); mbuf_trim(&nc->send_mbuf); } }
/* takes socket at state CLOSED, and start connect to s->remote * if s not CLOSED, return null * \return socket in connection state * \return = SExxx - some error * * */ tcp_socket_t *tcp_connect_restart (tcp_socket_t *s) { unsigned long optdata; ip_t *ip = s->ip; tcp_debug ("tcp reconnect to port %u\n", s->remote_port); s->lastack = s->snd_nxt - 1; s->snd_lbb = s->snd_nxt - 1; s->snd_wnd = TCP_WND; s->ssthresh = s->mss * 10; s->state = SYN_SENT; /* Build an MSS option */ optdata = HTONL (((unsigned long)2 << 24) | ((unsigned long)4 << 16) | (((unsigned long)s->mss / 256) << 8) | (s->mss & 255)); if (! tcp_enqueue_option4 (s, TCP_SYN, optdata)) { return 0; } mutex_lock (&ip->lock); s->tmr = ip->tcp_ticks; tcp_list_add (&ip->tcp_sockets, s); #if TCP_LOCK_STYLE <= TCP_LOCK_SURE tcp_output (s); mutex_unlock (&ip->lock); #elif TCP_LOCK_STYLE >= TCP_LOCK_RELAXED mutex_unlock (&ip->lock); tcp_output (s); #endif mutex_unlock (&s->lock); return s; }
static int tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) { int error = 0; struct inpcb *inp; struct tcpcb *tp = NULL; struct sockaddr_in6 *sin6p; TCPDEBUG0; sin6p = (struct sockaddr_in6 *)nam; if (nam->sa_len != sizeof (*sin6p)) return (EINVAL); /* * Must disallow TCP ``connections'' to multicast addresses. */ if (sin6p->sin6_family == AF_INET6 && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) return (EAFNOSUPPORT); INP_INFO_WLOCK(&tcbinfo); inp = sotoinpcb(so); KASSERT(inp != NULL, ("tcp6_usr_connect: inp == NULL")); INP_LOCK(inp); if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { error = EINVAL; goto out; } tp = intotcpcb(inp); TCPDEBUG1(); if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { struct sockaddr_in sin; if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) { error = EINVAL; goto out; } in6_sin6_2_sin(&sin, sin6p); inp->inp_vflag |= INP_IPV4; inp->inp_vflag &= ~INP_IPV6; if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0) goto out; error = tcp_output(tp); goto out; } inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; inp->inp_inc.inc_isipv6 = 1; if ((error = tcp6_connect(tp, nam, td)) != 0) goto out; error = tcp_output(tp); out: TCPDEBUG2(PRU_CONNECT); INP_UNLOCK(inp); INP_INFO_WUNLOCK(&tcbinfo); return (error); }
err_t tcp_client_reciver(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { char *data; char UID_STM32[16]; char IDon[7] ={0x67,0x74,0,0,1,0x0d,0x0a}; char IDoff[7]={0x67,0x74,0,0,0,0x0d,0x0a}; char IDs[7] ={0x67,0x74,0,0,2,0x0d,0x0a}; if (err == ERR_OK && p != NULL) { /* Inform TCP that we have taken the data. */ tcp_recved(tpcb, p->tot_len); data = p->payload; if (strncmp(data, "start", 5) == 0) { cansent=1; tcp_write(tpcb, "startsent\r\n", sizeof( "startsent\r\n"), 1); tcp_output(tpcb); } else if (strncmp(data, "stop", 4) == 0) { cansent=0; tcp_write(tpcb, "startsent\r\n", sizeof( "startsent\r\n"), 1); tcp_output(tpcb); } else if (strncmp(data, "getru", 5) == 0) { UID_STM32[0]=0xAA; UID_STM32[4]=retry_TCP_connect; UID_STM32[3]=retry_TCP_connect>>8; UID_STM32[2]=retry_TCP_connect>>16; //重练次数 UID_STM32[1]=retry_TCP_connect>>24; UID_STM32[8]=SystemRunTime; UID_STM32[7]=SystemRunTime>>8; //运行时间 UID_STM32[6]=SystemRunTime>>16; UID_STM32[5]=SystemRunTime>>24; UID_STM32[9]=0xBB; UID_STM32[10]=0x0d; UID_STM32[11]=0x0a; tcp_write(tpcb, &UID_STM32, 12, 1); tcp_output(tpcb); }
int PubSub_mbed::publish(char* pub_topic, char* msg) { uint8_t var_header_pub[strlen(pub_topic)+3]; strcpy((char *)&var_header_pub[2], pub_topic); var_header_pub[0] = 0; var_header_pub[1] = strlen(pub_topic); var_header_pub[sizeof(var_header_pub)-1] = 0; uint8_t fixed_header_pub[] = {MQTTPUBLISH,sizeof(var_header_pub)+strlen(msg)}; uint8_t packet_pub[sizeof(fixed_header_pub)+sizeof(var_header_pub)+strlen(msg)]; memset(packet_pub,0,sizeof(packet_pub)); memcpy(packet_pub,fixed_header_pub,sizeof(fixed_header_pub)); memcpy(packet_pub+sizeof(fixed_header_pub),var_header_pub,sizeof(var_header_pub)); memcpy(packet_pub+sizeof(fixed_header_pub)+sizeof(var_header_pub),msg,strlen(msg)); //Publish message err_t err = tcp_write(this->pcb, (void *)packet_pub, sizeof(packet_pub), 1); //TCP_WRITE_FLAG_MORE if (err == ERR_OK) { tcp_output(this->pcb); printf("Publish: %s ...\r\n", msg); } else { printf("Failed to publish...\r\n"); printf("Error is: %d\r\n",err); tcp_close(this->pcb); return -1; } printf("\r\n"); device_poll(); return 1; }
void PubSub_mbed::subscribe(char* topic) { if (connected) { uint8_t var_header_topic[] = {0,10}; uint8_t fixed_header_topic[] = {MQTTSUBSCRIBE,sizeof(var_header_topic)+strlen(topic)+3}; // utf topic uint8_t utf_topic[strlen(topic)+3]; strcpy((char *)&utf_topic[2], topic); utf_topic[0] = 0; utf_topic[1] = strlen(topic); utf_topic[sizeof(utf_topic)-1] = 0; char packet_topic[sizeof(var_header_topic)+sizeof(fixed_header_topic)+strlen(topic)+3]; memset(packet_topic,0,sizeof(packet_topic)); memcpy(packet_topic,fixed_header_topic,sizeof(fixed_header_topic)); memcpy(packet_topic+sizeof(fixed_header_topic),var_header_topic,sizeof(var_header_topic)); memcpy(packet_topic+sizeof(fixed_header_topic)+sizeof(var_header_topic),utf_topic,sizeof(utf_topic)); //Send message err_t err = tcp_write(this->pcb, (void *)packet_topic, sizeof(packet_topic), 1); //TCP_WRITE_FLAG_MORE if (err == ERR_OK) { tcp_output(this->pcb); printf("Subscribe sucessfull to: %s...\r\n", topic); } else { printf("Failed to subscribe to: %s...\r\n", topic); printf("Error is: %d\r\n",err); tcp_close(pcb); } printf("\r\n"); device_poll(); } }
void tcp_worker( struct epoll_event *events, int nfds, int thrd_id ) { ITEM *listItem = NULL; int i; mutex_block( _main->work->mutex ); _main->work->active++; mutex_unblock( _main->work->mutex ); for( i=0; i<nfds; i++ ) { if( events[i].data.fd == _main->tcp->sockfd ) { tcp_newconn(); } else { listItem = events[i].data.ptr; if( events[i].events & EPOLLIN ) { tcp_input( listItem ); } else if( events[i].events & EPOLLOUT ) { tcp_output( listItem ); } /* Close, Input or Output next? */ tcp_gate( listItem ); } } mutex_block( _main->work->mutex ); _main->work->active--; mutex_unblock( _main->work->mutex ); }
err_t data_send(struct tcp_pcb *pcb,const unsigned char* addr,int data_len,int no) { // struct pbuf *p; int cur_len=1460*3; int data_count=0; // // // err_t err1; // if(p!=NULL) { tcp_write(pcb,&no,4,0); // // // err1=tcp_output(pcb); while(data_len>0) { tcp_write(pcb,addr+data_count*cur_len,cur_len,0); // // // err1=tcp_output(pcb); // // // if(err1 == ERR_OK) { data_len=data_len-cur_len; data_count++; } } tcp_output(pcb); } // pbuf_free(p); // if(p == NULL) // { // tcp_abort(pcb); // tcp_close(pcb); // } return ERR_OK; }
/** * Requeue all unacked segments for retransmission * * Called by tcp_slowtmr() for slow retransmission. * * @param pcb the tcp_pcb for which to re-enqueue all unacked segments */ void tcp_rexmit_rto(struct tcp_pcb *pcb) { struct tcp_seg *seg; if (pcb->unacked == NULL) { return; } /* Move all unacked segments to the head of the unsent queue */ for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); /* concatenate unsent queue after unacked queue */ seg->next = pcb->unsent; #if TCP_OVERSIZE && TCP_OVERSIZE_DBGCHECK /* if last unsent changed, we need to update unsent_oversize */ if (pcb->unsent == NULL) { pcb->unsent_oversize = seg->oversize_left; } #endif /* TCP_OVERSIZE && TCP_OVERSIZE_DBGCHECK*/ /* unsent queue is the concatenated queue (of unacked, unsent) */ pcb->unsent = pcb->unacked; /* unacked queue is now empty */ pcb->unacked = NULL; /* increment number of retransmissions */ ++pcb->nrtx; /* Don't take any RTT measurements after retransmitting. */ pcb->rttest = 0; /* Do the actual retransmission */ tcp_output(pcb); }
void tcp_timer_delack(void *xtp) { struct tcpcb *tp = xtp; struct inpcb *inp; CURVNET_SET(tp->t_vnet); inp = tp->t_inpcb; /* * XXXRW: While this assert is in fact correct, bugs in the tcpcb * tear-down mean we need it as a work-around for races between * timers and tcp_discardcb(). * * KASSERT(inp != NULL, ("tcp_timer_delack: inp == NULL")); */ if (inp == NULL) { tcp_timer_race++; CURVNET_RESTORE(); return; } INP_WLOCK(inp); if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_delack) || !callout_active(&tp->t_timers->tt_delack)) { INP_WUNLOCK(inp); CURVNET_RESTORE(); return; } callout_deactivate(&tp->t_timers->tt_delack); tp->t_flags |= TF_ACKNOW; TCPSTAT_INC(tcps_delack); (void) tcp_output(tp); INP_WUNLOCK(inp); CURVNET_RESTORE(); }
static err_t conn_poll(void *arg, tcp_pcb *pcb) { ConnectionState *cs = (ConnectionState*)arg; if (cs != NULL && sendingTransaction != NULL && cs == sendingTransaction->GetConnection()) { // We tried to send data, but didn't receive an ACK within reasonable time. sendingRetries++; if (sendingRetries == 4) { reprap.GetPlatform()->Message(HOST_MESSAGE, "Network: Poll received error!\n"); tcp_abort(pcb); return ERR_ABRT; } // Try to send the remaining data once again err_t err = tcp_write(pcb, sendingWindow + (sendingWindowSize - sentDataOutstanding), sentDataOutstanding, 0); if (err == ERR_OK) { tcp_output(pcb); } else { reprap.GetPlatform()->Message(HOST_MESSAGE, "Network: tcp_write in conn_poll failed with code %d\n", err); tcp_abort(pcb); return ERR_ABRT; } } return ERR_OK; }
BOOL xMBTCPPortSendResponse( const UCHAR * pucMBTCPFrame, USHORT usTCPLength ) { BOOL bFrameSent = FALSE; if( pxPCBClient ) { /* Make sure we can send the packet. */ assert( tcp_sndbuf( pxPCBClient ) >= usTCPLength ); if( tcp_write( pxPCBClient, pucMBTCPFrame, ( u16_t ) usTCPLength, NETCONN_COPY ) == ERR_OK ) { #ifdef MB_TCP_DEBUG prvvMBTCPLogFrame( "MBTCP-SENT", &aucTCPBuf[0], usTCPLength ); #endif /* Make sure data gets sent immediately. */ ( void )tcp_output( pxPCBClient ); bFrameSent = TRUE; } else { /* Drop the connection in case of an write error. */ prvvMBPortReleaseClient( pxPCBClient ); } } return bFrameSent; }
/* * Mark the connection as being incapable of further output. */ static int tcp_usr_shutdown(struct socket *so) { int error = 0; struct inpcb *inp; struct tcpcb *tp = NULL; //printf("tcp_usr_shutdown: called\n"); TCPDEBUG0; INP_INFO_WLOCK(&tcbinfo); inp = sotoinpcb(so); KASSERT(inp != NULL, ("inp == NULL")); INP_LOCK(inp); if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { error = ECONNRESET; goto out; } tp = intotcpcb(inp); TCPDEBUG1(); socantsendmore(so); tcp_usrclosed(tp); error = tcp_output(tp); out: TCPDEBUG2(PRU_SHUTDOWN); INP_UNLOCK(inp); INP_INFO_WUNLOCK(&tcbinfo); return (error); }
/* * Initiate (or continue) disconnect. * If embryonic state, just send reset (once). * If in ``let data drain'' option and linger null, just drop. * Otherwise (hard), mark socket disconnecting and drop * current input data; switch states based on user close, and * send segment to peer (with FIN). */ static void tcp_disconnect(struct tcpcb *tp) { struct inpcb *inp = tp->t_inpcb; struct socket *so = inp->inp_socket; INP_INFO_WLOCK_ASSERT(&tcbinfo); INP_LOCK_ASSERT(inp); /* * Neither tcp_close() nor tcp_drop() should return NULL, as the * socket is still open. */ if (tp->t_state < TCPS_ESTABLISHED) { tp = tcp_close(tp); KASSERT(tp != NULL, ("tcp_disconnect: tcp_close() returned NULL")); } else if ((so->so_options & SO_LINGER) && so->so_linger == 0) { tp = tcp_drop(tp, 0); KASSERT(tp != NULL, ("tcp_disconnect: tcp_drop() returned NULL")); } else { soisdisconnecting(so); sbflush(&so->so_rcv); tcp_usrclosed(tp); if (!(inp->inp_vflag & INP_DROPPED)) tcp_output(tp); } }
/** * Function called when a packet needs to be sent thru Ethernet * Automatically split packet lenght to fit on packet max size * * @param tcp connection descriptor * @param bridge information * @return none */ static void BRIDGE_UART_ETH_SEND(struct tcp_pcb *pcb, struct bridge_state *hs) { err_t err; u16_t len; /* We cannot send more data than space available in the send buffer */ if (tcp_sndbuf(pcb) < hs->left) { len = tcp_sndbuf(pcb); } else { len = hs->left; } do { err = tcp_write(pcb, hs->data, len, TCP_WRITE_FLAG_COPY); if (err == ERR_MEM) { len /= 2; } } while (err == ERR_MEM && len > 1); if (err == ERR_OK) { hs->data += len; hs->left -= len; /*send it right now for performance*/ tcp_output(pcb); } }
/* requeue all unacked segments for retransmission */ void tcp_rexmit_rto(struct tcp_pcb *pcb) { struct tcp_seg *seg; if (pcb->unacked == NULL) { return; } /* Move all unacked segments to the head of the unsent queue */ for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); /* concatenate unsent queue after unacked queue */ seg->next = pcb->unsent; /* unsent queue is the concatenated queue (of unacked, unsent) */ pcb->unsent = pcb->unacked; /* unacked queue is now empty */ pcb->unacked = NULL; pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno); /* increment number of retransmissions */ ++pcb->nrtx; /* Don't take any RTT measurements after retransmitting. */ pcb->rttest = 0; /* Do the actual retransmission */ tcp_output(pcb); }
socket_error_t lwipv4_socket_send(struct socket *socket, const void * buf, const size_t len) { err_t err = ERR_VAL; switch(socket->family) { case SOCKET_DGRAM: { struct pbuf *pb = pbuf_alloc(PBUF_TRANSPORT,len,PBUF_RAM); socket_event_t e; socket_api_handler_t handler = socket->handler; err = pbuf_take(pb, buf, len); if (err != ERR_OK) break; err = udp_send(socket->impl, pb); pbuf_free(pb); if (err != ERR_OK) break; //Notify the application that the transfer is queued at the MAC layer e.event = SOCKET_EVENT_TX_DONE; e.sock = socket; e.i.t.sentbytes = len; socket->event = &e; handler(); socket->event = NULL; break; } case SOCKET_STREAM: err = tcp_write(socket->impl,buf,len,TCP_WRITE_FLAG_COPY); tcp_output(socket->impl); // TODO use opt instead with SOCKET_OPT_NAGGLE break; } return lwipv4_socket_error_remap(err); }
/** * Closes the connection held by the PCB. * */ err_t tcp_close(struct tcp_pcb *pcb) { err_t err; #if TCP_DEBUG LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in state ")); tcp_debug_print_state(pcb->state); LWIP_DEBUGF(TCP_DEBUG, ("\n")); #endif /* TCP_DEBUG */ switch (pcb->state) { case CLOSED: /* Closing a pcb in the CLOSED state might seem erroneous, * however, it is in this state once allocated and as yet unused * and the user needs some way to free it should the need arise. * Calling tcp_close() with a pcb that has already been closed, (i.e. twice) * or for a pcb that has been used and then entered the CLOSED state * is erroneous, but this should never happen as the pcb has in those cases * been freed, and so any remaining handles are bogus. */ err = ERR_OK; memp_free(MEMP_TCP_PCB, pcb); pcb = NULL; break; case LISTEN: err = ERR_OK; tcp_pcb_remove((struct tcp_pcb **)&tcp_listen_pcbs.pcbs, pcb); memp_free(MEMP_TCP_PCB_LISTEN, pcb); pcb = NULL; break; case SYN_SENT: err = ERR_OK; tcp_pcb_remove(&tcp_active_pcbs, pcb); memp_free(MEMP_TCP_PCB, pcb); pcb = NULL; break; case SYN_RCVD: case ESTABLISHED: err = tcp_send_ctrl(pcb, TCP_FIN); if (err == ERR_OK) { pcb->state = FIN_WAIT_1; } break; case CLOSE_WAIT: err = tcp_send_ctrl(pcb, TCP_FIN); if (err == ERR_OK) { pcb->state = LAST_ACK; } break; default: /* Has already been closed, do nothing. */ err = ERR_OK; pcb = NULL; break; } if (pcb != NULL && err == ERR_OK) { err = tcp_output(pcb); } return err; }
/* * Callout to process delayed ACKs for a TCPCB. */ void tcp_delack(void *arg) { struct tcpcb *tp = arg; /* * If tcp_output() wasn't able to transmit the ACK * for whatever reason, it will restart the delayed * ACK callout. */ mutex_enter(softnet_lock); if ((tp->t_flags & (TF_DEAD | TF_DELACK)) != TF_DELACK) { mutex_exit(softnet_lock); return; } if (!callout_expired(&tp->t_delack_ch)) { mutex_exit(softnet_lock); return; } tp->t_flags |= TF_ACKNOW; KERNEL_LOCK(1, NULL); (void) tcp_output(tp); KERNEL_UNLOCK_ONE(NULL); mutex_exit(softnet_lock); }
static err_t tcp_server_bm_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { int r; if (p == NULL) { // close the connection tcp_server_bm_close(tpcb); printf("Error in tcp_server_bm_recv"); return ERR_OK; } /* don't send an immediate ack here, do it later with the data */ // FIXME: send ack immediately! tpcb->flags |= TF_ACK_DELAY; assert(p->next == 0); // Send the data to benchmarking code for furthur analysis handle_data_arrived(p->payload, p->len); //XXX: can we do that without needing to copy it?? r = tcp_write(tpcb, p->payload, p->len, TCP_WRITE_FLAG_COPY); assert(r == ERR_OK); // make sure data gets sent immediately r = tcp_output(tpcb); assert(r == ERR_OK); tcp_recved(tpcb, p->len); //now we can advertise a bigger window pbuf_free(p); return ERR_OK; }
void tcp_rexmit(struct tcp_pcb *pcb) { struct tcp_seg *seg; if (pcb->unacked == NULL) { return; } /* Move the first unacked segment to the unsent queue */ seg = pcb->unacked->next; pcb->unacked->next = pcb->unsent; pcb->unsent = pcb->unacked; pcb->unacked = seg; pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno); ++pcb->nrtx; /* Don't take any rtt measurements after retransmitting. */ pcb->rttest = 0; /* Do the actual retransmission. */ snmp_inc_tcpretranssegs(); tcp_output(pcb); }
static void tcp_send_to_cb(void *ctx_p) { struct socket_t *socket_p = ctx_p; struct send_to_args_t *args_p; size_t size; args_p = socket_p->output.cb.args_p; size = MIN(args_p->extra.left, tcp_sndbuf(((struct tcp_pcb *)socket_p->pcb_p))); if (tcp_write(socket_p->pcb_p, args_p->buf_p, size, TCP_WRITE_FLAG_COPY) == ERR_OK) { args_p->buf_p += size; args_p->extra.left -= size; /* Resume if all data has been written. Otherwise the sent callback will send the rest of the data and resume. */ if (args_p->extra.left == 0) { tcp_output(socket_p->pcb_p); fs_counter_increment(&module.tcp_tx_bytes, args_p->size); resume_thrd(socket_p->output.cb.thrd_p, args_p->size); } else { socket_p->output.cb.state = STATE_SENDTO; } } else { resume_thrd(socket_p->output.cb.thrd_p, 0); } }
/* * Initiate connection to peer. * Create a template for use in transmissions on this connection. * Enter SYN_SENT state, and mark socket as connecting. * Start keep-alive timer, and seed output sequence space. * Send initial segment on connection. */ static int tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p) { int s = splnet(); int error = 0; struct inpcb *inp = sotoinpcb(so); struct tcpcb *tp; struct sockaddr_in *sinp; COMMON_START(); /* * Must disallow TCP ``connections'' to multicast addresses. */ sinp = (struct sockaddr_in *)nam; if (sinp->sin_family == AF_INET && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { error = EAFNOSUPPORT; goto out; } if ((error = tcp_connect(tp, nam, p)) != 0) goto out; error = tcp_output(tp); COMMON_END(PRU_CONNECT); }
/* send_resp * * Send a response back to the user. * * If the send is successful, this will return its 'length' parameter. If * not, it will close the connection, and then return -1. This is intended * for use by recv_fsm, which can tail-call send_resp with the number of * bytes that were consumed from the input. If the send succeeds, then that * value is returned; otherwise, the error is propagated up. */ static int RV send_resp(struct tcp_pcb *pcb, char resp, char cmd, int len) { struct dac_response response; response.response = resp; response.command = cmd; fill_status(&response.dac_status); err_t err = tcp_write(pcb, &response, sizeof(response), TCP_WRITE_FLAG_COPY); if (err == ERR_MEM) { if (ps_defer_ack(cmd, resp) < 0) { outputf("!!! DROPPING ACK !!!"); } else { outputf("deferring ACK"); } } else if (err != ERR_OK) { outputf("tcp_write returned %d", err); return close_conn(pcb, CONNCLOSED_SENDFAIL, len); } err = tcp_output(pcb); if (err != ERR_OK) { outputf("tcp_output returned %d", err); return close_conn(pcb, CONNCLOSED_SENDFAIL, len); } return len; }
/** * This function should be called by the application when it has * processed the data. The purpose is to advertise a larger window * when the data has been processed. * * @param pcb the tcp_pcb for which data is read * @param len the amount of bytes that have been read by the application */ void tcp_recved(struct tcp_pcb *pcb, u16_t len) { int wnd_inflation; LWIP_ASSERT("tcp_recved: len would wrap rcv_wnd\n", len <= 0xffff - pcb->rcv_wnd ); pcb->rcv_wnd += len; if (pcb->rcv_wnd > TCP_WND) { pcb->rcv_wnd = TCP_WND; } wnd_inflation = tcp_update_rcv_ann_wnd(pcb); /* If the change in the right edge of window is significant (default * watermark is TCP_WND/4), then send an explicit update now. * Otherwise wait for a packet to be sent in the normal course of * events (or more window to be available later) */ if (wnd_inflation >= TCP_WND_UPDATE_THRESHOLD) { tcp_ack_now(pcb); tcp_output(pcb); } LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %"U16_F" bytes, wnd %"U16_F" (%"U16_F").\n", len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd)); }
void tcp_rexmit(struct tcp_pcb *pcb) { struct tcp_seg *seg; if (pcb->unacked == NULL) { return; } /* Move all unacked segments to the unsent queue. */ for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); seg->next = pcb->unsent; pcb->unsent = pcb->unacked; pcb->unacked = NULL; pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno); ++pcb->nrtx; /* Don't take any rtt measurements after retransmitting. */ pcb->rttest = 0; /* Do the actual retransmission. */ tcp_output(pcb); }
static err_t txperf_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len) { #if __arm__ int copy = 3; #else int copy = 0; #endif err_t err; TxPerfConnMonCntr = 0; while (tcp_sndbuf(tpcb) > SEND_BUFSIZE) { err = tcp_write(tpcb, send_buf, SEND_BUFSIZE, copy); if (err != ERR_OK) { xil_printf("txperf: Error on tcp_write: %d\r\n", err); connected_pcb = NULL; return -1; } err = tcp_output(tpcb); if (err != ERR_OK) { xil_printf("txperf: Error on tcp_output: %d\r\n",err); } //xil_printf("sent_callback: ok\r\n"); } return ERR_OK; }
BST_IP_ERR_T BST_IP_RawTcpSend( BST_FD_T fd, BST_UINT8* pData, BST_UINT16 usLength ) { BST_IP_ERR_T stErrMsg; struct tcp_pcb *pstPcb; if( !BST_IP_IsRawFdValid(fd) ) { return BST_IP_ERR_MEM; } if( BST_NULL_PTR == pData ) { return BST_IP_ERR_MEM; } pstPcb = ( struct tcp_pcb * )fd.pFd; if( 0 == pstPcb->snd_wnd_max ) { return BST_IP_ERR_WIN; } stErrMsg = tcp_write( pstPcb, pData, usLength, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE ); if( BST_IP_ERR_OK != stErrMsg ) { BST_RLS_LOG1("BST_IP_RawTcpSend tcp_write Error:", stErrMsg ); } stErrMsg = tcp_output( pstPcb ); if( BST_IP_ERR_OK != stErrMsg ) { BST_RLS_LOG1("BST_IP_RawTcpSend tcp_output Error:", stErrMsg ); } return stErrMsg; }