LCOV - code coverage report
Current view: top level - libs/bsw/cpp2someip/src - UdpProxy.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 72.3 % 112 81
Test Date: 2026-09-11 12:05:06 Functions: 100.0 % 15 15

            Line data    Source code
       1              : /********************************************************************************
       2              :  * Copyright (c) 2026 Accenture
       3              :  *
       4              :  * This program and the accompanying materials are made available under the
       5              :  * terms of the Apache License Version 2.0 which is available at
       6              :  * https://www.apache.org/licenses/LICENSE-2.0
       7              :  *
       8              :  * SPDX-License-Identifier: Apache-2.0
       9              :  ********************************************************************************/
      10              : 
      11              : #include "someip/UdpProxy.h"
      12              : 
      13              : #include "someip/INetworkListener.h"
      14              : #include "someip/NetworkChannel.h"
      15              : #include "someip/SomeIpConstants.h"
      16              : #include "someip/logger.h"
      17              : 
      18              : #include <ip/to_str.h>
      19              : #include <udp/DatagramPacket.h>
      20              : 
      21              : // Logger API uses printf-style varargs for fixed diagnostic messages in this module.
      22              : // NOLINTBEGIN(cppcoreguidelines-pro-type-vararg)
      23              : 
      24              : namespace someip
      25              : {
      26              : using ::ip::IPAddress;
      27              : using ::ip::IPEndpoint;
      28              : using ::udp::AbstractDatagramSocket;
      29              : using ::udp::DatagramPacket;
      30              : using ::util::logger::SOMEIP;
      31              : 
      32           84 : UdpProxy::UdpProxy() : _pSocket(nullptr) {}
      33              : 
      34           74 : bool UdpProxy::isInitialized() const
      35              : {
      36           74 :     return NetworkResource::isInitialized() && (_pSocket != nullptr);
      37              : }
      38              : 
      39           86 : void UdpProxy::setSocket(AbstractDatagramSocket& socket)
      40              : {
      41           86 :     _pSocket = &socket;
      42           86 :     _pSocket->setDataListener(this);
      43           86 : }
      44              : 
      45           24 : AbstractDatagramSocket* UdpProxy::getSocket() const { return _pSocket; }
      46              : 
      47           41 : bool UdpProxy::isOpen() const { return isInitialized() && _pSocket->isBound(); }
      48              : 
      49            1 : bool UdpProxy::isConnected() const { return false; }
      50              : 
      51            7 : ::etl::expected<uint16_t, PortError> UdpProxy::getLocalPort() const
      52              : {
      53            7 :     if (isInitialized())
      54              :     {
      55            7 :         return _pSocket->getLocalPort();
      56              :     }
      57              : 
      58            0 :     return ::etl::unexpected<PortError>(PortError::NOT_INITIALIZED);
      59              : }
      60              : 
      61            1 : uint8_t UdpProxy::getProto() const { return proto::SD_L4_PROTO_UDP; }
      62              : 
      63            7 : bool UdpProxy::open(IPEndpoint const& localEndpoint)
      64              : {
      65            7 :     if (!isInitialized())
      66              :     {
      67            2 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::open() not initialized", this);
      68            2 :         return false;
      69              :     }
      70              : 
      71            5 :     if (isOpen())
      72              :     {
      73            1 :         return true;
      74              :     }
      75              : 
      76            4 :     if (!localEndpoint.isSet())
      77              :     {
      78            0 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::open() no local address", this);
      79            0 :         return false;
      80              :     }
      81              : 
      82              :     char localEndpointStr[::ip::MAX_ENDPOINT_STRING_LENGTH];
      83            4 :     INFO_LOG(
      84              :         SOMEIP,
      85              :         "UdpProxy[%p]::open() at: %s",
      86              :         this,
      87              :         ::ip::to_str(localEndpoint, localEndpointStr).data());
      88              : 
      89              :     AbstractDatagramSocket::ErrorCode const result
      90            4 :         = _pSocket->bind(&localEndpoint.getAddress(), localEndpoint.getPort());
      91              : 
      92            4 :     if (AbstractDatagramSocket::ErrorCode::UDP_SOCKET_OK != result)
      93              :     {
      94            0 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::open() bind failed: %d", this, result);
      95            0 :         return false;
      96              :     }
      97              : 
      98            4 :     return true;
      99              : }
     100              : 
     101            2 : bool UdpProxy::join(IPAddress const& multicastIp)
     102              : {
     103            2 :     if (!isInitialized())
     104              :     {
     105            0 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::join() not initialized", this);
     106            0 :         return false;
     107              :     }
     108              : 
     109            2 :     if (!isOpen())
     110              :     {
     111            0 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::join() not bound", this);
     112            0 :         return false;
     113              :     }
     114              : 
     115            2 :     if (::ip::isUnspecified(multicastIp))
     116              :     {
     117            0 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::join() no multicast address", this);
     118            0 :         close();
     119            0 :         return false;
     120              :     }
     121              : 
     122              :     char multicastIpStr[::ip::MAX_IP_STRING_LENGTH];
     123            2 :     INFO_LOG(
     124              :         SOMEIP,
     125              :         "UdpProxy[%p]::join(): joining %s",
     126              :         this,
     127              :         ::ip::to_str(multicastIp, multicastIpStr).data());
     128              : 
     129            2 :     AbstractDatagramSocket::ErrorCode const result = _pSocket->join(multicastIp);
     130              : 
     131            2 :     if (AbstractDatagramSocket::ErrorCode::UDP_SOCKET_OK != result)
     132              :     {
     133            0 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::join() failed: %d", this, result);
     134            0 :         close();
     135            0 :         return false;
     136              :     }
     137              : 
     138            2 :     return true;
     139              : }
     140              : 
     141            5 : void UdpProxy::close()
     142              : {
     143            5 :     if (!isOpen())
     144              :     {
     145            0 :         return;
     146              :     }
     147              : 
     148            5 :     INFO_LOG(SOMEIP, "UdpProxy[%p]::close()", this);
     149              : 
     150            5 :     _pSocket->close();
     151              : }
     152              : 
     153            2 : bool UdpProxy::send(IPEndpoint const& remoteEndpoint, uint32_t const length)
     154              : {
     155            2 :     uint8_t const ip0   = remoteEndpoint.getAddress().raw[0];
     156            2 :     uint8_t const ip1   = remoteEndpoint.getAddress().raw[1];
     157            2 :     uint8_t const ip2   = remoteEndpoint.getAddress().raw[2];
     158            2 :     uint8_t const ip3   = remoteEndpoint.getAddress().raw[3];
     159            2 :     uint16_t const port = remoteEndpoint.getPort();
     160              : 
     161            2 :     if (!isOpen())
     162              :     {
     163            0 :         ERROR_LOG(
     164              :             SOMEIP,
     165              :             "UdpProxy[%p]::send() not open. Remote: "
     166              :             "(%d,%d,%d,%d), Port: %d.",
     167              :             this,
     168              :             ip0,
     169              :             ip1,
     170              :             ip2,
     171              :             ip3,
     172              :             port);
     173            0 :         return false;
     174              :     }
     175              : 
     176            2 :     if (length == 0U)
     177              :     {
     178            1 :         ERROR_LOG(
     179              :             SOMEIP,
     180              :             "UdpProxy[%p]::send() no data. Remote: "
     181              :             "(%d,%d,%d,%d), Port: %d.",
     182              :             this,
     183              :             ip0,
     184              :             ip1,
     185              :             ip2,
     186              :             ip3,
     187              :             port);
     188            1 :         return false;
     189              :     }
     190              : 
     191            1 :     if (!remoteEndpoint.isSet())
     192              :     {
     193            0 :         ERROR_LOG(
     194              :             SOMEIP,
     195              :             "UdpProxy[%p]::send() no remote endpoint. Remote: "
     196              :             "(%d,%d,%d,%d), Port: %d.",
     197              :             this,
     198              :             ip0,
     199              :             ip1,
     200              :             ip2,
     201              :             ip3,
     202              :             port);
     203            0 :         return false;
     204              :     }
     205              : 
     206            1 :     if (length > _pOutputBuffer.size())
     207              :     {
     208            0 :         ERROR_LOG(
     209              :             SOMEIP,
     210              :             "UdpProxy[%p]::send() too much data (%d bytes). Remote: "
     211              :             "(%d,%d,%d,%d), Port: %d.",
     212              :             this,
     213              :             length,
     214              :             ip0,
     215              :             ip1,
     216              :             ip2,
     217              :             ip3,
     218              :             port);
     219            0 :         return false;
     220              :     }
     221              : 
     222              :     DatagramPacket const packet(
     223            1 :         _pOutputBuffer.data(),
     224              :         static_cast<uint16_t>(length),
     225            1 :         remoteEndpoint.getAddress(),
     226            1 :         remoteEndpoint.getPort());
     227              : 
     228            1 :     AbstractDatagramSocket::ErrorCode const result = _pSocket->send(packet);
     229              : 
     230            1 :     if (AbstractDatagramSocket::ErrorCode::UDP_SOCKET_OK != result)
     231              :     {
     232            1 :         ERROR_LOG(
     233              :             SOMEIP,
     234              :             "UdpProxy[%p]::send() failed: %d. Remote: "
     235              :             "(%d,%d,%d,%d), Port: %d.",
     236              :             this,
     237              :             result,
     238              :             ip0,
     239              :             ip1,
     240              :             ip2,
     241              :             ip3,
     242              :             port);
     243              :     }
     244              : 
     245            1 :     return AbstractDatagramSocket::ErrorCode::UDP_SOCKET_OK == result;
     246              : }
     247              : 
     248            1 : bool UdpProxy::send(uint32_t const length) { return NetworkResource::send(length); }
     249              : 
     250              : // virtual
     251            3 : void UdpProxy::dataReceived(
     252              :     AbstractDatagramSocket& /* socket */,
     253              :     IPAddress const sourceAddress,
     254              :     uint16_t const sourcePort,
     255              :     IPAddress const destinationAddress,
     256              :     uint16_t const length)
     257              : {
     258            3 :     if (::ip::isUnspecified(sourceAddress))
     259              :     {
     260            0 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::dataReceived() no source address", this);
     261            0 :         flush(length);
     262            0 :         return;
     263              :     }
     264              : 
     265            3 :     if (::ip::isUnspecified(destinationAddress))
     266              :     {
     267            0 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::dataReceived() no destination address", this);
     268            0 :         flush(length);
     269            0 :         return;
     270              :     }
     271              : 
     272            3 :     IPEndpoint const remoteEndpoint(sourceAddress, sourcePort);
     273            3 :     bool const isMulticast = ::ip::isMulticastAddress(destinationAddress);
     274              : 
     275            3 :     if (length == 0U)
     276              :     {
     277            1 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::received() no data", this);
     278            1 :         return;
     279              :     }
     280              : 
     281            2 :     if (length > _pInputBuffer.size())
     282              :     {
     283            1 :         ERROR_LOG(SOMEIP, "UdpProxy[%p]::received() too much data (%d bytes)", this, length);
     284            1 :         flush(length);
     285            1 :         return;
     286              :     }
     287              : 
     288              :     uint16_t const read
     289            1 :         = static_cast<uint16_t>(_pSocket->read(_pInputBuffer.data(), static_cast<size_t>(length)));
     290              : 
     291            1 :     if (read != length)
     292              :     {
     293            0 :         ERROR_LOG(
     294              :             SOMEIP, "UdpProxy[%p]::received() read failed (%d / %d bytes)", this, read, length);
     295            0 :         flush(length - read);
     296            0 :         return;
     297              :     }
     298            1 :     incRefCounter(); // in case of hanging proxy.
     299              :     {
     300            1 :         NetworkChannel channel(*this, remoteEndpoint, isMulticast);
     301            1 :         if (_pListener != nullptr)
     302              :         {
     303            1 :             _pListener->received(channel, length);
     304              :         }
     305            1 :     }
     306            1 :     decRefCounter();
     307              : }
     308              : 
     309            1 : void UdpProxy::flush(uint16_t const length)
     310              : {
     311            1 :     if (_pSocket != nullptr)
     312              :     {
     313            1 :         (void)_pSocket->read(nullptr, length);
     314              :     }
     315            1 : }
     316              : 
     317              : } // namespace someip
     318              : 
     319              : // NOLINTEND(cppcoreguidelines-pro-type-vararg)
        

Generated by: LCOV version 2.0-1