Beispiel #1
0
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;
}
Beispiel #2
0
static int tcp_op_open(struct socket * sock, __unused message * m)
{
	struct tcp_pcb * pcb;
	int ret;

	debug_tcp_print("socket num %ld", get_sock_num(sock));

	if (!(pcb = tcp_new()))
		return ENOMEM;
	debug_tcp_print("new tcp pcb %p\n", pcb);
	
	if ((ret = tcp_fill_new_socket(sock, pcb) != OK))
		tcp_abandon(pcb, 0);
	
	return ret;
}
Beispiel #3
0
/******************************************************************************
 * FunctionName : espconn_server_poll
 * Description  : The poll function is called every 3nd second.
 * If there has been no data sent (which resets the retries) in 3 seconds, close.
 * If the last portion of a file has not been sent in 3 seconds, close.
 *
 * This could be increased, but we don't want to waste resources for bad connections.
 * Parameters   : arg -- Additional argument to pass to the callback function
 *                pcb -- The connection pcb for which data has been acknowledged
 * Returns      : ERR_OK: try to send some data by calling tcp_output
 *                ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_server_poll(void *arg, struct tcp_pcb *pcb)
{
	espconn_msg *pspoll_cb = arg;

	/*exception calling abandon the connection for send a RST frame*/
    if (arg == NULL) {
        tcp_abandon(pcb, 0);
        tcp_poll(pcb, NULL, 0);
        return ERR_OK;
    }

    espconn_printf("espconn_server_poll %d %d\n", pspoll_cb->pcommon.recv_check, pcb->state);
    pspoll_cb->pcommon.pcb = pcb;
    if (pcb->state == ESTABLISHED) {
		pspoll_cb->pcommon.recv_check++;
		if (pspoll_cb->pcommon.timeout != 0){/*no data sent in one active connection's set timeout, close.*/
			if (pspoll_cb->pcommon.recv_check >= pspoll_cb->pcommon.timeout) {
				pspoll_cb->pcommon.recv_check = 0;
				espconn_server_close(pspoll_cb, pcb,0);
			}
		} else {
			espconn_msg *ptime_msg = pserver_list;
			while (ptime_msg != NULL) {
				if (ptime_msg->pespconn == pspoll_cb->preverse){
					if (ptime_msg->pcommon.timeout != 0){/*no data sent in server's set timeout, close.*/
						if (pspoll_cb->pcommon.recv_check >= ptime_msg->pcommon.timeout){
							pspoll_cb->pcommon.recv_check = 0;
							espconn_server_close(pspoll_cb, pcb,0);
						}
					} else {/*don't close for ever*/
						pspoll_cb->pcommon.recv_check = 0;
					}
					break;
				}
				ptime_msg = ptime_msg->pnext;
			}
		}
    } else {
        espconn_server_close(pspoll_cb, pcb,0);
    }

    return ERR_OK;
}
Beispiel #4
0
/******************************************************************************
 * FunctionName : espconn_client_poll
 * Description  : The poll function is called every 2nd second.
 * If there has been no data sent (which resets the retries) in 8 seconds, close.
 * If the last portion of a file has not been sent in 2 seconds, close.
 *
 * This could be increased, but we don't want to waste resources for bad connections.
 * Parameters   : arg -- Additional argument to pass to the callback function
 *                pcb -- The connection pcb for which data has been acknowledged
 * Returns      : ERR_OK: try to send some data by calling tcp_output
 *                ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_client_poll(void *arg, struct tcp_pcb *pcb)
{
	espconn_msg *ppoll_cb = arg;
	espconn_printf("espconn_client_poll pcb %p %p %d\n", pcb, arg, pcb->state);
    if (arg == NULL) {
        tcp_abandon(pcb, 0);
        tcp_poll(pcb, NULL, 0);
        return ERR_OK;
    }
    ppoll_cb->pcommon.pcb = pcb;
    if (pcb->state == ESTABLISHED) {
    } else {
        tcp_poll(pcb, espconn_client_poll, 0);
        espconn_client_close(ppoll_cb->pespconn, pcb);
    }

    return ERR_OK;
}
Beispiel #5
0
/******************************************************************************
 * FunctionName : espconn_server_poll
 * Description  : The poll function is called every 3nd second.
 * If there has been no data sent (which resets the retries) in 3 seconds, close.
 * If the last portion of a file has not been sent in 3 seconds, close.
 *
 * This could be increased, but we don't want to waste resources for bad connections.
 * Parameters   : arg -- Additional argument to pass to the callback function
 *                pcb -- The connection pcb for which data has been acknowledged
 * Returns      : ERR_OK: try to send some data by calling tcp_output
 *                ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/
static err_t ICACHE_FLASH_ATTR
espconn_server_poll(void *arg, struct tcp_pcb *pcb)
{
	espconn_msg *pspoll_cb = arg;

    if (arg == NULL) {
        tcp_abandon(pcb, 0);
        tcp_poll(pcb, NULL, 0);
        return ERR_OK;
    }

    espconn_printf("espconn_server_poll %d %d\n", pspoll_cb->pcommon.recv_check, pcb->state);
    pspoll_cb->pcommon.pcb = pcb;
    if (pcb->state == ESTABLISHED) {
		pspoll_cb->pcommon.recv_check++;
		if (pspoll_cb->pcommon.timeout != 0){
			if (pspoll_cb->pcommon.recv_check == pspoll_cb->pcommon.timeout) {
				pspoll_cb->pcommon.recv_check = 0;
				espconn_server_close(pspoll_cb, pcb);
			}
		} else if (link_timer != 0){
			if (pspoll_cb->pcommon.recv_check == link_timer) {
				pspoll_cb->pcommon.recv_check = 0;
				espconn_server_close(pspoll_cb, pcb);
			}
		} else {
			if (pspoll_cb->pcommon.recv_check == 0x0a) {
				pspoll_cb->pcommon.recv_check = 0;
				espconn_server_close(pspoll_cb, pcb);
			}
		}
    } else {
        espconn_server_close(pspoll_cb, pcb);
    }

    return ERR_OK;
}
Beispiel #6
0
/**
 * Aborts the connection by sending a RST (reset) segment to the remote
 * host. The pcb is deallocated. This function never fails.
 *
 * ATTENTION: When calling this from one of the TCP callbacks, make
 * sure you always return ERR_ABRT (and never return ERR_ABRT otherwise
 * or you will risk accessing deallocated memory or memory leaks!
 *
 * @param pcb the tcp pcb to abort
 */
