Beispiel #1
0
int ssl_socket_recv(void *ctx, unsigned char *buf, size_t len) {
  struct mg_connection *nc = (struct mg_connection *) ctx;
  struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
  struct pbuf *seg = cs->rx_chain;
  if (seg == NULL) {
    DBG(("%u - nothing to read", len));
    return MBEDTLS_ERR_SSL_WANT_READ;
  }
  size_t seg_len = (seg->len - cs->rx_offset);
  DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len));
  mgos_lock();
  len = MIN(len, seg_len);
  pbuf_copy_partial(seg, buf, len, cs->rx_offset);
  cs->rx_offset += len;
  /* TCP PCB may be NULL if connection has already been closed
   * but we still have data to deliver to SSL. */
  if (cs->pcb.tcp != NULL) tcp_recved(cs->pcb.tcp, len);
  if (cs->rx_offset == cs->rx_chain->len) {
    cs->rx_chain = pbuf_dechain(cs->rx_chain);
    pbuf_free(seg);
    cs->rx_offset = 0;
  }
  mgos_unlock();
  LOG(LL_DEBUG, ("%p <- %d", nc, (int) len));
  return len;
}
Beispiel #2
0
void mg_if_destroy_conn(struct mg_connection *nc) {
  int i;
  if (nc->sock != INVALID_SOCKET) {
    struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
    if (!(nc->flags & MG_F_UDP)) {
      struct tcp_pcb *tpcb = cs->pcb.tcp;
      if (tpcb != NULL) {
        tcp_arg(tpcb, NULL);
        DBG(("%p tcp_close %p", nc, tpcb));
        tcp_arg(tpcb, NULL);
        tcp_close(tpcb);
      }
      while (cs->rx_chain != NULL) {
        struct pbuf *seg = cs->rx_chain;
        cs->rx_chain = pbuf_dechain(cs->rx_chain);
        pbuf_free(seg);
      }
    } else {
      struct udp_pcb *upcb = cs->pcb.udp;
      if (upcb != NULL) {
        DBG(("%p udp_remove %p", nc, upcb));
        udp_remove(upcb);
      }
    }
    memset(cs, 0, sizeof(*cs));
    free(cs);
    nc->sock = INVALID_SOCKET;
  }
  /* Walk the queue and null-out further signals for this conn. */
  for (i = 0; i < MG_TASK_QUEUE_LEN; i++) {
    if ((struct mg_connection *) s_mg_task_queue[i].par == nc) {
      s_mg_task_queue[i].sig = MG_SIG_TOMBSTONE;
    }
  }
}
int32_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) {
  if(pb == 0){
    //os_printf("pb-null\n");
    return _close();
  }

  _rx_last_packet = millis();
    //use callback (onData defined)
    while(pb != NULL){
      if(pb->next == NULL){
        if(_recv_cb)
          _recv_cb(_recv_cb_arg, this, pb->payload, pb->len);
        tcp_recved(pcb, pb->len);
        pbuf_free(pb);
        pb = NULL;
      } else {
        pbuf *b = pb;
        pb = pbuf_dechain(b);
        if(_recv_cb)
          _recv_cb(_recv_cb_arg, this, b->payload, b->len);
        tcp_recved(pcb, b->len);
        pbuf_free(b);
      }
    }
  return ERR_OK;
}
// Read an entire pbuf from the NetworkTransaction
bool NetworkTransaction::ReadBuffer(char *&buffer, unsigned int &len)
{
	if (LostConnection() || pb == NULL)
	{
		return false;
	}

	if (inputPointer == pb->len)
	{
		// See if there is another pbuf in the chain
		if (inputPointer < pb->tot_len)
		{
			pb = pbuf_dechain(pb);
			if (pb == NULL)
			{
				return false;
			}
			inputPointer = 0;
		}
		else
		{
			return false;
		}
	}

	len = pb->len;
	buffer = static_cast<char *>(pb->payload);
	inputPointer += len;

	return true;
}
// Webserver calls this to read bytes that have come in from the network.
bool NetworkTransaction::Read(char& b)
{
	if (LostConnection() || pb == NULL)
	{
		return false;
	}

	if (inputPointer == pb->len)
	{
		// See if there is another pbuf in the chain
		if (inputPointer < pb->tot_len)
		{
			pb = pbuf_dechain(pb);
			if (pb == NULL)
			{
				return false;
			}
			inputPointer = 0;
		}
		else
		{
			return false;
		}
	}

	b = ((const char*)pb->payload)[inputPointer++];
	return true;
}
Beispiel #6
0
static int fetch_rcvbuf(struct socket *s, struct iovec *iov, int iovlen) {
  int left;
  int recved;
  int rc;
  struct pbuf *p;
  
  left = get_iovec_size(iov, iovlen);
  recved = 0;
  while (s->tcp.recvhead && left > 0) {
    p = s->tcp.recvhead;

    if (left < p->len) {
      rc = write_iovec(iov, iovlen, p->payload, left);
      if (rc < 0) return rc;

      recved += rc;
      left -= rc;

      pbuf_header(p, -rc);
    } else {
      rc = write_iovec(iov, iovlen, p->payload, p->len);
      if (rc < 0) return rc;

      recved += rc;
      left -= rc;

      s->tcp.recvhead = pbuf_dechain(p);
      if (!s->tcp.recvhead) s->tcp.recvtail = NULL;
      pbuf_free(p);
    }
  }

  return recved;
}
Beispiel #7
0
ssize_t kr_recv(int fd, void *buf, size_t len) {
  struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) fd;
  struct pbuf *seg = cs->rx_chain;
  if (seg == NULL) {
    DBG(("%u - nothing to read", len));
    return KR_IO_WOULDBLOCK;
  }
  size_t seg_len = (seg->len - cs->rx_offset);
  DBG(("%u %u %u %u", len, cs->rx_chain->len, seg_len, cs->rx_chain->tot_len));
  len = MIN(len, seg_len);
  pbuf_copy_partial(seg, buf, len, cs->rx_offset);
  cs->rx_offset += len;
  tcp_recved(cs->pcb.tcp, len);
  if (cs->rx_offset == cs->rx_chain->len) {
    cs->rx_chain = pbuf_dechain(cs->rx_chain);
    pbuf_free(seg);
    cs->rx_offset = 0;
  }
  return len;
}
Beispiel #8
0
static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
                                 struct pbuf *p, err_t err) {
  struct mg_connection *nc = (struct mg_connection *) arg;
  DBG(("%p %p %u %d", nc, tpcb, (p != NULL ? p->tot_len : 0), err));
  if (p == NULL) {
    if (nc != NULL) {
      system_os_post(MG_TASK_PRIORITY, MG_SIG_CLOSE_CONN, (uint32_t) nc);
    } else {
      /* Tombstoned connection, do nothing. */
    }
    return ERR_OK;
  } else if (nc == NULL) {
    tcp_abort(tpcb);
    return ERR_ARG;
  }
  struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
  /*
   * If we get a chain of more than one segment at once, we need to bump
   * refcount on the subsequent bufs to make them independent.
   */
  if (p->next != NULL) {
    struct pbuf *q = p->next;
    for (; q != NULL; q = q->next) pbuf_ref(q);
  }
  if (cs->rx_chain == NULL) {
    cs->rx_chain = p;
    cs->rx_offset = 0;
  } else {
    pbuf_chain(cs->rx_chain, p);
  }

#ifdef SSL_KRYPTON
  if (nc->ssl != NULL) {
    if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
      mg_lwip_ssl_recv(nc);
    } else {
      mg_lwip_ssl_do_hs(nc);
    }
    return ERR_OK;
  }
