Exemplo n.º 1
0
/**
 * Try to post a callback-message to the tcpip_thread mbox
 * This is intended to be used to send "static" messages from interrupt context.
 *
 * @param msg pointer to the message to post
 * @return sys_mbox_trypost() return code
 */
err_t
tcpip_trycallback(struct tcpip_callback_msg* msg)
{
    if (!sys_mbox_valid(&mbox)) {
        return ERR_VAL;
    }
    return sys_mbox_trypost(&mbox, msg);
}
Exemplo n.º 2
0
/**
 * Receive callback function for RAW netconns.
 * Doesn't 'eat' the packet, only references it and sends it to
 * conn->recvmbox
 *
 * @see raw.h (struct raw_pcb.recv) for parameters and return value
 */
static u8_t
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
         ip_addr_t *addr)
{
    struct pbuf *q;
    struct netbuf *buf;
    struct netconn *conn;

    LWIP_UNUSED_ARG(addr);
    conn = (struct netconn *)arg;

    if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) {
#if LWIP_SO_RCVBUF
        int recv_avail;
        SYS_ARCH_GET(conn->recv_avail, recv_avail);
        if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) {
            return 0;
        }
#endif /* LWIP_SO_RCVBUF */
        /* copy the whole packet into new pbufs */
        q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
        if(q != NULL) {
            if (pbuf_copy(q, p) != ERR_OK) {
                pbuf_free(q);
                q = NULL;
            }
        }

        if (q != NULL) {
            u16_t len;
            buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
            if (buf == NULL) {
                pbuf_free(q);
                return 0;
            }

            buf->p = q;
            buf->ptr = q;
            ip_addr_copy(buf->addr, *ip_current_src_addr());
            buf->port = pcb->protocol;

            len = q->tot_len;
            if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
                netbuf_delete(buf);
                return 0;
            } else {
#if LWIP_SO_RCVBUF
                SYS_ARCH_INC(conn->recv_avail, len);
#endif /* LWIP_SO_RCVBUF */
                /* Register event with callback */
                API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
            }
        }
    }

    return 0; /* do not eat the packet */
}
Exemplo n.º 3
0
/*
  Deallocates a mailbox. If there are messages still present in the
  mailbox when the mailbox is deallocated, it is an indication of a
  programming error in lwIP and the developer should be notified.
*/
void
sys_mbox_free(sys_mbox_t *mbox)
{
  uint32_t mbox_message_num = 0;

  if ( (NULL == mbox) || (NULL == *mbox) ) {
      return;
  }

  mbox_message_num = uxQueueMessagesWaiting((*mbox)->os_mbox);

  LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mbox free: mbox=%p os_mbox=%p owner=%p msg_num=%d\n", 
              *mbox, (*mbox)->os_mbox, (*mbox)->owner, mbox_message_num));

#if ESP_THREAD_SAFE
  if ((*mbox)->owner) {
    if (0 == mbox_message_num) {
      /*
       * If mbox->owner is not NULL, it indicates the mbox is recvmbox or acceptmbox,
       * we need to post a NULL message to mbox in case some application tasks are blocked
       * on this mbox
       */
      if (sys_mbox_trypost(mbox, NULL) != ERR_OK) {
        /* Should never be here because post a message to empty mbox should always be successful */
        ESP_LOGW(TAG, "WARNING: failed to post NULL msg to mbox\n");
      } else {
        LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mbox free: post null successfully\n"));
      }
    }
    (*mbox)->owner = NULL;
  } else {
    if (mbox_message_num > 1) {
      ESP_LOGW(TAG, "WARNING: mbox has %d message, potential memory leaking\n", mbox_message_num);
    }

    if (mbox_message_num > 0) {
      LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("mbox free: reset mbox queue\n"));
      xQueueReset((*mbox)->os_mbox); 
    }

    /* For recvmbox or acceptmbox, free them in netconn_free() when all sockets' API are returned */
    vQueueDelete((*mbox)->os_mbox);
    free(*mbox);
    *mbox = NULL;
  }
#else
  vQueueDelete((*mbox)->os_mbox);
  free(*mbox);
  *mbox = NULL;
