示例#1
0
/*
 * Closes the connection held by the PCB.
 * Return 1 on success, 0 on error.
 */
int
tcp_close (tcp_socket_t *s)
{
	mutex_lock (&s->lock);

	tcp_debug ("tcp_close: state=%S\n",
		tcp_state_name (s->state));

	switch (s->state) {
	default: /* Has already been closed. */
		tcp_queue_free (s);
		mutex_unlock (&s->lock);
		return 1;
	case LISTEN:
	case SYN_SENT:
		tcp_queue_free (s);
		mutex_unlock (&s->lock);
		mutex_lock (&s->ip->lock);
		tcp_socket_remove (s->state == LISTEN ?
			&s->ip->tcp_listen_sockets : &s->ip->tcp_sockets, s);
		mutex_unlock (&s->ip->lock);
		return 1;
	case SYN_RCVD:
	case ESTABLISHED:
	case CLOSE_WAIT:
		break;
	}
	for (;;) {
		if (tcp_enqueue (s, 0, 0, TCP_FIN, 0, 0))
			break;
		mutex_wait (&s->lock);
	}
	s->state = (s->state == CLOSE_WAIT) ? LAST_ACK : FIN_WAIT_1;
	mutex_unlock (&s->lock);

	mutex_lock (&s->ip->lock);
	if (s->unsent || (s->flags & TF_ACK_NOW))
		tcp_output (s);
	mutex_unlock (&s->ip->lock);

	mutex_lock (&s->lock);
	while (s->state != CLOSED) {
		if (s->state == TIME_WAIT && ! s->unsent) {
			tcp_queue_free (s);
			mutex_unlock (&s->lock);
			mutex_lock (&s->ip->lock);
			tcp_socket_remove (&s->ip->tcp_closing_sockets, s);
			mutex_unlock (&s->ip->lock);
			return 1;
		}
		mutex_wait (&s->lock);
	}
	mutex_unlock (&s->lock);
	return 1;
}
示例#2
0
/**
 * Connects to another host. The function given as the "connected"
 * argument will be called when the connection has been established.
 *
 * @param pcb the tcp_pcb used to establish the connection
 * @param ipaddr the remote ip address to connect to
 * @param port the remote tcp port to connect to
 * @param connected callback function to call when connected (or on error)
 * @return ERR_VAL if invalid arguments are given
 *         ERR_OK if connect request has been sent
 *         other err_t values if connect request couldn't be sent
 */
err_t
tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
      err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
{
  err_t ret;
  u32_t iss;

  LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);

  LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
  if (ipaddr != NULL) {
    pcb->remote_ip = *ipaddr;
  } else {
    return ERR_VAL;
  }
  pcb->remote_port = port;
  if (pcb->local_port == 0) {
    pcb->local_port = tcp_new_port();
  }
  iss = tcp_next_iss();
  pcb->rcv_nxt = 0;
  pcb->snd_nxt = iss;
  pcb->lastack = iss - 1;
  pcb->snd_lbb = iss - 1;
  pcb->rcv_wnd = TCP_WND;
  pcb->rcv_ann_wnd = TCP_WND;
  pcb->rcv_ann_right_edge = pcb->rcv_nxt;
  pcb->snd_wnd = TCP_WND;
  /* As initial send MSS, we use TCP_MSS but limit it to 536.
     The send MSS is updated when an MSS option is received. */
  pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
#if TCP_CALCULATE_EFF_SEND_MSS
  pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
  pcb->cwnd = 1;
  pcb->ssthresh = pcb->mss * 10;
  pcb->state = SYN_SENT;
#if LWIP_CALLBACK_API  
  pcb->connected = connected;
#endif /* LWIP_CALLBACK_API */
  TCP_RMV(&tcp_bound_pcbs, pcb);
  TCP_REG(&tcp_active_pcbs, pcb);

  snmp_inc_tcpactiveopens();
  
  ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, TF_SEG_OPTS_MSS
#if LWIP_TCP_TIMESTAMPS
                    | TF_SEG_OPTS_TS
#endif
                    );
  if (ret == ERR_OK) { 
    tcp_output(pcb);
  }
  return ret;
} 
示例#3
0
/*
 * Connect to another host. Wait until connection established.
 * Return 1 on success, 0 on error.
 */
