int UIPClient::read(uint8_t *buf, size_t size) { if (*this) { int remain = size; memhandle* p = &data->packets_in[0]; if (*p == NOBLOCK) return 0; int read; do { read = UIPEthernet.network.readPacket(*p,0,buf+size-remain,remain); if (read == UIPEthernet.network.blockSize(*p)) { remain -= read; _eatBlock(p); if (_uip_conn && uip_stopped(_uip_conn) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) data->state |= UIP_CLIENT_RESTART; if (*p == NOBLOCK) return size-remain; } else { UIPEthernet.network.resizeBlock(*p,read); break; } } while(remain > 0); return size; } return -1; }
int UIPClient::read(uint8_t *buf, size_t size) { if (*this) { uint16_t remain = size; if (data->packets_in[0] == NOBLOCK) return 0; uint16_t read; do { read = Enc28J60Network::readPacket(data->packets_in[0],0,buf+size-remain,remain); if (read == Enc28J60Network::blockSize(data->packets_in[0])) { remain -= read; _eatBlock(&data->packets_in[0]); if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) data->state |= UIP_CLIENT_RESTART; if (data->packets_in[0] == NOBLOCK) { if (data->state & UIP_CLIENT_REMOTECLOSED) { data->state = 0; data = NULL; } return size-remain; } } else { Enc28J60Network::resizeBlock(data->packets_in[0],read); break; } } while(remain > 0); return size; } return -1; }
void UIPClient::uip_callback(uip_tcp_appstate_t *s) { uip_userdata_t *u = (uip_userdata_t *) s->user; if (!u && uip_connected()) { #ifdef UIPETHERNET_DEBUG_CLIENT Serial.println("UIPClient uip_connected"); #endif // We want to store some data in our connections, so allocate some space // for it. The connection_data struct is defined in a separate .h file, // due to the way the Arduino IDE works. (typedefs come after function // definitions.) u = (uip_userdata_t*) malloc(sizeof(uip_userdata_t)); if (u) { memset(u,0,sizeof(uip_userdata_t)); s->user = u; } } if (u) { if (uip_newdata()) { #ifdef UIPETHERNET_DEBUG_CLIENT Serial.print("UIPClient uip_newdata, uip_len:"); Serial.println(uip_len); #endif if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_CLOSED))) { memhandle newPacket = UIPEthernet.network.allocBlock(uip_len); if (newPacket != NOBLOCK) { memhandle* p = _currentBlock(&u->packets_in[0]); //if it's not the first packet if (*p != NOBLOCK) { uint8_t slot = p - &u->packets_in[0]; if (slot < UIP_SOCKET_NUMPACKETS-1) p++; //if this is the last slot stop this connection if (slot >= UIP_SOCKET_NUMPACKETS-2) { uip_stop(); //if there's no free slot left omit loosing this packet and (again) stop this connection if (slot == UIP_SOCKET_NUMPACKETS-1) goto reject_newdata; } } UIPEthernet.network.copyPacket(newPacket,0,UIPEthernet.in_packet,((uint8_t*)uip_appdata)-uip_buf,uip_len); *p = newPacket; goto finish_newdata; } reject_newdata: UIPEthernet.packetstate &= ~UIPETHERNET_FREEPACKET; uip_stop(); } } finish_newdata: if (u->state & UIP_CLIENT_RESTART) { u->state &= ~UIP_CLIENT_RESTART; uip_restart(); } // If the connection has been closed, save received but unread data. if (uip_closed() || uip_timedout()) { #ifdef UIPETHERNET_DEBUG_CLIENT Serial.println("UIPClient uip_closed"); #endif // drop outgoing packets not sent yet: _flushBlocks(&u->packets_out[0]); if (u->packets_in[0] != NOBLOCK) { uip_userdata_closed_t** closed_conn_data = &UIPClient::closed_conns[0]; for (uip_socket_ptr i = 0; i < UIP_CONNS; i++) { if (!*closed_conn_data) { *closed_conn_data = (uip_userdata_closed_t*)u; (*closed_conn_data)->lport = uip_conn->lport; break; } closed_conn_data++; } } u->state |= UIP_CLIENT_CLOSED; // disassociate appdata. s->user = NULL; goto nodata; } if (uip_acked()) { #ifdef UIPETHERNET_DEBUG_CLIENT Serial.println("UIPClient uip_acked"); #endif _eatBlock(&u->packets_out[0]); } if (uip_poll() || uip_rexmit()) { #ifdef UIPETHERNET_DEBUG_CLIENT Serial.println("UIPClient uip_poll"); #endif memhandle p = u->packets_out[0]; if (p != NOBLOCK) { if (u->packets_out[1] == NOBLOCK) { uip_len = u->out_pos; if (uip_len > 0) { UIPEthernet.network.resizeBlock(p,0,uip_len); } } else uip_len = UIPEthernet.network.blockSize(p); if (uip_len > 0) { UIPEthernet.uip_hdrlen = ((uint8_t*)uip_appdata)-uip_buf; UIPEthernet.uip_packet = UIPEthernet.network.allocBlock(UIPEthernet.uip_hdrlen+uip_len); if (UIPEthernet.uip_packet != NOBLOCK) { UIPEthernet.network.copyPacket(UIPEthernet.uip_packet,UIPEthernet.uip_hdrlen,p,0,uip_len); UIPEthernet.packetstate |= UIPETHERNET_SENDPACKET; uip_send(uip_appdata,uip_len); } return; } } } // don't close connection unless all outgoing packets are sent if (u->state & UIP_CLIENT_CLOSE) { #ifdef UIPETHERNET_DEBUG_CLIENT Serial.print("UIPClient state UIP_CLIENT_CLOSE"); #endif if (u->packets_out[0] == NOBLOCK) { #ifdef UIPETHERNET_DEBUG_CLIENT Serial.print("UIPClient state UIP_CLIENT_CLOSE -> free userdata"); #endif free(u); s->user = NULL; uip_close(); } else uip_stop(); } } nodata: UIPEthernet.uip_packet = NOBLOCK; uip_len=0; }