4 * The secure anycast tunneling protocol (satp) defines a protocol used
5 * for communication between any combination of unicast and anycast
6 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
7 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
8 * ethernet, ip, arp ...). satp directly includes cryptography and
9 * message authentication based on the methodes used by SRTP. It is
10 * intended to deliver a generic, scaleable and secure solution for
11 * tunneling and relaying of packets of any protocol.
14 * Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl,
15 * Christian Pointner <satp@wirdorange.org>
17 * This file is part of Anytun.
19 * Anytun is free software: you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License version 3 as
21 * published by the Free Software Foundation.
23 * Anytun is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with anytun. If not, see <http://www.gnu.org/licenses/>.
39 #include <boost/bind.hpp>
41 #include "commandHandler.h"
42 #include "../buffer.h"
44 #include "../syncQueue.h"
45 #include "syncRtpCommand.h"
46 #include "rtpSessionTable.h"
47 #include "callIdQueue.h"
50 #define MAX_COMMAND_LENGTH 1000
52 CommandHandler::CommandHandler(SyncQueue
& q
, std::string lp
,PortWindow
& pw
) : thread_(boost::bind(run
,this)),
53 queue_(q
), running_(true), control_sock_(io_service_
),
54 local_address_(""), local_port_(lp
),port_window_(pw
)
56 proto::resolver
resolver(io_service_
);
57 proto::resolver::query
query(local_port_
);
58 proto::endpoint e
= *resolver
.resolve(query
);
59 control_sock_
.open(e
.protocol());
60 control_sock_
.bind(e
);
63 CommandHandler::CommandHandler(SyncQueue
& q
, string la
, std::string lp
, PortWindow
& pw
) : thread_(boost::bind(run
,this)),
64 queue_(q
), running_(true), control_sock_(io_service_
),
65 local_address_(la
), local_port_(lp
),port_window_(pw
)
67 proto::resolver
resolver(io_service_
);
68 proto::resolver::query
query(local_address_
, local_port_
);
69 proto::endpoint e
= *resolver
.resolve(query
);
70 control_sock_
.open(e
.protocol());
71 control_sock_
.bind(e
);
74 void CommandHandler::run(void* s
)
76 CommandHandler
* self
= reinterpret_cast<CommandHandler
*>(s
);
78 Buffer
buf(u_int32_t(MAX_COMMAND_LENGTH
));
81 proto::endpoint remote_end
;
86 buf
.setLength(MAX_COMMAND_LENGTH
);
88 len
= self
->control_sock_
.receive_from(boost::asio::buffer(buf
.getBuf(), buf
.getLength()), remote_end
);
91 std::string ret
= self
->handle(std::string(reinterpret_cast<char*>(buf
.getBuf()), buf
.getLength())); // TODO: reinterpret is ugly
93 cLog
.msg(Log::PRIO_DEBUG
) << "CommandHandler received Command from " << remote_end
<< ", ret='" << ret
<< "'";
95 self
->control_sock_
.send_to(boost::asio::buffer(ret
.c_str(), ret
.length()), remote_end
);
98 catch(std::exception
& e
)
100 self
->running_
= false;
102 self
->running_
= false;
105 bool CommandHandler::isRunning()
112 std::string
CommandHandler::handle(std::string command
)
114 istringstream
iss(command
);
120 oss
<< cookie
<< " ";
122 if(iss
.bad() || iss
.eof()) {
123 oss
<< RET_ERR_SYNTAX
;
128 std::vector
<std::string
> params
;
129 while(!iss
.bad() && !iss
.eof()) {
132 params
.push_back(tmp
);
135 switch(std::toupper(cmd
[0]))
138 if(params
.size() < 4) { oss
<< RET_ERR_SYNTAX
; break; }
139 oss
<< handleRequest(cmd
.erase(0,1), params
[0], params
[1], params
[2], params
[3], (params
.size() < 5) ? "" : params
[4]);
142 if(params
.size() < 4) { oss
<< RET_ERR_SYNTAX
; break; }
143 oss
<< handleResponse(cmd
.erase(0,1), params
[0], params
[1], params
[2], params
[3], (params
.size() < 5) ? "" : params
[4]);
146 if(params
.size() < 2) { oss
<< RET_ERR_SYNTAX
; break; }
147 oss
<< handleDelete(params
[0], params
[1], (params
.size() < 3) ? "" : params
[2]);
150 if(cmd
.length() > 1 && cmd
[1] == 'F') {
151 if(params
.size() < 1) { oss
<< RET_ERR_SYNTAX
; break; }
152 oss
<< handleVersionF(params
[0]);
155 oss
<< handleVersion();
161 oss
<< RET_ERR_SYNTAX
;
168 string
CommandHandler::handleRequest(string modifiers
, string call_id
, string addr
, string port
, string from_tag
, string to_tag
)
170 std::cout
<< "received request[" << modifiers
<< "] command ('" << call_id
<< "','" << addr
<< "','" << port
171 << "','" << from_tag
<< "','" << to_tag
<< "')" << std::endl
;
175 RtpSession::proto::resolver
resolver(io_service_
);
177 RtpSession
& session
= gRtpSessionTable
.getOrNewSession(call_id
, is_new
);
180 u_int16_t port1
= port_window_
.newPort(); // TODO: get next available port
181 u_int16_t port2
= port_window_
.newPort(); // TODO: get next available port
182 if( !port1
|| !port2
)
184 if( port1
) port_window_
.freePort(port1
);
185 if( port2
) port_window_
.freePort(port2
);
186 throw std::runtime_error("no free port found");
188 std::stringstream ps1
, ps2
;
192 RtpSession::proto::endpoint e1
, e2
;
193 if(gOpt
.getLocalAddr() == "") {
194 RtpSession::proto::resolver::query
query1(ps1
.str());
195 e1
= *resolver
.resolve(query1
);
196 RtpSession::proto::resolver::query
query2(ps2
.str());
197 e2
= *resolver
.resolve(query2
);
200 RtpSession::proto::resolver::query
query1(gOpt
.getLocalAddr(),ps1
.str());
201 e1
= *resolver
.resolve(query1
);
202 RtpSession::proto::resolver::query
query2(gOpt
.getLocalAddr(),ps2
.str());
203 e2
= *resolver
.resolve(query2
);
206 session
.setLocalEnd1(e1
);
207 session
.setLocalEnd2(e2
);
209 RtpSession::proto::resolver::query
query(addr
,port
);
210 session
.setRemoteEnd1(*resolver
.resolve(query
));
213 oss
<< session
.getLocalEnd2().port();
216 catch(std::exception
& e
)
218 return RET_ERR_UNKNOWN
; // TODO: change to corret error value
222 string
CommandHandler::handleResponse(string modifiers
, string call_id
, string addr
, string port
, string from_tag
, string to_tag
)
224 std::cout
<< "received response[" << modifiers
<< "] command ('" << call_id
<< "','" << addr
<< "','" << port
225 << "','" << from_tag
<< "','" << to_tag
<< "')" << std::endl
;
229 RtpSession
& session
= gRtpSessionTable
.getSession(call_id
);
230 RtpSession::proto::resolver
resolver(io_service_
);
231 RtpSession::proto::resolver::query
query(addr
,port
);
232 session
.setRemoteEnd2(*resolver
.resolve(query
));
233 session
.isComplete(true);
234 SyncRtpCommand
sc(call_id
);
238 oss
<< session
.getLocalEnd1().port();
241 catch(std::exception
& e
)
243 return RET_ERR_UNKNOWN
; // TODO: change to corret error value
247 string
CommandHandler::handleDelete(string call_id
, string from_tag
, string to_tag
)
249 std::cout
<< "received delete command ('" << call_id
<< "','" << from_tag
<< "','" << to_tag
<< "')" << std::endl
;
253 RtpSession
& session
= gRtpSessionTable
.getSession(call_id
);
254 session
.isDead(true);
255 SyncRtpCommand
sc(call_id
);
260 catch(std::exception
& e
)
262 return RET_ERR_UNKNOWN
; // TODO: change to corret error value
266 string
CommandHandler::handleVersion()
268 std::cout
<< "received version command" << std::endl
;
272 string
CommandHandler::handleVersionF(string date_code
)
274 std::cout
<< "received version[F] command ('" << date_code
<< "')" << std::endl
;
275 if(!date_code
.compare(SUP_VERSION
))
281 string
CommandHandler::handleInfo()
283 std::cout
<< "received info command, ignoring" << std::endl
;