tcp_socket_t *
tcp_connect (ip_t *ip, unsigned char *ipaddr, unsigned short port)
{
	tcp_socket_t *s;
	unsigned long optdata;

	tcp_debug ("tcp_connect to port %u\n", port);
	if (ipaddr == 0)
		return 0;
	mutex_lock (&ip->lock);

	s = tcp_alloc (ip);
	memcpy (s->remote_ip, ipaddr, 4);
	s->remote_port = port;
	if (s->local_port == 0) {
		s->local_port = tcp_new_port (ip);
	}
	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 (s, 0, 0, TCP_SYN, (unsigned char*) &optdata, 4)) {
		mem_free (s);
		mutex_unlock (&ip->lock);
		return 0;
	}
	tcp_list_add (&ip->tcp_sockets, s);
	tcp_output (s);
	mutex_unlock (&ip->lock);

	mutex_lock (&s->lock);
	for (;;) {
		mutex_wait (&s->lock);
		if (s->state == ESTABLISHED) {
			mutex_unlock (&s->lock);
			return s;
		}
		if (s->state == CLOSED) {
			mutex_unlock (&s->lock);
			mem_free (s);
			return 0;
		}
	}
}
示例#4
0
/*
 * Send len>0 bytes.
 * Return a number ob transmitted bytes, or -1 on error.
 */
int
tcp_write (tcp_socket_t *s, const void *arg, unsigned short len)
{
	tcp_debug ("tcp_write(s=%p, arg=%p, len=%u)\n",
		(void*) s, arg, len);
	mutex_lock (&s->lock);

	if (s->state != SYN_SENT && s->state != SYN_RCVD &&
	    s->state != ESTABLISHED /*&& s->state != CLOSE_WAIT*/) {
		mutex_unlock (&s->lock);
		tcp_debug ("tcp_write() called in invalid state\n");
		return -1;
	}
	if (len == 0) {
		mutex_unlock (&s->lock);
		return -1;
	}
	mutex_group_t *g = 0;
	ARRAY (group, sizeof(mutex_group_t) + 2 * sizeof(mutex_slot_t));

	while (tcp_enqueue (s, (void*) arg, len, 0, 0, 0) == 0) {
		/* Не удалось поставить пакет в очередь - мало памяти. */
		if (! g) {
			memset (group, 0, sizeof(group));
			g = mutex_group_init (group, sizeof(group));
			mutex_group_add (g, &s->lock);
			mutex_group_add (g, &s->ip->timer->decisec);
			mutex_group_listen (g);
		}
		/* Каждые 100 мсек делаем повторную попытку. */
		mutex_unlock (&s->lock);
		mutex_group_wait (g, 0, 0);
		mutex_lock (&s->lock);

		/* Проверим, не закрылось ли соединение. */
		if (s->state != SYN_SENT && s->state != SYN_RCVD &&
		    s->state != ESTABLISHED /*&& s->state != CLOSE_WAIT*/) {
			mutex_unlock (&s->lock);
			if (g)
				mutex_group_unlisten (g);
			return -1;
		}
	}
	mutex_unlock (&s->lock);
	if (g)
		mutex_group_unlisten (g);

	mutex_lock (&s->ip->lock);
	tcp_output (s);
	mutex_unlock (&s->ip->lock);
	return len;
}
示例#5
0
文件: tcp_output.c 项目: gz/aos10
/*-----------------------------------------------------------------------------------*/
err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
  if(pcb->state == SYN_SENT ||
     pcb->state == SYN_RCVD ||
     pcb->state == ESTABLISHED ||
     pcb->state == CLOSE_WAIT) {
    if(len > 0) {
      return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
    }
    return ERR_OK;
  } else {
    return ERR_CONN;
  }
}
示例#6
0
/**
 * Write data for sending (but does not send it immediately).
 *
 * It waits in the expectation of more data being sent soon (as
 * it can send them more efficiently by combining them together).
 * To prompt the system to send data now, call tcp_output() after
 * calling tcp_write().
 * 
 * @param pcb Protocol control block of the TCP connection to enqueue data for.
 * @param data pointer to the data to send
 * @param len length (in bytes) of the data to send
 * @param apiflags combination of following flags :
 * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack
 * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,
 * @return ERR_OK if enqueued, another err_t on error
 * 
 * @see tcp_write()
 */