#endif
}
Exemplo n.º 4
0
/**
 * Pass a received packet to tcpip_thread for input processing
 *
 * @param p the received packet, p->payload pointing to the Ethernet header or
 *          to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag)
 * @param inp the network interface on which the packet was received
 */
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
  struct tcpip_msg *msg;
	//===============
	// test by pegasus
	//	struct pbuf *q;
	//	int i, plen = p->tot_len;
	//	char* dat;
	//===============

   		/*/
		// 调试打印接收信息
		lwip_printf("\r\n********tcpip_input*************\r\n");
		lwip_printf("接收数据长度:%d <--->\r\n",plen);
		for (q = p; q!=NULL; q = q->next)
		{
			dat = (char*)q->payload;
			plen= q->len;
			for(i=0;i<plen;i++)
			{
				lwip_printf("%4x ",dat[i]);
				if((i%6)==5) lwip_printf("\r\n");
			}
			lwip_printf("\r\n<*<*<*>*>*>\r\n");

		}
		lwip_printf("\r\n+++++++++++++++++++++\r\n");
		/**/
	
  if (mbox != SYS_MBOX_NULL) {
    msg = memp_malloc(MEMP_TCPIP_MSG_INPKT);
    if (msg == NULL) {
      return ERR_MEM;
    }

    msg->type = TCPIP_MSG_INPKT;
    msg->msg.inp.p = p;
    msg->msg.inp.netif = inp;
    if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
      memp_free(MEMP_TCPIP_MSG_INPKT, msg);
      return ERR_MEM;
    }
    return ERR_OK;
  }
  return ERR_VAL;
}
Exemplo n.º 5
0
/*
  Deallocates a mailbox. If there are messages still present in the
  mailbox when the mailbox is deallocated, it is an indication of a
  programming error in lwIP and the developer should be notified.
*/
void
sys_mbox_free(sys_mbox_t *mbox)
{
#define MAX_POLL_CNT 100
#define PER_POLL_DELAY 20
  uint16_t count = 0;
  bool post_null = true;

  LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: set alive false\n"));
  (*mbox)->alive = false;

  while ( count++ < MAX_POLL_CNT ){ //ESP32_WORKAROUND
    LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free:try lock=%d\n", count));
    if (!sys_mutex_trylock( &(*mbox)->lock )){
      LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free:get lock ok %d\n", count));
      sys_mutex_unlock( &(*mbox)->lock );
      break;
    }

    if (post_null){
      LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: post null to mbox\n"));
      if (sys_mbox_trypost( mbox, NULL) != ERR_OK){
        ESP_STATS_DROP_INC(esp.free_mbox_post_fail);
        LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: post null mbox fail\n"));
      } else {
        post_null = false;
        LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free: post null mbox ok\n"));
      }
    }

    if (count == (MAX_POLL_CNT-1)){
      ESP_LOGW(TAG, "WARNING: mbox %p had a consumer who never unblocked. Leaking!\n", (*mbox)->os_mbox);
    }
    sys_delay_ms(PER_POLL_DELAY);
  }

  LWIP_DEBUGF(ESP_THREAD_SAFE_DEBUG, ("sys_mbox_free:free mbox\n"));

  if (uxQueueMessagesWaiting((*mbox)->os_mbox)) {
    xQueueReset((*mbox)->os_mbox);
    /* Line for breakpoint.  Should never break here! */
    __asm__ volatile ("nop");
  }
Exemplo n.º 6
0
/**
 * Pass a received packet to tcpip_thread for input processing
 *
 * @param p the received packet, p->payload pointing to the Ethernet header or
 *          to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
 *          NETIF_FLAG_ETHERNET flags)
 * @param inp the network interface on which the packet was received
 */
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
#if LWIP_TCPIP_CORE_LOCKING_INPUT
  err_t ret;
  LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp));
  LOCK_TCPIP_CORE();
#if LWIP_ETHERNET
  if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
    ret = ethernet_input(p, inp);
  } else
#endif /* LWIP_ETHERNET */
  {
    ret = ip_input(p, inp);
  }
  UNLOCK_TCPIP_CORE();
  return ret;
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
  struct tcpip_msg *msg;

  if (sys_mbox_valid(&mbox)) {
    msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
    if (msg == NULL) {
      return ERR_MEM;
    }

    msg->type = TCPIP_MSG_INPKT;
#ifdef __ADSPBLACKFIN__
    msg->flags = 0;
#endif
    msg->msg.inp.p = p;
    msg->msg.inp.netif = inp;
    if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
      memp_free(MEMP_TCPIP_MSG_INPKT, msg);
      return ERR_MEM;
    }
    return ERR_OK;
  }
  return ERR_VAL;
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
}
Exemplo n.º 7
0
/**
 * Pass a received packet to tcpip_thread for input processing
 *
 * @param p the received packet, p->payload pointing to the Ethernet header or
 *          to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag)
 * @param inp the network interface on which the packet was received
 */
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
  struct tcpip_msg *msg;

  if (mbox != SYS_MBOX_NULL) {
    msg = memp_malloc(MEMP_TCPIP_MSG_INPKT);
    if (msg == NULL) {
      return ERR_MEM;
    }

    msg->type = TCPIP_MSG_INPKT;
    msg->msg.inp.p = p;
    msg->msg.inp.netif = inp;
    if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
      memp_free(MEMP_TCPIP_MSG_INPKT, msg);
      return ERR_MEM;
    }
    return ERR_OK;
  }
  return ERR_VAL;
}
Exemplo n.º 8
0
Arquivo: tcpip.c Projeto: wosayttn/aos
/**
 * Pass a received packet to tcpip_thread for input processing
 *
 * @param p the received packet
 * @param inp the network interface on which the packet was received
 * @param input_fn input function to call
 */
