36   #include <arpa/inet.h> 
   37   #include <sys/socket.h> 
   40 using namespace basis;
 
   53 #define LOG(to_print) CLASS_EMERGENCY_LOG(program_wide_logger::get(), to_print) 
   74 class socket_data_amorph : 
public amorph<socket_data> {};
 
   78 class socket_minder_prompter : 
public ethread 
   81   socket_minder_prompter(socket_minder &parent)
 
   88   ~socket_minder_prompter() {
 
   92   virtual void perform_activity(
void *
formal(ptr)) { _parent.snoozy_select(); }
 
   95   socket_minder &_parent;  
 
  101     int event_type, 
int message)
 
  103   _parent_route(parent_route),
 
  104   _event_type(event_type),
 
  106   _socket_list(new socket_data_amorph),
 
  111   _prompter(new socket_minder_prompter(*this))
 
  137   for (
int i = 0; i < _socket_list->elements(); i++) {
 
  140     if (i != _socket_list->elements() - 1)
 
  141       to_return += parser_bits::platform_eol_to_chars();
 
  157   for (
int p = 0; p < pending.
length(); p++) {
 
  166   if (!ret || (!read_sox.
length() && !write_sox.
length()) ) {
 
  175   for (
int r = 0; r < read_sox.
length(); r++) {
 
  176     const int sock = read_sox[r];
 
  188   for (
int w = 0; w < write_sox.
length(); w++) {
 
  189     const int sock = write_sox[w];
 
  205   for (
int i = 0; i < _socket_list->elements(); i++) {
 
  223   for (
int i = 0; i < _socket_list->elements(); i++) {
 
  224     if (_socket_list->borrow(i)->_socket == socket) 
return true;
 
  232   for (
int i = 0; i < _socket_list->elements(); i++)
 
  233     if (_socket_list->borrow(i)->_socket == socket)
 
  234       return _socket_list->borrow(i);
 
  242   if (!to_unlock) 
return;
 
  248     bool connected_mode, 
bool connection_pending)
 
  262   _socket_list->append(new_data);
 
  270   for (
int i = 0; i < _socket_list->elements(); i++) {
 
  271     if (_socket_list->borrow(i)->_socket == socket) {
 
  274       _socket_list->zap(i, i);
 
  284 #ifdef DEBUG_SOCKET_MINDER 
  288 #ifdef DEBUG_SOCKET_MINDER 
  289   LOG(
astring(astring::SPRINTF, 
"registering interest of %d for socket " 
  290       "%d.", interests, socket));
 
  292   if (!harpo) 
return false;
 
  301   if (!harpo) 
return false;
 
  310   if (!harpo) 
return false;
 
  316 void socket_minder::fire_event(
int to_fire, 
int at_whom,
 
  327     _pending_sox->
insert(0, 1);
 
  328     (*_pending_sox)[0] = to_put;
 
  330     *_pending_sox += to_put;
 
  337   if (!_pending_sox->
member(socket)) 
return false;
 
  338   _pending_sox->
remove(socket);
 
  345   if (!_pending_sox->
length()) 
return 0;
 
  346   int to_return = _pending_sox->
get(0);
 
  347   _pending_sox->
zap(0, 0);
 
  353   FUNCDEF(
"handle_pending_connecters");
 
  367 #ifdef DEBUG_SOCKET_MINDER 
  368     LOG(
a_sprintf(
"sending client SI_CONNECTED event on parent %d",
 
  377     socklen_t sock_len = 
sizeof(sock_addr);
 
  378     int new_sock = int(::accept(to_peek.
_socket, &sock_addr, &sock_len));
 
  381       LOG(
a_sprintf(
"accept got a client socket %d.", new_sock));
 
  382       if (_pending_sox->
member(new_sock)) {
 
  383         LOG(
a_sprintf(
"already have seen socket %d in pending!", new_sock));
 
  385         *_pending_sox += new_sock;
 
  386 #ifdef DEBUG_SOCKET_MINDER 
  387         LOG(
a_sprintf(
"sending server SI_CONNECTED event on parent %d",
 
  392     } 
else if (_pending_sox->
length()) {
 
  432     fire_event(_message, _parent_route, to_peek.
_socket,
 
  444     LOG(
"not supposed to try this when not connected yet...");
 
  447 #ifdef DEBUG_SOCKET_MINDER 
  466       error_code = critical_events::system_error();
 
  468 #ifdef DEBUG_SOCKET_MINDER 
  469       LOG(
a_sprintf(
"updating that %d bytes got sent out of %d to send.",
 
  470           len_sent, to_send.
length()));
 
  471       if (to_send.
length() != len_sent)
 
  472         LOG(
a_sprintf(
"size to send (%d) not same as size sent (%d).",
 
  473             to_send.
length(), len_sent));
 
  476       to_send.
zap(0, len_sent - 1);
 
  483       LOG(
astring(astring::SPRINTF, 
"error on socket %d is %s.",
 
  486     switch (error_code) {
 
  491         LOG(
a_sprintf(
"due to %s condition, closing socket %d.",
 
  493         fire_event(_message, _parent_route, to_poke.
_socket,
 
  506     LOG(
"not supposed to try this when not connected yet...");
 
  509 #ifdef DEBUG_SOCKET_MINDER 
  520     bool got_something = 
true;  
 
  525       got_something = 
false;  
 
  529 #ifdef DEBUG_SOCKET_MINDER 
  533         got_something = 
true;
 
  542         error_code = critical_events::system_error();
 
  554           _socks->
close(deader);
 
  562 #ifdef DEBUG_SOCKET_MINDER 
  569     fire_event(_message, _parent_route, to_poke.
_socket,
 
  576       LOG(
astring(astring::SPRINTF, 
"error on socket %d is %s.",
 
  579     switch (error_code) {
 
  584         LOG(
a_sprintf(
"due to %s condition, closing socket %d.",
 
  586         fire_event(_message, _parent_route, to_poke.
_socket,
 
  589         _socks->
close(deader);
 
a_sprintf is a specialization of astring that provides printf style support.
outcome insert(int index, int new_indices)
Adds "new_indices" new positions for objects into the array at "index".
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
const contents * observe() const
Returns a pointer to the underlying C array of data.
const contents & get(int index) const
Accesses individual objects stored in "this" at the "index" position.
int length() const
Returns the current reported length of the allocated C array.
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
int last() const
Returns the last valid element in the array.
Provides a dynamically resizable ASCII character string.
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
auto_synchronizer simplifies concurrent code by automatically unlocking.
A very common template for a dynamic array of bytes.
A simple object that wraps a templated array of ints.
void lock()
Clamps down on the mutex, if possible.
void unlock()
Gives up the possession of the mutex.
Models an OS-level event so we can represent activities occurring there.
Provides a platform-independent object for adding threads to a program.
Manages a collection of mailboxes and implements delivery routes for mail.
void drop_off(const structures::unique_int &id, letter *package)
sends a "package" on its way to the "id" via the registered route.
int close(basis::un_int &socket)
int select(basis::un_int socket, int selection_mode, int timeout=0) const
bool set_non_blocking(basis::un_int socket, bool non_blocking=true)
basis::astring text_form() const
basis::byte_array _receive_buffer
basis::byte_array _partially_received
timely::time_stamp _last_conn_alert
int _registered_interests
basis::byte_array _partially_sent
void get_sockets(basis::int_array &read_sox, basis::int_array &write_sox, basis::int_array &pending) const
bool is_connection_pending(int socket)
bool handle_pending_connecters(socket_data &to_peek)
void put_pending_server(int to_put, bool at_head)
bool set_connection_pending(int socket, bool pending)
bool remove_socket_data(int socket)
bool register_interest(int socket, int interests)
virtual bool evaluate_interest(socket_data &to_examine)
bool zap_pending_server(int socket)
socket_data * lock_socket_data(int socket)
void push_sends(socket_data &to_poke, int states)
bool add_socket_data(int socket, bool server, int server_socket, bool connected_mode, bool connection_pending)
void push_receives(socket_data &to_poke, int states)
basis::astring text_form() const
bool owns_socket(int socket) const
void unlock_socket_data(socket_data *to_unlock)
Helpful functions for interacting with TCP/IP stacks.
static basis::astring tcpip_error_name(int error_value)
A simple object that wraps a templated set of ints.
bool member(const contents &to_test) const
Returns true if the item "to_test" is a member of this set.
bool remove(const contents &to_remove)
Removes the item "to_remove" from the set.
Represents a point in time relative to the operating system startup time.
void reset()
sets the stamp time back to now.
#define formal(parameter)
This macro just eats what it's passed; it marks unused formal parameters.
#define NULL_POINTER
The value representing a pointer to nothing.
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
The guards collection helps in testing preconditions and reporting errors.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
unsigned int un_int
Abbreviated name for unsigned integers.
const int KILOBYTE
Number of bytes in a kilobyte.
A logger that sends to the console screen using the standard output device.
Provides access to the operating system's socket methods.
const int SOCKMIND_MAXIMUM_RECEIVES
const int MAXIMUM_TRANSFER_CHUNK
const int CONN_ALERT_INTERVAL
const int MULTI_SELECT_TIMEOUT
const int SOCKET_CHECK_INTERVAL
A dynamic container class that holds any kind of object via pointers.
#define SOCK_ECONNABORTED