#endif

  while (cs->rx_chain != NULL) {
    struct pbuf *seg = cs->rx_chain;
    size_t len = (seg->len - cs->rx_offset);
    char *data = (char *) malloc(len);
    if (data == NULL) {
      DBG(("OOM"));
      return ERR_MEM;
    }
    pbuf_copy_partial(seg, data, len, cs->rx_offset);
    mg_if_recv_tcp_cb(nc, data, len); /* callee takes over data */
    cs->rx_offset += len;
    if (cs->rx_offset == cs->rx_chain->len) {
      cs->rx_chain = pbuf_dechain(cs->rx_chain);
      pbuf_free(seg);
      cs->rx_offset = 0;
    }
  }

  if (nc->send_mbuf.len > 0) {
    mg_lwip_mgr_schedule_poll(nc->mgr);
  }
  return ERR_OK;
}
Beispiel #9
0
static err_t mg_lwip_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
                                 struct pbuf *p, err_t err) {
  struct mg_connection *nc = (struct mg_connection *) arg;
  DBG(("%p %p %u %d", nc, tpcb, (p != NULL ? p->tot_len : 0), err));
  if (p == NULL) {
    if (nc != NULL) {
      mg_lwip_post_signal(MG_SIG_CLOSE_CONN, nc);
    } else {
      /* Tombstoned connection, do nothing. */
    }
    return ERR_OK;
  } else if (nc == NULL) {
    tcp_abort(tpcb);
    return ERR_ARG;
  }
  struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock;
  /*
   * If we get a chain of more than one segment at once, we need to bump
   * refcount on the subsequent bufs to make them independent.
   */
  if (p->next != NULL) {
    struct pbuf *q = p->next;
    for (; q != NULL; q = q->next) pbuf_ref(q);
  }
  if (cs->rx_chain == NULL) {
    cs->rx_chain = p;
    cs->rx_offset = 0;
  } else {
    if (pbuf_clen(cs->rx_chain) >= 4) {
      /* ESP SDK has a limited pool of 5 pbufs. We must not hog them all or RX
       * will be completely blocked. We already have at least 4 in the chain,
       * this one is, so we have to make a copy and release this one. */
      struct pbuf *np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
      if (np != NULL) {
        pbuf_copy(np, p);
        pbuf_free(p);
        p = np;
      }
    }
    pbuf_chain(cs->rx_chain, p);
  }

#ifdef SSL_KRYPTON
  if (nc->ssl != NULL) {
    if (nc->flags & MG_F_SSL_HANDSHAKE_DONE) {
      mg_lwip_ssl_recv(nc);
    } else {
      mg_lwip_ssl_do_hs(nc);
    }
    return ERR_OK;
  }
#endif

  while (cs->rx_chain != NULL) {
    struct pbuf *seg = cs->rx_chain;
    size_t len = (seg->len - cs->rx_offset);
    char *data = (char *) malloc(len);
    if (data == NULL) {
      DBG(("OOM"));
      return ERR_MEM;
    }
    pbuf_copy_partial(seg, data, len, cs->rx_offset);
    mg_if_recv_tcp_cb(nc, data, len); /* callee takes over data */
    cs->rx_offset += len;
    if (cs->rx_offset == cs->rx_chain->len) {
      cs->rx_chain = pbuf_dechain(cs->rx_chain);
      pbuf_free(seg);
      cs->rx_offset = 0;
    }
  }

  if (nc->send_mbuf.len > 0) {
    mg_lwip_mgr_schedule_poll(nc->mgr);
  }
  return ERR_OK;
}