err_t
tcpip_signal_netif_event(struct netif *inp, u32_t event, netif_drv_fn drv_fn)
{
  struct tcpip_msg *msg;

  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));

  msg = (struct tcpip_msg *)memp_malloc(MEMP_NETIF_DRV_MSG);
  if (msg == NULL) {
    return ERR_MEM;
  }

  msg->type = TCPIP_MSG_DRV;
  //msg->msg.inp.p = p;
  msg->msg.drv.netif = inp;
  msg->msg.drv.event = event;
  msg->msg.drv.drv_fn = drv_fn;
  if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
    memp_free(MEMP_NETIF_DRV_MSG, msg);
    return ERR_MEM;
  }
  return ERR_OK;
}
Exemplo n.º 9
0
/**
 * Receive callback function for UDP netconns.
 * Posts the packet to conn->recvmbox or deletes it on memory error.
 *
 * @see udp.h (struct udp_pcb.recv) for parameters
 */
static void
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
         ip_addr_t *addr, u16_t port)
{
    struct netbuf *buf;
    struct netconn *conn;
    u16_t len;
#if LWIP_SO_RCVBUF
    int recv_avail;
#endif /* LWIP_SO_RCVBUF */

    LWIP_UNUSED_ARG(pcb); /* only used for asserts... */
    LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
    LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
    conn = (struct netconn *)arg;
    LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);

#if LWIP_SO_RCVBUF
    SYS_ARCH_GET(conn->recv_avail, recv_avail);
    if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) ||
            ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
#else  /* LWIP_SO_RCVBUF */
    if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) {
#endif /* LWIP_SO_RCVBUF */
        pbuf_free(p);
        return;
    }

    buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
    if (buf == NULL) {
        pbuf_free(p);
        return;
    } else {
        buf->p = p;
        buf->ptr = p;
        ip_addr_set(&buf->addr, addr);
        buf->port = port;
#if LWIP_NETBUF_RECVINFO
        {
            const struct ip_hdr* iphdr = ip_current_header();
            /* get the UDP header - always in the first pbuf, ensured by udp_input */
            const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr));
#if LWIP_CHECKSUM_ON_COPY
            buf->flags = NETBUF_FLAG_DESTADDR;
#endif /* LWIP_CHECKSUM_ON_COPY */
            ip_addr_set(&buf->toaddr, ip_current_dest_addr());
            buf->toport_chksum = udphdr->dest;
        }
#endif /* LWIP_NETBUF_RECVINFO */
    }

    len = p->tot_len;
    if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
        netbuf_delete(buf);
        return;
    } else {
#if LWIP_SO_RCVBUF
        SYS_ARCH_INC(conn->recv_avail, len);
#endif /* LWIP_SO_RCVBUF */
        /* Register event with callback */
        API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
    }
}
#endif /* LWIP_UDP */

#if LWIP_TCP
/**
 * Receive callback function for TCP netconns.
 * Posts the packet to conn->recvmbox, but doesn't delete it on errors.
 *
 * @see tcp.h (struct tcp_pcb.recv) for parameters and return value
 */
static err_t
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
    struct netconn *conn;
    u16_t len;

    LWIP_UNUSED_ARG(pcb);
    LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
    LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
    conn = (struct netconn *)arg;
    LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);

    if (conn == NULL) {
        return ERR_VAL;
    }
    if (!sys_mbox_valid(&conn->recvmbox)) {
        /* recvmbox already deleted */
        if (p != NULL) {
            tcp_recved(pcb, p->tot_len);
            pbuf_free(p);
        }
        return ERR_OK;
    }
    /* Unlike for UDP or RAW pcbs, don't check for available space
       using recv_avail since that could break the connection
       (data is already ACKed) */

    /* don't overwrite fatal errors! */
    NETCONN_SET_SAFE_ERR(conn, err);

    if (p != NULL) {
        len = p->tot_len;
    } else {
        len = 0;
    }

    if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) {
        /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
        return ERR_MEM;
    } else {
#if LWIP_SO_RCVBUF
        SYS_ARCH_INC(conn->recv_avail, len);
#endif /* LWIP_SO_RCVBUF */
        /* Register event with callback */
        API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
    }

    return ERR_OK;
}

/**
 * Poll callback function for TCP netconns.
 * Wakes up an application thread that waits for a connection to close
 * or data to be sent. The application thread then takes the
 * appropriate action to go on.
 *
 * Signals the conn->sem.
 * netconn_close waits for conn->sem if closing failed.
 *
 * @see tcp.h (struct tcp_pcb.poll) for parameters and return value
 */
