Imported Upstream version 0.3
[anytun.git] / src / syncClient.cpp
1 /*
2  *  anytun
3  *
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.
12  *
13  *
14  *  Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl, 
15  *                          Christian Pointner <satp@wirdorange.org>
16  *
17  *  This file is part of Anytun.
18  *
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.
22  *
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.
27  *
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/>.
30  */
31 #include <sstream>
32 #include <iostream>
33 #include <string>
34 #include "connectionList.h"
35 #include "syncCommand.h"
36
37 #include <boost/archive/text_oarchive.hpp>
38 #include <boost/archive/text_iarchive.hpp>
39
40
41 #include "log.h"
42 #include "syncClient.h"
43 #include "syncTcpConnection.h"
44 #include "buffer.h"
45 #include <boost/array.hpp>
46
47
48 SyncClient::SyncClient(std::string hostname,std::string port)
49 :hostname_( hostname),port_(port)
50 {
51 }
52
53 void SyncClient::run()
54 {
55         bool connected(false);
56         for(;;)
57         {
58                 try
59                 {
60                         boost::asio::io_service io_service;
61                         SyncTcpConnection::proto::resolver resolver(io_service);
62                         SyncTcpConnection::proto::resolver::query query( hostname_, port_);
63                   SyncTcpConnection::proto::resolver::iterator endpoint_iterator = resolver.resolve(query);
64                         SyncTcpConnection::proto::resolver::iterator end;
65
66                         SyncTcpConnection::proto::socket socket(io_service);
67                         boost::system::error_code error = boost::asio::error::host_not_found;
68                         while (error && endpoint_iterator != end)
69                         {
70                                 socket.close();
71                                 socket.connect(*endpoint_iterator++, error);
72                         }
73                         if (error)
74                                 throw boost::system::system_error(error);
75                         if (!connected)
76                                 cLog.msg(Log::PRIO_NOTICE) << "sync: connected to " << hostname_ <<":"<< port_;
77                         connected=true;
78                         readAndProcess(socket); //endless loop
79                 }
80                 catch (std::exception& e)
81                 {
82                         if (connected) 
83                                 cLog.msg(Log::PRIO_NOTICE) << "sync: connection to " << hostname_ <<":"<< port_<< " lost ("<< e.what() << ") retrying every 10sec";
84                         connected=false;
85                         boost::this_thread::sleep(boost::posix_time::milliseconds(10000));
86                 }
87         }
88 }
89
90 void SyncClient::readAndProcess(SyncTcpConnection::proto::socket & socket)
91 {
92         ConnectionList & cl_ (gConnectionList);
93         size_t message_lenght ;
94         for (;;)
95         {
96                 std::stringstream message_lenght_stream;
97                 readExactly(socket,5,message_lenght_stream);
98                 message_lenght_stream >> message_lenght;
99                 std::stringstream void_stream;
100                 readExactly(socket,1,void_stream); //skip space
101                 std::stringstream sync_command_stream;
102                 readExactly(socket,message_lenght, sync_command_stream);
103                 //cLog.msg(Log::PRIO_NOTICE) << "recieved sync inforamtaion "<<tmp.str()<< std::endl;
104                 boost::archive::text_iarchive ia(sync_command_stream);
105                 SyncCommand scom(cl_);
106                 ia >> scom;
107         }
108 }
109
110 void SyncClient::readExactly(SyncTcpConnection::proto::socket & socket,size_t toread, std::iostream & result)
111 {
112         size_t hasread = 0;
113         while (toread > hasread)
114         {
115                         //TODO read bigger buffers
116                         boost::array<char, 1> buf;
117                         boost::system::error_code error;
118                         size_t len = socket.read_some(boost::asio::buffer(buf), error);
119                         if (error == boost::asio::error::eof)
120                                 break; // Connection closed cleanly by peer.
121                         else if (error)
122                                 throw boost::system::system_error(error); // Some other error.
123                         //for (size_t pos=0; pos<len; pos++)
124                                 result<<buf[0];
125                         hasread+=len;
126         }
127 }