err_t
tcp_write(struct tcp_pcb *pcb, const void *data, u16_t len, u8_t apiflags)
{
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, data=%p, len=%"U16_F", apiflags=%"U16_F")\n", (void *)pcb,
    data, len, (u16_t)apiflags));
  /* connection is in valid state for data transmission? */
  if (pcb->state == ESTABLISHED ||
     pcb->state == CLOSE_WAIT ||
     pcb->state == SYN_SENT ||
     pcb->state == SYN_RCVD) {
    if (len > 0) {
#if LWIP_TCP_TIMESTAMPS
      return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 
                         pcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0);
#else
      return tcp_enqueue(pcb, (void *)data, len, 0, apiflags, 0);
#endif
    }
    return ERR_OK;
  } else {
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_STATE | LWIP_DBG_LEVEL_SEVERE, ("tcp_write() called in invalid state\n"));
    return ERR_CONN;
  }
}
示例#7
0
文件: tcp.c 项目: BlueSkyGjj/nRF52
/**
 * Connects to another host. The function given as the "connected"
 * argument will be called when the connection has been established.
 *
 */
err_t
tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
      err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
{
  u32_t optdata;
  err_t ret;
  u32_t iss;

  LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
  if (ipaddr != NULL) {
    pcb->remote_ip = *ipaddr;
  } else {
    return ERR_VAL;
  }
  pcb->remote_port = port;
  if (pcb->local_port == 0) {
    pcb->local_port = tcp_new_port();
  }
  iss = tcp_next_iss();
  pcb->rcv_nxt = 0;
  pcb->snd_nxt = iss;
  pcb->lastack = iss - 1;
  pcb->snd_lbb = iss - 1;
  pcb->rcv_wnd = TCP_WND;
  pcb->snd_wnd = TCP_WND;
  pcb->mss = TCP_MSS;
  pcb->cwnd = 1;
  pcb->ssthresh = pcb->mss * 10;
  pcb->state = SYN_SENT;
#if LWIP_CALLBACK_API  
  pcb->connected = connected;
#endif /* LWIP_CALLBACK_API */  
  TCP_REG(&tcp_active_pcbs, pcb);

  snmp_inc_tcpactiveopens();
  
  /* Build an MSS option */
  optdata = htonl(((u32_t)2 << 24) | 
      ((u32_t)4 << 16) | 
      (((u32_t)pcb->mss / 256) << 8) |
      (pcb->mss & 255));

  ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, (u8_t *)&optdata, 4);
  if (ret == ERR_OK) { 
    tcp_output(pcb);
  }
  return ret;
} 
示例#8
0
文件: tcp.c 项目: imaginegit/wifisdk
uint8 tcp_connect(TCP_PCB *pcb, IP_ADDR *ipaddr, uint16 port)
{
    uint8 ret;
    uint32 iss;

    if (ipaddr != NULL)
    {
        pcb->remote_ip = *ipaddr;
    }
    else
    {
        return ERR_VAL;
    }

    pcb->remote_port = port;
    if (pcb->local_port == 0)
    {
        pcb->local_port = 4096;
    }
    iss = tcp_next_iss();

    pcb->rcv_nxt = 0;
    pcb->snd_nxt = iss;
    pcb->lastack = iss - 1;
    pcb->snd_lbb = iss - 1;
    pcb->rcv_wnd = TCP_WND;
    pcb->rcv_ann_wnd = TCP_WND;
    pcb->rcv_ann_right_edge = pcb->rcv_nxt;
    pcb->snd_wnd = TCP_WND;
    /* As initial send MSS, we use TCP_MSS but limit it to 536.
       The send MSS is updated when an MSS option is received. */
    pcb->mss = (TCP_MSS > 1460) ? 1460 : TCP_MSS;//(TCP_MSS > 536) ? 536 : TCP_MSS;
    pcb->cwnd = 1;
    pcb->ssthresh = TCP_WND;
    pcb->state = SYN_SENT;

	printf("SYN\n");   
    ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, TCP_WRITE_FLAG_COPY, TF_SEG_OPTS_MSS);
    if (ret == ERR_OK)
    {
        tcp_output(pcb);
    }
	
    return ret;
}
示例#9
0
err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%u, copy=%d)\n", (void *)pcb,
    arg, len, (unsigned int)copy));
  if (pcb->state == SYN_SENT ||
     pcb->state == SYN_RCVD ||
     pcb->state == ESTABLISHED ||
     pcb->state == CLOSE_WAIT) {
    if (len > 0) {
      return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
    }
    return ERR_OK;
  } else {
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
    return ERR_CONN;
  }
}
err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
  LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb,
    arg, len, (u16_t)copy));
  /* connection is in valid state for data transmission? */
  if (pcb->state == ESTABLISHED ||
     pcb->state == CLOSE_WAIT ||
     pcb->state == SYN_SENT ||
     pcb->state == SYN_RCVD) {
    if (len > 0) {
      return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
    }
    return ERR_OK;
  } else {
    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
    return ERR_CONN;
  }
}
示例#11
0
/*
 * Flush output buffer.
 */