static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb)
{
    struct netconn *conn = (struct netconn *)arg;

    LWIP_UNUSED_ARG(pcb);
    LWIP_ASSERT("conn != NULL", (conn != NULL));

    if (conn->state == NETCONN_WRITE) {
        do_writemore(conn);
    } else if (conn->state == NETCONN_CLOSE) {
        do_close_internal(conn);
    }
    /* @todo: implement connect timeout here? */

    /* Did a nonblocking write fail before? Then check available write-space. */
    if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) {
        /* If the queued byte- or pbuf-count drops below the configured low-water limit,
           let select mark this pcb as writable again. */
        if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
                (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
            conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
            API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
        }
    }

    return ERR_OK;
}

/**
 * Sent callback function for TCP netconns.
 * Signals the conn->sem and calls API_EVENT.
 * netconn_write waits for conn->sem if send buffer is low.
 *
 * @see tcp.h (struct tcp_pcb.sent) for parameters and return value
 */
static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
    struct netconn *conn = (struct netconn *)arg;

    LWIP_UNUSED_ARG(pcb);
    LWIP_ASSERT("conn != NULL", (conn != NULL));

    if (conn->state == NETCONN_WRITE) {
        do_writemore(conn);
    } else if (conn->state == NETCONN_CLOSE) {
        do_close_internal(conn);
    }

    if (conn) {
        /* If the queued byte- or pbuf-count drops below the configured low-water limit,
           let select mark this pcb as writable again. */
        if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT) &&
                (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT)) {
            conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
            API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
        }
    }

    return ERR_OK;
}

/**
 * Error callback function for TCP netconns.
 * Signals conn->sem, posts to all conn mboxes and calls API_EVENT.
 * The application thread has then to decide what to do.
 *
 * @see tcp.h (struct tcp_pcb.err) for parameters
 */
static void
err_tcp(void *arg, err_t err)
{
    struct netconn *conn;
    enum netconn_state old_state;
    SYS_ARCH_DECL_PROTECT(lev);

    conn = (struct netconn *)arg;
    LWIP_ASSERT("conn != NULL", (conn != NULL));

    conn->pcb.tcp = NULL;

    /* no check since this is always fatal! */
    SYS_ARCH_PROTECT(lev);
    conn->last_err = err;
    SYS_ARCH_UNPROTECT(lev);

    /* reset conn->state now before waking up other threads */
    old_state = conn->state;
    conn->state = NETCONN_NONE;

    /* Notify the user layer about a connection error. Used to signal
       select. */
    API_EVENT(conn, NETCONN_EVT_ERROR, 0);
    /* Try to release selects pending on 'read' or 'write', too.
       They will get an error if they actually try to read or write. */
    API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
    API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);

    /* pass NULL-message to recvmbox to wake up pending recv */
    if (sys_mbox_valid(&conn->recvmbox)) {
        /* use trypost to prevent deadlock */
        sys_mbox_trypost(&conn->recvmbox, NULL);
    }
    /* pass NULL-message to acceptmbox to wake up pending accept */
    if (sys_mbox_valid(&conn->acceptmbox)) {
        /* use trypost to preven deadlock */
        sys_mbox_trypost(&conn->acceptmbox, NULL);
    }

    if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
            (old_state == NETCONN_CONNECT)) {
        /* calling do_writemore/do_close_internal is not necessary
           since the pcb has already been deleted! */
        int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn);
        SET_NONBLOCKING_CONNECT(conn, 0);

        if (!was_nonblocking_connect) {
            /* set error return code */
            LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
            conn->current_msg->err = err;
            conn->current_msg = NULL;
            /* wake up the waiting task */
            sys_sem_signal(&conn->op_completed);
        }
    } else {
        LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL);
    }
}

/**
 * Setup a tcp_pcb with the correct callback function pointers
 * and their arguments.
 *
 * @param conn the TCP netconn to setup
 */
static void
setup_tcp(struct netconn *conn)
{
    struct tcp_pcb *pcb;

    pcb = conn->pcb.tcp;
    tcp_arg(pcb, conn);
    tcp_recv(pcb, recv_tcp);
    tcp_sent(pcb, sent_tcp);
    tcp_poll(pcb, poll_tcp, 4);
    tcp_err(pcb, err_tcp);
}

/**
 * Accept callback function for TCP netconns.
 * Allocates a new netconn and posts that to conn->acceptmbox.
 *
 * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value
 */
