diff options
Diffstat (limited to 'ml/dlib/dlib/bridge')
-rw-r--r-- | ml/dlib/dlib/bridge/bridge.h | 669 | ||||
-rw-r--r-- | ml/dlib/dlib/bridge/bridge_abstract.h | 347 |
2 files changed, 1016 insertions, 0 deletions
diff --git a/ml/dlib/dlib/bridge/bridge.h b/ml/dlib/dlib/bridge/bridge.h new file mode 100644 index 000000000..da4e0bd7e --- /dev/null +++ b/ml/dlib/dlib/bridge/bridge.h @@ -0,0 +1,669 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BRIDGe_Hh_ +#define DLIB_BRIDGe_Hh_ + +#include <iostream> +#include <memory> +#include <string> + +#include "bridge_abstract.h" +#include "../pipe.h" +#include "../threads.h" +#include "../serialize.h" +#include "../sockets.h" +#include "../sockstreambuf.h" +#include "../logger.h" +#include "../algs.h" + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + struct connect_to_ip_and_port + { + connect_to_ip_and_port ( + const std::string& ip_, + unsigned short port_ + ): ip(ip_), port(port_) + { + // make sure requires clause is not broken + DLIB_ASSERT(is_ip_address(ip) && port != 0, + "\t connect_to_ip_and_port()" + << "\n\t Invalid inputs were given to this function" + << "\n\t ip: " << ip + << "\n\t port: " << port + << "\n\t this: " << this + ); + } + + private: + friend class bridge; + const std::string ip; + const unsigned short port; + }; + + inline connect_to_ip_and_port connect_to ( + const network_address& addr + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(addr.port != 0, + "\t connect_to_ip_and_port()" + << "\n\t The TCP port to connect to can't be 0." + << "\n\t addr.port: " << addr.port + ); + + if (is_ip_address(addr.host_address)) + { + return connect_to_ip_and_port(addr.host_address, addr.port); + } + else + { + std::string ip; + if(hostname_to_ip(addr.host_address,ip)) + throw socket_error(ERESOLVE,"unable to resolve '" + addr.host_address + "' in connect_to()"); + + return connect_to_ip_and_port(ip, addr.port); + } + } + + struct listen_on_port + { + listen_on_port( + unsigned short port_ + ) : port(port_) + { + // make sure requires clause is not broken + DLIB_ASSERT( port != 0, + "\t listen_on_port()" + << "\n\t Invalid inputs were given to this function" + << "\n\t port: " << port + << "\n\t this: " << this + ); + } + + private: + friend class bridge; + const unsigned short port; + }; + + template <typename pipe_type> + struct bridge_transmit_decoration + { + bridge_transmit_decoration ( + pipe_type& p_ + ) : p(p_) {} + + private: + friend class bridge; + pipe_type& p; + }; + + template <typename pipe_type> + bridge_transmit_decoration<pipe_type> transmit ( pipe_type& p) { return bridge_transmit_decoration<pipe_type>(p); } + + template <typename pipe_type> + struct bridge_receive_decoration + { + bridge_receive_decoration ( + pipe_type& p_ + ) : p(p_) {} + + private: + friend class bridge; + pipe_type& p; + }; + + template <typename pipe_type> + bridge_receive_decoration<pipe_type> receive ( pipe_type& p) { return bridge_receive_decoration<pipe_type>(p); } + +// ---------------------------------------------------------------------------------------- + + struct bridge_status + { + bridge_status() : is_connected(false), foreign_port(0){} + + bool is_connected; + unsigned short foreign_port; + std::string foreign_ip; + }; + + inline void serialize ( const bridge_status& , std::ostream& ) + { + throw serialization_error("It is illegal to serialize bridge_status objects."); + } + + inline void deserialize ( bridge_status& , std::istream& ) + { + throw serialization_error("It is illegal to serialize bridge_status objects."); + } + +// ---------------------------------------------------------------------------------------- + + namespace impl_brns + { + class impl_bridge_base + { + public: + + virtual ~impl_bridge_base() {} + + virtual bridge_status get_bridge_status ( + ) const = 0; + }; + + template < + typename transmit_pipe_type, + typename receive_pipe_type + > + class impl_bridge : public impl_bridge_base, private noncopyable, private multithreaded_object + { + /*! + CONVENTION + - if (list) then + - this object is supposed to be listening on the list object for incoming + connections when not connected. + - else + - this object is supposed to be attempting to connect to ip:port when + not connected. + + - get_bridge_status() == current_bs + !*/ + public: + + impl_bridge ( + unsigned short listen_port, + transmit_pipe_type* transmit_pipe_, + receive_pipe_type* receive_pipe_ + ) : + s(m), + receive_thread_active(false), + transmit_thread_active(false), + port(0), + transmit_pipe(transmit_pipe_), + receive_pipe(receive_pipe_), + dlog("dlib.bridge"), + keepalive_code(0), + message_code(1) + { + int status = create_listener(list, listen_port); + if (status == PORTINUSE) + { + std::ostringstream sout; + sout << "Error, the port " << listen_port << " is already in use."; + throw socket_error(EPORT_IN_USE, sout.str()); + } + else if (status == OTHER_ERROR) + { + throw socket_error("Unable to create listening socket for an unknown reason."); + } + + register_thread(*this, &impl_bridge::transmit_thread); + register_thread(*this, &impl_bridge::receive_thread); + register_thread(*this, &impl_bridge::connect_thread); + + start(); + } + + impl_bridge ( + const std::string ip_, + unsigned short port_, + transmit_pipe_type* transmit_pipe_, + receive_pipe_type* receive_pipe_ + ) : + s(m), + receive_thread_active(false), + transmit_thread_active(false), + port(port_), + ip(ip_), + transmit_pipe(transmit_pipe_), + receive_pipe(receive_pipe_), + dlog("dlib.bridge"), + keepalive_code(0), + message_code(1) + { + register_thread(*this, &impl_bridge::transmit_thread); + register_thread(*this, &impl_bridge::receive_thread); + register_thread(*this, &impl_bridge::connect_thread); + + start(); + } + + ~impl_bridge() + { + // tell the threads to terminate + stop(); + + // save current pipe enabled status so we can restore it to however + // it was before this destructor ran. + bool transmit_enabled = true; + bool receive_enabled = true; + + // make any calls blocked on a pipe return immediately. + if (transmit_pipe) + { + transmit_enabled = transmit_pipe->is_dequeue_enabled(); + transmit_pipe->disable_dequeue(); + } + if (receive_pipe) + { + receive_enabled = receive_pipe->is_enqueue_enabled(); + receive_pipe->disable_enqueue(); + } + + { + auto_mutex lock(m); + s.broadcast(); + // Shutdown the connection if we have one. This will cause + // all blocked I/O calls to return an error. + if (con) + con->shutdown(); + } + + // wait for all the threads to terminate. + wait(); + + if (transmit_pipe && transmit_enabled) + transmit_pipe->enable_dequeue(); + if (receive_pipe && receive_enabled) + receive_pipe->enable_enqueue(); + } + + bridge_status get_bridge_status ( + ) const + { + auto_mutex lock(current_bs_mutex); + return current_bs; + } + + private: + + + template <typename pipe_type> + typename enable_if<is_convertible<bridge_status, typename pipe_type::type> >::type enqueue_bridge_status ( + pipe_type* p, + const bridge_status& status + ) + { + if (p) + { + typename pipe_type::type temp(status); + p->enqueue(temp); + } + } + + template <typename pipe_type> + typename disable_if<is_convertible<bridge_status, typename pipe_type::type> >::type enqueue_bridge_status ( + pipe_type* , + const bridge_status& + ) + { + } + + void connect_thread ( + ) + { + while (!should_stop()) + { + auto_mutex lock(m); + int status = OTHER_ERROR; + if (list) + { + do + { + status = list->accept(con, 1000); + } while (status == TIMEOUT && !should_stop()); + } + else + { + status = create_connection(con, port, ip); + } + + if (should_stop()) + break; + + if (status != 0) + { + // The last connection attempt failed. So pause for a little bit before making another attempt. + s.wait_or_timeout(2000); + continue; + } + + dlog << LINFO << "Established new connection to " << con->get_foreign_ip() << ":" << con->get_foreign_port() << "."; + + bridge_status temp_bs; + { auto_mutex lock(current_bs_mutex); + current_bs.is_connected = true; + current_bs.foreign_port = con->get_foreign_port(); + current_bs.foreign_ip = con->get_foreign_ip(); + temp_bs = current_bs; + } + enqueue_bridge_status(receive_pipe, temp_bs); + + + receive_thread_active = true; + transmit_thread_active = true; + + s.broadcast(); + + // Wait for the transmit and receive threads to end before we continue. + // This way we don't invalidate the con pointer while it is in use. + while (receive_thread_active || transmit_thread_active) + s.wait(); + + + dlog << LINFO << "Closed connection to " << con->get_foreign_ip() << ":" << con->get_foreign_port() << "."; + { auto_mutex lock(current_bs_mutex); + current_bs.is_connected = false; + current_bs.foreign_port = con->get_foreign_port(); + current_bs.foreign_ip = con->get_foreign_ip(); + temp_bs = current_bs; + } + enqueue_bridge_status(receive_pipe, temp_bs); + } + + } + + + void receive_thread ( + ) + { + while (true) + { + // wait until we have a connection + { auto_mutex lock(m); + while (!receive_thread_active && !should_stop()) + { + s.wait(); + } + + if (should_stop()) + break; + } + + + + try + { + if (receive_pipe) + { + sockstreambuf buf(con); + std::istream in(&buf); + typename receive_pipe_type::type item; + // This isn't necessary but doing it avoids a warning about + // item being uninitialized sometimes. + assign_zero_if_built_in_scalar_type(item); + + while (in.peek() != EOF) + { + unsigned char code; + in.read((char*)&code, sizeof(code)); + if (code == message_code) + { + deserialize(item, in); + receive_pipe->enqueue(item); + } + } + } + else + { + // Since we don't have a receive pipe to put messages into we will + // just read the bytes from the connection and ignore them. + char buf[1000]; + while (con->read(buf, sizeof(buf)) > 0) ; + } + } + catch (std::bad_alloc& ) + { + dlog << LERROR << "std::bad_alloc thrown while deserializing message from " + << con->get_foreign_ip() << ":" << con->get_foreign_port(); + } + catch (dlib::serialization_error& e) + { + dlog << LERROR << "dlib::serialization_error thrown while deserializing message from " + << con->get_foreign_ip() << ":" << con->get_foreign_port() + << ".\nThe exception error message is: \n" << e.what(); + } + catch (std::exception& e) + { + dlog << LERROR << "std::exception thrown while deserializing message from " + << con->get_foreign_ip() << ":" << con->get_foreign_port() + << ".\nThe exception error message is: \n" << e.what(); + } + + + + + con->shutdown(); + auto_mutex lock(m); + receive_thread_active = false; + s.broadcast(); + } + + auto_mutex lock(m); + receive_thread_active = false; + s.broadcast(); + } + + void transmit_thread ( + ) + { + while (true) + { + // wait until we have a connection + { auto_mutex lock(m); + while (!transmit_thread_active && !should_stop()) + { + s.wait(); + } + + if (should_stop()) + break; + } + + + + try + { + sockstreambuf buf(con); + std::ostream out(&buf); + typename transmit_pipe_type::type item; + // This isn't necessary but doing it avoids a warning about + // item being uninitialized sometimes. + assign_zero_if_built_in_scalar_type(item); + + + while (out) + { + bool dequeue_timed_out = false; + if (transmit_pipe ) + { + if (transmit_pipe->dequeue_or_timeout(item,1000)) + { + out.write((char*)&message_code, sizeof(message_code)); + serialize(item, out); + if (transmit_pipe->size() == 0) + out.flush(); + + continue; + } + + dequeue_timed_out = (transmit_pipe->is_enabled() && transmit_pipe->is_dequeue_enabled()); + } + + // Pause for about a second. Note that we use a wait_or_timeout() call rather + // than sleep() here because we want to wake up immediately if this object is + // being destructed rather than hang for a second. + if (!dequeue_timed_out) + { + auto_mutex lock(m); + if (should_stop()) + break; + + s.wait_or_timeout(1000); + } + // Just send the keepalive byte periodically so we can + // tell if the connection is alive. + out.write((char*)&keepalive_code, sizeof(keepalive_code)); + out.flush(); + } + } + catch (std::bad_alloc& ) + { + dlog << LERROR << "std::bad_alloc thrown while serializing message to " + << con->get_foreign_ip() << ":" << con->get_foreign_port(); + } + catch (dlib::serialization_error& e) + { + dlog << LERROR << "dlib::serialization_error thrown while serializing message to " + << con->get_foreign_ip() << ":" << con->get_foreign_port() + << ".\nThe exception error message is: \n" << e.what(); + } + catch (std::exception& e) + { + dlog << LERROR << "std::exception thrown while serializing message to " + << con->get_foreign_ip() << ":" << con->get_foreign_port() + << ".\nThe exception error message is: \n" << e.what(); + } + + + + + con->shutdown(); + auto_mutex lock(m); + transmit_thread_active = false; + s.broadcast(); + } + + auto_mutex lock(m); + transmit_thread_active = false; + s.broadcast(); + } + + mutex m; + signaler s; + bool receive_thread_active; + bool transmit_thread_active; + std::unique_ptr<connection> con; + std::unique_ptr<listener> list; + const unsigned short port; + const std::string ip; + transmit_pipe_type* const transmit_pipe; + receive_pipe_type* const receive_pipe; + logger dlog; + const unsigned char keepalive_code; + const unsigned char message_code; + + mutex current_bs_mutex; + bridge_status current_bs; + }; + } + + +// ---------------------------------------------------------------------------------------- + + class bridge : noncopyable + { + public: + + bridge () {} + + template < typename T, typename U, typename V > + bridge ( + T network_parameters, + U pipe1, + V pipe2 + ) { reconfigure(network_parameters,pipe1,pipe2); } + + template < typename T, typename U> + bridge ( + T network_parameters, + U pipe + ) { reconfigure(network_parameters,pipe); } + + + void clear ( + ) + { + pimpl.reset(); + } + + template < typename T, typename R > + void reconfigure ( + listen_on_port network_parameters, + bridge_transmit_decoration<T> transmit_pipe, + bridge_receive_decoration<R> receive_pipe + ) { pimpl.reset(); pimpl.reset(new impl_brns::impl_bridge<T,R>(network_parameters.port, &transmit_pipe.p, &receive_pipe.p)); } + + template < typename T, typename R > + void reconfigure ( + listen_on_port network_parameters, + bridge_receive_decoration<R> receive_pipe, + bridge_transmit_decoration<T> transmit_pipe + ) { pimpl.reset(); pimpl.reset(new impl_brns::impl_bridge<T,R>(network_parameters.port, &transmit_pipe.p, &receive_pipe.p)); } + + template < typename T > + void reconfigure ( + listen_on_port network_parameters, + bridge_transmit_decoration<T> transmit_pipe + ) { pimpl.reset(); pimpl.reset(new impl_brns::impl_bridge<T,T>(network_parameters.port, &transmit_pipe.p, 0)); } + + template < typename R > + void reconfigure ( + listen_on_port network_parameters, + bridge_receive_decoration<R> receive_pipe + ) { pimpl.reset(); pimpl.reset(new impl_brns::impl_bridge<R,R>(network_parameters.port, 0, &receive_pipe.p)); } + + + + + template < typename T, typename R > + void reconfigure ( + connect_to_ip_and_port network_parameters, + bridge_transmit_decoration<T> transmit_pipe, + bridge_receive_decoration<R> receive_pipe + ) { pimpl.reset(); pimpl.reset(new impl_brns::impl_bridge<T,R>(network_parameters.ip, network_parameters.port, &transmit_pipe.p, &receive_pipe.p)); } + + template < typename T, typename R > + void reconfigure ( + connect_to_ip_and_port network_parameters, + bridge_receive_decoration<R> receive_pipe, + bridge_transmit_decoration<T> transmit_pipe + ) { pimpl.reset(); pimpl.reset(new impl_brns::impl_bridge<T,R>(network_parameters.ip, network_parameters.port, &transmit_pipe.p, &receive_pipe.p)); } + + template < typename R > + void reconfigure ( + connect_to_ip_and_port network_parameters, + bridge_receive_decoration<R> receive_pipe + ) { pimpl.reset(); pimpl.reset(new impl_brns::impl_bridge<R,R>(network_parameters.ip, network_parameters.port, 0, &receive_pipe.p)); } + + template < typename T > + void reconfigure ( + connect_to_ip_and_port network_parameters, + bridge_transmit_decoration<T> transmit_pipe + ) { pimpl.reset(); pimpl.reset(new impl_brns::impl_bridge<T,T>(network_parameters.ip, network_parameters.port, &transmit_pipe.p, 0)); } + + + bridge_status get_bridge_status ( + ) const + { + if (pimpl) + return pimpl->get_bridge_status(); + else + return bridge_status(); + } + + private: + + std::unique_ptr<impl_brns::impl_bridge_base> pimpl; + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BRIDGe_Hh_ + diff --git a/ml/dlib/dlib/bridge/bridge_abstract.h b/ml/dlib/dlib/bridge/bridge_abstract.h new file mode 100644 index 000000000..76ed21153 --- /dev/null +++ b/ml/dlib/dlib/bridge/bridge_abstract.h @@ -0,0 +1,347 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_BRIDGe_ABSTRACT_ +#ifdef DLIB_BRIDGe_ABSTRACT_ + +#include <string> +#include "../pipe/pipe_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + struct connect_to_ip_and_port + { + connect_to_ip_and_port ( + const std::string& ip, + unsigned short port + ); + /*! + requires + - is_ip_address(ip) == true + - port != 0 + ensures + - this object will represent a request to make a TCP connection + to the given IP address and port number. + !*/ + }; + + connect_to_ip_and_port connect_to ( + const network_address& addr + ); + /*! + requires + - addr.port != 0 + ensures + - converts the given network_address object into a connect_to_ip_and_port + object. + !*/ + + struct listen_on_port + { + listen_on_port( + unsigned short port + ); + /*! + requires + - port != 0 + ensures + - this object will represent a request to listen on the given + port number for incoming TCP connections. + !*/ + }; + + template < + typename pipe_type + > + bridge_transmit_decoration<pipe_type> transmit ( + pipe_type& p + ); + /*! + requires + - pipe_type is some kind of dlib::pipe object + - the objects in the pipe must be serializable + ensures + - Adds a type decoration to the given pipe, marking it as a transmit pipe, and + then returns it. + !*/ + + template < + typename pipe_type + > + bridge_receive_decoration<pipe_type> receive ( + pipe_type& p + ); + /*! + requires + - pipe_type is some kind of dlib::pipe object + - the objects in the pipe must be serializable + ensures + - Adds a type decoration to the given pipe, marking it as a receive pipe, and + then returns it. + !*/ + +// ---------------------------------------------------------------------------------------- + + struct bridge_status + { + /*! + WHAT THIS OBJECT REPRESENTS + This simple struct represents the state of a bridge object. A + bridge is either connected or not. If it is connected then it + is connected to a foreign host with an IP address and port number + as indicated by this object. + !*/ + + bridge_status( + ); + /*! + ensures + - #is_connected == false + - #foreign_port == 0 + - #foreign_ip == "" + !*/ + + bool is_connected; + unsigned short foreign_port; + std::string foreign_ip; + }; + +// ---------------------------------------------------------------------------------------- + + class bridge : noncopyable + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is a tool for bridging a dlib::pipe object between + two network connected applications. + + + Note also that this object contains a dlib::logger object + which will log various events taking place inside a bridge. + If you want to see these log messages then enable the logger + named "dlib.bridge". + + + BRIDGE PROTOCOL DETAILS + The bridge object creates a single TCP connection between + two applications. Whenever it sends an object from a pipe + over a TCP connection it sends a byte with the value 1 followed + immediately by the serialized copy of the object from the pipe. + The serialization is performed by calling the global serialize() + function. + + Additionally, a bridge object will periodically send bytes with + a value of 0 to ensure the TCP connection remains alive. These + are just read and ignored. + !*/ + + public: + + bridge ( + ); + /*! + ensures + - this object is properly initialized + - #get_bridge_status().is_connected == false + !*/ + + template <typename T, typename U, typename V> + bridge ( + T network_parameters, + U pipe1, + V pipe2 + ); + /*! + requires + - T is of type connect_to_ip_and_port or listen_on_port + - U and V are of type bridge_transmit_decoration or bridge_receive_decoration, + however, U and V must be of different types (i.e. one is a receive type and + another a transmit type). + ensures + - this object is properly initialized + - performs: reconfigure(network_parameters, pipe1, pipe2) + (i.e. using this constructor is identical to using the default constructor + and then calling reconfigure()) + !*/ + + template <typename T, typename U> + bridge ( + T network_parameters, + U pipe + ); + /*! + requires + - T is of type connect_to_ip_and_port or listen_on_port + - U is of type bridge_transmit_decoration or bridge_receive_decoration. + ensures + - this object is properly initialized + - performs: reconfigure(network_parameters, pipe) + (i.e. using this constructor is identical to using the default constructor + and then calling reconfigure()) + !*/ + + ~bridge ( + ); + /*! + ensures + - blocks until all resources associated with this object have been destroyed. + !*/ + + void clear ( + ); + /*! + ensures + - returns this object to its default constructed state. That is, it will + be inactive, neither maintaining a connection nor attempting to acquire one. + - Any active connections or listening sockets will be closed. + !*/ + + bridge_status get_bridge_status ( + ) const; + /*! + ensures + - returns the current status of this bridge object. In particular, returns + an object BS such that: + - BS.is_connected == true if and only if the bridge has an active TCP + connection to another computer. + - if (BS.is_connected) then + - BS.foreign_ip == the IP address of the remote host we are connected to. + - BS.foreign_port == the port number on the remote host we are connected to. + - else if (the bridge has previously been connected to a remote host but hasn't been + reconfigured or cleared since) then + - BS.foreign_ip == the IP address of the remote host we were connected to. + - BS.foreign_port == the port number on the remote host we were connected to. + - else + - BS.foreign_ip == "" + - BS.foreign_port == 0 + !*/ + + + + template < typename T, typename R > + void reconfigure ( + listen_on_port network_parameters, + bridge_transmit_decoration<T> transmit_pipe, + bridge_receive_decoration<R> receive_pipe + ); + /*! + ensures + - This object will begin listening on the port specified by network_parameters + for incoming TCP connections. Any previous bridge state is cleared out. + - Onces a connection is established we will: + - Stop accepting new connections. + - Begin dequeuing objects from the transmit pipe and serializing them over + the TCP connection. + - Begin deserializing objects from the TCP connection and enqueueing them + onto the receive pipe. + - if (the current TCP connection is lost) then + - This object goes back to listening for a new connection. + - if (the receive pipe can contain bridge_status objects) then + - Whenever the bridge's status changes the updated bridge_status will be + enqueued onto the receive pipe unless the change was a TCP disconnect + resulting from a user calling reconfigure(), clear(), or destructing this + bridge. The status contents are defined by get_bridge_status(). + throws + - socket_error + This exception is thrown if we are unable to open the listening socket. + !*/ + template < typename T, typename R > + void reconfigure ( + listen_on_port network_parameters, + bridge_receive_decoration<R> receive_pipe, + bridge_transmit_decoration<T> transmit_pipe + ); + /*! + ensures + - performs reconfigure(network_parameters, transmit_pipe, receive_pipe) + !*/ + template < typename T > + void reconfigure ( + listen_on_port network_parameters, + bridge_transmit_decoration<T> transmit_pipe + ); + /*! + ensures + - This function is identical to the above two reconfigure() functions + except that there is no receive pipe. + !*/ + template < typename R > + void reconfigure ( + listen_on_port network_parameters, + bridge_receive_decoration<R> receive_pipe + ); + /*! + ensures + - This function is identical to the above three reconfigure() functions + except that there is no transmit pipe. + !*/ + + + + template <typename T, typename R> + void reconfigure ( + connect_to_ip_and_port network_parameters, + bridge_transmit_decoration<T> transmit_pipe, + bridge_receive_decoration<R> receive_pipe + ); + /*! + ensures + - This object will begin making TCP connection attempts to the IP address and port + specified by network_parameters. Any previous bridge state is cleared out. + - Onces a connection is established we will: + - Stop attempting new connections. + - Begin dequeuing objects from the transmit pipe and serializing them over + the TCP connection. + - Begin deserializing objects from the TCP connection and enqueueing them + onto the receive pipe. + - if (the current TCP connection is lost) then + - This object goes back to attempting to make a TCP connection with the + IP address and port specified by network_parameters. + - if (the receive pipe can contain bridge_status objects) then + - Whenever the bridge's status changes the updated bridge_status will be + enqueued onto the receive pipe unless the change was a TCP disconnect + resulting from a user calling reconfigure(), clear(), or destructing this + bridge. The status contents are defined by get_bridge_status(). + !*/ + template <typename T, typename R> + void reconfigure ( + connect_to_ip_and_port network_parameters, + bridge_receive_decoration<R> receive_pipe, + bridge_transmit_decoration<T> transmit_pipe + ); + /*! + ensures + - performs reconfigure(network_parameters, transmit_pipe, receive_pipe) + !*/ + template <typename T> + void reconfigure ( + connect_to_ip_and_port network_parameters, + bridge_transmit_decoration<T> transmit_pipe + ); + /*! + ensures + - This function is identical to the above two reconfigure() functions + except that there is no receive pipe. + !*/ + template <typename R> + void reconfigure ( + connect_to_ip_and_port network_parameters, + bridge_receive_decoration<R> receive_pipe + ); + /*! + ensures + - This function is identical to the above three reconfigure() functions + except that there is no transmit pipe. + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BRIDGe_ABSTRACT_ + + |