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; }
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; }
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; }
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; }
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; }
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; }