static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    struct netconn *newconn;
    struct netconn *conn = (struct netconn *)arg;

    LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));

    if (!sys_mbox_valid(&conn->acceptmbox)) {
        LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n"));
        return ERR_VAL;
    }

    /* We have to set the callback here even though
     * the new socket is unknown. conn->socket is marked as -1. */
    newconn = netconn_alloc(conn->type, conn->callback);
    if (newconn == NULL) {
        return ERR_MEM;
    }
    newconn->pcb.tcp = newpcb;
    setup_tcp(newconn);
    /* no protection: when creating the pcb, the netconn is not yet known
       to the application thread */
    newconn->last_err = err;

    if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) {
        /* When returning != ERR_OK, the pcb is aborted in tcp_process(),
           so do nothing here! */
        /* remove all references to this netconn from the pcb */
        struct tcp_pcb* pcb = newconn->pcb.tcp;
        tcp_arg(pcb, NULL);
        tcp_recv(pcb, NULL);
        tcp_sent(pcb, NULL);
        tcp_poll(pcb, NULL, 4);
        tcp_err(pcb, NULL);
        /* remove reference from to the pcb from this netconn */
        newconn->pcb.tcp = NULL;
        /* no need to drain since we know the recvmbox is empty. */
        sys_mbox_free(&newconn->recvmbox);
        sys_mbox_set_invalid(&newconn->recvmbox);
        netconn_free(newconn);
        return ERR_MEM;
    } else {
        /* Register event with callback */
        API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
    }

    return ERR_OK;
}
#endif /* LWIP_TCP */

/**
 * Create a new pcb of a specific type.
 * Called from do_newconn().
 *
 * @param msg the api_msg_msg describing the connection type
 * @return msg->conn->err, but the return value is currently ignored
 */
static void
pcb_new(struct api_msg_msg *msg)
{
    LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);

    /* Allocate a PCB for this connection */
    switch(NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
    case NETCONN_RAW:
        msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
        if(msg->conn->pcb.raw == NULL) {
            msg->err = ERR_MEM;
            break;
        }
        raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
        break;
#endif /* LWIP_RAW */
#if LWIP_UDP
    case NETCONN_UDP:
        msg->conn->pcb.udp = udp_new();
        if(msg->conn->pcb.udp == NULL) {
            msg->err = ERR_MEM;
            break;
        }
#if LWIP_UDPLITE
        if (msg->conn->type==NETCONN_UDPLITE) {
            udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
        }
#endif /* LWIP_UDPLITE */
        if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
            udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
        }
        udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
        break;
#endif /* LWIP_UDP */
#if LWIP_TCP
    case NETCONN_TCP:
        msg->conn->pcb.tcp = tcp_new();
        if(msg->conn->pcb.tcp == NULL) {
            msg->err = ERR_MEM;
            break;
        }
        setup_tcp(msg->conn);
        break;
