Merge branch 'master' of feistymeow.org:feisty_meow
[feisty_meow.git] / octopi / library / sockets / socket_minder.h
1 #ifndef SOCKET_MINDER_CLASS
2 #define SOCKET_MINDER_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : socket_minder                                                     *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *  Purpose:                                                                   *
10 *                                                                             *
11 *    Provides a base for activities that tend a communication element called  *
12 *  a socket.  Sockets are numerically identified, but the number is only      *
13 *  unique on the specific medium of interest.  The socket minder also tracks  *
14 *  the send and receive status and buffers for the socket.                    *
15 *                                                                             *
16 *******************************************************************************
17 * Copyright (c) 1999-$now By Author.  This program is free software; you can  *
18 * redistribute it and/or modify it under the terms of the GNU General Public  *
19 * License as published by the Free Software Foundation; either version 2 of   *
20 * the License or (at your option) any later version.  This is online at:      *
21 *     http://www.fsf.org/copyleft/gpl.html                                    *
22 * Please send any updates to: fred@gruntose.com                               *
23 \*****************************************************************************/
24
25 #include <basis/contracts.h>
26 #include <processes/mailbox.h>
27 #include <processes/post_office.h>
28
29 namespace sockets {
30
31 // forward declarations.
32 class raw_socket;
33 class socket_data;
34 class socket_data_amorph;
35 class socket_minder_prompter;
36 class tcpip_stack;
37
38 //////////////
39
40 class socket_minder : public virtual basis::root_object
41 {
42 public:
43   socket_minder(processes::post_office &post, int parent_route, int event_type,
44           int message);
45     // the "parent_route" is where we will send asynchronous tcpip events,
46     // which will be stored in the "post".  the "event_type" is the identifier
47     // for the OS_events that will be generated and the "message" is the id
48     // stored inside the events.
49
50   virtual ~socket_minder();
51
52   void disengage();
53     // this method should be invoked before the socket_minder is destroyed.
54     // it ensures that the object is released from background event delivery.
55
56   DEFINE_CLASS_NAME("socket_minder");
57
58   basis::astring text_form() const;
59     // returns a dump of the minder's current state.
60
61   socket_data *lock_socket_data(int socket);
62     // locates the data for the "socket" specified.  the list is left locked
63     // unless NULL_POINTER is returned.
64
65   void unlock_socket_data(socket_data *to_unlock);
66     // unlocks the list of socket data again and zeroes "to_unlock".
67
68   bool add_socket_data(int socket, bool server, int server_socket,
69           bool connected_mode, bool connection_pending);
70     // adds a new record for the "socket" which is possibly a "server".  only
71     // fails with false when the socket is already listed.  the
72     // "connected_mode" should be true if this socket is connection-oriented.
73
74   bool remove_socket_data(int socket);
75     // rips out the data held for "socket".  only fails with false when the
76     // record couldn't be found to delete.
77
78   bool set_connection_pending(int socket, bool pending);
79     // changes the state of pending connection for the "socket".  if "pending"
80     // is true, then the socket is either trying to accept connections or it
81     // is trying to connect.  if false, then it is no longer attempting this.
82
83   bool is_connection_pending(int socket);
84     // returns the current state of pending-ness for the "socket".  false could
85     // also mean the socket cannot be found.
86
87   bool register_interest(int socket, int interests);
88     // sets the events to watch for on the "socket" from the "interests".
89     // these are values merged bitwise from the socket_interests enum.  they
90     // must be interpreted appropriately by different kinds of transports.  the
91     // evaluate_interest() method must be over-ridden for the interests to
92     // actually be implemented.  registering with "interests" as zero will
93     // reset all interests to be... disinterested.
94
95   virtual bool evaluate_interest(socket_data &to_examine);
96     // this can be over-ridden by a derived socket minder to handle needs
97     // besides simple bsd socket management.  but the implementation provided
98     // here will generate events upon occurrence of a registered interest on
99     // the socket.  an event letter is sent to the appropriate parent id
100     // containing the event that was noticed.  true is returned if "to_examine"
101     // was successfully evaluated.  any changes made to the socket's data are
102     // recorded.  since the socket minder is locked during this upcall, it is
103     // important not to cause any deadlocks by careless additional locking.
104
105   int get_pending_server();
106     // returns a non-zero socket number if a server socket was accepted on
107     // and is waiting to be processed.
108
109   bool zap_pending_server(int socket);
110     // removes the "socket" from the pending servers list, if present.
111
112   void put_pending_server(int to_put, bool at_head);
113     // stores a pending server socket into the list, either since it just got
114     // noticed as an accepted socket or because it cannot be processed yet.
115
116   void get_sockets(basis::int_array &read_sox, basis::int_array &write_sox,
117           basis::int_array &pending) const;
118     // reports the set of sockets that this minder is handling in "read_sox",
119     // since we assume any socket could be checked for pending received data.
120     // if there is pending data to send, then they are put into the "write_sox"
121     // to be checked for writability.  the existing contents of the lists are
122     // not cleared, so this function can be used to join the lists of several
123     // socket_minders together.
124
125   bool owns_socket(int socket) const;
126     // returns true if this minder owns the "socket" in question.
127
128   void push_sends(socket_data &to_poke, int states);
129   void push_receives(socket_data &to_poke, int states);
130     // if the state is right, we'll try our hand at grabbing some data.  if the
131     // "states" include SI_READABLE, then we'll try and receive on the socket
132     // in push_receives.  if they include SI_WRITABLE, then we'll send out
133     // pending data in push_sends.
134
135   bool handle_pending_connecters(socket_data &to_peek);
136     // returns true if the socket "to_peek" is awaiting a connection and we
137     // have prompted that activity appropriately.  false means that this
138     // socket is not awaiting a connection.
139
140   void snoozy_select();
141     // goes into a select on all applicable sockets and waits until one
142     // of them has activity before waking up.
143
144 private:
145   processes::post_office &_post;  // manages recycling of letters for us.
146   int _parent_route;  // the identifier of our parent in the postal system.
147   int _event_type;  // what we generate OS_events as.
148   basis::mutex *_lock;  // maintains list integrity.
149   socket_data_amorph *_socket_list;  // the table of information per socket.
150   raw_socket *_socks;  // lets us access the OS's socket subsystem.
151   tcpip_stack *_stack;  // provides tcpip protocol stack.
152   int _message;  // the message type stored inside the generated OS_events.
153   structures::int_set *_pending_sox;  // accepted servers that are waiting to be processed.
154   socket_minder_prompter *_prompter;  // snoozes on sockets awaiting activity.
155
156   void fire_event(int to_fire, int at_whom, basis::un_int parm1, basis::un_int parm2);
157
158   // not implemented:
159   socket_minder(const socket_minder &sm);
160   socket_minder &operator =(const socket_minder &sm);
161 };
162
163 } //namespace.
164
165 #endif
166