void mg_if_recved(struct mg_connection *nc, size_t len) { if (nc->flags & MG_F_UDP) return; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; if (nc->sock == INVALID_SOCKET || cs->pcb.tcp == NULL) { DBG(("%p invalid socket", nc)); return; } DBG(("%p %p %u", nc, cs->pcb.tcp, len)); /* Currently SSL acknowledges data immediately. * TODO(rojer): Find a way to propagate mg_if_recved. */ if (nc->ssl == NULL) { tcp_recved(cs->pcb.tcp, len); } mbuf_trim(&nc->recv_mbuf); }
static err_t InternalRecvEventHandler(void *arg, PTCP_PCB pcb, struct pbuf *p, const err_t err) { PCONNECTION_ENDPOINT Connection = arg; /* Make sure the socket didn't get closed */ if (!arg) { if (p) pbuf_free(p); return ERR_OK; } if (p) { LibTCPEnqueuePacket(Connection, p); tcp_recved(pcb, p->tot_len); TCPRecvEventHandler(arg); } else if (err == ERR_OK) { /* Complete pending reads with 0 bytes to indicate a graceful closure, * but note that send is still possible in this state so we don't close the * whole socket here (by calling tcp_close()) as that would violate TCP specs */ Connection->ReceiveShutdown = TRUE; Connection->ReceiveShutdownStatus = STATUS_SUCCESS; /* This code path executes for both remotely and locally initiated closures, * and we need to distinguish between them */ if (Connection->SocketContext) { /* Remotely initiated close */ TCPRecvEventHandler(arg); } else { /* Locally initated close */ TCPFinEventHandler(arg, ERR_CLSD); } } return ERR_OK; }
void iperfserver_send(struct tcp_pcb *tpcb, struct iperfserver_state *es) { struct pbuf *ptr; err_t wr_err = ERR_OK; while ((wr_err == ERR_OK) && (es->p != NULL) && (es->p->len <= tcp_sndbuf(tpcb))) { ptr = es->p; /* enqueue data for transmission */ wr_err = tcp_write(tpcb, ptr->payload, ptr->len, TCP_WRITE_FLAG_COPY); if (wr_err == ERR_OK) { u16_t plen; u8_t freed; plen = ptr->len; /* continue with next pbuf in chain (if any) */ es->p = ptr->next; if(es->p != NULL) { /* new reference! */ pbuf_ref(es->p); } /* chop first pbuf from chain */ do { /* try hard to free pbuf */ freed = pbuf_free(ptr); } while(freed == 0); /* we can read more data now */ tcp_recved(tpcb, plen); } else if(wr_err == ERR_MEM) { /* we are low on memory, try later / harder, defer to poll */ es->p = ptr; } else { /* other problem ?? */ } } }
static err_t tcp_is_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err) { // debug_printf("tcp is recv\n"); static int tot = 0; int len; char *payload; if (pb == NULL) { // connection closed. clean up and then EXIT the program. debug_printf("finished receiving file. %d bytes\n", tot); close_connection(pcb); fflush(recv_f); fclose(recv_f); exit(EXIT_SUCCESS); } else if ((err == ERR_OK) && (pb != NULL)) { // pointer to the payload payload = (char *)pb->payload; // size of the payload len = pb->tot_len; // debug_printf("Got data [%d bytes]\n", len); // printf("data: %s\n", payload); // write out to file int n = fwrite(payload, 1, len, recv_f); fflush(recv_f); // debug_printf("wrote %d bytes\n", n); tot += n; // debug_printf("for a total of: %d bytes\n", tot); // Inform TCP that we have taken the data. tcp_recved(pcb, pb->tot_len); // Free the packet buffer pbuf_free(pb); } // debug_printf("done tcp is recv\n"); return ERR_OK; }
static err_t rxperf_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { /* close socket if the peer has sent the FIN packet */ if (p == NULL) { tcp_close(tpcb); return ERR_OK; } /* all we do is say we've received the packet */ /* we don't actually make use of it */ tcp_recved(tpcb, p->tot_len); pbuf_free(p); return ERR_OK; }
static err_t sink_recv(void *arg, struct tcp_pcb * pcb, struct pbuf * pbuf, err_t err) { if (pbuf == NULL) { outputf("ps: connection closed"); tcp_recv(pcb, NULL); tcp_close(pcb); return ERR_OK; } /* Tell lwIP we're done with this packet. */ tcp_recved(pcb, pbuf->tot_len); pbuf_free(pbuf); return ERR_OK; }
// flush queues err_t flushq(struct client *c) { struct tcp_pcb *pcb = c->pcb; while (c->p != NULL && c->p->len < tcp_sndbuf(pcb)) { if (tcp_write(pcb, c->p->payload, c->p->len, 1) != ERR_OK) break; // defer to poll u32_t oldlen = c->p->len; struct pbuf *next = c->p->next; pbuf_free(c->p); if ((c->p = next)) pbuf_ref(c->p); tcp_recved(pcb, oldlen); } if (c->st == TERMINATED) client_kill(c); return ERR_OK; }
void NetworkTransaction::FreePbuf() { // Tell LWIP that we have processed data if (cs != NULL && bufferLength > 0 && cs->pcb != NULL) { tcp_recved(cs->pcb, bufferLength); bufferLength = 0; } // Free pbuf (pbufs are thread-safe) if (pb != NULL) { pbuf_free(pb); pb = NULL; } }
void NetworkTransaction::FreePbuf() { // See if we have to send an ACK to the client if (IsConnected() && pb != nullptr && !dataAcknowledged) { tcp_recved(cs->pcb, pb->tot_len); dataAcknowledged = true; } // Free all pbufs (pbufs are thread-safe) if (pb != nullptr) { pbuf_free(pb); pb = readingPb = nullptr; } }
/** * Copy data to the reading threads' buffer and resume the thread if * all requested data has been read. */ static void tcp_recv_buffer(struct socket_t *socket_p) { struct recv_from_args_t *args_p; size_t size; struct pbuf *pbuf_p; pbuf_p = socket_p->input.u.recvfrom.pbuf_p; args_p = socket_p->input.cb.args_p; /* Copy data from pbuf_p to the read buffer. */ size = MIN(socket_p->input.u.recvfrom.left, args_p->extra.left); pbuf_copy_partial(pbuf_p, args_p->buf_p, size, pbuf_p->tot_len - socket_p->input.u.recvfrom.left); args_p->extra.left -= size; args_p->buf_p += size; socket_p->input.u.recvfrom.left -= size; /* Free pbuf_p if all data has been read. */ if (socket_p->input.u.recvfrom.left == 0) { tcp_recved(socket_p->pcb_p, pbuf_p->tot_len); pbuf_free(pbuf_p); socket_p->input.u.recvfrom.pbuf_p = NULL; socket_p->input.u.recvfrom.left = 0; /* Resume the thread is the socket is closed since there is no more data to read. */ if (socket_p->input.u.recvfrom.closed == 1) { socket_p->input.cb.state = STATE_IDLE; fs_counter_increment(&module.tcp_rx_bytes, args_p->size - args_p->extra.left); resume_thrd(socket_p->input.cb.thrd_p, args_p->size - args_p->extra.left); return; } } /* Resume the reader when the receive buffer is full. */ if (args_p->extra.left == 0) { socket_p->input.cb.state = STATE_IDLE; fs_counter_increment(&module.tcp_rx_bytes, args_p->size); resume_thrd(socket_p->input.cb.thrd_p, args_p->size); } else { socket_p->input.cb.state = STATE_RECVFROM; } }
// Helper function for recv/recvfrom to handle TCP packets STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { if (socket->incoming.pbuf == NULL) { // Non-blocking socket if (socket->timeout == 0) { *_errno = EAGAIN; return -1; } mp_uint_t start = mp_hal_ticks_ms(); while (socket->state == STATE_CONNECTED && socket->incoming.pbuf == NULL) { if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) { *_errno = ETIMEDOUT; return -1; } poll_sockets(); } if (socket->state == STATE_PEER_CLOSED) { if (socket->incoming.pbuf == NULL) { // socket closed and no data left in buffer return 0; } } else if (socket->state != STATE_CONNECTED) { *_errno = -socket->state; return -1; } } struct pbuf *p = socket->incoming.pbuf; if (socket->leftover_count == 0) { socket->leftover_count = p->tot_len; } u16_t result = pbuf_copy_partial(p, buf, ((socket->leftover_count >= len) ? len : socket->leftover_count), (p->tot_len - socket->leftover_count)); if (socket->leftover_count > len) { // More left over... socket->leftover_count -= len; } else { pbuf_free(p); socket->incoming.pbuf = NULL; socket->leftover_count = 0; } tcp_recved(socket->pcb.tcp, result); return (mp_uint_t) result; }
/****************************************************************************** * FunctionName : espconn_client_recv * Description : Data has been received on this pcb. * Parameters : arg -- Additional argument to pass to the callback function * pcb -- The connection pcb which received data * p -- The received data (or NULL when the connection has been closed!) * err -- An error code if there has been an error receiving * Returns : ERR_ABRT: if you have called tcp_abort from within the function! *******************************************************************************/ static err_t ICACHE_FLASH_ATTR espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { espconn_msg *precv_cb = arg; tcp_arg(pcb, arg); if (p != NULL) { /*To update and advertise a larger window*/ if(precv_cb->recv_hold_flag == 0) tcp_recved(pcb, p->tot_len); else precv_cb->recv_holded_buf_Len += p->tot_len; } if (err == ERR_OK && p != NULL) { char *pdata = NULL; u16_t length = 0; /*Copy the contents of a packet buffer to an application buffer. *to prevent memory leaks, ensure that each allocated is deleted*/ pdata = (char *)malloc(p ->tot_len + 1); length = pbuf_copy_partial(p, pdata, p ->tot_len, 0); pbuf_free(p); if (length != 0) { /*switch the state of espconn for application process*/ precv_cb->pespconn ->state = ESPCONN_READ; precv_cb->pcommon.pcb = pcb; if (precv_cb->pespconn->recv_callback != NULL) { precv_cb->pespconn->recv_callback(precv_cb->pespconn, pdata, length); } /*switch the state of espconn for next packet copy*/ if (pcb->state == ESTABLISHED) precv_cb->pespconn ->state = ESPCONN_CONNECT; } /*to prevent memory leaks, ensure that each allocated is deleted*/ free(pdata); pdata = NULL; } if (err == ERR_OK && p == NULL) { espconn_client_close(precv_cb, pcb,0); } return ERR_OK; }
void echo_send(struct tcp_pcb *tpcb, struct echo_state *es) { struct pbuf *ptr; err_t wr_err = ERR_OK; while ((wr_err == ERR_OK) && (es->p != NULL) && (es->p->len <= tcp_sndbuf(tpcb))) { ptr = es->p; // enqueue data for transmission wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1); if (wr_err == ERR_OK) { u16_t plen; u8_t freed; plen = ptr->len; // continue with next pbuf in chain (if any) es->p = ptr->next; if(es->p != NULL) { // new reference! pbuf_ref(es->p); } // chop first pbuf from chain do { // try hard to free pbuf freed = pbuf_free(ptr); } while(freed == 0); // we can read more data now tcp_recved(tpcb, plen); } else if(wr_err == ERR_MEM) { // we are low on memory, try later / harder, defer to poll es->p = ptr; } else { // other problem ?? } } }
static void raw_sk_free_pbuf_custom_fn(struct pbuf *p) { struct raw_sk_pbuf_custom *pcr = (struct raw_sk_pbuf_custom*)p; if(p != NULL) { // printf("\nraw_sk_free_pbuf_custom_fn,len=%d\n",p->tot_len); tcp_recved((struct tcp_pcb *)pcr->param, p->tot_len); if (pcr->original != NULL) { // printf("\ngo to pbuf_free,original pbuf=%x\n",pcr->original); pbuf_free(pcr->original); } raw_sk_free_pbuf_custom(pcr); } }
static int cos_net_tcp_recv(struct intern_connection *ic, void *data, int sz) { int xfer_amnt = 0; assert(ic->conn_type == TCP); /* If there is data available, get it */ if (ic->incoming_size > 0) { struct packet_queue *pq; struct tcp_pcb *tp; char *data_start; int data_left; pq = ic->incoming; assert(pq); data_start = ((char*)pq->data) + ic->incoming_offset; data_left = pq->len - ic->incoming_offset; assert(data_left > 0 && (u32_t)data_left <= pq->len); /* Consume all of first packet? */ if (data_left <= sz) { ic->incoming = pq->next; if (ic->incoming_last == pq) { assert(NULL == ic->incoming); ic->incoming_last = NULL; } memcpy(data, data_start, data_left); xfer_amnt = data_left; ic->incoming_offset = 0; #ifdef TEST_TIMING ic->ts_start = timing_record(APP_RECV, pq->ts_start); #endif free(pq); } /* Consume part of first packet */ else { memcpy(data, data_start, sz); xfer_amnt = sz; ic->incoming_offset += sz; assert(ic->incoming_offset >= 0 && (u32_t)ic->incoming_offset < pq->len); } ic->incoming_size -= xfer_amnt; tp = ic->conn.tp; tcp_recved(tp, xfer_amnt); } return xfer_amnt; }
static err_t recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { struct iperf_state *is = (struct iperf_state *) arg; if (p == NULL) { is->recv_end_ticks = rte_get_timer_cycles(); return disconnect(is, tpcb); } if (!is->valid_hdr) parse_header(is, tpcb, p->payload); is->recv_bytes += p->tot_len; tcp_recved(tpcb, p->tot_len); pbuf_free(p); return ERR_OK; }
err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { /* do not read the packet if we are not in ESTABLISHED state */ if (!p) { tcp_close(tpcb); tcp_recv(tpcb, NULL); return ERR_OK; } /* indicate that the packet has been received */ tcp_recved(tpcb, p->len); if(!init) { /* read the packet (first should be just 4 bytes) */ char *pack; int j; pack = (char *)calloc(p->len, 1); for(j=0;j<p->len;j++) { pack[j] = *(unsigned char*)(p->payload + j); } if(((int)*(int *)pack) == (ENDIAN_FLIP(0xbabeface))) { if (tcp_sndbuf(tpcb) > 4) { err = tcp_write(tpcb, p->payload, 4, 1); tcp_output(tpcb); } else print("no space in tcp_sndbuf\n\r"); /* free the received pbuf */ pbuf_free(p); pcb = tpcb; init = 1; } } else { ret = 1; packet = p; } return ERR_OK; }
/** * Data has been received on this pcb. * For HTTP 1.0, this should normally only happen once (if the request fits in one packet). */ static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { err_t parsed = ERR_ABRT; struct http_state *hs = arg; LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: pcb=0x%08X pbuf=0x%08X err=%s\n", pcb, p, lwip_strerr(err))); if (p != NULL) { /* Inform TCP that we have taken the data. */ tcp_recved(pcb, p->tot_len); } if (hs == NULL) { /* be robust */ LWIP_DEBUGF(HTTPD_DEBUG, ("Error, http_recv: hs is NULL, abort\n")); http_close_conn(pcb, hs); return ERR_OK; } if ((err != ERR_OK) || (p == NULL)) { /* error or closed by other side */ if (p != NULL) { pbuf_free(p); } http_close_conn(pcb, hs); return ERR_OK; } if (hs->file == NULL) { parsed = http_parse_request(p, hs); } else { LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: already sending data\n")); } pbuf_free(p); if (parsed == ERR_OK) { LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: data %p len %ld\n", hs->file, hs->left)); http_send_data(pcb, hs); } else if (parsed == ERR_ABRT) { http_close_conn(pcb, hs); return ERR_OK; } return ERR_OK; }
void _tcp_flush(void *v) { TCP *es=v; if(es->pcb->snd_queuelen > TCP_SND_QUEUELEN-1) // !!!! pred vpisom preveri, ce ni queue ze poln tcp_output(es->pcb); // kratkih blokov (Nagle algoritem bo javil MEM error....) else if(es->io) { // sicer nadaljevanje... char c[256]; int k,n=0; if(es->rx) { // a je kaj za sprejem ??? struct pbuf *q; for(q=es->rx; q != NULL; q=es->rx) { // preskanirat je treba celo verigo pbuf n+=k=_buffer_push(es->io[0],q->payload, q->len); // push v io if(k < q->len) { pbuf_header(q,-k); // skrajsaj header break; } es->rx = es->rx->next; if (es->rx != NULL) pbuf_ref(es->rx); pbuf_free(q); } tcp_recved(es->pcb,n); // free raw input } n=_buffer_count(es->io[1]); // koliko je v buferju za izpis ... if(n > tcp_sndbuf(es->pcb)) // ne sme biti vec kot je placa na raw output .... n = tcp_sndbuf(es->pcb); if(n > 256) // ne sme bit vec kot 1024.... glej c[1024] n=256; if(n) { // ce je sploh kej ... struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, n , PBUF_POOL); if(p != NULL) { // ce je alokacija pbuf uspela n=_buffer_pull(es->io[1],c,n); // kopiraj pull vsebino v vmesni buffer pbuf_take(p,c,n); // formiraj pbuf if(es->tx) // verizi, ce je se kaj od prej.. pbuf_chain(es->tx,p); // else es->tx = p; // sicer nastavi nov pointer tcp_sent(es->pcb, TCP_sent); // set callback & send.. TCP_send(es->pcb, es); tcp_output(es->pcb); } } } }
static void tcp_echoserver_send(struct tcp_pcb *tpcb, struct tcp_echoserver_struct *es) { struct pbuf *ptr; err_t wr_err = ERR_OK; while ((wr_err == ERR_OK) && (es->p != NULL) && (es->p->len <= tcp_sndbuf(tpcb))) { ptr = es->p; wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1); if (wr_err == ERR_OK) { u16_t plen; plen = ptr->len; es->p = ptr->next; if(es->p != NULL) { pbuf_ref(es->p); } pbuf_free(ptr); /* Update tcp window size to be advertized : should be called when received data (with the amount plen) has been processed by the application layer */ tcp_recved(tpcb, plen); } else if(wr_err == ERR_MEM) { /* we are low on memory, try later / harder, defer to poll */ es->p = ptr; } else { /* other problem ?? */ } } }
//lwIP tcp_recv()函数的回调函数 err_t tcp_client_recv(void *arg,struct tcp_pcb *tpcb,struct pbuf *p,err_t err) { //arg参数可以由tcp_arg函数来设置。 int data_len = 0; struct pbuf *q; struct tcp_client_struct *es; err_t ret_err; //LWIP_ASSERT("arg != NULL",arg != NULL); es=(struct tcp_client_struct *)arg; if(p==NULL)//如果从服务器接收到空的数据帧就关闭连接 { ret_err=ERR_OK; }else if(err!= ERR_OK)//当接收到一个非空的数据帧,但是err!=ERR_OK { if(p) pbuf_free(p);//释放接收pbuf ret_err=err; }else{ if(p!=NULL)//当处于连接状态并且接收到的数据不为空时 { memset(tcp_client_recvbuf,0,512); //数据接收缓冲区清零 for(q=p;q!=NULL;q=q->next) //遍历完整个pbuf链表 { //判断要拷贝到TCP_CLIENT_RX_BUFSIZE中的数据是否大于TCP_CLIENT_RX_BUFSIZE的剩余空间,如果大于 //的话就只拷贝TCP_CLIENT_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 if(q->len > (512-data_len)) memcpy(tcp_client_recvbuf+data_len,q->payload,(512-data_len));//拷贝数据 else memcpy(tcp_client_recvbuf+data_len,q->payload,q->len); data_len += q->len; if(data_len > 512) break; //超出TCP客户端接收数组,跳出 } tcp_recved(tpcb,p->tot_len);//用于获取接收数据,通知LWIP可以获取更多数据 pbuf_free(p); //释放内存 ret_err=ERR_OK; printf(tcp_client_recvbuf);//打印出接受的数据 } } //tcp_client_connection_close(tpcb);//关闭连接 return ret_err; }
/** * Data has been received on this pcb. */ err_t http_simple_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { if (p != NULL){ /* Inform TCP that we have taken the data. */ tcp_recved(pcb, p->tot_len); } if (err != ERR_OK) { /* error or closed by other side */ if (p != NULL) { pbuf_free(p); } http_simple_close_conn(pcb); return ERR_OK; } char *data; int i; /* If we got a NULL pbuf in p, the remote end has closed the connection. */ err_t request_supported = ERR_ARG; if(p != NULL) { /* The payload pointer in the pbuf contains the data in the TCP segment. */ data = p->payload; /* @todo: support POST, check p->len */ if (strncmp(data, "GET ", 4) == 0) { request_supported = ERR_OK; for(i = 0; i < 40; i++) { if (((char *)data + 4)[i] == ' ' || ((char *)data + 4)[i] == '\r' || ((char *)data + 4)[i] == '\n') { ((char *)data + 4)[i] = 0; } } } if (request_supported == ERR_OK) tcp_write(pcb, indexdata, sizeof(indexdata), 0); /* Free the pbuf. */ pbuf_free(p); } http_simple_close_conn(pcb); return ERR_OK; }
/* TCP 客户端接收到PC发送过来的数据,tcp_client_recv为数据处理*/ static err_t tcp_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { u8 temp[17]; printf("TCP client receive 0: %s\n",p->payload); if(err == ERR_OK && p != NULL) { /* Inform TCP that we have taken the data. */ tcp_recved(pcb, p->tot_len); tcp_write(pcb,p->payload,p->tot_len,0); printf("TCP client receive : %s\n",p->payload); MEMCPY(temp,p->payload,14); printf("TCP client receive : %d\n",temp[9]); } else if(err == ERR_OK && p == NULL) { tcp_close(pcb); TcpClient.connected=0; } pbuf_free(p); return ERR_OK; }
/** * @brief This function is the implementation for tcp_recv LwIP callback * @param arg: pointer on a argument for the tcp_pcb connection * @param tpcb: pointer on the tcp_pcb connection * @param pbuf: pointer on the received pbuf * @param err: error information regarding the reveived pbuf * @retval err_t: error code */ static err_t TCP_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { err_t ret_err; TCP *es; LWIP_ASSERT("arg != NULL",arg != NULL); es = (TCP *)arg; if (p == NULL) { /* if we receive an empty tcp frame from client => close connection */ es->state = ES_CLOSING; /* remote host closed connection */ if (es->tx == NULL) { TCP_close(tpcb, es); /* we're done sending, close connection */ } else { /* we're not done yet */ tcp_sent(tpcb, TCP_sent); /* send remaining data*/ TCP_send(tpcb, es); /* acknowledge received packet */ } ret_err = ERR_OK; } else if(err != ERR_OK) { /* else : a non empty frame was received from client but for some reason err != ERR_OK */ if (p != NULL) { es->tx = NULL; pbuf_free(p); /* free received pbuf*/ } ret_err = err; } else if(es->state == ES_ACCEPTED) { /* first data chunk in p->payload */ es->state = ES_RECEIVED; es->rx = p; /* store reference to incoming pbuf (chain) */ ret_err = ERR_OK; } else if (es->state == ES_RECEIVED) { if (es->rx) pbuf_chain(es->rx,p); else es->rx = p; ret_err = ERR_OK; } else { /* data received when connection already closed */ tcp_recved(tpcb, p->tot_len); /* Acknowledge data reception */ es->tx = NULL; pbuf_free(p); /* free pbuf and do nothing */ ret_err = ERR_OK; } return ret_err; }
// Helper function for recv/recvfrom to handle TCP packets STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { if (socket->connected == 3) { return 0; } if (socket->incoming == NULL) { if (socket->timeout != -1) { for (mp_uint_t retries = socket->timeout / 100; retries--;) { mp_hal_delay_ms(100); if (socket->incoming != NULL) break; } if (socket->incoming == NULL) { *_errno = ETIMEDOUT; return -1; } } else { while (socket->incoming == NULL) { mp_hal_delay_ms(100); } } } struct pbuf *p = (struct pbuf *)socket->incoming; if (socket->leftover_count == 0) { socket->leftover_count = p->tot_len; } u16_t result = pbuf_copy_partial(p, buf, ((socket->leftover_count >= len) ? len : socket->leftover_count), (p->tot_len - socket->leftover_count)); if (socket->leftover_count > len) { // More left over... socket->leftover_count -= len; } else { pbuf_free(p); socket->incoming = NULL; socket->leftover_count = 0; } tcp_recved((struct tcp_pcb *)socket->pcb, result); return (mp_uint_t) result; }
int EthernetClient::readLocked() { INT_PROTECT_INIT(oldLevel); /* protect the code from preemption of the ethernet interrupt servicing */ INT_PROTECT(oldLevel); if (!available()) { INT_UNPROTECT(oldLevel); return -1; } uint8_t *buf = (uint8_t *) cs->p->payload; uint8_t b = buf[cs->read]; cs->read++; /* Indicate data was received only if still connected */ if (cs->cpcb) { tcp_recved((tcp_pcb*)cs->cpcb, cs->read); } /* Read any data still in the buffer regardless of connection state */ if ((cs->read == cs->p->len) && cs->p->next) { cs->read = 0; struct pbuf * q = (pbuf*)cs->p; cs->p = cs->p->next; /* Increase ref count on p->next * 1->3->1->etc */ pbuf_ref((pbuf*)cs->p); /* Free p which decreases ref count of the chain * and frees up to p->next in this case * ...->1->1->etc */ pbuf_free(q); } else if (cs->read == cs->p->len) { cs->read = 0; pbuf_free((pbuf*)cs->p); cs->p = NULL; } INT_UNPROTECT(oldLevel); return b; }
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 yee_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { if(err == ERR_OK && p != NULL) { /* Inform TCP that we have taken the data. */ tcp_recved(pcb, p->tot_len); //xdbug_buf("RECV HTTP RESPONSE",p->payload,p->tot_len); //tcp_write(pcb,p->payload,p->tot_len,0); #ifdef DEBUG_ON printf("<-------------[%s]",p->payload); #endif process_recv_html(p->payload); } else if(err == ERR_OK && p == NULL) { tcp_close(pcb); YeeClient.connected=0; } pbuf_free(p); return ERR_OK; }
err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { /* do not read the packet if we are not in ESTABLISHED state */ if (!p) { print("Connection lost, reseting buffers ..."); tcp_close(tpcb); tcp_recv(tpcb, NULL); print("Done.\r\n"); return ERR_OK; } print("Processing command packet.\r\n"); /* indicate that the packet has been received */ tcp_recved(tpcb, p->len); /* echo back the payload */ /* in this case, we assume that the payload is < TCP_SND_BUF */ if (tcp_sndbuf(tpcb) > p->len) { //err = tcp_write(tpcb, p->payload, p->len, 1); xil_printf("\tSetting IO state to: %08x."); // TODO: set io } else { print("ERROR: no space in tcp_sndbuf\n\r"); } /* free the received pbuf */ pbuf_free(p); return ERR_OK; }
err_t LwipNetTcpSocket::recvCb(tcp_pcb* tpcb, pbuf *p, err_t err) { //Store pbuf ptr // DBG("Receive CB with err = %d & len = %d.\n", err, p->tot_len); // tcp_recved( (tcp_pcb*) m_pPcb, p->tot_len); //Acknowledge the reception if(err) { queueEvent(NETTCPSOCKET_ERROR); return ERR_OK; //FIXME: More robust error handling there } else if(!p) { DBG("NetTcpSocket %p - Connection closed by remote host (LwipNetTcpSocket::recvCb).\n", (void*)this); //Buf is NULL, that means that the connection has been closed by remote host //FIX: 27/05/2010: We do not want to deallocate the socket while some data might still be readable //REMOVED: close(); //However we do not want to close the socket yet queueEvent(NETTCPSOCKET_DISCONNECTED); return ERR_OK; } //We asserted that p is a valid pointer //New data processing tcp_recved( tpcb, p->tot_len); //Acknowledge the reception if(!m_pReadPbuf) { m_pReadPbuf = p; queueEvent(NETTCPSOCKET_READABLE); } else { pbuf_cat((pbuf*)m_pReadPbuf, p); //m_pReadPbuf is not empty, tail p to it and drop our ref //No need to queue an event in that case since the read buf has not been processed yet } return ERR_OK; }