ana/test/ana_client.cpp

Go to the documentation of this file.
00001 /* $Id: ana_client.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 
00003 /**
00004  * @file
00005  * @brief Client side chat application. Example for the ana project.
00006  *
00007  * ana: Asynchronous Network API.
00008  * Copyright (C) 2010 - 2012 Guillermo Biset.
00009  *
00010  * This file is part of the ana project.
00011  *
00012  * System:         ana
00013  * Language:       C++
00014  *
00015  * Author:         Guillermo Biset
00016  * E-Mail:         billybiset AT gmail DOT com
00017  *
00018  * ana is free software: you can redistribute it and/or modify
00019  * it under the terms of the GNU General Public License as published by
00020  * the Free Software Foundation, either version 2 of the License, or
00021  * (at your option) any later version.
00022  *
00023  * ana is distributed in the hope that it will be useful,
00024  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00025  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026  * GNU General Public License for more details.
00027  *
00028  * You should have received a copy of the GNU General Public License
00029  * along with ana.  If not, see <http://www.gnu.org/licenses/>.
00030  *
00031  */
00032 
00033 #include <iostream>
00034 
00035 #include "ana.hpp"
00036 
00037 using namespace ana;
00038 
00039 const port DEFAULT_PORT = "2000";
00040 
00041 const char* const DEFAULT_ADDRESS = "127.0.0.1";
00042 const char* const DEFAULT_NAME    = "Unnamed";
00043 
00044 
00045 void show_help(char* const command)
00046 {
00047     std::cout << "The following options should be given in order and are all optional:\n"
00048         "\tName:            [recommended] Set name. Default=" << DEFAULT_NAME << std::endl <<
00049         "\tAddress:         [optional]    Set address. Default=" << DEFAULT_ADDRESS << std::endl <<
00050         "\tPort:            [optional]    Set port. Default=" << DEFAULT_PORT << std::endl <<
00051         "\tProxy address:   [optional]    Set proxy address." << std::endl <<
00052         "\tProxy port:      [optional]    Set proxy port." << std::endl <<
00053         "\tProxy user:      [optional]    Set proxy authentication user name." << std::endl <<
00054         "\tProxy password:  [optional]    Set proxy authentication password." << std::endl <<
00055         "Examples:\n" <<
00056         "\t" << command << " billy localhost 12345\n" <<
00057         "\t\tConnect to a local server on port 12345 with nick billy.\n" <<
00058         "\t" << command << " billy X.K.C.D 12345 localhost 3128 foo bar\n" <<
00059         "\t\tConnect to a remote server at X.K.C.D:12345 using a local proxy with credentials foo:bar.\n\n";
00060         ;
00061 }
00062 
00063 struct connection_info
00064 {
00065     connection_info() :
00066         pt(DEFAULT_PORT),
00067         address(DEFAULT_ADDRESS),
00068         name(DEFAULT_NAME),
00069         proxyaddr(),
00070         proxyport(),
00071         user(),
00072         password()
00073     {
00074     }
00075 
00076     bool use_proxy() const
00077     {
00078         return proxyaddr != "" && proxyport != "";
00079     }
00080 
00081     port        pt;
00082     std::string address;
00083     std::string name;
00084     std::string proxyaddr;
00085     std::string proxyport;
00086     std::string user;
00087     std::string password;
00088 };
00089 
00090 class ChatClient : public ana::listener_handler,
00091                    public ana::send_handler,
00092                    public ana::connection_handler
00093 {
00094     public:
00095         ChatClient(connection_info ci) :
00096             conn_info_( ci ),
00097             continue_(true),
00098             client_( ana::client::create(ci.address, ci.pt) ),
00099             name_(ci.name)
00100         {
00101         }
00102 
00103         std::string get_name(const std::string& msg)
00104         {
00105             size_t pos = msg.find(" ");
00106 
00107             return msg.substr(pos+1);
00108         }
00109 
00110         void parse_command(const std::string& msg)
00111         {
00112             if (msg[1] == 'n') //Lame: assume name command
00113             {
00114                 name_ = get_name(msg);
00115             }
00116         }
00117 
00118         void run_input()
00119         {
00120             std::string msg;
00121             do
00122             {
00123                 std::cout << name_ << " : ";
00124                 std::getline(std::cin, msg);
00125 
00126                 if (msg[0] == '/')
00127                     parse_command(msg);
00128 
00129                 if (msg == "/quit")
00130                     std::cout << "\nExiting.\n";
00131                 else
00132                     if (!msg.empty())
00133                         client_->send( ana::buffer( msg ), this);
00134 
00135             } while ( (msg != "/quit") && continue_);
00136         }
00137 
00138         void run()
00139         {
00140             try
00141             {
00142 
00143                 if ( ! conn_info_.use_proxy() )
00144                     client_->connect( this );
00145                 else
00146                     client_->connect_through_proxy(conn_info_.proxyaddr,
00147                                                    conn_info_.proxyport,
00148                                                    this,
00149                                                    conn_info_.user,
00150                                                    conn_info_.password);
00151 
00152                 client_->set_listener_handler( this );
00153                 client_->run();
00154 
00155                 std::cout << "Available commands: \n"  <<
00156                              "    '/quit'      : Quit. \n"
00157                              "    '/who'       : List connected users. \n" <<
00158                              "    '/name name' : Change name." << std::endl;
00159 
00160                 run_input();
00161 
00162             }
00163             catch(const std::exception& e)
00164             {
00165                 std::cerr << e.what() << std::endl;
00166             }
00167 
00168             delete client_;
00169         }
00170 
00171     private:
00172 
00173         virtual void handle_connect( ana::error_code error, net_id server_id )
00174         {
00175             if ( error )
00176             {
00177                 std::cerr << "\nError connecting." << std::endl;
00178                 continue_ = false;
00179             }
00180             else
00181                 client_->send( ana::buffer( std::string("/name ") + name_) , this);
00182         }
00183 
00184         virtual void handle_disconnect( ana::error_code error, net_id server_id)
00185         {
00186             std::cerr << "\nServer disconnected. Enter to exit." << std::endl;
00187             continue_ = false;
00188         }
00189 
00190         virtual void handle_receive( ana::error_code error, net_id, ana::read_buffer msg)
00191         {
00192             if (! error)
00193             {
00194                 std::cout << std::endl << msg->string()
00195                           << std::endl << name_ << " : ";
00196                 std::cout.flush();
00197             }
00198         }
00199 
00200         virtual void handle_send( ana::error_code error, net_id client)
00201         {
00202             if ( error )
00203                 std::cout << "Error. Timeout?" << std::endl;
00204         }
00205 
00206         connection_info     conn_info_;
00207         bool                continue_;
00208         ana::client*        client_;
00209         std::string         name_;
00210 };
00211 
00212 int main(int argc, char **argv)
00213 {
00214     show_help(argv[0]);
00215 
00216     connection_info ci;
00217 
00218     if ( argc > 1 )
00219         ci.name      = argv[1];
00220     if ( argc > 2 )
00221         ci.address   = argv[2];
00222     if ( argc > 3 )
00223         ci.pt        = argv[3];
00224     if ( argc > 4 )
00225         ci.proxyaddr = argv[4];
00226     if ( argc > 5 )
00227         ci.proxyport = argv[5];
00228     if ( argc > 6 )
00229         ci.user      = argv[6];
00230     if ( argc > 7 )
00231         ci.password  = argv[7];
00232 
00233     std::cout << "Main client app.: Starting client" << std::endl;
00234 
00235     ChatClient client(ci);
00236     client.run();
00237 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Tue May 22 2012 01:03:40 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs