1 |
#include <iostream> |
2 |
#include <csignal> |
3 |
#include <string> |
4 |
#include <asio.hpp> |
5 |
#include <boost/bind.hpp> |
6 |
#include <boost/function.hpp> |
7 |
#include <boost/lexical_cast.hpp> |
8 |
#include <rutil/Data.hxx> |
9 |
#include "reTurnServer.hxx" |
10 |
#include "TcpServer.hxx" |
11 |
#include "TlsServer.hxx" |
12 |
#include "UdpServer.hxx" |
13 |
#include "ReTurnConfig.hxx" |
14 |
#include "RequestHandler.hxx" |
15 |
#include "TurnManager.hxx" |
16 |
#include <rutil/WinLeakCheck.hxx> |
17 |
#include <rutil/Log.hxx> |
18 |
#include <rutil/Logger.hxx> |
19 |
#include "ReTurnSubsystem.hxx" |
20 |
|
21 |
#define RESIPROCATE_SUBSYSTEM ReTurnSubsystem::RETURN |
22 |
|
23 |
#if defined(_WIN32) |
24 |
|
25 |
boost::function0<void> console_ctrl_function; |
26 |
|
27 |
BOOL WINAPI console_ctrl_handler(DWORD ctrl_type) |
28 |
{ |
29 |
switch (ctrl_type) |
30 |
{ |
31 |
case CTRL_C_EVENT: |
32 |
case CTRL_BREAK_EVENT: |
33 |
case CTRL_CLOSE_EVENT: |
34 |
case CTRL_SHUTDOWN_EVENT: |
35 |
console_ctrl_function(); |
36 |
return TRUE; |
37 |
default: |
38 |
return FALSE; |
39 |
} |
40 |
} |
41 |
#endif // defined(_WIN32) |
42 |
|
43 |
int main(int argc, char* argv[]) |
44 |
{ |
45 |
reTurn::ReTurnServerProcess proc; |
46 |
return proc.main(argc, argv); |
47 |
} |
48 |
|
49 |
reTurn::ReTurnServerProcess::ReTurnServerProcess() |
50 |
{ |
51 |
} |
52 |
|
53 |
reTurn::ReTurnServerProcess::~ReTurnServerProcess() |
54 |
{ |
55 |
} |
56 |
|
57 |
int |
58 |
reTurn::ReTurnServerProcess::main(int argc, char* argv[]) |
59 |
{ |
60 |
#if defined(WIN32) && defined(_DEBUG) && defined(LEAK_CHECK) |
61 |
resip::FindMemoryLeaks fml; |
62 |
#endif |
63 |
|
64 |
resip::Data defaultConfig("reTurnServer.config"); |
65 |
reTurn::ReTurnConfig reTurnConfig; |
66 |
try |
67 |
{ |
68 |
reTurnConfig.parseConfig(argc, argv, defaultConfig); |
69 |
} |
70 |
catch(std::exception& e) |
71 |
{ |
72 |
ErrLog(<< "Exception parsing configuration: " << e.what()); |
73 |
exit(-1); |
74 |
} |
75 |
|
76 |
setPidFile(reTurnConfig.mPidFile); |
77 |
// Daemonize if necessary |
78 |
if(reTurnConfig.mDaemonize) |
79 |
{ |
80 |
daemonize(); |
81 |
} |
82 |
|
83 |
try |
84 |
{ |
85 |
// Initialize Logging |
86 |
resip::Log::initialize(reTurnConfig.mLoggingType, reTurnConfig.mLoggingLevel, "reTurnServer", reTurnConfig.mLoggingFilename.c_str()); |
87 |
resip::GenericLogImpl::MaxLineCount = reTurnConfig.mLoggingFileMaxLineCount; |
88 |
|
89 |
// Initialize server. |
90 |
asio::io_service ioService; // The one and only ioService for the stunServer |
91 |
reTurn::TurnManager turnManager(ioService, reTurnConfig); // The one and only Turn Manager |
92 |
|
93 |
boost::shared_ptr<reTurn::UdpServer> udpTurnServer; // also a1p1StunUdpServer |
94 |
boost::shared_ptr<reTurn::TcpServer> tcpTurnServer; |
95 |
boost::shared_ptr<reTurn::TlsServer> tlsTurnServer; |
96 |
boost::shared_ptr<reTurn::UdpServer> a1p2StunUdpServer; |
97 |
boost::shared_ptr<reTurn::UdpServer> a2p1StunUdpServer; |
98 |
boost::shared_ptr<reTurn::UdpServer> a2p2StunUdpServer; |
99 |
|
100 |
// The one and only RequestHandler - if altStunPort is non-zero, then assume RFC3489 support is enabled and pass settings to request handler |
101 |
reTurn::RequestHandler requestHandler(turnManager, |
102 |
reTurnConfig.mAltStunPort != 0 ? &reTurnConfig.mTurnAddress : 0, |
103 |
reTurnConfig.mAltStunPort != 0 ? &reTurnConfig.mTurnPort : 0, |
104 |
reTurnConfig.mAltStunPort != 0 ? &reTurnConfig.mAltStunAddress : 0, |
105 |
reTurnConfig.mAltStunPort != 0 ? &reTurnConfig.mAltStunPort : 0); |
106 |
|
107 |
udpTurnServer.reset(new reTurn::UdpServer(ioService, requestHandler, reTurnConfig.mTurnAddress, reTurnConfig.mTurnPort)); |
108 |
tcpTurnServer.reset(new reTurn::TcpServer(ioService, requestHandler, reTurnConfig.mTurnAddress, reTurnConfig.mTurnPort)); |
109 |
tlsTurnServer.reset(new reTurn::TlsServer(ioService, requestHandler, reTurnConfig.mTurnAddress, reTurnConfig.mTlsTurnPort)); |
110 |
|
111 |
if(reTurnConfig.mAltStunPort != 0) // if alt stun port is non-zero, then RFC3489 support is enabled |
112 |
{ |
113 |
a1p2StunUdpServer.reset(new reTurn::UdpServer(ioService, requestHandler, reTurnConfig.mTurnAddress, reTurnConfig.mAltStunPort)); |
114 |
a2p1StunUdpServer.reset(new reTurn::UdpServer(ioService, requestHandler, reTurnConfig.mAltStunAddress, reTurnConfig.mTurnPort)); |
115 |
a2p2StunUdpServer.reset(new reTurn::UdpServer(ioService, requestHandler, reTurnConfig.mAltStunAddress, reTurnConfig.mAltStunPort)); |
116 |
udpTurnServer->setAlternateUdpServers(a1p2StunUdpServer.get(), a2p1StunUdpServer.get(), a2p2StunUdpServer.get()); |
117 |
a1p2StunUdpServer->setAlternateUdpServers(udpTurnServer.get(), a2p2StunUdpServer.get(), a2p1StunUdpServer.get()); |
118 |
a2p1StunUdpServer->setAlternateUdpServers(a2p2StunUdpServer.get(), udpTurnServer.get(), a1p2StunUdpServer.get()); |
119 |
a2p2StunUdpServer->setAlternateUdpServers(a2p1StunUdpServer.get(), a1p2StunUdpServer.get(), udpTurnServer.get()); |
120 |
a1p2StunUdpServer->start(); |
121 |
a2p1StunUdpServer->start(); |
122 |
a2p2StunUdpServer->start(); |
123 |
} |
124 |
|
125 |
udpTurnServer->start(); |
126 |
tcpTurnServer->start(); |
127 |
tlsTurnServer->start(); |
128 |
|
129 |
#ifdef _WIN32 |
130 |
// Set console control handler to allow server to be stopped. |
131 |
console_ctrl_function = boost::bind(&asio::io_service::stop, &ioService); |
132 |
SetConsoleCtrlHandler(console_ctrl_handler, TRUE); |
133 |
#else |
134 |
// Block all signals for background thread. |
135 |
sigset_t new_mask; |
136 |
sigfillset(&new_mask); |
137 |
sigset_t old_mask; |
138 |
pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask); |
139 |
#endif |
140 |
|
141 |
// Run the ioService until stopped. |
142 |
// Create a pool of threads to run all of the io_services. |
143 |
boost::shared_ptr<asio::thread> thread(new asio::thread( |
144 |
boost::bind(&asio::io_service::run, &ioService))); |
145 |
|
146 |
#ifndef _WIN32 |
147 |
// Restore previous signals. |
148 |
pthread_sigmask(SIG_SETMASK, &old_mask, 0); |
149 |
|
150 |
// Wait for signal indicating time to shut down. |
151 |
sigset_t wait_mask; |
152 |
sigemptyset(&wait_mask); |
153 |
sigaddset(&wait_mask, SIGINT); |
154 |
sigaddset(&wait_mask, SIGQUIT); |
155 |
sigaddset(&wait_mask, SIGTERM); |
156 |
pthread_sigmask(SIG_BLOCK, &wait_mask, 0); |
157 |
int sig = 0; |
158 |
sigwait(&wait_mask, &sig); |
159 |
ioService.stop(); |
160 |
#endif |
161 |
|
162 |
// Wait for thread to exit |
163 |
thread->join(); |
164 |
} |
165 |
catch (std::exception& e) |
166 |
{ |
167 |
ErrLog(<< "exception: " << e.what()); |
168 |
} |
169 |
|
170 |
return 0; |
171 |
} |
172 |
|
173 |
|
174 |
/* ==================================================================== |
175 |
|
176 |
Copyright (c) 2007-2008, Plantronics, Inc. |
177 |
All rights reserved. |
178 |
|
179 |
Redistribution and use in source and binary forms, with or without |
180 |
modification, are permitted provided that the following conditions are |
181 |
met: |
182 |
|
183 |
1. Redistributions of source code must retain the above copyright |
184 |
notice, this list of conditions and the following disclaimer. |
185 |
|
186 |
2. Redistributions in binary form must reproduce the above copyright |
187 |
notice, this list of conditions and the following disclaimer in the |
188 |
documentation and/or other materials provided with the distribution. |
189 |
|
190 |
3. Neither the name of Plantronics nor the names of its contributors |
191 |
may be used to endorse or promote products derived from this |
192 |
software without specific prior written permission. |
193 |
|
194 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
195 |
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
196 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
197 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
198 |
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
199 |
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
200 |
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
201 |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
202 |
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
203 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
204 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
205 |
|
206 |
==================================================================== */ |