/* * eth_udp_client.cpp * * Created on: 15 мар. 2023 г. * Author: sychev */ #include "ethernet_ip/eth_udp_client.hpp" #include "base/swap.h" #include "ethernet_ip/eth_udp_types.h" #include "ethernet_ip/eth_ip_types.h" #include "ethernet_ip/eth_checksum.h" #include "ethernet_ip/eth_ip_prots_id.h" #include #include free_rtos::EthUpdClient::EthUpdClient(EthIpIface& ip_iface, TEthMacPorts port_id, uint16_t port_dst_be, uint16_t port_src_be, bool use_chksum) : port_dst_be_{port_dst_be}, port_src_be_{port_src_be}, use_checksum_{use_chksum}, ip_iface_{ip_iface}, port_id_{port_id} { } void free_rtos::EthUpdClient::put_data(uint32_t src_ip, uint8_t * p_data, uint32_t len) { if ((p_data == nullptr) || (len == 0)) { return; } /// Копируем данные в буфер { LockGuard lock(rx_mut_); /// Блокируем мьютекс /// Ограничиваем максимальный размер данных в буфере if (buff_.size() < max_buf_size) { buff_.insert(buff_.end(), p_data, p_data + len); } } src_ip_ = src_ip; rx_sem_.post(); } int32_t free_rtos::EthUpdClient::read(uint8_t * p_data, uint32_t len) { if ((p_data == nullptr) || (len == 0)) { return 0; } /// Если буфер пуст, ожидаем приема данных if (buff_.empty()) { rx_sem_.pend(); } uint32_t size = buff_.size(); if (size > len) { size = len; } { LockGuard lock(rx_mut_); /// Блокируем мьютекс auto item_begin = buff_.begin(); auto item_end = item_begin + size; /// Извлекаем данные из буфера и копипуем в буфер пользователя std::copy(item_begin, item_end, p_data); /// Удаляем скопированные данные из буфера buff_.erase(item_begin, item_end); } return size; } void free_rtos::EthUpdClient::clear() { LockGuard lock(rx_mut_); buff_.clear(); } int32_t free_rtos::EthUpdClient::write(uint32_t ip_dst_be, uint8_t * p_data, uint32_t len) { TUdpHeader * hdr = (TUdpHeader *)(eth_pkt_.data + sizeof(TIpHeader) + sizeof(TEthFrameHeader)); uint8_t * p_udp_data = (uint8_t *)(eth_pkt_.data + sizeof(TIpHeader) + sizeof(TEthFrameHeader) + sizeof(TUdpHeader)); if (ip_dst_be == 0) { ip_dst_be = src_ip_; } eth_pkt_.length = len + sizeof(TUdpHeader); hdr->Src_port = port_src_be_; hdr->Dst_port = port_dst_be_; hdr->Length = BASE_SWAP16(eth_pkt_.length); hdr->Chk_sum = 0; /// Копируем данные memcpy(p_udp_data, p_data, len); /// Если нужно считать контроольную сумму if (use_checksum_) { uint32_t self_ip = ip_iface_.getSelfIpAddr(); uint32_t chk_sum32 = 0; uint8_t * const dst_ip = (uint8_t *)&ip_dst_be; 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 + eth_pkt_.length; uint16_t chk_sum16 = eth_calcChksum(chk_sum32, (uint8_t *)hdr, eth_pkt_.length); hdr->Chk_sum = BASE_SWAP16(chk_sum16); } return ip_iface_.send(port_id_, ip_dst_be, IP_PROT_UDP, eth_pkt_); }