reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
reTurnServer.cxx
Go to the documentation of this file.
1#if defined(HAVE_CONFIG_H)
2#include "config.h"
3#endif
4
5#include <iostream>
6#include <csignal>
7#include <memory>
8#include <string>
9#include <asio.hpp>
10#ifdef USE_SSL
11#include <asio/ssl.hpp>
12#endif
13#include <rutil/Data.hxx>
14#include "reTurnServer.hxx"
15#include "TcpServer.hxx"
16#include "TlsServer.hxx"
17#include "UdpServer.hxx"
18#include "ReTurnConfig.hxx"
19#include "RequestHandler.hxx"
20#include "TurnManager.hxx"
22#include <rutil/Log.hxx>
23#include <rutil/Logger.hxx>
24#include "ReTurnSubsystem.hxx"
25
26#include <functional>
27
28#define RESIPROCATE_SUBSYSTEM ReTurnSubsystem::RETURN
29
30#if defined(_WIN32)
31
32std::function<void()> console_ctrl_function;
33
35{
36 switch (ctrl_type)
37 {
38 case CTRL_C_EVENT:
43 return TRUE;
44 default:
45 return FALSE;
46 }
47}
48#endif // defined(_WIN32)
49
50int main(int argc, char* argv[])
51{
53 return proc.main(argc, argv);
54}
55
56int
58{
59#if defined(WIN32) && defined(_DEBUG) && defined(LEAK_CHECK)
60 resip::FindMemoryLeaks fml;
61#endif
62
63 resip::Data defaultConfig("reTurnServer.config");
65 try
66 {
68 }
69 catch(const std::exception& e)
70 {
71 ErrLog(<< "Exception parsing configuration: " << e.what());
72 exit(-1);
73 }
74
75 if(!reTurnConfig.mPidFile.empty() && checkPosixProcessControl("PidFile"))
76 {
77 setPidFile(reTurnConfig.mPidFile);
78 }
80 {
81 std::cerr << "Already running, will not start two instances. Please stop existing process and/or delete PID file.";
82#ifndef WIN32
83 syslog(LOG_DAEMON | LOG_CRIT, "Already running, will not start two instances. Please stop existing process and/or delete PID file.");
84#endif
85 return false;
86 }
87
88 // Daemonize if necessary
89 if(reTurnConfig.mDaemonize && checkPosixProcessControl("Daemonize"))
90 {
91 daemonize();
92 }
93
94 try
95 {
96 // Initialize Logging
98
99 // Initialize server. The io_context is destroyed first at shutdown (see below), so it's
100 // held by a pointer.
101 std::unique_ptr<asio::io_context> ioContext(new asio::io_context);
102 asio::io_context& ioService = *ioContext; // The one and only ioService for the stunServer
103 reTurn::TurnManager turnManager(ioService, reTurnConfig); // The one and only Turn Manager
104
105 std::shared_ptr<reTurn::UdpServer> udpTurnServer; // also a1p1StunUdpServer
106 std::shared_ptr<reTurn::TcpServer> tcpTurnServer;
107#ifdef USE_SSL
108 std::shared_ptr<reTurn::TlsServer> tlsTurnServer;
109#endif
110 std::shared_ptr<reTurn::UdpServer> a1p2StunUdpServer;
111 std::shared_ptr<reTurn::UdpServer> a2p1StunUdpServer;
112 std::shared_ptr<reTurn::UdpServer> a2p2StunUdpServer;
113
114#ifdef USE_IPV6
115 std::shared_ptr<reTurn::UdpServer> udpV6TurnServer;
116 std::shared_ptr<reTurn::TcpServer> tcpV6TurnServer;
117#ifdef USE_SSL
118 std::shared_ptr<reTurn::TlsServer> tlsV6TurnServer;
119#endif
120#endif
121
122 // The one and only RequestHandler - if altStunPort is non-zero, then assume RFC3489 support is enabled and pass settings to request handler
124 reTurnConfig.mAltStunPort != 0 ? &reTurnConfig.mTurnAddress : 0,
125 reTurnConfig.mAltStunPort != 0 ? &reTurnConfig.mTurnPort : 0,
126 reTurnConfig.mAltStunPort != 0 ? &reTurnConfig.mAltStunAddress : 0,
127 reTurnConfig.mAltStunPort != 0 ? &reTurnConfig.mAltStunPort : 0);
128
129 udpTurnServer = std::make_shared<reTurn::UdpServer>(ioService, requestHandler, reTurnConfig.mTurnAddress, reTurnConfig.mTurnPort);
130 tcpTurnServer = std::make_shared<reTurn::TcpServer>(ioService, requestHandler, reTurnConfig.mTurnAddress, reTurnConfig.mTurnPort);
131#ifdef USE_SSL
132 if(reTurnConfig.mTlsTurnPort != 0)
133 {
134 tlsTurnServer = std::make_shared<reTurn::TlsServer>(ioService, requestHandler, reTurnConfig.mTurnAddress, reTurnConfig.mTlsTurnPort);
135 }
136#endif
137
138#ifdef USE_IPV6
139 udpV6TurnServer = std::make_shared<reTurn::UdpServer>(ioService, requestHandler, reTurnConfig.mTurnV6Address, reTurnConfig.mTurnPort);
140 tcpV6TurnServer = std::make_shared<reTurn::TcpServer>(ioService, requestHandler, reTurnConfig.mTurnV6Address, reTurnConfig.mTurnPort);
141#ifdef USE_SSL
142 if(reTurnConfig.mTlsTurnPort != 0)
143 {
144 tlsV6TurnServer = std::make_shared<reTurn::TlsServer>(ioService, requestHandler, reTurnConfig.mTurnV6Address, reTurnConfig.mTlsTurnPort);
145 }
146#endif
147#endif
148
149 if(reTurnConfig.mAltStunPort != 0) // if alt stun port is non-zero, then RFC3489 support is enabled
150 {
151 a1p2StunUdpServer = std::make_shared<reTurn::UdpServer>(ioService, requestHandler, reTurnConfig.mTurnAddress, reTurnConfig.mAltStunPort);
152 a2p1StunUdpServer = std::make_shared<reTurn::UdpServer>(ioService, requestHandler, reTurnConfig.mAltStunAddress, reTurnConfig.mTurnPort);
153 a2p2StunUdpServer = std::make_shared<reTurn::UdpServer>(ioService, requestHandler, reTurnConfig.mAltStunAddress, reTurnConfig.mAltStunPort);
154 udpTurnServer->setAlternateUdpServers(a1p2StunUdpServer.get(), a2p1StunUdpServer.get(), a2p2StunUdpServer.get());
155 a1p2StunUdpServer->setAlternateUdpServers(udpTurnServer.get(), a2p2StunUdpServer.get(), a2p1StunUdpServer.get());
156 a2p1StunUdpServer->setAlternateUdpServers(a2p2StunUdpServer.get(), udpTurnServer.get(), a1p2StunUdpServer.get());
157 a2p2StunUdpServer->setAlternateUdpServers(a2p1StunUdpServer.get(), a1p2StunUdpServer.get(), udpTurnServer.get());
158 a1p2StunUdpServer->start();
159 a2p1StunUdpServer->start();
160 a2p2StunUdpServer->start();
161 }
162
163 udpTurnServer->start();
164 tcpTurnServer->start();
165#ifdef USE_SSL
166 if(tlsTurnServer)
167 {
168 tlsTurnServer->start();
169 }
170#endif
171
172#ifdef USE_IPV6
173 udpV6TurnServer->start();
174 tcpV6TurnServer->start();
175#ifdef USE_SSL
177 {
178 tlsV6TurnServer->start();
179 }
180#endif
181#endif
182
183 // Drop privileges (can do this now that sockets are bound)
184 if(!reTurnConfig.mRunAsUser.empty() && checkPosixProcessControl("RunAsUser/RunAsGroup"))
185 {
186 InfoLog( << "Trying to drop privileges, configured uid = " << reTurnConfig.mRunAsUser << " gid = " << reTurnConfig.mRunAsGroup);
187 dropPrivileges(reTurnConfig.mRunAsUser, reTurnConfig.mRunAsGroup);
188 }
189
190 std::unique_ptr<ReTurnUserFileScanner> userFileScanner(new ReTurnUserFileScanner(ioService, reTurnConfig));
191 userFileScanner->start();
192
193#ifdef _WIN32
194 // Set console control handler to allow server to be stopped.
197#else
198 // Block all signals for background thread.
203#endif
204
205 // Run the ioService until stopped.
206 // Create a pool of threads to run all of the io_contexts.
207 asio::thread thread([&ioService] { ioService.run(); });
208
209#ifndef _WIN32
210 // Restore previous signals.
212
213 // Wait for signal indicating time to shut down.
220 int sig = 0;
222 ioService.stop();
223#endif
224
225 // Wait for thread to exit
226 thread.join();
227
228 // Shut down in order: first what uses the io_context, then the io_context itself. Its
229 // pending handlers keep servers, connections and their allocations alive, and those use the
230 // TurnManager and RequestHandler - so they must go while those still exist.
231 userFileScanner.reset();
232 udpTurnServer.reset();
233 tcpTurnServer.reset();
234#ifdef USE_SSL
235 tlsTurnServer.reset();
236#endif
237 a1p2StunUdpServer.reset();
238 a2p1StunUdpServer.reset();
239 a2p2StunUdpServer.reset();
240#ifdef USE_IPV6
241 udpV6TurnServer.reset();
242 tcpV6TurnServer.reset();
243#ifdef USE_SSL
244 tlsV6TurnServer.reset();
245#endif
246#endif
247 ioContext.reset();
248 }
249 catch (const std::exception& e)
250 {
251 ErrLog(<< "exception: " << e.what());
252 }
253
254 return 0;
255}
256
257
258/* ====================================================================
259
260 Copyright (c) 2026, SIP Spectrum, Inc. https://www.sipspectrum.com
261 Copyright (c) 2007-2008, Plantronics, Inc.
262 All rights reserved.
263
264 Redistribution and use in source and binary forms, with or without
265 modification, are permitted provided that the following conditions are
266 met:
267
268 1. Redistributions of source code must retain the above copyright
269 notice, this list of conditions and the following disclaimer.
270
271 2. Redistributions in binary form must reproduce the above copyright
272 notice, this list of conditions and the following disclaimer in the
273 documentation and/or other materials provided with the distribution.
274
275 3. Neither the name of Plantronics nor the names of its contributors
276 may be used to endorse or promote products derived from this
277 software without specific prior written permission.
278
279 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
280 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
281 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
283 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
284 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
285 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
286 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
287 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
288 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
289 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
290
291 ==================================================================== */
#define InfoLog(args_)
Definition Logger.hxx:131
#define ErrLog(args_)
Definition Logger.hxx:137
virtual void parseConfig(int argc, char **argv, const resip::Data &defaultConfigFilename)
virtual int main(int argc, char *argv[])
The common handler for all incoming requests.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
static void initialize(Type type, Level level, const Data &appName, const char *logFileName=0, ExternalLogger *externalLogger=0, const Data &syslogFacility="LOG_DAEMON", MessageStructure messageStructure=Unstructured, const Data &instanceName="")
Definition Log.cxx:268
void dropPrivileges(const Data &runAsUser, const Data &runAsGroup)
void setPidFile(const Data &pidFile)
bool checkPosixProcessControl(const Data &dependentSettings)
int main(int argc, char *argv[])
void list()
Definition userAdmin.cxx:66