#endif /* LWIP_TCP */
    default:
        /* Unsupported netconn type, e.g. protocol disabled */
        msg->err = ERR_VAL;
        break;
    }
}
Exemplo n.º 10
0
static int
pxudp_pmgr_pump(struct pollmgr_handler *handler, SOCKET fd, int revents)
{
    struct pxudp *pxudp;
    struct pbuf *p;
    ssize_t nread;
    err_t error;

    pxudp = (struct pxudp *)handler->data;
    LWIP_ASSERT1(handler == &pxudp->pmhdl);
    LWIP_ASSERT1(fd == pxudp->sock);
    LWIP_UNUSED_ARG(fd);


    if (revents & ~(POLLIN|POLLERR)) {
        DPRINTF(("%s: unexpected revents 0x%x\n", __func__, revents));
        return pxudp_schedule_delete(pxudp);
    }

    /*
     * XXX: AFAICS, there's no way to match the error with the
     * outgoing datagram that triggered it, since we do non-blocking
     * sends from lwip thread.
     */
    if (revents & POLLERR) {
        int sockerr = -1;
        socklen_t optlen = (socklen_t)sizeof(sockerr);
        int status;

        status = getsockopt(pxudp->sock, SOL_SOCKET,
                            SO_ERROR, (char *)&sockerr, &optlen);
        if (status < 0) {
            DPRINTF(("%s: sock %d: SO_ERROR failed:%R[sockerr]\n",
                     __func__, pxudp->sock, SOCKERRNO()));
        }
        else {
            DPRINTF(("%s: sock %d: %R[sockerr]\n",
                     __func__, pxudp->sock, sockerr));
        }
    }

    if ((revents & POLLIN) == 0) {
        return POLLIN;
    }

    nread = recv(pxudp->sock, pollmgr_udpbuf, sizeof(pollmgr_udpbuf), 0);
    if (nread == SOCKET_ERROR) {
        DPRINTF(("%s: %R[sockerr]\n", __func__, SOCKERRNO()));
        return POLLIN;
    }

    p = pbuf_alloc(PBUF_RAW, (u16_t)nread, PBUF_RAM);
    if (p == NULL) {
        DPRINTF(("%s: pbuf_alloc(%d) failed\n", __func__, (int)nread));
        return POLLIN;
    }

    error = pbuf_take(p, pollmgr_udpbuf, (u16_t)nread);
    if (error != ERR_OK) {
        DPRINTF(("%s: pbuf_take(%d) failed\n", __func__, (int)nread));
        pbuf_free(p);
        return POLLIN;
    }

    error = sys_mbox_trypost(&pxudp->inmbox, p);
    if (error != ERR_OK) {
        pbuf_free(p);
        return POLLIN;
    }

    proxy_lwip_post(&pxudp->msg_inbound);

    return POLLIN;
}
Exemplo n.º 11
0
int
fwtcp_pmgr_listen(struct pollmgr_handler *handler, SOCKET fd, int revents)
{
    struct fwtcp *fwtcp;
    struct sockaddr_storage ss;
    socklen_t sslen;
    void *peer_addr;
    uint16_t peer_port;
    struct pxtcp *pxtcp;
    SOCKET newsock;
    int status;
    err_t error;

    fwtcp = (struct fwtcp *)handler->data;
    pxtcp = NULL;

    LWIP_ASSERT1(fwtcp != NULL);
    LWIP_ASSERT1(fd == fwtcp->sock);
    LWIP_ASSERT1(revents == POLLIN);
    LWIP_UNUSED_ARG(fd);
    LWIP_UNUSED_ARG(revents);

    LWIP_ASSERT1(sys_mbox_valid(&fwtcp->connmbox));

    sslen = sizeof(ss);
    newsock = accept(fwtcp->sock, (struct sockaddr *)&ss, &sslen);
    if (newsock == INVALID_SOCKET) {
        return POLLIN;
    }


    if (ss.ss_family == PF_INET) {
        struct sockaddr_in *peer4 = (struct sockaddr_in *)&ss;
        peer_addr = &peer4->sin_addr;
        peer_port = peer4->sin_port;
    }
    else { /* PF_INET6 */
        struct sockaddr_in6 *peer6 = (struct sockaddr_in6 *)&ss;
        peer_addr = &peer6->sin6_addr;
        peer_port = peer6->sin6_port;
    }
    peer_port = ntohs(peer_port);

#if PLEASE_ABSTAIN_FROM_DPRINFING > 1 /* DPRINTF */ && !defined(RT_OS_WINDOWS)
    {
        char addrbuf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
        const char *addrstr;

        addrstr = inet_ntop(ss.ss_family, peer_addr, addrbuf, sizeof(addrbuf));
        DPRINTF(("<--- TCP %s%s%s:%d\n",
                 ss.ss_family == AF_INET6 ? "[" : "",
                 addrstr,
                 ss.ss_family == AF_INET6 ? "]" : "",
                 peer_port));
    }
#endif  /* DPRINTF */


    pxtcp = pxtcp_create_forwarded(newsock);
    if (pxtcp == NULL) {
        proxy_reset_socket(newsock);
        return POLLIN;
    }

    status = pxtcp_pmgr_add(pxtcp);
    if (status < 0) {
        pxtcp_cancel_forwarded(pxtcp);
        return POLLIN;
    }

    error = sys_mbox_trypost(&fwtcp->connmbox, (void *)pxtcp);
    if (error != ERR_OK) {
        pxtcp_pmgr_del(pxtcp);
        pxtcp_cancel_forwarded(pxtcp);
        return POLLIN;
    }

    proxy_lwip_post(&fwtcp->msg_connect);
    return POLLIN;
}
Exemplo n.º 12
0
void sys_mbox_post(struct sys_mbox** mbox, void* msg) {
	sys_mbox_trypost(mbox, msg);
}
Exemplo n.º 13
0
/*----------------------------------------------------------------------*/
void sys_mbox_post(sys_mbox_t mbox, void *msg)
{
  sys_mbox_trypost(mbox, msg); 
}
Exemplo n.º 14
0
Arquivo: tcpip.c Projeto: wosayttn/aos
/**
 * Try to post a callback-message to the tcpip_thread mbox
 * This is intended to be used to send "static" messages from interrupt context.
 *
 * @param msg pointer to the message to post
 * @return sys_mbox_trypost() return code
 */
err_t
tcpip_trycallback(struct tcpip_callback_msg* msg)
{
  LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox));
  return sys_mbox_trypost(&mbox, msg);
}
Exemplo n.º 15
-1
/**
 * Receive callback function for RAW netconns.
 * Doesn't 'eat' the packet, only references it and sends it to
 * conn->recvmbox
 *
 * @see raw.h (struct raw_pcb.recv) for parameters and return value
 */
static u8_t
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
    struct ip_addr *addr)
{
  struct pbuf *q;
  struct netbuf *buf;
  struct netconn *conn;
#if LWIP_SO_RCVBUF
  int recv_avail;
#endif /* LWIP_SO_RCVBUF */

