reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
UdpEchoServer.cxx
Go to the documentation of this file.
1#include <iostream>
2#include <string>
3#include <asio.hpp>
4#ifdef USE_SSL
5#include <asio/ssl.hpp>
6#endif
7
8#include "UdpEchoServer.hxx"
9#include "../AsyncSocketBase.hxx"
10#include "../ReTurnSubsystem.hxx"
11#include <rutil/Logger.hxx>
13
14#ifdef BOOST_ASIO_HAS_STD_CHRONO
15using namespace std::chrono;
16#else
17#include <chrono>
18using namespace std::chrono;
19#endif
20
21using namespace std;
22using namespace resip;
23using namespace reTurn;
24
25#define RESIPROCATE_SUBSYSTEM ReTurnSubsystem::RETURN
26
27// Simple UDP Echo Server
28UdpEchoServer::UdpEchoServer(const Data& localAddress, unsigned int port) :
29 mPort(port),
30 mSocket(mIOContext),
31 mIntervalReadCount(0)
32{
33 asio::ip::address address = asio::ip::make_address(localAddress.c_str());
34 asio::error_code errorCode;
35 mSocket.open(address.is_v6() ? asio::ip::udp::v6() : asio::ip::udp::v4(), errorCode);
36 if (!errorCode)
37 {
39 mSocket.bind(asio::ip::udp::endpoint(address, port));
40 }
41 mIntervalReadCount = 0;
42
43 if (mPort == 0)
44 {
45 mPort = mSocket.local_endpoint().port();
46 }
47 InfoLog(<< "UdpEchoServer: Started, localAddress=" << localAddress << ", localPort=" << mPort);
48
49 read();
50}
51
53{
54 mTimeOfFirstRead = chrono::steady_clock::now();
55 mIOContext.run();
56 InfoLog(<< "UdpEchoServer: thread completed");
57}
58
60{
61 mIOContext.stop();
62}
63
64void UdpEchoServer::read()
65{
66 mSocket.async_receive_from(asio::buffer(mReceiveBuffer, sizeof(mReceiveBuffer)), mRemoteEndpoint,
67 [this](asio::error_code ec, std::size_t length)
68 {
69 if (ec)
70 {
71 if (ec.value() == 10054 || // Ignore 10054 errors
72 ec.value() == 10061) // Ignore 10061 errors
73 {
74 InfoLog(<< "UdpEchoServer[" << mPort << "]: Received 10054 read error, ignoring!");
75 read();
76 return;
77 }
78
79 ErrLog(<< "UdpEchoServer[" << mPort << "]: error calling async_receive_from: error=" << ec.value() << ", message=" << ec.message());
80 return;
81 }
82
83 mIntervalReadCount++;
84 checkLog();
85
86 mReceiveSize = length;
87 DebugLog(<< "UdpEchoServer[" << mPort << "]: Received data from: " << mRemoteEndpoint << ", size=" << length);
88 if (!isShutdown())
89 {
90 write();
91 }
92 }
93 );
94}
95
96void UdpEchoServer::write()
97{
98 mSocket.async_send_to(asio::buffer(mReceiveBuffer, mReceiveSize),
99 mRemoteEndpoint,
100 [this](asio::error_code ec, std::size_t length)
101 {
102 if (ec)
103 {
104 ErrLog(<< "UdpEchoServer[" << mPort << "]: error calling async_send_to: error=" << ec.value() << ", message=" << ec.message());
105 return;
106 }
107 if (!isShutdown())
108 {
109 read();
110 }
111 }
112 );
113}
114
115void UdpEchoServer::checkLog()
116{
117 std::chrono::time_point<chrono::steady_clock> now = chrono::steady_clock::now();
118 long long secondsPassed = chrono::duration_cast<chrono::seconds>(now - mTimeOfFirstRead).count();
119 if (secondsPassed > 30)
120 {
121 InfoLog(<< "UdpEchoServer[" << mPort << "]: Echo'd " << mIntervalReadCount << " packets in the last " << secondsPassed << " seconds.");
122 mIntervalReadCount = 0;
123 mTimeOfFirstRead = now;
124 }
125}
126
127
128/* ====================================================================
129
130 Copyright (c) 2024-2026 SIP Spectrum, Inc http://www.sipspectrum.com
131 All rights reserved.
132
133 Redistribution and use in source and binary forms, with or without
134 modification, are permitted provided that the following conditions are
135 met:
136
137 1. Redistributions of source code must retain the above copyright
138 notice, this list of conditions and the following disclaimer.
139
140 2. Redistributions in binary form must reproduce the above copyright
141 notice, this list of conditions and the following disclaimer in the
142 documentation and/or other materials provided with the distribution.
143
144 3. Neither the name of Plantronics nor the names of its contributors
145 may be used to endorse or promote products derived from this
146 software without specific prior written permission.
147
148 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
149 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
150 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
151 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
152 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
153 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
154 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
155 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
156 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
157 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
158 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
159
160 ==================================================================== */
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
static void setExclusiveAddressUse(asio::ip::udp::socket &socket)
For a UDP socket, between open() and bind().
void thread() override
void shutdown() override
UdpEchoServer(const Data &localAddress, unsigned int port)
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
bool isShutdown() const
Definition ThreadIf.cxx:212
dcm! – add UnusedChecking(_enum) below;