static void
stream_flush (tcp_stream_t *u)
{
/*debug_printf ("tstream output"); buf_print_data (u->outdata, len);*/
    tcp_socket_t*  s = u->socket;
    unsigned char* src = u->outdata;
	while (u->outptr != src){
	    int len = u->outptr - src;
	    int sent = tcp_enqueue (u->socket, (void*) u->outdata, len, 0);
	    tcp_debug("tcp-stream: sent %d bytes\n", sent);
	    src   += sent;
	    if (sent != len) {
#         if TCP_LOCK_STYLE < TCP_LOCK_RELAXED
	        mutex_unlock (&s->lock);
#         endif
	        tcp_output (s);
#         if TCP_LOCK_STYLE < TCP_LOCK_RELAXED
	        mutex_lock (&s->lock);
#         endif
	        mutex_wait (&s->lock);
	    }
	}
	u->outptr = u->outdata;
}
err_t
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
{
  /* no data, no length, flags, copy=1, no optdata, no optdatalen */
  return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
}
示例#13
0
/*
 * Send len>0 bytes.
 * Return a number ob transmitted bytes, or -1 on error.
 */
int
tcp_write (tcp_socket_t *s, const void *arg, unsigned short len)
{
	tcp_debug ("tcp_write(s=%p, arg=%p, len=%u)\n",
		(void*) s, arg, len);

	if (!tcp_socket_is_state(s, TCP_STATES_TRANSFER)) {
		tcp_debug ("tcp_write() called in invalid state\n");
		return -1;
	}
	if (len == 0) {
		return -1;
	}
	mutex_group_t *g = 0;
	ARRAY (group, sizeof(mutex_group_t) + 2 * sizeof(mutex_slot_t));

	const char* ptr = (const char*)arg;
	unsigned left = len;
	while (left > 0){

	    int sent = tcp_enqueue (s, ptr, len, 0);
	    left    -= sent;
        ptr     += sent;

        if (left == 0)
            break;

#       if TCP_LOCK_STYLE <= TCP_LOCK_SURE
        if (mutex_is_my(&s->lock))
        mutex_unlock (&s->lock);
        tcp_output_poll (s);
#       elif TCP_LOCK_STYLE <= TCP_LOCK_RELAXED
        tcp_output_poll (s);
        mutex_unlock (&s->lock);
#       endif

        /* Не удалось поставить пакет в очередь - мало памяти. */
        if (! g) {
            memset (group, 0, sizeof(group));
            g = mutex_group_init (group, sizeof(group));
            mutex_group_add (g, &s->lock);
            mutex_group_add (g, &s->ip->timer->decisec);
            mutex_group_listen (g);
        }
        /* Каждые 100 мсек делаем повторную попытку. */
        mutex_group_wait (g, 0, 0);
        /* Проверим, не закрылось ли соединение. */
        if (!tcp_socket_is_state(s, TCP_STATES_TRANSFER)) {
            if (g)
                mutex_group_unlisten (g);
            return -1;
        }
	}

	if (g)
		mutex_group_unlisten (g);

#       if TCP_LOCK_STYLE <= TCP_LOCK_SURE
        mutex_unlock (&s->lock);
        tcp_output (s);
#       elif TCP_LOCK_STYLE <= TCP_LOCK_RELAXED
        tcp_output (s);
        mutex_unlock (&s->lock);
#       endif
	return len;
}
示例#14
0
文件: tcp_in.c 项目: BlueSkyGjj/nRF52
/**
 * Called by tcp_input() when a segment arrives for a listening
 * connection (from tcp_input()).
 *
 * @param pcb the tcp_pcb_listen for which a segment arrived
 * @return ERR_OK if the segment was processed
 *         another err_t on error
 *
 * @note the return value is not (yet?) used in tcp_input()
 * @note the segment which arrived is saved in global variables, therefore only the pcb
 *       involved is passed as a parameter to this function
 */
