2023-05-03 14:01:32 +03:00
|
|
|
|
/*
|
|
|
|
|
|
* eth_udp_client.cpp
|
|
|
|
|
|
*
|
2024-02-21 10:41:56 +03:00
|
|
|
|
* Created on: 15 апреля. 2023 год.
|
2023-05-03 14:01:32 +03:00
|
|
|
|
* Author: sychev
|
|
|
|
|
|
*/
|
2023-06-26 18:22:30 +03:00
|
|
|
|
#include "free_rtos/ethernet_ip/eth_udp_client.hpp"
|
|
|
|
|
|
#include "free_rtos/base/swap.h"
|
|
|
|
|
|
#include "free_rtos/ethernet_ip/eth_ip_types.h"
|
|
|
|
|
|
#include "free_rtos/ethernet_ip/eth_checksum.h"
|
|
|
|
|
|
#include "free_rtos/ethernet_ip/eth_ip_prots_id.h"
|
2023-05-03 14:01:32 +03:00
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-10-26 13:47:28 +03:00
|
|
|
|
free_rtos::EthUpdClient::EthUpdClient(EthIpIface& ip_iface, EthArpIface& arp,
|
|
|
|
|
|
TEthMacPorts port_id, uint16_t port_dst_be, uint16_t port_src_be,
|
2023-05-03 14:01:32 +03:00
|
|
|
|
bool use_chksum) :
|
|
|
|
|
|
port_dst_be_{port_dst_be},
|
|
|
|
|
|
port_src_be_{port_src_be},
|
|
|
|
|
|
use_checksum_{use_chksum},
|
|
|
|
|
|
ip_iface_{ip_iface},
|
2023-10-26 13:47:28 +03:00
|
|
|
|
arp_{arp},
|
2023-05-03 14:01:32 +03:00
|
|
|
|
port_id_{port_id}
|
2023-10-17 17:08:48 +03:00
|
|
|
|
{ }
|
2023-05-03 14:01:32 +03:00
|
|
|
|
|
2023-10-24 14:02:04 +03:00
|
|
|
|
void free_rtos::EthUpdClient::put_data(uint8_t * p_data, uint32_t len)
|
2023-05-03 14:01:32 +03:00
|
|
|
|
{
|
|
|
|
|
|
if ((p_data == nullptr) || (len == 0)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-20 10:25:51 +03:00
|
|
|
|
UDPToggle toggle = in_toggle_.exchange(UDPToggle::UDP_BUSY);
|
2023-10-17 17:08:48 +03:00
|
|
|
|
|
2023-10-20 10:25:51 +03:00
|
|
|
|
std::vector<uint8_t>& buff = buff_[toggle];
|
2023-10-19 15:11:51 +03:00
|
|
|
|
uint32_t new_size = buff.size() + len;
|
2023-10-11 10:23:04 +03:00
|
|
|
|
|
2023-10-19 15:11:51 +03:00
|
|
|
|
if(new_size > max_buf_size) {
|
2023-10-20 10:25:51 +03:00
|
|
|
|
in_toggle_.exchange(toggle);
|
2023-10-11 10:23:04 +03:00
|
|
|
|
|
2023-10-24 14:02:04 +03:00
|
|
|
|
EnetAppUtils_print("Warning ! UDP client buffer overflow !\r\n");
|
2023-10-19 15:11:51 +03:00
|
|
|
|
return;
|
2023-05-03 14:01:32 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-19 15:11:51 +03:00
|
|
|
|
buff.reserve(new_size);
|
|
|
|
|
|
buff.insert(buff.end(), p_data, p_data + len);
|
|
|
|
|
|
|
2023-10-20 10:25:51 +03:00
|
|
|
|
in_toggle_.exchange(toggle);
|
2023-05-03 14:01:32 +03:00
|
|
|
|
rx_sem_.post();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-26 10:21:41 +03:00
|
|
|
|
size_t free_rtos::EthUpdClient::get_data(uint8_t * p_data, uint32_t len)
|
2023-05-03 14:01:32 +03:00
|
|
|
|
{
|
2023-10-20 10:25:51 +03:00
|
|
|
|
std::vector<uint8_t>& buff = buff_[out_toggle_];
|
2023-10-26 10:21:41 +03:00
|
|
|
|
size_t size = buff.size();
|
2023-05-03 14:01:32 +03:00
|
|
|
|
|
2023-10-19 15:11:51 +03:00
|
|
|
|
if (size > len) {
|
|
|
|
|
|
size = len;
|
|
|
|
|
|
}
|
2023-10-17 17:08:48 +03:00
|
|
|
|
|
2023-10-19 15:11:51 +03:00
|
|
|
|
auto item_begin = buff.begin();
|
|
|
|
|
|
auto item_end = item_begin + size;
|
2023-10-17 17:08:48 +03:00
|
|
|
|
|
2023-10-19 15:11:51 +03:00
|
|
|
|
std::copy(item_begin, item_end, p_data);
|
|
|
|
|
|
buff.erase(item_begin, item_end);
|
|
|
|
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
|
}
|
2023-10-17 17:08:48 +03:00
|
|
|
|
|
2023-10-19 15:11:51 +03:00
|
|
|
|
bool free_rtos::EthUpdClient::capture_buffer()
|
|
|
|
|
|
{
|
2023-10-20 10:25:51 +03:00
|
|
|
|
UDPToggle desired = out_toggle_;
|
|
|
|
|
|
UDPToggle expected = static_cast<UDPToggle>((desired + 1)%UDPToggle::UDP_BUF_NUM);
|
2023-05-03 14:01:32 +03:00
|
|
|
|
|
2023-10-20 10:25:51 +03:00
|
|
|
|
if(in_toggle_.compare_exchange_weak(expected, desired) == false) {
|
2023-10-26 10:21:41 +03:00
|
|
|
|
return false;
|
2023-10-19 15:11:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-20 10:25:51 +03:00
|
|
|
|
out_toggle_ = expected;
|
2023-10-19 15:11:51 +03:00
|
|
|
|
|
2023-10-26 10:21:41 +03:00
|
|
|
|
return true;
|
2023-10-19 15:11:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t free_rtos::EthUpdClient::get_data_size()
|
|
|
|
|
|
{
|
2023-10-26 10:21:41 +03:00
|
|
|
|
size_t size = buff_[out_toggle_].size();
|
|
|
|
|
|
|
|
|
|
|
|
if (size == 0) {
|
|
|
|
|
|
if(capture_buffer() != false) {
|
|
|
|
|
|
size = buff_[out_toggle_].size();
|
2023-10-19 15:11:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-26 10:21:41 +03:00
|
|
|
|
return size;
|
2023-05-03 14:01:32 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-07-17 17:51:18 +03:00
|
|
|
|
int32_t free_rtos::EthUpdClient::read(uint8_t * p_data, uint32_t len)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((p_data == nullptr) || (len == 0)) {
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-26 10:21:41 +03:00
|
|
|
|
if(buff_[out_toggle_].size() == 0) {
|
|
|
|
|
|
while (capture_buffer() == false) {
|
2023-10-19 15:11:51 +03:00
|
|
|
|
rx_sem_.pend();
|
|
|
|
|
|
}
|
2023-07-17 17:51:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return get_data(p_data, len);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int32_t free_rtos::EthUpdClient::read_async(uint8_t * p_data, uint32_t len)
|
|
|
|
|
|
{
|
|
|
|
|
|
if ((p_data == nullptr) || (len == 0)) {
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-26 10:21:41 +03:00
|
|
|
|
if (buff_[out_toggle_].size() == 0) {
|
|
|
|
|
|
if(capture_buffer() == false) {
|
2023-10-19 15:11:51 +03:00
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2023-07-17 17:51:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return get_data(p_data, len);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-05-03 14:01:32 +03:00
|
|
|
|
void free_rtos::EthUpdClient::clear()
|
|
|
|
|
|
{
|
2023-10-20 10:25:51 +03:00
|
|
|
|
buff_[out_toggle_].clear();
|
2023-10-26 10:21:41 +03:00
|
|
|
|
|
|
|
|
|
|
while (capture_buffer() == false) {
|
|
|
|
|
|
rx_sem_.pend();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
buff_[out_toggle_].clear();
|
2023-05-03 14:01:32 +03:00
|
|
|
|
}
|
2023-10-26 10:21:41 +03:00
|
|
|
|
|
|
|
|
|
|
bool free_rtos::EthUpdClient::write(uint32_t ip_dst_be, uint8_t * p_data, uint32_t len)
|
|
|
|
|
|
{
|
|
|
|
|
|
UDPHandlerArgs udpHandlerArgs;
|
2023-10-26 13:47:28 +03:00
|
|
|
|
uint64_t mac_dst{0x0000000000000000};
|
2023-10-26 10:21:41 +03:00
|
|
|
|
|
|
|
|
|
|
if (ip_dst_be == 0) {
|
|
|
|
|
|
ip_dst_be = src_ip_;
|
2023-10-26 13:47:28 +03:00
|
|
|
|
mac_dst = src_mac_;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (arp_.getMacAddr(ip_dst_be, mac_dst) == false) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2023-10-26 10:21:41 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//udpHandlerArgs.buffer = nullptr;
|
|
|
|
|
|
udpHandlerArgs.port_id = port_id_;
|
|
|
|
|
|
//udpHandlerArgs.stack_handler = nullptr;
|
|
|
|
|
|
udpHandlerArgs.ip_header_len = sizeof(TUdpHeader);
|
|
|
|
|
|
udpHandlerArgs.ip_data_len = len;
|
|
|
|
|
|
udpHandlerArgs.dest_ip = ip_dst_be;
|
2023-10-26 13:47:28 +03:00
|
|
|
|
udpHandlerArgs.dest_mac = mac_dst;
|
2023-10-26 10:21:41 +03:00
|
|
|
|
udpHandlerArgs.ip_prot_id = IP_PROT_UDP;
|
|
|
|
|
|
udpHandlerArgs.ip_handler = this;
|
|
|
|
|
|
udpHandlerArgs.p_data = p_data;
|
|
|
|
|
|
|
|
|
|
|
|
return ip_iface_.send(udpHandlerArgs);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-26 17:59:51 +03:00
|
|
|
|
uint16_t free_rtos::EthUpdClient::fill_udp_header(UDPHandlerArgs& udpHandlerArgs) {
|
|
|
|
|
|
uint16_t udp_len = udpHandlerArgs.ip_header_len + udpHandlerArgs.ip_data_len;
|
|
|
|
|
|
TUdpHeader * udp_hdr = (TUdpHeader *)(udpHandlerArgs.buffer + sizeof(TEthFrameHeader) + sizeof(TIpHeader));
|
|
|
|
|
|
TUdpHeader udp_header;
|
|
|
|
|
|
|
|
|
|
|
|
udp_header.Src_port = port_src_be_;
|
|
|
|
|
|
udp_header.Dst_port = port_dst_be_;
|
|
|
|
|
|
udp_header.Length = BASE_SWAP16(udp_len);
|
|
|
|
|
|
udp_header.Chk_sum = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (use_checksum_) {
|
|
|
|
|
|
uint32_t self_ip = ip_iface_.getSelfIpAddr();
|
|
|
|
|
|
uint32_t chk_sum32 = 0;
|
|
|
|
|
|
uint8_t * const dst_ip = (uint8_t *)&udpHandlerArgs.dest_ip;
|
|
|
|
|
|
uint8_t * const src_ip = (uint8_t *)&self_ip;
|
|
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < ETH_IP_ADDR_LEN; j += 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
chk_sum32 += ((uint16_t)dst_ip[j] << 8) + dst_ip[j+1];
|
|
|
|
|
|
chk_sum32 += ((uint16_t)src_ip[j] << 8) + src_ip[j+1];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
chk_sum32 += IP_PROT_UDP + udp_len;
|
|
|
|
|
|
|
|
|
|
|
|
//uint16_t chk_sum16 = eth_calcChksum2(chk_sum32, (uint8_t *)&udpHandlerArgs.udp_header, sizeof(TUdpHeader), (uint8_t *)udpHandlerArgs.p_data, udpHandlerArgs.ip_data_len);
|
2024-02-21 10:41:56 +03:00
|
|
|
|
//Расчет контрольной суммы совмещен с копированием данных !
|
2023-10-26 17:59:51 +03:00
|
|
|
|
uint16_t chk_sum16 = eth_calcChksum3(udp_hdr, chk_sum32,
|
|
|
|
|
|
&udp_header, sizeof(TUdpHeader),
|
|
|
|
|
|
udpHandlerArgs.p_data, udpHandlerArgs.ip_data_len);
|
|
|
|
|
|
|
|
|
|
|
|
udp_hdr->Chk_sum = BASE_SWAP16(chk_sum16);
|
2023-12-08 14:41:58 +03:00
|
|
|
|
} else {
|
|
|
|
|
|
uint8_t* udp_data = udpHandlerArgs.buffer + sizeof(TEthFrameHeader) + sizeof(TIpHeader) + sizeof(TUdpHeader);
|
|
|
|
|
|
|
|
|
|
|
|
*udp_hdr = udp_header;
|
|
|
|
|
|
memcpy(udp_data, udpHandlerArgs.p_data, udpHandlerArgs.ip_data_len);
|
2023-10-26 17:59:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-08 14:41:58 +03:00
|
|
|
|
return sizeof(TUdpHeader) + udpHandlerArgs.ip_data_len;
|
2023-10-26 17:59:51 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-10-26 10:21:41 +03:00
|
|
|
|
uint16_t free_rtos::EthUpdClient::Sender(HandlerArgs& handlerArgs, size_t scatter_segment)
|
|
|
|
|
|
{
|
|
|
|
|
|
UDPHandlerArgs& udpHandlerArgs = static_cast<UDPHandlerArgs&>(handlerArgs); // downcasting back to derived type
|
|
|
|
|
|
|
2023-10-26 17:59:51 +03:00
|
|
|
|
fill_udp_header(udpHandlerArgs);
|
2023-10-26 10:21:41 +03:00
|
|
|
|
|
2023-12-08 14:41:58 +03:00
|
|
|
|
return sizeof(TUdpHeader) + udpHandlerArgs.ip_data_len;
|
2023-10-24 14:02:04 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int32_t free_rtos::EthUpdClient::Process(uint8_t * p_data, uint32_t len)
|
|
|
|
|
|
{
|
|
|
|
|
|
put_data(p_data, len);
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|