  LWIP_UNUSED_ARG(addr);
  conn = arg;

#if LWIP_SO_RCVBUF
  SYS_ARCH_GET(conn->recv_avail, recv_avail);
  if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL) &&
      ((recv_avail + (int)(p->tot_len)) <= conn->recv_bufsize)) {
#else  /* LWIP_SO_RCVBUF */
  if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL)) {
#endif /* LWIP_SO_RCVBUF */
    /* copy the whole packet into new pbufs */
    q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
    if(q != NULL) {
      if (pbuf_copy(q, p) != ERR_OK) {
        pbuf_free(q);
        q = NULL;
      }
    }

    if(q != NULL) {
      buf = memp_malloc(MEMP_NETBUF);
      if (buf == NULL) {
        pbuf_free(q);
        return 0;
      }

      buf->p = q;
      buf->ptr = q;
      buf->addr = &(((struct ip_hdr*)(q->payload))->src);
      buf->port = pcb->protocol;

      if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
        netbuf_delete(buf);
        return 0;
      } else {
        SYS_ARCH_INC(conn->recv_avail, q->tot_len);
        /* Register event with callback */
        API_EVENT(conn, NETCONN_EVT_RCVPLUS, q->tot_len);
      }
    }
  }

  return 0; /* do not eat the packet */
}
#endif /* LWIP_RAW*/

#if LWIP_UDP
/**
 * Receive callback function for UDP netconns.
 * Posts the packet to conn->recvmbox or deletes it on memory error.
 *
 * @see udp.h (struct udp_pcb.recv) for parameters
 */
static void
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
   struct ip_addr *addr, u16_t port)
{
  struct netbuf *buf;
  struct netconn *conn;
#if LWIP_SO_RCVBUF
  int recv_avail;
#endif /* LWIP_SO_RCVBUF */

  LWIP_UNUSED_ARG(pcb); /* only used for asserts... */
  LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
  LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
  conn = arg;
  LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);

#if LWIP_SO_RCVBUF
  SYS_ARCH_GET(conn->recv_avail, recv_avail);
  if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL) ||
      ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
#else  /* LWIP_SO_RCVBUF */
  if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
#endif /* LWIP_SO_RCVBUF */
    pbuf_free(p);
    return;
  }

  buf = memp_malloc(MEMP_NETBUF);
  if (buf == NULL) {
    pbuf_free(p);
    return;
  } else {
    buf->p = p;
    buf->ptr = p;
    buf->addr = addr;
    buf->port = port;
#if LWIP_NETBUF_RECVINFO
    {
      const struct ip_hdr* iphdr = ip_current_header();
      /* get the UDP header - always in the first pbuf, ensured by udp_input */
      const struct udp_hdr* udphdr = (void*)(((char*)iphdr) + IPH_LEN(iphdr));
      buf->toaddr = (struct ip_addr*)&iphdr->dest;
      buf->toport = udphdr->dest;
    }
#endif /* LWIP_NETBUF_RECVINFO */
  }

  if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) {
    netbuf_delete(buf);
    return;
  } else {
    SYS_ARCH_INC(conn->recv_avail, p->tot_len);
    /* Register event with callback */
    API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
  }
}
#endif /* LWIP_UDP */

#if LWIP_TCP
/**
 * Receive callback function for TCP netconns.
 * Posts the packet to conn->recvmbox, but doesn't delete it on errors.
 *
 * @see tcp.h (struct tcp_pcb.recv) for parameters and return value
 */
static err_t
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
  struct netconn *conn;
  u16_t len;

  LWIP_UNUSED_ARG(pcb);
  LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
  LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
  conn = arg;
  LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);

  if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) {
    return ERR_VAL;
  }

  conn->err = err;
  if (p != NULL) {
    len = p->tot_len;
    SYS_ARCH_INC(conn->recv_avail, len);
  } else {
    len = 0;
  }

  if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) {
    return ERR_MEM;
  } else {
    /* Register event with callback */
    API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
  }

  return ERR_OK;
}

/**
 * Poll callback function for TCP netconns.
 * Wakes up an application thread that waits for a connection to close
 * or data to be sent. The application thread then takes the
 * appropriate action to go on.
 *
 * Signals the conn->sem.
 * netconn_close waits for conn->sem if closing failed.
 *
 * @see tcp.h (struct tcp_pcb.poll) for parameters and return value
 */
static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb)
{
  struct netconn *conn = arg;

  LWIP_UNUSED_ARG(pcb);
  LWIP_ASSERT("conn != NULL", (conn != NULL));

  if (conn->state == NETCONN_WRITE) {
    do_writemore(conn);
  } else if (conn->state == NETCONN_CLOSE) {
    do_close_internal(conn);
  }

  return ERR_OK;
}

/**
 * Sent callback function for TCP netconns.
 * Signals the conn->sem and calls API_EVENT.
 * netconn_write waits for conn->sem if send buffer is low.
 *
 * @see tcp.h (struct tcp_pcb.sent) for parameters and return value
 */
static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
  struct netconn *conn = arg;

  LWIP_UNUSED_ARG(pcb);
  LWIP_ASSERT("conn != NULL", (conn != NULL));

  if (conn->state == NETCONN_WRITE) {
    LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL);
    do_writemore(conn);
  } else if (conn->state == NETCONN_CLOSE) {
    do_close_internal(conn);
  }

  if (conn) {
    if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)) {
      API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
    }
  }
  
  return ERR_OK;
}

