diff --git a/examples/UDP_Client/UDP_Client.ino b/examples/UDP_Client/UDP_Client.ino index 4fea78b..55929ef 100644 --- a/examples/UDP_Client/UDP_Client.ino +++ b/examples/UDP_Client/UDP_Client.ino @@ -29,8 +29,6 @@ static T1SMacSettings const t1s_default_mac_settings; static IPAddress const UDP_SERVER_IP_ADDR = {192, 168, 42, 100 + 0}; static uint16_t const UDP_CLIENT_PORT = 8889; static uint16_t const UDP_SERVER_PORT = 8888; -static uint8_t udp_tx_msg_buf[256] = {0}; -static uint8_t udp_rx_msg_buf[256] = {0}; /************************************************************************************** * GLOBAL VARIABLES @@ -123,6 +121,7 @@ void loop() prev_udp_packet_sent = now; /* Prepare UDP packet. */ + uint8_t udp_tx_msg_buf[256] = {0}; int const tx_packet_size = snprintf((char *)udp_tx_msg_buf, sizeof(udp_tx_msg_buf), "Single-Pair Ethernet / 10BASE-T1S: packet cnt = %d", tx_packet_cnt); /* Send a UDP packet to the UDP server. */ @@ -143,7 +142,7 @@ void loop() int const rx_packet_size = udp_client.parsePacket(); if (rx_packet_size) { - /* Receive incoming UDP packets. */ + /* Print some metadata from received UDP packet. */ Serial.print("Received "); Serial.print(rx_packet_size); Serial.print(" bytes from "); @@ -152,15 +151,27 @@ void loop() Serial.print(udp_client.remotePort()); Serial.println(); - int const bytes_read = udp_client.read(udp_rx_msg_buf, sizeof(udp_rx_msg_buf)); - if (bytes_read > 0) { - udp_rx_msg_buf[bytes_read] = 0; - } Serial.print("["); Serial.print(millis()); Serial.print("] UDP_Client received packet content: \""); - Serial.print(reinterpret_cast(udp_rx_msg_buf)); + + /* Read from received UDP packet. */ + size_t const UDP_RX_MSG_BUF_SIZE = 16 + 1; /* Reserve the last byte for the '\0' termination. */ + uint8_t udp_rx_msg_buf[UDP_RX_MSG_BUF_SIZE] = {0}; + int bytes_read = udp_client.read(udp_rx_msg_buf, UDP_RX_MSG_BUF_SIZE - 1); + while(bytes_read != 0) + { + /* Print received data to Serial. */ + udp_rx_msg_buf[bytes_read] = '\0'; /* Terminate buffer so that we can print it as a C-string. */ + Serial.print(reinterpret_cast(udp_rx_msg_buf)); + + /* Continue reading. */ + bytes_read = udp_client.read(udp_rx_msg_buf, UDP_RX_MSG_BUF_SIZE - 1); + } Serial.println("\""); + + /* Finish reading the current packet. */ + udp_client.flush(); } } diff --git a/examples/UDP_Server/UDP_Server.ino b/examples/UDP_Server/UDP_Server.ino index 701c81c..a6b446c 100644 --- a/examples/UDP_Server/UDP_Server.ino +++ b/examples/UDP_Server/UDP_Server.ino @@ -33,7 +33,6 @@ static T1SPlcaSettings const t1s_plca_settings{T1S_PLCA_NODE_ID}; static T1SMacSettings const t1s_default_mac_settings; static uint16_t const UDP_SERVER_LOCAL_PORT = 8888; -static uint8_t udp_rx_msg_buf[256] = {0}; /************************************************************************************** * GLOBAL VARIABLES @@ -119,29 +118,50 @@ void loop() } /* Check for incoming UDP packets. */ - int const packet_size = udp_server.parsePacket(); - if (packet_size) + int const rx_packet_size = udp_server.parsePacket(); + if (rx_packet_size) { - /* Receive incoming UDP packets. */ + std::vector udp_tx_buf; + IPAddress const destination_ip = udp_server.remoteIP(); + uint16_t const destination_port = udp_server.remotePort(); + + /* Print some metadata from received UDP packet. */ Serial.print("Received "); - Serial.print(packet_size); + Serial.print(rx_packet_size); Serial.print(" bytes from "); Serial.print(udp_server.remoteIP()); Serial.print(" port "); Serial.print(udp_server.remotePort()); Serial.println(); - int const bytes_read = udp_server.read(udp_rx_msg_buf, sizeof(udp_rx_msg_buf)); - if (bytes_read > 0) { - udp_rx_msg_buf[bytes_read] = 0; + Serial.print("["); + Serial.print(millis()); + Serial.print("] UDP_Client received packet content: \""); + + /* Read from received UDP packet. */ + size_t const UDP_RX_MSG_BUF_SIZE = 16 + 1; /* Reserve the last byte for the '\0' termination. */ + uint8_t udp_rx_msg_buf[UDP_RX_MSG_BUF_SIZE] = {0}; + int bytes_read = udp_server.read(udp_rx_msg_buf, UDP_RX_MSG_BUF_SIZE - 1); + while(bytes_read != 0) + { + /* Copy received data into transmit buffer for echo functionality. */ + std::copy(udp_rx_msg_buf, udp_rx_msg_buf + bytes_read, std::back_inserter(udp_tx_buf)); + + /* Print received data to Serial. */ + udp_rx_msg_buf[bytes_read] = '\0'; /* Terminate buffer so that we can print it as a C-string. */ + Serial.print(reinterpret_cast(udp_rx_msg_buf)); + + /* Continue reading. */ + bytes_read = udp_server.read(udp_rx_msg_buf, UDP_RX_MSG_BUF_SIZE - 1); } - Serial.print("UDP_Server received packet content: \""); - Serial.print(reinterpret_cast(udp_rx_msg_buf)); Serial.println("\""); + /* Finish reading the current packet. */ + udp_server.flush(); + /* Send back a reply, to the IP address and port we got the packet from. */ - udp_server.beginPacket(udp_server.remoteIP(), udp_server.remotePort()); - udp_server.write((const uint8_t *)udp_rx_msg_buf, packet_size); + udp_server.beginPacket(destination_ip, destination_port); + udp_server.write(udp_tx_buf.data(), udp_tx_buf.size()); udp_server.endPacket(); } } diff --git a/src/Arduino_10BASE_T1S_UDP.cpp b/src/Arduino_10BASE_T1S_UDP.cpp index 23b77ab..0e46c00 100644 --- a/src/Arduino_10BASE_T1S_UDP.cpp +++ b/src/Arduino_10BASE_T1S_UDP.cpp @@ -26,8 +26,6 @@ static void lwIp_udp_raw_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, co Arduino_10BASE_T1S_UDP::Arduino_10BASE_T1S_UDP() : _udp_pcb{nullptr} -, _remote_ip{0,0,0,0} -, _remote_port{0} , _send_to_ip{0,0,0,0} , _send_to_port{0} { @@ -131,77 +129,99 @@ size_t Arduino_10BASE_T1S_UDP::write(uint8_t data) size_t Arduino_10BASE_T1S_UDP::write(const uint8_t * buffer, size_t size) { - _tx_data.reserve(_tx_data.size() + size); std::copy(buffer, buffer + size, std::back_inserter(_tx_data)); return size; } int Arduino_10BASE_T1S_UDP::parsePacket() { - return available(); + if (_rx_pkt_list.size()) + return _rx_pkt_list.front()->totalSize(); + else + return 0; } int Arduino_10BASE_T1S_UDP::available() { - return _rx_data.size(); + if (_rx_pkt_list.size()) + return _rx_pkt_list.front()->available(); + else + return 0; } int Arduino_10BASE_T1S_UDP::read() { - uint8_t const data = _rx_data.front(); - _rx_data.pop_front(); - return data; + if (_rx_pkt_list.size()) + return _rx_pkt_list.front()->read(); + else + return -1; } int Arduino_10BASE_T1S_UDP::read(unsigned char* buffer, size_t len) { - size_t bytes_read = 0; - for (; bytes_read < len && !_rx_data.empty(); bytes_read++) - { - buffer[bytes_read] = _rx_data.front(); - _rx_data.pop_front(); - } - return bytes_read; + if (_rx_pkt_list.size()) + return _rx_pkt_list.front()->read(buffer, len); + else + return -1; } int Arduino_10BASE_T1S_UDP::read(char* buffer, size_t len) { - return read((unsigned char*)buffer, len); + if (_rx_pkt_list.size()) + return _rx_pkt_list.front()->read(buffer, len); + else + return -1; } int Arduino_10BASE_T1S_UDP::peek() { - return _rx_data.front(); + if (_rx_pkt_list.size()) + return _rx_pkt_list.front()->peek(); + else + return -1; } void Arduino_10BASE_T1S_UDP::flush() { - /* Nothing to be done. */ + /* Drop packet from receive buffer. */ + if (_rx_pkt_list.size()) + _rx_pkt_list.pop_front(); } IPAddress Arduino_10BASE_T1S_UDP::remoteIP() { - return _remote_ip; + if (_rx_pkt_list.size()) + return _rx_pkt_list.front()->remoteIP(); + else + return IPAddress(); } uint16_t Arduino_10BASE_T1S_UDP::remotePort() { - return _remote_port; + if (_rx_pkt_list.size()) + return _rx_pkt_list.front()->remotePort(); + else + return 0; } void Arduino_10BASE_T1S_UDP::onUdpRawRecv(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, uint16_t port) { /* Obtain remote port and remote IP. */ - _remote_ip = IPAddress(ip4_addr1(addr), - ip4_addr2(addr), - ip4_addr3(addr), - ip4_addr4(addr)); - _remote_port = port; - - /* Copy data into buffer. */ - std::copy((uint8_t *)p->payload, - (uint8_t *)p->payload + p->len, - std::back_inserter(_rx_data)); + auto const remote_ip = IPAddress( + ip4_addr1(addr), + ip4_addr2(addr), + ip4_addr3(addr), + ip4_addr4(addr)); + auto const remote_port = port; + + /* Create UDP object. */ + auto const rx_pkt = std::make_shared( + remote_ip, + remote_port, + (uint8_t const *)p->payload, + p->len); + + _rx_pkt_list.push_back(rx_pkt); /* Free pbuf */ pbuf_free(p); diff --git a/src/Arduino_10BASE_T1S_UDP.h b/src/Arduino_10BASE_T1S_UDP.h index 60f775a..71eaa6c 100644 --- a/src/Arduino_10BASE_T1S_UDP.h +++ b/src/Arduino_10BASE_T1S_UDP.h @@ -14,8 +14,10 @@ * INCLUDE **************************************************************************************/ +#include #include #include +#include #include #include @@ -67,13 +69,74 @@ class Arduino_10BASE_T1S_UDP : public UDP private: + /* LWIP */ struct udp_pcb * _udp_pcb; - IPAddress _remote_ip; - uint16_t _remote_port; - std::deque _rx_data; - + /* UDP TRANSMISSION */ IPAddress _send_to_ip; uint16_t _send_to_port; std::vector _tx_data; + + /* UDP RECEPTION */ + class UdpRxPacket + { + private: + IPAddress const _remote_ip; + uint16_t const _remote_port; + size_t const _rx_data_len; + std::deque _rx_data; + + public: + UdpRxPacket( + IPAddress const remote_ip, + uint16_t const remote_port, + uint8_t const * p_data, + size_t const data_len) + : _remote_ip(remote_ip) + , _remote_port(remote_port) + , _rx_data_len(data_len) + , _rx_data(p_data, p_data + data_len) + { + } + + typedef std::shared_ptr SharedPtr; + + IPAddress remoteIP() const { return _remote_ip; } + uint16_t remotePort() const { return _remote_port; } + size_t totalSize() const { return _rx_data_len; } + + int available() + { + return _rx_data.size(); + } + + int read() + { + uint8_t const data = _rx_data.front(); + _rx_data.pop_front(); + return data; + } + + int read(unsigned char* buffer, size_t len) + { + size_t bytes_read = 0; + for (; bytes_read < len && !_rx_data.empty(); bytes_read++) + { + buffer[bytes_read] = _rx_data.front(); + _rx_data.pop_front(); + } + return bytes_read; + } + + int read(char* buffer, size_t len) + { + return read((unsigned char*)buffer, len); + } + + int peek() + { + return _rx_data.front(); + } + }; + std::list _rx_pkt_list; };