00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include "config.h"
00025
00026 #include <cstring>
00027 #include <exception>
00028 #include <memory>
00029 #include <netdb.h>
00030 #include <sys/socket.h>
00031 #include <sys/types.h>
00032
00033 #include <scalestack/kernel/module.h>
00034 #include <scalestack/kernel/option.h>
00035 #include <scalestack/network/ip/address_service.h>
00036 #include <scalestack/network/ip/tcp/listener_service.h>
00037 #include <scalestack/network/listener.h>
00038 #include <scalestack/network/stream_service.h>
00039
00040 using namespace std;
00041
00042 namespace scalestack
00043 {
00044 namespace network
00045 {
00046 namespace ip
00047 {
00048 namespace tcp
00049 {
00050
00055 class listener_address_service: public ip::address_service
00056 {
00057 public:
00058
00059 listener_address_service(kernel::module& module,
00060 event::handler_service& _handler_service,
00061 stream_service_provider& _stream_service_provider);
00062
00066 bool add_addresses(const struct addrinfo* addresses);
00067
00068 private:
00069
00070 event::handler_service& _handler_service;
00071 stream_service_provider& _stream_service_provider;
00072 };
00073
00074
00075
00076
00077
00078 void listener_service::options(kernel::module& module,
00079 const std::string& addresses)
00080 {
00081 module.add_option("addresses", _("List of host:port pairs to listen on."),
00082 "[HOST:]PORT[,[HOST:]PORT]...", addresses);
00083 module.add_option("backlog", _("Backlog value to use for listen(2)."),
00084 "BACKLOG", "64");
00085 }
00086
00087 listener_service::listener_service(kernel::module& module,
00088 std::auto_ptr<stream_service_provider> stream_service_provider,
00089 const std::string& default_host):
00090 network::listener_service(module, stream_service_provider),
00091 _default_host(default_host)
00092 {
00093 }
00094
00095 listener_service::~listener_service()
00096 {
00097 _handler_service.stop();
00098 }
00099
00100 void listener_service::add_listeners(void)
00101 {
00102 add_listeners(_module.get_option("addresses").get_value());
00103 }
00104
00105 void listener_service::add_listeners(const std::string& addresses)
00106 {
00107 struct addrinfo address_options;
00108
00109 memset(&address_options, 0, sizeof(struct addrinfo));
00110 address_options.ai_flags = AI_PASSIVE;
00111 address_options.ai_family = AF_UNSPEC;
00112 address_options.ai_socktype = SOCK_STREAM;
00113 address_options.ai_protocol = IPPROTO_TCP;
00114
00115 listener_address_service address_service(_module, _handler_service,
00116 *_stream_service_provider);
00117 address_service.parse_addresses(addresses, true, _default_host,
00118 address_options);
00119 }
00120
00121
00122
00123
00124
00125 listener_address_service::listener_address_service(
00126 kernel::module& module,
00127 event::handler_service& handler_service,
00128 stream_service_provider& stream_service_provider):
00129 ip::address_service(module),
00130 _handler_service(handler_service),
00131 _stream_service_provider(stream_service_provider)
00132 {
00133 }
00134
00135 bool listener_address_service::add_addresses(const struct addrinfo* addresses)
00136 {
00137 char host_name[NI_MAXHOST];
00138 char port_name[NI_MAXSERV];
00139 int return_code;
00140 bool added = false;
00141
00142 for (; addresses != NULL; addresses = addresses->ai_next)
00143 {
00144 return_code = getnameinfo(addresses->ai_addr,
00145 addresses->ai_addrlen,
00146 host_name, NI_MAXHOST,
00147 port_name, NI_MAXSERV,
00148 NI_NUMERICHOST | NI_NUMERICSERV);
00149 if (return_code != 0)
00150 _module.log_fatal(_("Failed getnameinfo: %s"), gai_strerror(return_code));
00151
00152 _module.log_info(_("TCP listener trying to bind to %s:%s"), host_name,
00153 port_name);
00154 try
00155 {
00156 auto_ptr<listener> new_listener(
00157 new listener(_handler_service,
00158 *addresses,
00159 _module.get_option("backlog").get_int_value(),
00160 _stream_service_provider));
00161 new_listener->start();
00162 new_listener.release();
00163 added = true;
00164 _module.log_notice(_("TCP listener bound to %s:%s"), host_name,
00165 port_name);
00166 }
00167 catch (exception&)
00168 {
00169
00170 }
00171 }
00172
00173 if (!added)
00174 _module.log_fatal(_("Could not add any TCP listeners"));
00175
00176 return true;
00177 }
00178
00179 }
00180 }
00181 }
00182 }