/**
 * Error callback function for TCP netconns.
 * Signals conn->sem, posts to all conn mboxes and calls API_EVENT.
 * The application thread has then to decide what to do.
 *
 * @see tcp.h (struct tcp_pcb.err) for parameters
 */
static void
err_tcp(void *arg, err_t err)
{
  struct netconn *conn;

  conn = arg;
  LWIP_ASSERT("conn != NULL", (conn != NULL));

  conn->pcb.tcp = NULL;

  conn->err = err;
  if (conn->recvmbox != SYS_MBOX_NULL) {
    /* Register event with callback */
    API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
    sys_mbox_post(conn->recvmbox, NULL);
  }
  if (conn->op_completed != SYS_SEM_NULL && conn->state == NETCONN_CONNECT) {
    conn->state = NETCONN_NONE;
    sys_sem_signal(conn->op_completed);
  }
  if (conn->acceptmbox != SYS_MBOX_NULL) {
    /* Register event with callback */
    API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
    sys_mbox_post(conn->acceptmbox, NULL);
  }
  if ((conn->state == NETCONN_WRITE) || (conn->state == NETCONN_CLOSE)) {
    /* calling do_writemore/do_close_internal is not necessary
       since the pcb has already been deleted! */
    conn->state = NETCONN_NONE;
    /* wake up the waiting task */
    sys_sem_signal(conn->op_completed);
  }
}

/**
 * Setup a tcp_pcb with the correct callback function pointers
 * and their arguments.
 *
 * @param conn the TCP netconn to setup
 */
static void
setup_tcp(struct netconn *conn)
{
  struct tcp_pcb *pcb;

  pcb = conn->pcb.tcp;
  tcp_arg(pcb, conn);
  tcp_recv(pcb, recv_tcp);
  tcp_sent(pcb, sent_tcp);
  tcp_poll(pcb, poll_tcp, 4);
  tcp_err(pcb, err_tcp);
}

/**
 * Accept callback function for TCP netconns.
 * Allocates a new netconn and posts that to conn->acceptmbox.
 *
 * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value
 */
static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
  struct netconn *newconn;
  struct netconn *conn;

#if API_MSG_DEBUG
#if TCP_DEBUG
  tcp_debug_print_state(newpcb->state);
#endif /* TCP_DEBUG */
#endif /* API_MSG_DEBUG */
  conn = (struct netconn *)arg;

  LWIP_ERROR("accept_function: invalid conn->acceptmbox",
             conn->acceptmbox != SYS_MBOX_NULL, return ERR_VAL;);

  /* We have to set the callback here even though
   * the new socket is unknown. conn->socket is marked as -1. */
  newconn = netconn_alloc(conn->type, conn->callback);
  if (newconn == NULL) {
    return ERR_MEM;
  }
  newconn->pcb.tcp = newpcb;
  setup_tcp(newconn);
  newconn->err = err;

  if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) {
    /* When returning != ERR_OK, the connection is aborted in tcp_process(),
       so do nothing here! */
    newconn->pcb.tcp = NULL;
    netconn_free(newconn);
    return ERR_MEM;
  } else {
    /* Register event with callback */
    API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
  }

  return ERR_OK;
}
#endif /* LWIP_TCP */

/**
 * Create a new pcb of a specific type.
 * Called from do_newconn().
 *
 * @param msg the api_msg_msg describing the connection type
 * @return msg->conn->err, but the return value is currently ignored
 */
static err_t
pcb_new(struct api_msg_msg *msg)
{
   msg->conn->err = ERR_OK;

   LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);

   /* Allocate a PCB for this connection */
   switch(NETCONNTYPE_GROUP(msg->conn->type)) {
#if LWIP_RAW
   case NETCONN_RAW:
     msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
     if(msg->conn->pcb.raw == NULL) {
       msg->conn->err = ERR_MEM;
       break;
     }
     raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
     break;
#endif /* LWIP_RAW */
#if LWIP_UDP
   case NETCONN_UDP:
     msg->conn->pcb.udp = udp_new();
     if(msg->conn->pcb.udp == NULL) {
       msg->conn->err = ERR_MEM;
       break;
     }
#if LWIP_UDPLITE
     if (msg->conn->type==NETCONN_UDPLITE) {
       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
     }
#endif /* LWIP_UDPLITE */
     if (msg->conn->type==NETCONN_UDPNOCHKSUM) {
       udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
     }
     udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
     break;
#endif /* LWIP_UDP */
#if LWIP_TCP
   case NETCONN_TCP:
     msg->conn->pcb.tcp = tcp_new();
     if(msg->conn->pcb.tcp == NULL) {
       msg->conn->err = ERR_MEM;
       break;
     }
     setup_tcp(msg->conn);
     break;
#endif /* LWIP_TCP */
   default:
     /* Unsupported netconn type, e.g. protocol disabled */
     msg->conn->err = ERR_VAL;
     break;
   }

  return msg->conn->err;
}