void
tcp_abort(struct tcp_pcb *pcb)
{
  tcp_abandon(pcb, 1);
}
Beispiel #7
0
static err_t tcp_recv_callback(void *arg,
				struct tcp_pcb *tpcb,
				struct pbuf *pbuf,
				err_t err)
{
	int ret, enqueued = 0;
	struct socket * sock = (struct socket *) arg;

	debug_tcp_print("socket num %ld", get_sock_num(sock));

	if (sock->pcb == NULL) {
		if (sock_select_set(sock))
			sock_select_notify(sock);
		return ERR_OK;
	}

	assert((struct tcp_pcb *) sock->pcb == tpcb);

	if (err != ERR_OK)
		return ERR_OK;
	if (!pbuf) {
		debug_tcp_print("tcp stream closed on the remote side");
		// sock->flags |= SOCK_FLG_CLOSED;

		/* wake up the reader and report EOF */
		if (sock->flags & SOCK_FLG_OP_PENDING &&
				sock->flags & SOCK_FLG_OP_READING &&
				!(sock->flags & SOCK_FLG_OP_REVIVING)) {
			sock_revive(sock, 0);
			sock->flags &= ~(SOCK_FLG_OP_PENDING |
					SOCK_FLG_OP_READING);
		}
#if 0
		/* if there are any undelivered data, drop them */
		sock_dequeue_data_all(sock, tcp_recv_free);
		tcp_abandon(tpcb, 0);
		sock->pcb = NULL;
#endif

		return ERR_OK;
	}

	/*
	 * FIXME we always enqueue the data first. If the head is empty and read
	 * operation is pending we could try to deliver immeditaly without
	 * enqueueing
	 */
	if (enqueue_rcv_data(sock, pbuf) == ERR_OK)
		enqueued = 1;

	/*
	 * Deliver data if there is a pending read operation, otherwise notify
	 * select if the socket is being monitored
	 */
	if (sock->flags & SOCK_FLG_OP_PENDING) {
		if (sock->flags & SOCK_FLG_OP_READING) {
			ret = read_from_tcp(sock, &sock->mess);
			debug_tcp_print("read op finished");
			sock_revive(sock, ret);
			sock->flags &= ~(SOCK_FLG_OP_PENDING |
					SOCK_FLG_OP_READING);
		}
	} else if (!(sock->flags & SOCK_FLG_OP_WRITING) &&
			sock_select_rw_set(sock))
		sock_select_notify(sock);

	/* perhaps we have deliverd some data to user, try to enqueue again */
	if (!enqueued) {
		return enqueue_rcv_data(sock, pbuf);
	} else
		return ERR_OK;
}
Beispiel #8
0
/**
 * 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;
	err_t rc;

	/* 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) {
			LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
			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->rcv_ann_right_edge = npcb->rcv_nxt;
		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();

		/* Send a SYN|ACK together with the MSS option. */
		rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
#if LWIP_TCP_TIMESTAMPS
						 /* and maybe include the TIMESTAMP option */
						 | (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
#endif
						);
		if (rc != ERR_OK) {
			tcp_abandon(npcb, 0);
			return rc;
		}
		return tcp_output(npcb);
	}
	return ERR_OK;
}