static err_t
tcp_listen_input(struct tcp_pcb_listen *pcb)
{
  struct tcp_pcb *npcb;
  u32_t optdata;

  /* In the LISTEN state, we check for incoming SYN segments,
     creates a new PCB, and responds with a SYN|ACK. */
  if (flags & TCP_ACK) {
    /* For incoming segments with the ACK flag set, respond with a
       RST. */
    LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
    tcp_rst(ackno + 1, seqno + tcplen,
      &(iphdr->dest), &(iphdr->src),
      tcphdr->dest, tcphdr->src);
  } else if (flags & TCP_SYN) {
    LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
#if TCP_LISTEN_BACKLOG
    if (pcb->accepts_pending >= pcb->backlog) {
      return ERR_ABRT;
    }
#endif /* TCP_LISTEN_BACKLOG */
    npcb = tcp_alloc(pcb->prio);
    /* If a new PCB could not be created (probably due to lack of memory),
       we don't do anything, but rely on the sender will retransmit the
       SYN at a time when we have more memory available. */
    if (npcb == NULL) {
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
      TCP_STATS_INC(tcp.memerr);
      return ERR_MEM;
    }
#if TCP_LISTEN_BACKLOG
    pcb->accepts_pending++;
#endif /* TCP_LISTEN_BACKLOG */
    /* Set up the new PCB. */
    ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
    npcb->local_port = pcb->local_port;
    ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
    npcb->remote_port = tcphdr->src;
    npcb->state = SYN_RCVD;
    npcb->rcv_nxt = seqno + 1;
    npcb->snd_wnd = tcphdr->wnd;
    npcb->ssthresh = npcb->snd_wnd;
    npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
    npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API
    npcb->accept = pcb->accept;
#endif /* LWIP_CALLBACK_API */
    /* inherit socket options */
    npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
    /* Register the new PCB so that we can begin receiving segments
       for it. */
    TCP_REG(&tcp_active_pcbs, npcb);

    /* Parse any options in the SYN. */
    tcp_parseopt(npcb);
#if TCP_CALCULATE_EFF_SEND_MSS
    npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));
#endif /* TCP_CALCULATE_EFF_SEND_MSS */

    snmp_inc_tcppassiveopens();

    /* Build an MSS option. */
    optdata = TCP_BUILD_MSS_OPTION();
    /* Send a SYN|ACK together with the MSS option. */
    tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, (u8_t *)&optdata, 4);
    return tcp_output(npcb);
  }
  return ERR_OK;
}
示例#15
0
/**
 * Connects to another host. The function given as the "connected"
 * argument will be called when the connection has been established.
 *
 * @param pcb the tcp_pcb used to establish the connection
 * @param ipaddr the remote ip address to connect to
 * @param port the remote tcp port to connect to
 * @param connected callback function to call when connected (or on error)
 * @return ERR_VAL if invalid arguments are given
 *         ERR_OK if connect request has been sent
 *         other err_t values if connect request couldn't be sent
 */
err_t
tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
      err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))
{
  err_t ret;
  u32_t iss;

  LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN);

  LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port));
	/* 远端IP地址有效,则记录到TCP控制块中 */
  if (ipaddr != NULL) {
    pcb->remote_ip = *ipaddr;
  } else {
    return ERR_VAL;
  }
	/* 记录远端PORT */
  pcb->remote_port = port;
	/* 如果本地端口未绑定,则绑定一个短暂端口 */
  if (pcb->local_port == 0) {
    pcb->local_port = tcp_new_port();
  }
	/* 获取初始序号 */
  iss = tcp_next_iss();
	/* 设置接收窗口下一个接收的序号 */
  pcb->rcv_nxt = 0;
	/* 设置发送窗口各个字段 */
  pcb->snd_nxt = iss;
  pcb->lastack = iss - 1;
  pcb->snd_lbb = iss - 1;
	/* 设置接收窗口各个字段 */
  pcb->rcv_wnd = TCP_WND;
  pcb->rcv_ann_wnd = TCP_WND;
  pcb->rcv_ann_right_edge = pcb->rcv_nxt;
  pcb->snd_wnd = TCP_WND;
  /* As initial send MSS, we use TCP_MSS but limit it to 536.
     The send MSS is updated when an MSS option is received. */
	/* 设置MSS */
  pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
