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/datagram.h>
00036 #include <scalestack/network/datagram_service.h>
00037 #include <scalestack/network/ip/address_service.h>
00038 #include <scalestack/network/ip/udp/socket_service.h>
00039
00040 using namespace std;
00041
00042 namespace scalestack
00043 {
00044 namespace network
00045 {
00046 namespace ip
00047 {
00048 namespace udp
00049 {
00050
00055 class socket_address_service: public ip::address_service
00056 {
00057 public:
00058
00059 socket_address_service(kernel::module& module,
00060 socket_service& socket_service,
00061 bool local);
00062
00066 bool add_addresses(const struct addrinfo* addresses);
00067
00068 private:
00069
00070 bool _local;
00071 socket_service& _socket_service;
00072 };
00073
00074
00075
00076
00077
00078 void socket_service::local_options(kernel::module& module,
00079 const std::string& addresses)
00080 {
00081 module.add_option("addresses", _("List of host:port pairs to bind to."),
00082 "[HOST:]PORT[,[HOST:]PORT]...", addresses);
00083 }
00084
00085 void socket_service::peer_options(kernel::module& module,
00086 const std::string& addresses)
00087 {
00088 module.add_option("addresses", _("List of host:port pairs to send to."),
00089 "HOST[:PORT][,HOST[:PORT]]...", addresses);
00090 }
00091
00092 socket_service::socket_service(kernel::module& module,
00093 std::auto_ptr<datagram_service> datagram_service,
00094 const std::string& default_host,
00095 const std::string& default_port):
00096 kernel::service(module),
00097 _datagram_service(datagram_service),
00098 _default_host(default_host),
00099 _default_port(default_port),
00100 _handler_service(module)
00101 {
00102 }
00103
00104 socket_service::~socket_service()
00105 {
00106 _handler_service.stop();
00107 }
00108
00109 void socket_service::add_socket(const struct addrinfo* local,
00110 const struct addrinfo* peer)
00111 {
00112 char host_name[NI_MAXHOST];
00113 char port_name[NI_MAXSERV];
00114 int return_code;
00115
00116 if (local != NULL)
00117 {
00118 return_code = getnameinfo(local->ai_addr,
00119 local->ai_addrlen,
00120 host_name, NI_MAXHOST,
00121 port_name, NI_MAXSERV,
00122 NI_NUMERICHOST | NI_NUMERICSERV);
00123 if (return_code != 0)
00124 _module.log_fatal(_("Failed getnameinfo: %s"), gai_strerror(return_code));
00125
00126 _module.log_info(_("UDP socket trying to bind to %s:%s"), host_name,
00127 port_name);
00128 }
00129
00130 if (peer != NULL)
00131 {
00132 return_code = getnameinfo(peer->ai_addr,
00133 peer->ai_addrlen,
00134 host_name, NI_MAXHOST,
00135 port_name, NI_MAXSERV,
00136 NI_NUMERICHOST | NI_NUMERICSERV);
00137 if (return_code != 0)
00138 _module.log_fatal(_("Failed getnameinfo: %s"), gai_strerror(return_code));
00139
00140 _module.log_info(_("UDP socket with peer %s:%s"), host_name, port_name);
00141 }
00142
00143 auto_ptr<datagram_provider> new_socket(
00144 new datagram_provider(_handler_service, *_datagram_service, local, peer));
00145 new_socket->start();
00146 new_socket.release();
00147
00148 if (local != NULL)
00149 _module.log_notice(_("UDP socket bound to %s:%s"), host_name, port_name);
00150 }
00151
00152 void socket_service::add_local_sockets(void)
00153 {
00154 add_local_sockets(_module.get_option("addresses").get_value());
00155 }
00156
00157 void socket_service::add_local_sockets(const std::string& addresses)
00158 {
00159 struct addrinfo address_options;
00160
00161 memset(&address_options, 0, sizeof(struct addrinfo));
00162 address_options.ai_flags = AI_PASSIVE;
00163 address_options.ai_family = AF_UNSPEC;
00164 address_options.ai_socktype = SOCK_DGRAM;
00165 address_options.ai_protocol = IPPROTO_UDP;
00166
00167 socket_address_service address_service(_module, *this, true);
00168 address_service.parse_addresses(addresses, true, _default_host,
00169 address_options);
00170 }
00171
00172 void socket_service::add_peer_sockets(void)
00173 {
00174 add_peer_sockets(_module.get_option("addresses").get_value());
00175 }
00176
00177 void socket_service::add_peer_sockets(const std::string& addresses)
00178 {
00179 struct addrinfo address_options;
00180
00181 memset(&address_options, 0, sizeof(struct addrinfo));
00182 address_options.ai_flags = AI_PASSIVE;
00183 address_options.ai_family = AF_UNSPEC;
00184 address_options.ai_socktype = SOCK_DGRAM;
00185 address_options.ai_protocol = IPPROTO_UDP;
00186
00187 socket_address_service address_service(_module, *this, false);
00188 address_service.parse_addresses(addresses, false, _default_port,
00189 address_options);
00190 }
00191
00192
00193
00194
00195
00196 socket_address_service::socket_address_service(
00197 kernel::module& module, socket_service& socket_service, bool local):
00198 ip::address_service(module),
00199 _local(local),
00200 _socket_service(socket_service)
00201 {
00202 }
00203
00204 bool socket_address_service::add_addresses(const struct addrinfo* addresses)
00205 {
00206 if (!_local)
00207 {
00208 _socket_service.add_socket(NULL, addresses);
00209 return true;
00210 }
00211
00212 bool added = false;
00213 for (; addresses != NULL; addresses = addresses->ai_next)
00214 {
00215 try
00216 {
00217 _socket_service.add_socket(addresses, NULL);
00218 added = true;
00219 }
00220 catch (exception&)
00221 {
00222
00223 }
00224 }
00225
00226 if (!added)
00227 _module.log_fatal(_("Could not add any UDP sockets"));
00228
00229 return true;
00230 }
00231
00232 }
00233 }
00234 }
00235 }