00001 #ifndef SOCKET_MINDER_CLASS 00002 #define SOCKET_MINDER_CLASS 00003 00004 /*****************************************************************************\ 00005 * * 00006 * Name : socket_minder * 00007 * Author : Chris Koeritz * 00008 * * 00009 * Purpose: * 00010 * * 00011 * Provides a base for activities that tend a communication element called * 00012 * a socket. Sockets are numerically identified, but the number is only * 00013 * unique on the specific medium of interest. The socket minder also tracks * 00014 * the send and receive status and buffers for the socket. * 00015 * * 00016 ******************************************************************************* 00017 * Copyright (c) 1999-$now By Author. This program is free software; you can * 00018 * redistribute it and/or modify it under the terms of the GNU General Public * 00019 * License as published by the Free Software Foundation; either version 2 of * 00020 * the License or (at your option) any later version. This is online at: * 00021 * http://www.fsf.org/copyleft/gpl.html * 00022 * Please send any updates to: fred@gruntose.com * 00023 \*****************************************************************************/ 00024 00025 #include "sockets_dll.h" 00026 00027 #include <basis/object_base.h> 00028 00029 // forward. 00030 class mailbox; 00031 class post_office; 00032 class raw_socket; 00033 class socket_data; 00034 class socket_data_amorph; 00035 class socket_minder_prompter; 00036 class tcpip_stack; 00037 00039 00040 class SOCKETS_CLASS_STYLE socket_minder : public virtual object_base 00041 { 00042 public: 00043 socket_minder(post_office &post, int parent_route, int event_type, 00044 int message); 00045 // the "parent_route" is where we will send asynchronous tcpip events, 00046 // which will be stored in the "post". the "event_type" is the identifier 00047 // for the OS_events that will be generated and the "message" is the id 00048 // stored inside the events. 00049 00050 virtual ~socket_minder(); 00051 00052 void disengage(); 00053 // this method should be invoked before the socket_minder is destroyed. 00054 // it ensures that the object is released from background event delivery. 00055 00056 IMPLEMENT_CLASS_NAME("socket_minder"); 00057 00058 istring text_form() const; 00059 // returns a dump of the minder's current state. 00060 00061 socket_data *lock_socket_data(int socket); 00062 // locates the data for the "socket" specified. the list is left locked 00063 // unless NIL is returned. 00064 00065 void unlock_socket_data(socket_data *to_unlock); 00066 // unlocks the list of socket data again and zeroes "to_unlock". 00067 00068 bool add_socket_data(int socket, bool server, int server_socket, 00069 bool connected_mode, bool connection_pending); 00070 // adds a new record for the "socket" which is possibly a "server". only 00071 // fails with false when the socket is already listed. the 00072 // "connected_mode" should be true if this socket is connection-oriented. 00073 00074 bool remove_socket_data(int socket); 00075 // rips out the data held for "socket". only fails with false when the 00076 // record couldn't be found to delete. 00077 00078 bool set_connection_pending(int socket, bool pending); 00079 // changes the state of pending connection for the "socket". if "pending" 00080 // is true, then the socket is either trying to accept connections or it 00081 // is trying to connect. if false, then it is no longer attempting this. 00082 00083 bool is_connection_pending(int socket); 00084 // returns the current state of pending-ness for the "socket". false could 00085 // also mean the socket cannot be found. 00086 00087 bool register_interest(int socket, int interests); 00088 // sets the events to watch for on the "socket" from the "interests". 00089 // these are values merged bitwise from the socket_interests enum. they 00090 // must be interpreted appropriately by different kinds of transports. the 00091 // evaluate_interest() method must be over-ridden for the interests to 00092 // actually be implemented. registering with "interests" as zero will 00093 // reset all interests to be... disinterested. 00094 00095 virtual bool evaluate_interest(socket_data &to_examine); 00096 // this can be over-ridden by a derived socket minder to handle needs 00097 // besides simple bsd socket management. but the implementation provided 00098 // here will generate events upon occurrence of a registered interest on 00099 // the socket. an event letter is sent to the appropriate parent id 00100 // containing the event that was noticed. true is returned if "to_examine" 00101 // was successfully evaluated. any changes made to the socket's data are 00102 // recorded. since the socket minder is locked during this upcall, it is 00103 // important not to cause any deadlocks by careless additional locking. 00104 00105 int get_pending_server(); 00106 // returns a non-zero socket number if a server socket was accepted on 00107 // and is waiting to be processed. 00108 00109 bool zap_pending_server(int socket); 00110 // removes the "socket" from the pending servers list, if present. 00111 00112 void put_pending_server(int to_put, bool at_head); 00113 // stores a pending server socket into the list, either since it just got 00114 // noticed as an accepted socket or because it cannot be processed yet. 00115 00116 void get_sockets(int_array &read_sox, int_array &write_sox, 00117 int_array &pending) const; 00118 // reports the set of sockets that this minder is handling in "read_sox", 00119 // since we assume any socket could be checked for pending received data. 00120 // if there is pending data to send, then they are put into the "write_sox" 00121 // to be checked for writability. the existing contents of the lists are 00122 // not cleared, so this function can be used to join the lists of several 00123 // socket_minders together. 00124 00125 bool owns_socket(int socket) const; 00126 // returns true if this minder owns the "socket" in question. 00127 00128 void push_sends(socket_data &to_poke, int states); 00129 void push_receives(socket_data &to_poke, int states); 00130 // if the state is right, we'll try our hand at grabbing some data. if the 00131 // "states" include SI_READABLE, then we'll try and receive on the socket 00132 // in push_receives. if they include SI_WRITABLE, then we'll send out 00133 // pending data in push_sends. 00134 00135 bool handle_pending_connecters(socket_data &to_peek); 00136 // returns true if the socket "to_peek" is awaiting a connection and we 00137 // have prompted that activity appropriately. false means that this 00138 // socket is not awaiting a connection. 00139 00140 void snoozy_select(); 00141 // goes into a select on all applicable sockets and waits until one 00142 // of them has activity before waking up. 00143 00144 private: 00145 post_office &_post; // manages recycling of letters for us. 00146 int _parent_route; // the identifier of our parent in the postal system. 00147 int _event_type; // what we generate OS_events as. 00148 mutex *_lock; // maintains list integrity. 00149 socket_data_amorph *_socket_list; // the table of information per socket. 00150 raw_socket *_socks; // lets us access the OS's socket subsystem. 00151 tcpip_stack *_stack; // provides tcpip protocol stack. 00152 int _message; // the message type stored inside the generated OS_events. 00153 int_set *_pending_sox; // accepted servers that are waiting to be processed. 00154 socket_minder_prompter *_prompter; // snoozes on sockets awaiting activity. 00155 00156 void fire_event(int to_fire, int at_whom, u_int parm1, u_int parm2); 00157 00158 // not implemented: 00159 socket_minder(const socket_minder &sm); 00160 socket_minder &operator =(const socket_minder &sm); 00161 }; 00162 00163 #endif 00164
1.5.1