#if TCP_CALCULATE_EFF_SEND_MSS
  pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
	/* 初始化阻塞窗口 */
  pcb->cwnd = 1;
  pcb->ssthresh = pcb->mss * 10;
	/* TCP控制块状态设为SYN_SENT */
  pcb->state = SYN_SENT;
#if LWIP_CALLBACK_API
	/* 设置回调函数 */
  pcb->connected = connected;
#endif /* LWIP_CALLBACK_API */
	/* 把TCP控制块从tcp_bound_pcbs链表移除 */
  TCP_RMV(&tcp_bound_pcbs, pcb);
	/* 把TCP控制块插入tcp_active_pcbs链表 */
  TCP_REG(&tcp_active_pcbs, pcb);

  snmp_inc_tcpactiveopens();
  
	/* 构造TCP报文,长度为0,SYN置1,并包含MSS选项字段 */
  ret = tcp_enqueue(pcb, NULL, 0, TCP_SYN, 0, TF_SEG_OPTS_MSS
#if LWIP_TCP_TIMESTAMPS
                    | TF_SEG_OPTS_TS
#endif
                    );
  if (ret == ERR_OK) { 
		/* 发送构造的TCP报文 */
    tcp_output(pcb);
  }
  return ret;
} 
示例#16
0
tcp_socket_t *
tcp_accept (tcp_socket_t *s)
{
	tcp_socket_t *ns;
	buf_t *p;
	ip_hdr_t *iph;
	tcp_hdr_t *h;
	unsigned long optdata;
again:
	mutex_lock (&s->lock);
	for (;;) {
		if (s->state != LISTEN) {
			mutex_unlock (&s->lock);
			tcp_debug ("tcp_accept: called in invalid state\n");
			return 0;
		}
		if (! tcp_queue_is_empty (s)) {
			p = tcp_queue_get (s);
			break;
		}
		mutex_wait (&s->lock);
	}
	mutex_unlock (&s->lock);

	/* Create a new PCB, and respond with a SYN|ACK.
	 * If a new PCB could not be created (probably due to lack of memory),
	 * we don't do anything, but rely on the sender will retransmit
	 * the SYN at a time when we have more memory available. */
	mutex_lock (&s->ip->lock);
	ns = tcp_alloc (s->ip);
	if (ns == 0) {
		tcp_debug ("tcp_accept: could not allocate PCB\n");
		++s->ip->tcp_in_discards;
		mutex_unlock (&s->ip->lock);
		buf_free (p);
		goto again;
	}
	h = (tcp_hdr_t*) p->payload;
	iph = ((ip_hdr_t*) p->payload) - 1;

	/* Set up the new PCB. */
	memcpy (ns->local_ip, iph->dest, 4);
	ns->local_port = s->local_port;
	memcpy (ns->remote_ip, iph->src, 4);
	ns->remote_port = h->src;
	ns->state = SYN_RCVD;
	ns->rcv_nxt = s->ip->tcp_input_seqno + 1;
	ns->snd_wnd = h->wnd;
	ns->ssthresh = ns->snd_wnd;
	ns->snd_wl1 = s->ip->tcp_input_seqno;
	ns->ip = s->ip;

	/* Register the new PCB so that we can begin receiving
	 * segments for it. */
	tcp_list_add (&s->ip->tcp_sockets, ns);

	/* Parse any options in the SYN. */
	tcp_parseopt (ns, h);

	/* Build an MSS option. */
	optdata = HTONL (((unsigned long)2 << 24) | ((unsigned long)4 << 16) |
		(((unsigned long)ns->mss / 256) << 8) | (ns->mss & 255));
	buf_free (p);

	/* Send a SYN|ACK together with the MSS option. */
	tcp_enqueue (ns, 0, 0, TCP_SYN | TCP_ACK, (unsigned char*) &optdata, 4);
	tcp_output (ns);
	mutex_unlock (&s->ip->lock);
	return ns;
}
示例#17
0
/**
 * Called by tcp_close() to send a segment including flags but not data.
 *
 * @param pcb the tcp_pcb over which to send a segment
 * @param flags the flags to set in the segment header
 * @return ERR_OK if sent, another err_t otherwise
 */
err_t
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
{
  /* no data, no length, flags, copy=1, no optdata */
  return tcp_enqueue(pcb, NULL, 0, flags, TCP_WRITE_FLAG_COPY, 0);
}
示例#18
0
err_t
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
{
  return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);

}