1 #ifndef SOCKET_MINDER_CLASS
2 #define SOCKET_MINDER_CLASS
4 /*****************************************************************************\
6 * Name : socket_minder *
7 * Author : Chris Koeritz *
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. *
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 \*****************************************************************************/
25 #include <basis/contracts.h>
26 #include <processes/mailbox.h>
27 #include <processes/post_office.h>
31 // forward declarations.
34 class socket_data_amorph;
35 class socket_minder_prompter;
40 class socket_minder : public virtual basis::root_object
43 socket_minder(processes::post_office &post, int parent_route, int event_type,
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.
50 virtual ~socket_minder();
53 // this method should be invoked before the socket_minder is destroyed.
54 // it ensures that the object is released from background event delivery.
56 DEFINE_CLASS_NAME("socket_minder");
58 basis::astring text_form() const;
59 // returns a dump of the minder's current state.
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.
65 void unlock_socket_data(socket_data *to_unlock);
66 // unlocks the list of socket data again and zeroes "to_unlock".
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.
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.
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.
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.
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.
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.
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.
109 bool zap_pending_server(int socket);
110 // removes the "socket" from the pending servers list, if present.
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.
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.
125 bool owns_socket(int socket) const;
126 // returns true if this minder owns the "socket" in question.
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.
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.
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.
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.
156 void fire_event(int to_fire, int at_whom, basis::un_int parm1, basis::un_int parm2);
159 socket_minder(const socket_minder &sm);
160 socket_minder &operator =(const socket_minder &sm);