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 methods 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-2014 Markus Grüneis, 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/>.
32 * In addition, as a special exception, the copyright holders give
33 * permission to link the code of portions of this program with the
34 * OpenSSL library under certain conditions as described in each
35 * individual source file, and distribute linked combinations
37 * You must obey the GNU General Public License in all respects
38 * for all of the code used other than OpenSSL. If you modify
39 * file(s) with this exception, you may extend this exception to your
40 * version of the file(s), but you are not obligated to do so. If you
41 * do not wish to do so, delete this exception statement from your
42 * version. If you delete this exception statement from all source
43 * files in the program, then also delete it here.
53 #include <boost/bind.hpp>
55 #include "commandHandler.h"
56 #include "../buffer.h"
58 #include "../syncQueue.h"
59 #include "syncRtpCommand.h"
60 #include "rtpSessionTable.h"
61 #include "callIdQueue.h"
64 #define MAX_COMMAND_LENGTH 1000
66 CommandHandler::CommandHandler(SyncQueue& q, std::string lp,PortWindow& pw) : thread_(boost::bind(run,this)),
67 queue_(q), running_(true), control_sock_(io_service_),
68 local_address_(""), local_port_(lp),port_window_(pw)
70 proto::resolver resolver(io_service_);
71 proto::resolver::query query(local_port_);
72 proto::endpoint e = *resolver.resolve(query);
73 control_sock_.open(e.protocol());
74 control_sock_.bind(e);
77 CommandHandler::CommandHandler(SyncQueue& q, string la, std::string lp, PortWindow& pw) : thread_(boost::bind(run,this)),
78 queue_(q), running_(true), control_sock_(io_service_),
79 local_address_(la), local_port_(lp),port_window_(pw)
81 proto::resolver resolver(io_service_);
82 proto::resolver::query query(local_address_, local_port_);
83 proto::endpoint e = *resolver.resolve(query);
84 control_sock_.open(e.protocol());
85 control_sock_.bind(e);
88 void CommandHandler::run(void* s)
90 CommandHandler* self = reinterpret_cast<CommandHandler*>(s);
92 Buffer buf(uint32_t(MAX_COMMAND_LENGTH));
94 proto::endpoint remote_end;
98 buf.setLength(MAX_COMMAND_LENGTH);
100 len = self->control_sock_.receive_from(boost::asio::buffer(buf.getBuf(), buf.getLength()), remote_end);
103 std::string ret = self->handle(std::string(reinterpret_cast<char*>(buf.getBuf()), buf.getLength())); // TODO: reinterpret is ugly
105 cLog.msg(Log::PRIO_DEBUG) << "CommandHandler received Command from " << remote_end << ", ret='" << ret << "'";
107 self->control_sock_.send_to(boost::asio::buffer(ret.c_str(), ret.length()), remote_end);
109 } catch(std::exception& e) {
110 self->running_ = false;
112 self->running_ = false;
115 bool CommandHandler::isRunning()
122 std::string CommandHandler::handle(std::string command)
124 istringstream iss(command);
130 oss << cookie << " ";
132 if(iss.bad() || iss.eof()) {
133 oss << RET_ERR_SYNTAX;
138 std::vector<std::string> params;
139 while(!iss.bad() && !iss.eof()) {
142 params.push_back(tmp);
145 switch(std::toupper(cmd[0])) {
147 if(params.size() < 4) { oss << RET_ERR_SYNTAX; break; }
148 oss << handleRequest(cmd.erase(0,1), params[0], params[1], params[2], params[3], (params.size() < 5) ? "" : params[4]);
151 if(params.size() < 4) { oss << RET_ERR_SYNTAX; break; }
152 oss << handleResponse(cmd.erase(0,1), params[0], params[1], params[2], params[3], (params.size() < 5) ? "" : params[4]);
155 if(params.size() < 2) { oss << RET_ERR_SYNTAX; break; }
156 oss << handleDelete(params[0], params[1], (params.size() < 3) ? "" : params[2]);
159 if(cmd.length() > 1 && cmd[1] == 'F') {
160 if(params.size() < 1) { oss << RET_ERR_SYNTAX; break; }
161 oss << handleVersionF(params[0]);
164 oss << handleVersion();
170 oss << RET_ERR_SYNTAX;
177 string CommandHandler::handleRequest(string modifiers, string call_id, string addr, string port, string from_tag, string to_tag)
179 std::cout << "received request[" << modifiers << "] command ('" << call_id << "','" << addr << "','" << port
180 << "','" << from_tag << "','" << to_tag << "')" << std::endl;
183 RtpSession::proto::resolver resolver(io_service_);
185 RtpSession& session = gRtpSessionTable.getOrNewSession(call_id, is_new);
187 uint16_t port1 = port_window_.newPort(); // TODO: get next available port
188 uint16_t port2 = port_window_.newPort(); // TODO: get next available port
189 if(!port1 || !port2) {
190 if(port1) { port_window_.freePort(port1); }
191 if(port2) { port_window_.freePort(port2); }
192 throw std::runtime_error("no free port found");
194 std::stringstream ps1, ps2;
198 RtpSession::proto::endpoint e1, e2;
199 if(gOpt.getLocalAddr() == "") {
200 RtpSession::proto::resolver::query query1(ps1.str());
201 e1 = *resolver.resolve(query1);
202 RtpSession::proto::resolver::query query2(ps2.str());
203 e2 = *resolver.resolve(query2);
205 RtpSession::proto::resolver::query query1(gOpt.getLocalAddr(),ps1.str());
206 e1 = *resolver.resolve(query1);
207 RtpSession::proto::resolver::query query2(gOpt.getLocalAddr(),ps2.str());
208 e2 = *resolver.resolve(query2);
211 session.setLocalEnd1(e1);
212 session.setLocalEnd2(e2);
214 RtpSession::proto::resolver::query query(addr,port);
215 session.setRemoteEnd1(*resolver.resolve(query));
218 oss << session.getLocalEnd2().port();
220 } catch(std::exception& e) {
221 return RET_ERR_UNKNOWN; // TODO: change to corret error value
225 string CommandHandler::handleResponse(string modifiers, string call_id, string addr, string port, string from_tag, string to_tag)
227 std::cout << "received response[" << modifiers << "] command ('" << call_id << "','" << addr << "','" << port
228 << "','" << from_tag << "','" << to_tag << "')" << std::endl;
231 RtpSession& session = gRtpSessionTable.getSession(call_id);
232 RtpSession::proto::resolver resolver(io_service_);
233 RtpSession::proto::resolver::query query(addr,port);
234 session.setRemoteEnd2(*resolver.resolve(query));
235 session.isComplete(true);
236 SyncRtpCommand sc(call_id);
240 oss << session.getLocalEnd1().port();
242 } 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;
252 RtpSession& session = gRtpSessionTable.getSession(call_id);
253 session.isDead(true);
254 SyncRtpCommand sc(call_id);
258 } catch(std::exception& e) {
259 return RET_ERR_UNKNOWN; // TODO: change to corret error value
263 string CommandHandler::handleVersion()
265 std::cout << "received version command" << std::endl;
269 string CommandHandler::handleVersionF(string date_code)
271 std::cout << "received version[F] command ('" << date_code << "')" << std::endl;
272 if(!date_code.compare(SUP_VERSION)) {
279 string CommandHandler::handleInfo()
281 std::cout << "received info command, ignoring" << std::endl;