Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <iostream>
00034 #include <iomanip>
00035
00036 #include "ana.hpp"
00037
00038 using namespace ana;
00039
00040 const port DEFAULT_PORT = "30303";
00041
00042 const char* const DEFAULT_ADDRESS = "127.0.0.1";
00043 const char* const DEFAULT_NAME = "Unnamed";
00044
00045
00046 void show_help(char* const command)
00047 {
00048 std::cout << "The following options should be given in order and are all optional:\n"
00049 "\tName: [recommended] Set name. Default=" << DEFAULT_NAME << std::endl <<
00050 "\tAddress: [optional] Set address. Default=" << DEFAULT_ADDRESS << std::endl <<
00051 "\tPort: [optional] Set port. Default=" << DEFAULT_PORT << std::endl <<
00052 "\tProxy address: [optional] Set proxy address." << std::endl <<
00053 "\tProxy port: [optional] Set proxy port." << std::endl <<
00054 "\tProxy user: [optional] Set proxy authentication user name." << std::endl <<
00055 "\tProxy password: [optional] Set proxy authentication password." << std::endl <<
00056 "Examples:\n" <<
00057 "\t" << command << " billy localhost 12345\n" <<
00058 "\t\tConnect to a local server on port 12345 with nick billy.\n" <<
00059 "\t" << command << " billy X.K.C.D 12345 localhost 3128 foo bar\n" <<
00060 "\t\tConnect to a remote server at X.K.C.D:12345 with proxy credentials foo:bar.\n\n";
00061 ;
00062 }
00063
00064 struct connection_info
00065 {
00066 connection_info() :
00067 pt(DEFAULT_PORT),
00068 address(DEFAULT_ADDRESS),
00069 name(DEFAULT_NAME),
00070 proxyaddr(),
00071 proxyport(),
00072 user(),
00073 password()
00074 {
00075 }
00076
00077 bool use_proxy() const
00078 {
00079 return proxyaddr != "" && proxyport != "";
00080 }
00081
00082 port pt;
00083 std::string address;
00084 std::string name;
00085 std::string proxyaddr;
00086 std::string proxyport;
00087 std::string user;
00088 std::string password;
00089 };
00090
00091 class ChatClient : public ana::listener_handler,
00092 public ana::send_handler,
00093 public ana::connection_handler
00094 {
00095 public:
00096 ChatClient(connection_info ci) :
00097 conn_info_( ci ),
00098 continue_(true),
00099 client_( ana::client::create(ci.address, ci.pt) ),
00100 name_(ci.name)
00101 {
00102 }
00103
00104 std::string get_name(const std::string& msg)
00105 {
00106 size_t pos = msg.find(" ");
00107
00108 return msg.substr(pos+1);
00109 }
00110
00111 double get_seconds(const std::string& msg)
00112 {
00113 size_t pos = msg.find(" ");
00114
00115 std::stringstream ss( msg.substr(pos+1) );
00116
00117 double result;
00118
00119 ss >> result;
00120
00121 return result;
00122 }
00123
00124
00125 void parse_command(const std::string& msg)
00126 {
00127 if (msg[1] == 'n')
00128 name_ = get_name(msg);
00129 else if (msg[1] == 's')
00130 {
00131 const ana::stats* acum_stats = client_->get_stats( ana::ACCUMULATED );
00132 const ana::stats* sec_stats = client_->get_stats( ana::SECONDS );
00133 const ana::stats* min_stats = client_->get_stats( ana::MINUTES );
00134 const ana::stats* hour_stats = client_->get_stats( ana::HOURS );
00135 const ana::stats* day_stats = client_->get_stats( ana::DAYS );
00136
00137 std::cout << " Network Statistics\n\n"
00138 << "Uptime : " << acum_stats->uptime() << " seconds.\n\n"
00139 << "+-----------------+-----------------+-----------------+\n"
00140 << "| | Packets | Bytes |\n"
00141 << "| +-----------------+--------+--------+\n"
00142 << "| | In | Out | In | Out |\n"
00143 << "+-----------------+--------+--------+--------+--------+\n"
00144 << "| Accumulated |" << std::setw(8) << acum_stats->packets_in() <<"|"
00145 << std::setw(8) << acum_stats->packets_out() <<"|"
00146 << std::setw(8) << acum_stats->bytes_in() <<"|"
00147 << std::setw(8) << acum_stats->bytes_out() <<"|\n"
00148 << "+-----------------+-----------------+-----------------+\n"
00149 << "| Last second |" << std::setw(8) << sec_stats->packets_in() <<"|"
00150 << std::setw(8) << sec_stats->packets_out() <<"|"
00151 << std::setw(8) << sec_stats->bytes_in() <<"|"
00152 << std::setw(8) << sec_stats->bytes_out() <<"|\n"
00153 << "+-----------------+-----------------+-----------------+\n"
00154 << "| Last minute |" << std::setw(8) << min_stats->packets_in() <<"|"
00155 << std::setw(8) << min_stats->packets_out() <<"|"
00156 << std::setw(8) << min_stats->bytes_in() <<"|"
00157 << std::setw(8) << min_stats->bytes_out() <<"|\n"
00158 << "+-----------------+-----------------+-----------------+\n"
00159 << "| Last hour |" << std::setw(8) << hour_stats->packets_in() <<"|"
00160 << std::setw(8) << hour_stats->packets_out() <<"|"
00161 << std::setw(8) << hour_stats->bytes_in() <<"|"
00162 << std::setw(8) << hour_stats->bytes_out() <<"|\n"
00163 << "+-----------------+-----------------+-----------------+\n"
00164 << "| Last day |" << std::setw(8) << day_stats->packets_in() <<"|"
00165 << std::setw(8) << day_stats->packets_out() <<"|"
00166 << std::setw(8) << day_stats->bytes_in() <<"|"
00167 << std::setw(8) << day_stats->bytes_out() <<"|\n"
00168 << "+-----------------+-----------------+-----------------+\n";
00169 }
00170 else if ( msg[1] == 'h' )
00171 {
00172 double seconds = get_seconds( msg );
00173 client_->expecting_message( ana::time::seconds( seconds ) );
00174 }
00175 }
00176
00177 void run_input()
00178 {
00179 std::string msg;
00180 do
00181 {
00182 std::cout << name_ << " : ";
00183 std::getline(std::cin, msg);
00184
00185 if (msg[0] == '/')
00186 parse_command(msg);
00187
00188 if (msg == "/quit")
00189 std::cout << "\nExiting.\n";
00190 else if (msg == "/empty")
00191 {
00192 const std::string empty_str;
00193
00194 client_->send( ana::buffer( empty_str ), this );
00195 }
00196 else
00197 if (!msg.empty())
00198 client_->send( ana::buffer( msg ), this);
00199
00200 } while ( (msg != "/quit") && continue_);
00201
00202 client_->disconnect();
00203 }
00204
00205 void run()
00206 {
00207 try
00208 {
00209 if ( ! conn_info_.use_proxy() )
00210 client_->connect( this );
00211 else
00212 client_->connect_through_proxy(conn_info_.proxyaddr,
00213 conn_info_.proxyport,
00214 this,
00215 conn_info_.user,
00216 conn_info_.password);
00217
00218 client_->set_listener_handler( this );
00219 client_->run();
00220 client_->set_timeouts(ana::FixedTime, ana::time::seconds(10));
00221
00222 std::cout << "Available commands: \n" <<
00223 " '/quit' : Quit. \n"
00224 " '/who' : List connected users. \n" <<
00225 " '/stats' : Print full network stats. \n" <<
00226 " '/hold secs' : Wait secs for a new message. \n" <<
00227 " '/name name' : Change name." << std::endl;
00228
00229 run_input();
00230
00231 }
00232 catch(const std::exception& e)
00233 {
00234 std::cerr << e.what() << std::endl;
00235 }
00236
00237 delete client_;
00238 }
00239
00240 private:
00241
00242 virtual void handle_connect( ana::error_code error, net_id server_id )
00243 {
00244 if ( error )
00245 {
00246 std::cerr << "\nError connecting." << std::endl;
00247 continue_ = false;
00248 }
00249 else
00250 client_->send( ana::buffer( std::string("/name ") + name_) , this);
00251 }
00252
00253 virtual void handle_disconnect( ana::error_code error, net_id server_id)
00254 {
00255 std::cerr << "\nServer disconnected. Enter to exit." << std::endl;
00256 continue_ = false;
00257 }
00258
00259 virtual void handle_receive( ana::error_code error, net_id, ana::read_buffer msg)
00260 {
00261 if (! error)
00262 {
00263 std::cout << std::endl << msg->string()
00264 << std::endl << name_ << " : ";
00265 std::cout.flush();
00266 }
00267 else if ( error == ana::timeout_error )
00268 std::cerr << "\nTimeout for waiting message.\n";
00269 }
00270
00271 virtual void handle_send( ana::error_code error, net_id client, ana::operation_id op_id)
00272 {
00273 if ( error )
00274 std::cout << "Error. Timeout?" << std::endl;
00275 }
00276
00277 connection_info conn_info_;
00278 bool continue_;
00279 ana::client* client_;
00280 std::string name_;
00281 };
00282
00283 int main(int argc, char **argv)
00284 {
00285 show_help(argv[0]);
00286
00287 connection_info ci;
00288
00289 if ( argc > 1 )
00290 ci.name = argv[1];
00291 if ( argc > 2 )
00292 ci.address = argv[2];
00293 if ( argc > 3 )
00294 ci.pt = argv[3];
00295 if ( argc > 4 )
00296 ci.proxyaddr = argv[4];
00297 if ( argc > 5 )
00298 ci.proxyport = argv[5];
00299 if ( argc > 6 )
00300 ci.user = argv[6];
00301 if ( argc > 7 )
00302 ci.password = argv[7];
00303
00304 std::cout << "Main client app.: Starting client" << std::endl;
00305
00306 ChatClient client(ci);
00307 client.run();
00308 }