L:/channel/channel/include/TcpSockConnector.h

Go to the documentation of this file.
00001 
00002 // Copyright (c) 2005, 2006 Yigong Liu
00003 // Permission to use, copy, modify, distribute and sell this software for any 
00004 //     purpose is hereby granted without fee, provided that the above copyright 
00005 //     notice appear in all copies and that both that copyright notice and this 
00006 //     permission notice appear in supporting documentation.
00007 // The author makes no representations about the 
00008 //     suitability of this software for any purpose. It is provided "as is" 
00009 //     without express or implied warranty.
00011 
00012 #ifndef _TCP_SOCK_CONNECTOR_
00013 #define _TCP_SOCK_CONNECTOR_
00014 
00015 //for tcp socket
00016 #include "ace/SOCK_Acceptor.h"
00017 #include "ace/SOCK_Connector.h"
00018 #include "ace/SOCK_Stream.h"
00019 #include "ace/INET_Addr.h"
00020 //acceptor-connector-svc_handler framework
00021 #include "ace/Acceptor.h"
00022 #include "ace/Connector.h"
00023 #include "ace/Svc_Handler.h"
00024 //for msg marshalling/demarshalling
00025 #include "ace/CDR_Stream.h"
00026 #include "ace/Message_Block.h"
00027 //other major headers
00028 #include "ace/Task.h"
00029 #include "ace/Thread_Manager.h"
00030 #include "ace/Thread_Mutex.h"
00031 #include "ace/Thread_Semaphore.h"
00032 #include "ace/Get_Opt.h"
00033 #include "ace/Reactor.h"
00034 #include "ace/Service_Object.h"
00035 #include "ace/Signal.h"
00036 #include "ace/Handle_Set.h"
00037 #include "ace/FILE_Addr.h"
00038 #include "ace/OS.h"
00039 #include "ace/os_include/os_netdb.h"
00040 #include "ace/Log_Msg.h"
00041 #include "ace/Synch_Options.h"
00042 
00043 //chan
00044 #include <BaseDef.h>
00045 
00046 //std
00047 #include <iostream>
00048 #include <sstream>
00049 #include <string>
00050 #include <sstream>
00051 #include <vector>
00052 #include <algorithm>
00053 #include <netinet/in.h>
00054 
00059 namespace channel {
00060 
00061   class ConnInfo;
00062   template <class, class> class ConnHandler;
00063   template <class, class> class Connector;
00064   template <class> class TcpSockTransport;
00065 
00066   u_short UNDEFINED_TCP_PORT=0;
00067   u_short DEFAULT_TCP_PORT=3456;
00068 
00071   template <class Channel>
00072   class Tcp_ConnHandler
00073     : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>, 
00074       public ConnHandler<Channel, TcpSockTransport<Channel> > {
00075     public:
00076     typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> PARENT;
00077     Tcp_ConnHandler () {}
00078     virtual int open (void *) // Initialization hook method.
00079       {
00080         ACE_DEBUG ((LM_DEBUG, "a new tcp conn comes up...\n"));
00081 
00082         int bufsiz = ACE_DEFAULT_MAX_SOCKET_BUFSIZ;
00083         peer ().set_option (SOL_SOCKET, SO_SNDBUF,
00084                             &bufsiz, sizeof bufsiz);
00085 
00086         return activate (THR_NEW_LWP | THR_DETACHED);
00087       }
00088     virtual int close(u_long flag=0)
00089       {
00090         ACE_UNUSED_ARG(flag);
00091         ACE_DEBUG ((LM_DEBUG, "(%t) Tcp_ConnHandler<Channel>::close\n"));
00092         if(this->cm_ != NULL && this->cm_->exit_start_) {
00093           ACE_DEBUG ((LM_DEBUG, "(%t) Tcp_ConnHandler<Channel>::close: release exit_sema_\n"));
00094           //Q: why need this->
00095           this->cm_->exit_sema_.release();
00096           //free resources
00097           PARENT::close();
00098         }
00099         return 0;
00100       }
00101     virtual void shut_down(void) {
00102       //close the stream, hope the reader thread will wake up
00103       //try to shutdown the thread and clean up data gracely
00104       ACE_DEBUG((LM_DEBUG,"one tcp socket close...\n"));
00105       ACE_OS::closesocket(get_handle());
00106       //peer().close();
00107     }
00108     virtual ACE_SOCK_Stream &peer_stream(void) {
00109       return (ACE_SOCK_Stream &) ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>::peer();
00110     }
00111     virtual int svc (void) 
00112       { 
00113         return ConnHandler<Channel, TcpSockTransport<Channel> >::service(); 
00114       }
00115   };
00116 
00118   template <class Channel>
00119   class Tcp_Acceptor
00120     : public ACE_Acceptor<Tcp_ConnHandler<Channel>, ACE_SOCK_Acceptor> {
00121     public:
00122     typedef ACE_Acceptor<Tcp_ConnHandler<Channel>, ACE_SOCK_Acceptor>
00123       PARENT;
00124 
00125     Connector<Channel, TcpSockTransport<Channel> > *cm_;
00126     virtual int activate_svc_handler (Tcp_ConnHandler<Channel> *sh)
00127       {
00128         //hook up connection handler with framework
00129         sh->set_up (cm_, PASSIVE_ROLE);
00130         //activate threads etc
00131         if(PARENT::activate_svc_handler(sh)==-1) return -1;
00132         return 0;
00133       }
00134 
00135     //all use default behaviour
00136   };
00137 
00139   template <class Channel>
00140   class Tcp_Connector
00141     : public ACE_Connector<Tcp_ConnHandler<Channel>, ACE_SOCK_Connector> {
00142     public:
00143     typedef ACE_Connector<Tcp_ConnHandler<Channel>, ACE_SOCK_Connector>
00144       PARENT;
00145 
00146     Connector<Channel, TcpSockTransport<Channel> > *cm_;
00147     virtual int activate_svc_handler (Tcp_ConnHandler<Channel> *sh)
00148       {
00149         //hook up connection handler with framework
00150         sh->set_up (cm_, ACTIVE_ROLE);
00151         //activate threads etc
00152         if(PARENT::activate_svc_handler(sh)==-1) return -1;
00153         return 0;
00154       }
00155 
00156    //all use default behaviours 
00157   };
00158 
00160   template <class Channel>
00161     class  TcpSockTransport {
00162     typedef ConnHandler<Channel, TcpSockTransport<Channel> > ConnHandler;
00163     typedef Connector<Channel, TcpSockTransport<Channel> > Connector;
00164     private:
00165 
00166     // address I am listening for new connections
00167     std::string host_addr_;
00168     u_short port_;
00169     // Factory that passively wait for connections
00170     Tcp_Acceptor<Channel> tcp_acceptor_;
00171     // Factory that actively connects to remotes
00172     Tcp_Connector<Channel> tcp_connector_;
00173 
00174     public:
00175 
00176     typedef TcpSockTransport<Channel> TransportType;
00177 
00178     TcpSockTransport(Connector *c) {
00179       port_ = UNDEFINED_TCP_PORT;
00180       //pass cm to conn_handlers thru acceptor/connector
00181       tcp_acceptor_.cm_ = c;
00182       tcp_connector_.cm_ = c;
00183     }
00184     static Interface_Type type(void) { return INET_SOCK; }
00185 
00186     //helpers
00187     std::string host_addr(void) { return host_addr_; }
00188     int port(void) { return port_;}
00189 
00191     Status get_my_ip(std::string &addr) {
00192       struct hostent *host_info;
00193       ACE_utsname host_data;
00194       if (ACE_OS::uname (&host_data) < 0)
00195         return FAILURE;
00196       if ((host_info = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR(host_data.nodename))) == NULL)
00197         return FAILURE;
00198       long host,host_addr;
00199       ACE_OS::memcpy ((char *) &host,
00200                       (char *) host_info->h_addr,
00201                       host_info->h_length);
00202       host_addr = ntohl(host);
00203       ACE_DEBUG ((LM_DEBUG, "my name =[%s]  my addr=[%ld]\n", host_data.nodename, host_addr));
00204       ACE_INET_Addr inaddr(1234,host_addr);
00205       addr = inaddr.get_host_addr();
00206       ACE_DEBUG ((LM_DEBUG, "my_addr=[%s]\n",addr.c_str()));
00207       return SUCCESS;
00208     }
00209 
00211     Status get_map_index(ConnInfo &addr)
00212       {
00213         std::string addr_index;
00214         ACE_INET_Addr inaddr(addr.port(), addr.ip().c_str());
00215         if(std::string(addr.get_host_addr()).find(ACE_LOCALHOST)!=std::string::npos) {
00216           if (get_my_ip(addr_index) != SUCCESS)
00217             return FAILURE;
00218         }
00219         else
00220           addr_index = inaddr.get_host_addr();
00221         addr.set_host_addr (addr_index.c_str());
00222         return SUCCESS;
00223       }
00224     
00226     Status open(ConnInfo ci)
00227       {
00228         port_ = ci.port();
00229 
00230         ACE_DEBUG ((LM_DEBUG, "============= My Info ==============\n"));
00231 
00232         if(port_ != UNDEFINED_TCP_PORT) {
00233           ACE_INET_Addr addr(port_, INADDR_ANY);
00234           ACE_DEBUG ((LM_DEBUG, "port=%d host_name=%s\n",port_, addr.get_host_name()));
00235 
00236           if (get_my_ip(host_addr_) != SUCCESS)
00237             return FAILURE;
00238  
00239           if(tcp_acceptor_.open(addr) == -1) {//start listening for incoming connections
00240             ACE_DEBUG ((LM_DEBUG, "fail to open tcp lsitening sock...\n"));
00241             return FAILURE;
00242           }
00243         }
00244         ACE_DEBUG ((LM_DEBUG, "=================================\n"));
00245         return SUCCESS;
00246       }
00247 
00248     Status close(void)
00249       {
00250         if(port_ != UNDEFINED_TCP_PORT)
00251           tcp_acceptor_.close();  //?
00252         return SUCCESS;
00253       }
00254 
00256     Status connect(ConnInfo addr, ConnHandler *&conn_handler)
00257       {
00258         ACE_DEBUG ((LM_DEBUG, "TcpSockTransport<Channel>::connect...\n"));
00259 
00260         addr.dump();
00261         ACE_INET_Addr inaddr(addr.port(), addr.ip().c_str());
00262 
00263         Tcp_ConnHandler<Channel> *handler=NULL;
00264         handler = new Tcp_ConnHandler<Channel>();
00265         if(tcp_connector_.connect(handler, inaddr, ACE_Synch_Options::synch) == -1) //ask connector create conn handler
00266           if (errno != EWOULDBLOCK) {
00267             ACE_DEBUG ((LM_DEBUG, " !!! server %s | %d is DOWN !!!\n", inaddr.get_host_addr(), inaddr.get_port_number()));
00268             delete handler;
00269             return FAILURE; 
00270           }
00271         conn_handler = handler;
00272         ACE_DEBUG ((LM_DEBUG, "TcpSockTransport<Channel>::connect...finish...\n"));
00273         return SUCCESS;
00274       }
00275     Status disconnect(ConnInfo addr) { 
00276       ACE_UNUSED_ARG(addr);
00277       return SUCCESS; }
00278 
00279   };
00280 
00281 };
00282 
00283 #endif
00284 

Generated on Mon Feb 27 19:59:21 2006 for channel by  doxygen 1.4.6-NO