Flow 1.0.2
Flow project: Public API.
|
A server socket able to listen on a single Flow port for incoming connections and return peer sockets (Peer_socket objects) to the local user once such connections are established. More...
#include <server_socket.hpp>
Public Types | |
enum class | State { S_LISTENING , S_CLOSING , S_CLOSED } |
State of a Server_socket. More... | |
using | Peer_socket_ptr = boost::shared_ptr< Peer_socket > |
Equivalent to Peer_socket::Ptr, but can't use that due to C++'s circular reference nonsense. | |
Public Types inherited from flow::util::Shared_ptr_alias_holder< boost::shared_ptr< Server_socket > > | |
using | Ptr = boost::shared_ptr< Server_socket > |
Short-hand for ref-counted pointer to mutable values of type Target_type::element_type (a-la T* ). | |
using | Const_ptr = Const_target_ptr |
Short-hand for ref-counted pointer to immutable values of type Target_type::element_type (a-la T const * ). | |
Public Member Functions | |
~Server_socket () override | |
Boring virtual destructor. Note that deletion is to be handled exclusively via shared_ptr , never explicitly. | |
State | state () const |
Current State of the socket. More... | |
Node * | node () const |
Node that produced this Server_socket. More... | |
flow_port_t | local_port () const |
The local Flow-protocol port on which this server is or was listening. More... | |
Peer_socket_ptr | accept (Error_code *err_code=0) |
Non-blocking accept: obtain socket for the least recently established not-yet-obtained peer connection on this server. More... | |
template<typename Rep , typename Period > | |
Peer_socket_ptr | sync_accept (const boost::chrono::duration< Rep, Period > &max_wait, bool reactor_pattern=false, Error_code *err_code=0) |
Blocking (synchronous) version of accept(). More... | |
Peer_socket_ptr | sync_accept (bool reactor_pattern=false, Error_code *err_code=0) |
Equivalent to sync_accept(duration::max(), reactor_pattern, err_code) ; i.e., sync_accept() with no user timeout. More... | |
Error_code | disconnect_cause () const |
The error code that perviously caused state() to become State::S_CLOSED, or success code if state is not CLOSED. More... | |
Public Member Functions inherited from flow::util::Null_interface | |
virtual | ~Null_interface ()=0 |
Boring virtual destructor. More... | |
Public Member Functions inherited from flow::log::Log_context | |
Log_context (Logger *logger=0) | |
Constructs Log_context by storing the given pointer to a Logger and a null Component. More... | |
template<typename Component_payload > | |
Log_context (Logger *logger, Component_payload component_payload) | |
Constructs Log_context by storing the given pointer to a Logger and a new Component storing the specified generically typed payload (an enum value). More... | |
Log_context (const Log_context &src) | |
Copy constructor that stores equal Logger* and Component values as the source. More... | |
Log_context (Log_context &&src) | |
Move constructor that makes this equal to src , while the latter becomes as-if default-constructed. More... | |
Log_context & | operator= (const Log_context &src) |
Assignment operator that behaves similarly to the copy constructor. More... | |
Log_context & | operator= (Log_context &&src) |
Move assignment operator that behaves similarly to the move constructor. More... | |
void | swap (Log_context &other) |
Swaps Logger pointers and Component objects held by *this and other . More... | |
Logger * | get_logger () const |
Returns the stored Logger pointer, particularly as many FLOW_LOG_*() macros expect. More... | |
const Component & | get_log_component () const |
Returns reference to the stored Component object, particularly as many FLOW_LOG_*() macros expect. More... | |
Protected Member Functions | |
Server_socket (log::Logger *logger, const Peer_socket_options *child_sock_opts) | |
Constructs object; initializes most values to well-defined (0, empty, etc.) but not necessarily meaningful values. More... | |
Related Functions | |
(Note that these are not member functions.) | |
std::ostream & | operator<< (std::ostream &os, const Server_socket *serv) |
Prints string representation of given socket to given standard ostream and returns the latter. More... | |
std::ostream & | operator<< (std::ostream &os, Server_socket::State state) |
Prints string representation of given socket state to given standard ostream and returns the latter. More... | |
Additional Inherited Members | |
Static Public Member Functions inherited from flow::util::Shared_ptr_alias_holder< boost::shared_ptr< Server_socket > > | |
static Ptr | ptr_cast (const From_ptr &ptr_to_cast) |
Provides syntactic-sugary way to perform a static_pointer_cast<> from a compatible smart pointer type From_ptr , typically From_ptr::element_type being in the same class hierarchy as Target_ptr::element_type . More... | |
static Const_ptr | const_ptr_cast (const From_ptr &ptr_to_cast) |
Identical to ptr_cast() but adds const -ness (immutability) to the pointed-to type. More... | |
static Ptr | dynamic_ptr_cast (const From_ptr &ptr_to_cast) |
Equivalent to ptr_cast() but a dynamic_pointer_cast instead of static. More... | |
static Const_ptr | dynamic_const_ptr_cast (const From_ptr &ptr_to_cast) |
Identical to const_ptr_cast() but a dynamic_pointer_cast instead of static. More... | |
A server socket able to listen on a single Flow port for incoming connections and return peer sockets (Peer_socket objects) to the local user once such connections are established.
A given Server_socket can only arise by calling Node::listen(). Node generates a new Server_socket and returns it (factory pattern). Server_socket is not instantiable otherwise. A Server_socket cannot be deleted explicitly by the user and will only be returned via boost::shared_ptr<>
; when both the Node and all user code no longer refers to it, the Server_socket will be destroyed.
Once a Flow-protocol user has a Server_socket object, that object represents a socket in one of the following basic states:
Exactly the following state transitions are possible for a given Server_socket returned by Node:
Note, in particular, that Closed is final; socket cannot move from Closed to Listening. If after an error or valid closing you want to reestablish a server, obtain a new Server_socket from Node's factory. Same rationale as for equivalent design decision in Peer_socket.
Closing means either this side or other side initiated the closing of this server socket for any reason, but Node is still finishing up operations related to that in the background (such as closing in-progress peer connections). Closed means Node has finished any such operations and has disowned the Server_socket.
In either case the only operation Server_socket supports (accept() and derivatives thereof) is impossible in Closing and Closed. Therefore the two states are distinguished for diagnostic/informational purposes only. Generally one should only accept() when Acceptable, and accept() will return an error if the state is Closing or Closed.
Note that a Closing or Closed Server_socket does NOT mean that already accept()ed Peer_socket objects will be in any way affected.
Server_socket::close()
functionality – at least the equivalent of Peer_socket::close_abruptly().Server_socket, like a TCP server socket, stores a queue of fully established peer connections. A Peer_socket is placed onto this internal queue only once its state() == State::S_OPEN (i.e., the connection handshake is finished/successful). Peer_socket objects are then obtained from this queue via the Server_socket::accept() call and its derivatives.
The sync_accept() method is efficient, in that it uses no processor cycles until Acceptable is achieved (i.e., it sleeps until that point). The non-blocking accept() method doesn't sleep/block, however. For a program using it to be efficient it should sleep until Acceptable and only then call accept(), when a Peer_socket is certainly available for immediate acceptance. Moreover, a complex program is likely to want to perform this sleep-and-conditional-wake on a set of several Server_sockets (and/or other sockets) simultaneously (similarly to select()
, epoll*()
, etc.). Use class Event_set for this purpose.
Same as for Node. (Briefly: all operations safe for simultaneous execution on separate or the same object.)
|
strong |
State of a Server_socket.
Enumerator | |
---|---|
S_LISTENING | Future or current accept()s may be possible. A socket in this state may be Acceptable. |
S_CLOSING | No accept()s are or will be possible, but Node is still finishing up the closing operation. |
S_CLOSED | No accept()s are or will be possible, AND Node has disowned the Server_socket. |
|
explicitprotected |
Constructs object; initializes most values to well-defined (0, empty, etc.) but not necessarily meaningful values.
logger | The Logger implementation to use subsequently. |
child_sock_opts | Pointer to a per-socket options struct to copy and store; for each Peer_socket resulting from this Server_socket, the options will be a copy of this copy. If null pointer, then instead the enclosing Node's global per-socket options will be used to produce the copy. |
Peer_socket::Ptr flow::net_flow::Server_socket::accept | ( | Error_code * | err_code = 0 | ) |
Non-blocking accept: obtain socket for the least recently established not-yet-obtained peer connection on this server.
There is a queue (FIFO) of not-yet-claimed connections, and this returns the one at the front of the queue.
If state() is State::S_CLOSING or State::S_CLOSED (i.e., not State::S_LISTENING), this will return null (and an error), even if connections have been queued up. Rationale: BSD sockets act similarly: cannot succeed with accept(s)
, if s
is not listening; also internal implementation is simpler. Anti-rationale: our API is much more amenable to allowing accept()s in that situation; and it would mirror the fact that Peer_socket::receive() can succeed in S_OPEN+S_DISCONNECTING
state. Why rationale > anti-rationale: it's a judgment call, and I'm going with simplicity of implementation at least for now.
err_code | See flow::Error_code docs for error reporting semantics. Note: no available connections is not, in itself, an error. So it's quite possible for null to be returned but *err_code is success. |
sock
with sock->state() == Peer_socket::State::S_OPEN
. If no connections are available (including if bool(*err_code) == true
), returns null pointer. Error_code flow::net_flow::Server_socket::disconnect_cause | ( | ) | const |
The error code that perviously caused state() to become State::S_CLOSED, or success code if state is not CLOSED.
Note that once it returns non-success, the returned value subsequently will always be the same.
flow_port_t flow::net_flow::Server_socket::local_port | ( | ) | const |
The local Flow-protocol port on which this server is or was listening.
For a given Server_socket, this will always return the same value, even if CLOSED. However, when CLOSED, the port may be unused or taken by another socket.
Node * flow::net_flow::Server_socket::node | ( | ) | const |
Node that produced this Server_socket.
Server_socket::State flow::net_flow::Server_socket::state | ( | ) | const |
Current State of the socket.
Peer_socket::Ptr flow::net_flow::Server_socket::sync_accept | ( | bool | reactor_pattern = false , |
Error_code * | err_code = 0 |
||
) |
Equivalent to sync_accept(duration::max(), reactor_pattern, err_code)
; i.e., sync_accept() with no user timeout.
err_code | See other sync_accept(). |
reactor_pattern | See other sync_accept(). |
Server_socket::Peer_socket_ptr flow::net_flow::Server_socket::sync_accept | ( | const boost::chrono::duration< Rep, Period > & | max_wait, |
bool | reactor_pattern = false , |
||
Error_code * | err_code = 0 |
||
) |
Blocking (synchronous) version of accept().
Acts just like accept(), except that if *this
is not immediately Acceptable (i.e., accept() would return null and no error), waits until it is Acceptable (accept() would return either non-null, or null and an error) and returns accept(err_code)
. In reactor_pattern
mode (see arg doc), if it were to otherwise return a non-null Peer_socket::Ptr
, it instead leaves the ready peer socket available for subsequence acceptance and returns null.
If a timeout is specified, and this timeout expires before socket is Acceptable, acts like accept() executed on an un-Acceptable server socket.
These are the possible outcomes.
!reactor_pattern
then the new socket is returned, and no error is returned via *err_code
; otherwise the socket is left available for acceptance, while null is returned, and (similarly to non-reactor-pattern mode) no error is returned via *err_code
.*err_code
is set to reason for connection failure unless null. (If err_code
null, Runtime_error thrown.) The code error::Code::S_WAIT_INTERRUPTED means the wait was interrupted (similarly to POSIX's EINTR
).Note that – if !reactor_pattern
– it is NOT possible to return null and no error.
Tip: Typical types you might use for max_wait
: boost::chrono::milliseconds
, boost::chrono::seconds
, boost::chrono::high_resolution_clock::duration
.
Rep | See boost::chrono::duration documentation (and see above tip). |
Period | See boost::chrono::duration documentation (and see above tip). |
max_wait | The maximum amount of time from now to wait before giving up on the wait and returning. "duration<Rep, Period>::max()" will eliminate the time limit and cause indefinite wait (i.e., no timeout). |
reactor_pattern | If and only if true , and the call successfully waited until server socket became Acceptable, then we return a null pointer and leave the peer socket ready to be accepted by the caller. If false , then in that same situation the socket is accepted and returned. The parameter doesn't affect any other situations. |
err_code | See flow::Error_code docs for error reporting semantics. |
reactor_pattern
mode this may be null, yet indeed a socket is Acceptable (the presence or lack of an error indicates whether that's the case).
|
related |
Prints string representation of given socket to given standard ostream
and returns the latter.
The representation includes the local endpoint and the hex pointer value.
shared_ptr
forwards ostream
output to the underlying pointer type, so this will affect Ptr
output as well. os | Stream to print to. |
serv | Object to serialize. May be null. |
os
.
|
related |
Prints string representation of given socket state to given standard ostream
and returns the latter.
os | Stream to print to. |
state | Value to serialize. |
os
.