moved rtp stuff to anyrtpproxy and removed it from anytun
[anytun.git] / src / anyrtpproxy / commandHandler.cpp
blob01613ec87e3223d9ca4a7b546f0d40ed27b8f43c
1 /*
2 * anytun
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/>.
32 #include <sstream>
33 #include <vector>
35 #include <iomanip>
36 #include <iostream>
37 #include <sstream>
39 #include <boost/bind.hpp>
41 #include "commandHandler.h"
42 #include "../buffer.h"
43 #include "../log.h"
44 #include "../syncQueue.h"
45 #include "syncRtpCommand.h"
46 #include "rtpSessionTable.h"
47 #include "callIdQueue.h"
48 #include "options.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));
79 try
81 proto::endpoint remote_end;
83 int len;
84 while(1)
86 buf.setLength(MAX_COMMAND_LENGTH);
88 len = self->control_sock_.receive_from(boost::asio::buffer(buf.getBuf(), buf.getLength()), remote_end);
89 buf.setLength(len);
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()
107 return running_;
112 std::string CommandHandler::handle(std::string command)
114 istringstream iss(command);
115 ostringstream oss;
116 std::string cookie;
117 std::string cmd;
119 iss >> cookie;
120 oss << cookie << " ";
122 if(iss.bad() || iss.eof()) {
123 oss << RET_ERR_SYNTAX;
124 return oss.str();
126 iss >> cmd;
128 std::vector<std::string> params;
129 while(!iss.bad() && !iss.eof()) {
130 std::string tmp;
131 iss >> tmp;
132 params.push_back(tmp);
135 switch(std::toupper(cmd[0]))
137 case CMD_REQUEST:
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]);
140 break;
141 case CMD_RESPONSE:
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]);
144 break;
145 case CMD_DELETE:
146 if(params.size() < 2) { oss << RET_ERR_SYNTAX; break; }
147 oss << handleDelete(params[0], params[1], (params.size() < 3) ? "" : params[2]);
148 break;
149 case CMD_VERSION:
150 if(cmd.length() > 1 && cmd[1] == 'F') {
151 if(params.size() < 1) { oss << RET_ERR_SYNTAX; break; }
152 oss << handleVersionF(params[0]);
153 break;
155 oss << handleVersion();
156 break;
157 case CMD_INFO:
158 oss << handleInfo();
159 break;
160 default:
161 oss << RET_ERR_SYNTAX;
162 break;
165 return oss.str();
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;
173 try
175 RtpSession::proto::resolver resolver(io_service_);
176 bool is_new;
177 RtpSession& session = gRtpSessionTable.getOrNewSession(call_id, is_new);
178 if(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;
189 ps1 << port1;
190 ps2 << port2;
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);
199 else {
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));
212 ostringstream oss;
213 oss << session.getLocalEnd2().port();
214 return oss.str();
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);
235 queue_.push(sc);
237 ostringstream oss;
238 oss << session.getLocalEnd1().port();
239 return oss.str();
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);
256 queue_.push(sc);
258 return RET_OK;
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;
269 return BASE_VERSION;
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))
276 return "1";
278 return "0";
281 string CommandHandler::handleInfo()
283 std::cout << "received info command, ignoring" << std::endl;
284 return RET_OK;