SockIt

UdpServer.cpp

Go to the documentation of this file.
00001 /* Udpserver.cpp
00002  *
00003  * Listens to connections over UDP. This class is directly exposed to the Javascript. Will not listen to the port
00004  * specified until the listen() method is invoked. This is so the handlers can be attached beforehand.
00005  *
00006  */
00007 
00008 #include "UdpServer.h"
00009 
00010 
00011 UdpServer::UdpServer(int port, boost::asio::io_service & io_service) 
00012     : Udp("SERVER", port, io_service), socket(new udp::socket(io_service))
00013 {
00014     initialize();
00015 }
00016 
00017 
00018 UdpServer::UdpServer(int port, boost::asio::io_service & io_service, map<string, string> options) 
00019     : Udp("SERVER", port, io_service), socket(new udp::socket(io_service))
00020 {
00021     parse_args(options);
00022 
00023     initialize();
00024 }
00025 
00026 
00027 void UdpServer::shutdown()
00028 {
00029     if(!failed)
00030     {
00031         should_close = true;
00032 
00033         if (pending_sends == 0) {
00034             fire_close();
00035             close();
00036         }
00037     }
00038     else
00039     {
00040         // Log & fire an error
00041         string message("Trying to shutdown a permanently failed UDP server!");
00042         Logger::error(message, port, host);
00043     }
00044 
00045 }
00046 
00047 void UdpServer::close()
00048 {
00049     /*
00050     if (socket->is_open())
00051     {
00052         if(multicast && multicast_group)
00053         {
00054             socket->set_option(
00055                     boost::asio::ip::multicast::leave_group(
00056                         boost::asio::ip::address::from_string(*multicast_group)));
00057         }
00058 
00059         socket->close();
00060     }
00061     */
00062     if(socket->is_open())
00063         socket->close();
00064 }
00065 
00066 
00067 void UdpServer::initialize()
00068 {
00069     log_options();
00070 
00071     listening = false;
00072 
00073     if(using_ipv6 && *using_ipv6)
00074         socket->open(udp::v6());
00075     else
00076         socket->open(udp::v4());
00077 
00078     if(!socket->is_open())
00079     {
00080         string message("UDP server failed to initialize, could not open socket");
00081         Logger::error(message, port, host);
00082         fire_error(message);
00083     }
00084 
00085     // synchronize the buffer size of the socket with this class's buffer size
00086     boost::asio::socket_base::receive_buffer_size buf_size_option(BUFFER_SIZE);
00087     socket->set_option(buf_size_option);
00088 
00089     if(do_not_route)
00090     {
00091         boost::asio::socket_base::do_not_route option(*do_not_route);
00092         socket->set_option(option);
00093     }
00094 
00095     if(reuse_address)
00096     {
00097         boost::asio::socket_base::reuse_address option(*reuse_address);
00098         socket->set_option(option);
00099     }
00100 
00101     if(multicast)
00102     {
00103         /* force this to be set */
00104         boost::asio::socket_base::reuse_address option(true);
00105         socket->set_option(option);
00106     }
00107 
00108     if(multicast_ttl)
00109     {
00110         boost::asio::ip::multicast::hops option(*multicast_ttl);
00111         socket->set_option(option);
00112     }
00113 
00114     // register these methods so they can be invoked from the Javascript
00115     registerMethod("listen", make_method(this, &UdpServer::start_listening));
00116 }
00117 
00118 
00119 UdpServer::~UdpServer()
00120 {
00121     close();
00122 }
00123 
00124 
00125 void UdpServer::start_listening()
00126 {
00127     if(failed)
00128     {
00129         // Log & fire an error
00130         string message("Trying to start a UDP server that has permanently failed!");
00131         Logger::error(message, port, host);
00132         return;
00133     }
00134 
00135     if(listening) return;
00136 
00137     try
00138     {
00139         if(using_ipv6 && *using_ipv6)
00140             socket->bind(udp::endpoint(udp::v6(), port));
00141         else
00142             socket->bind(udp::endpoint(udp::v4(), port));
00143     }
00144     catch (boost::system::system_error &e)
00145     {
00146         // Catch this error, and fail gracefully
00147         string message(string("Caught error initializing UDP server: '") + e.what() + "'");
00148         Logger::error(message, port, host);
00149 
00150         // Stop this server from ever doing anything again
00151         failed = true;
00152         return;
00153     }
00154 
00155     Logger::info("bind!", port, host);
00156 
00157     if(multicast)
00158     {
00159         if(!multicast_group)
00160         {
00161             Logger::error("UdpServer: Multicast set, but no multicast group given", port, host);
00162         }
00163         else
00164         {
00165             // Try to join the multicast group, and fail gracefully if we can't join it
00166             try
00167             {
00168                 socket->set_option(boost::asio::ip::multicast::join_group(
00169                             boost::asio::ip::address::from_string(*multicast_group)));
00170             }
00171             catch(boost::system::system_error & error)
00172             {
00173                 // Catch this error, and fail gracefully
00174                 string message(string("Caught error initializing UDP joinging multicast group: '") + error.what() + "'");
00175                 Logger::error(message, port, host);
00176 
00177                 failed = true;
00178                 return;
00179             }
00180         }
00181     }
00182 
00183     listen();
00184     fire_open();
00185 
00186     listening = true;
00187 }
00188 
00189 
00190 void UdpServer::listen()
00191 {
00192     Logger::info("udpserver: starting to listen", port, host);
00193 
00194     if(remote_endpoint && remote_endpoint.get())
00195         socket->async_receive_from(boost::asio::buffer(receive_buffer), *remote_endpoint,
00196                 boost::bind(&UdpServer::receive_handler, this, _1, _2, socket, remote_endpoint, host, port));
00197     else
00198         Logger::warn("remote endpoint is null", port, host);
00199 }
00200 
00201 int UdpServer::get_port()
00202 {
00203     return port;
00204 }
00205 
00206 
00207 void UdpServer::fire_error_event(const string & message)
00208 {
00209     fire_error(message);
00210 }
00211 
00212 
00213 void UdpServer::fire_data_event(const string data, boost::shared_ptr<udp::socket> socket, boost::shared_ptr<udp::endpoint> endpoint)
00214 {
00215     fire_data(boost::make_shared<UdpEvent>(this, socket, endpoint, data));
00216 }
 All Classes Files Functions Variables Typedefs Friends Defines