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-2009 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 as published by
21 * the Free Software Foundation, either version 3 of the License, or
24 * Anytun is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with anytun. If not, see <http://www.gnu.org/licenses/>.
40 #include <boost/bind.hpp>
42 #include "commandHandler.h"
43 #include "../buffer.h"
45 #include "../syncQueue.h"
46 #include "syncRtpCommand.h"
47 #include "rtpSessionTable.h"
48 #include "callIdQueue.h"
51 #define MAX_COMMAND_LENGTH 1000
53 CommandHandler::CommandHandler(SyncQueue& q, std::string lp,PortWindow & pw) : thread_(boost::bind(run,this)),
54 queue_(q), running_(true), control_sock_(io_service_),
55 local_address_(""), local_port_(lp),port_window_(pw)
57 proto::resolver resolver(io_service_);
58 proto::resolver::query query(local_port_);
59 proto::endpoint e = *resolver.resolve(query);
60 control_sock_.open(e.protocol());
61 control_sock_.bind(e);
64 CommandHandler::CommandHandler(SyncQueue& q, string la, std::string lp, PortWindow & pw) : thread_(boost::bind(run,this)),
65 queue_(q), running_(true), control_sock_(io_service_),
66 local_address_(la), local_port_(lp),port_window_(pw)
68 proto::resolver resolver(io_service_);
69 proto::resolver::query query(local_address_, local_port_);
70 proto::endpoint e = *resolver.resolve(query);
71 control_sock_.open(e.protocol());
72 control_sock_.bind(e);
75 void CommandHandler::run(void* s)
77 CommandHandler* self = reinterpret_cast<CommandHandler*>(s);
79 Buffer buf(u_int32_t(MAX_COMMAND_LENGTH));
82 proto::endpoint remote_end;
87 buf.setLength(MAX_COMMAND_LENGTH);
89 len = self->control_sock_.receive_from(boost::asio::buffer(buf.getBuf(), buf.getLength()), remote_end);
92 std::string ret = self->handle(std::string(reinterpret_cast<char*>(buf.getBuf()), buf.getLength())); // TODO: reinterpret is ugly
94 cLog.msg(Log::PRIO_DEBUG) << "CommandHandler received Command from " << remote_end << ", ret='" << ret << "'";
96 self->control_sock_.send_to(boost::asio::buffer(ret.c_str(), ret.length()), remote_end);
99 catch(std::exception& e)
101 self->running_ = false;
103 self->running_ = false;
106 bool CommandHandler::isRunning()
113 std::string CommandHandler::handle(std::string command)
115 istringstream iss(command);
121 oss << cookie << " ";
123 if(iss.bad() || iss.eof()) {
124 oss << RET_ERR_SYNTAX;
129 std::vector<std::string> params;
130 while(!iss.bad() && !iss.eof()) {
133 params.push_back(tmp);
136 switch(std::toupper(cmd[0]))
139 if(params.size() < 4) { oss << RET_ERR_SYNTAX; break; }
140 oss << handleRequest(cmd.erase(0,1), params[0], params[1], params[2], params[3], (params.size() < 5) ? "" : params[4]);
143 if(params.size() < 4) { oss << RET_ERR_SYNTAX; break; }
144 oss << handleResponse(cmd.erase(0,1), params[0], params[1], params[2], params[3], (params.size() < 5) ? "" : params[4]);
147 if(params.size() < 2) { oss << RET_ERR_SYNTAX; break; }
148 oss << handleDelete(params[0], params[1], (params.size() < 3) ? "" : params[2]);
151 if(cmd.length() > 1 && cmd[1] == 'F') {
152 if(params.size() < 1) { oss << RET_ERR_SYNTAX; break; }
153 oss << handleVersionF(params[0]);
156 oss << handleVersion();
162 oss << RET_ERR_SYNTAX;
169 string CommandHandler::handleRequest(string modifiers, string call_id, string addr, string port, string from_tag, string to_tag)
171 std::cout << "received request[" << modifiers << "] command ('" << call_id << "','" << addr << "','" << port
172 << "','" << from_tag << "','" << to_tag << "')" << std::endl;
176 RtpSession::proto::resolver resolver(io_service_);
178 RtpSession& session = gRtpSessionTable.getOrNewSession(call_id, is_new);
181 u_int16_t port1 = port_window_.newPort(); // TODO: get next available port
182 u_int16_t port2 = port_window_.newPort(); // TODO: get next available port
183 if( !port1 || !port2)
185 if( port1) port_window_.freePort(port1);
186 if( port2) port_window_.freePort(port2);
187 throw std::runtime_error("no free port found");
189 std::stringstream ps1, ps2;
193 RtpSession::proto::endpoint e1, e2;
194 if(gOpt.getLocalAddr() == "") {
195 RtpSession::proto::resolver::query query1(ps1.str());
196 e1 = *resolver.resolve(query1);
197 RtpSession::proto::resolver::query query2(ps2.str());
198 e2 = *resolver.resolve(query2);
201 RtpSession::proto::resolver::query query1(gOpt.getLocalAddr(),ps1.str());
202 e1 = *resolver.resolve(query1);
203 RtpSession::proto::resolver::query query2(gOpt.getLocalAddr(),ps2.str());
204 e2 = *resolver.resolve(query2);
207 session.setLocalEnd1(e1);
208 session.setLocalEnd2(e2);
210 RtpSession::proto::resolver::query query(addr,port);
211 session.setRemoteEnd1(*resolver.resolve(query));
214 oss << session.getLocalEnd2().port();
217 catch(std::exception& e)
219 return RET_ERR_UNKNOWN; // TODO: change to corret error value
223 string CommandHandler::handleResponse(string modifiers, string call_id, string addr, string port, string from_tag, string to_tag)
225 std::cout << "received response[" << modifiers << "] command ('" << call_id << "','" << addr << "','" << port
226 << "','" << from_tag << "','" << to_tag << "')" << std::endl;
230 RtpSession& session = gRtpSessionTable.getSession(call_id);
231 RtpSession::proto::resolver resolver(io_service_);
232 RtpSession::proto::resolver::query query(addr,port);
233 session.setRemoteEnd2(*resolver.resolve(query));
234 session.isComplete(true);
235 SyncRtpCommand sc(call_id);
239 oss << session.getLocalEnd1().port();
242 catch(std::exception& e)
244 return RET_ERR_UNKNOWN; // TODO: change to corret error value
248 string CommandHandler::handleDelete(string call_id, string from_tag, string to_tag)
250 std::cout << "received delete command ('" << call_id << "','" << from_tag << "','" << to_tag << "')" << std::endl;
254 RtpSession& session = gRtpSessionTable.getSession(call_id);
255 session.isDead(true);
256 SyncRtpCommand sc(call_id);
261 catch(std::exception& e)
263 return RET_ERR_UNKNOWN; // TODO: change to corret error value
267 string CommandHandler::handleVersion()
269 std::cout << "received version command" << std::endl;
273 string CommandHandler::handleVersionF(string date_code)
275 std::cout << "received version[F] command ('" << date_code << "')" << std::endl;
276 if(!date_code.compare(SUP_VERSION))
282 string CommandHandler::handleInfo()
284 std::cout << "received info command, ignoring" << std::endl;