예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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);
  }
}
예제 #4
0
/* 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);
}
예제 #6
0
  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);
					 }
예제 #7
0
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;
}
예제 #8
0
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();
    }
}
예제 #9
0
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 );
}
예제 #10
0
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;
}
예제 #11
0
파일: tcp_out.c 프로젝트: AlexeyAB/libvma
/**
 * 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);
}
예제 #12
0
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();
}
예제 #13
0
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;
}
예제 #14
0
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);
	}
}
예제 #17
0
/**
 * 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);
}
예제 #20
0
/**
 * 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;
}
예제 #21
0
/*
 * 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);
}
예제 #22
0
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);

}
예제 #24
0
파일: socket.c 프로젝트: eerimoq/simba
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);
    }
}
예제 #25
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);
}
예제 #26
0
/* 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;
}
예제 #27
0
/**
 * 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));
}
예제 #28
0
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);

}
예제 #29
0
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;
}