feisty meow concerns codebase  2.140
spocket.h
Go to the documentation of this file.
1 #ifndef SPOCKET_CLASS
2 #define SPOCKET_CLASS
3 
4 /*****************************************************************************\
5 * *
6 * Name : spocket *
7 * Author : Chris Koeritz *
8 * *
9 * Purpose: *
10 * *
11 * *
12 *******************************************************************************
13 * Copyright (c) 1989-$now By Author. This program is free software; you can *
14 * redistribute it and/or modify it under the terms of the GNU General Public *
15 * License as published by the Free Software Foundation; either version 2 of *
16 * the License or (at your option) any later version. This is online at: *
17 * http://www.fsf.org/copyleft/gpl.html *
18 * Please send any updates to: fred@gruntose.com *
19 \*****************************************************************************/
20 
21 #include "tcpip_stack.h"
22 
23 #include <basis/contracts.h>
24 #include <basis/mutex.h>
25 #include <timely/time_stamp.h>
26 
27 namespace sockets {
28 
29 // forward declarations.
30 class internet_address;
31 class raw_socket;
32 
34 
39 class spocket : public virtual basis::root_object
40 {
41 public:
42  enum sock_types {
43  CONNECTED, // connected socket over TCP.
44  BROADCAST, // broadcasting socket over UDP.
45  UNICAST, // single-address targeted socket over UDP.
46  BOGUS_SOCK // special type that goes nowhere and provides no data.
47  };
48 
50  // constructs the spocket object. "where" provides the network location
51  // for either this side (for a server) or the other side (for a client).
52  // the decision about this socket's orientation (client or server) will not
53  // be made until either connect() or accept() are invoked. note however
54  // that BROADCAST sockets are only appropriate for use as a client; they
55  // can receive and send broadcasts that way without needing a server role.
56 
57  ~spocket();
58  // drops any connection that was made and destroys the spocket object.
59 
60  DEFINE_CLASS_NAME("spocket");
61 
62  bool healthy();
63  // returns true if the spocket seems to be okay.
64 
65  const internet_address &where() const;
66  // returns the location where this socket exists.
67 
68  const internet_address &remote() const;
69  // returns the location that we have accepted from.
70 
71  enum outcomes {
72  OKAY = basis::common::OKAY,
73  TIMED_OUT = basis::common::TIMED_OUT,
74  ACCESS_DENIED = basis::common::ACCESS_DENIED,
75  BAD_INPUT = basis::common::BAD_INPUT,
76  NONE_READY = basis::common::NONE_READY,
77  PARTIAL = basis::common::PARTIAL,
78 
79  NO_CONNECTION = sockets::communication_commons::NO_CONNECTION,
80  NO_ANSWER = sockets::communication_commons::NO_ANSWER,
81 
82  DEFINE_OUTCOME(NOT_SERVER, -39, "Accept was tried on a spocket that is "
83  "not a root server")
84  };
85 
86  static const char *outcome_name(const basis::outcome &to_name);
87  // returns the text for "to_name" if it's a member of spocket outcomes.
88 
89  // informative functions...
90 
92  // returns a readable version of the contents of the spocket.
93 
94  bool was_connected() const { return _was_connected; }
95  // a simple check of whether a connection has been made on this object.
96  // if this is not true, then the object is not usable yet. this state
97  // will also get set to false when the spocket gets disconnected.
98 
99  bool connected();
100  // returns true if the spocket is "currently" connected. this causes an
101  // interrogation of the operating system and may take a short while.
102 
103  // these report what type of spocket this is.
104  bool is_client() const { return _client; }
105  bool is_server() const { return !_client; }
106  bool is_root_server() const { return is_server() && !!_server_socket; }
107 
108  basis::un_int OS_socket() { return _socket; }
109  // returns the low-level operating system form of our normal action socket.
110  // this is zero for a root server. note: this will still record what the
111  // socket was after it is closed out, just for record keeping; do not
112  // control the returned socket outside of this class.
113  basis::un_int OS_root_socket() { return _server_socket; }
114  // returns the OS form of our server socket, but only if this is a root
115  // server type of socket.
116 
117  void bind_client(const internet_address &source);
119 
123  // major operations for connected mode sockets...
124 
125  basis::outcome connect(int communication_wait = 20 * basis::SECOND_ms);
126  // acts as a client and connects to a destination. the timeout is
127  // specified in milliseconds by "communication_wait". this can be as low
128  // as zero if you don't want to wait. TIMED_OUT is returned if the
129  // connection hasn't finished within the connection_wait. OKAY is returned
130  // if the connection succeeded. other outcomes denote failures.
131 
132  basis::outcome accept(spocket * &sock, bool wait);
133  // makes this spocket act as a root server and accepts a connection from a
134  // client if possible. a root server is a spocket object that manages a
135  // server spocket but which does not allow any normal sending or receiving.
136  // only root servers can have accept called on them. the "sock" will be
137  // a normal server spocket which can be used to send and receive if it
138  // got connected. for "sock" to be valid, it must return as NULL_POINTER
139  // and the returned outcome must be OKAY. if no new connections are
140  // available, then NO_CONNECTION is returned. if the "wait" flag is true,
141  // then the accept on the root server will block until a connection is
142  // accepted and the returned spocket will be made non-blocking. if "wait"
143  // is false, then no blocking will occur at all. note that multiple
144  // threads can invoke this without tripping over the protective locking;
145  // once the root socket is initialized, accept will not lock the spocket.
146 
148  // closes the connection. the state is returned to the post-construction
149  // state, i.e. it will appear that this object had never connected yet.
150 
151  // these report which side of the connection this is functioning as.
152  bool client() const { return _client; }
153  bool server() const { return !_client; }
154 
155  // send and receive functions...
156  //
157  // if the outcome from one of these is NO_CONNECTION, then somehow the
158  // connection has dropped or never succeeded.
159 
160  basis::outcome send(const basis::abyte *buffer, int size, int &len_sent);
161  // sends "size" bytes from the "buffer". the number actually sent is
162  // stored in "len_sent". this can only be used for CONNECTED type sockets.
163 
164  basis::outcome send(const basis::byte_array &to_send, int &len_sent);
165  // this version takes a byte_array.
166 
167  basis::outcome send_to(const internet_address &where_to, const basis::abyte *buffer,
168  int size, int &len_sent);
169  // this version is used for sending when the socket type is BROADCAST
170  // or UNICAST.
171 
172  basis::outcome send_to(const internet_address &where_to, const basis::byte_array &to_send,
173  int &len_sent);
174  // clone of above, using byte_array.
175 
176  basis::outcome receive(basis::abyte *buffer, int &size);
177  // attempts to retrieve data from the spocket and place it in the "buffer".
178  // the "size" specifies how much space is available. if successful, the
179  // buffer will be filled with data and "size" will report how much there
180  // actually is.
181 
182  basis::outcome receive(basis::byte_array &buffer, int &size);
183  // this version uses a byte_array for the "buffer". the "size" expected
184  // must still be set and "size" will still report the bytes read.
185 //hmmm: could remove the size parameter for byte array type.
186 
187  // these methods are used for BROADCAST and other non-connected types of
188  // spockets. they report the data as the above receive methods do, but they
189  // also report the sender.
190  basis::outcome receive_from(basis::abyte *buffer, int &size,
191  internet_address &where_from);
192  basis::outcome receive_from(basis::byte_array &buffer, int &size,
193  internet_address &where_from);
194 
195  basis::outcome await_readable(int timeout);
196  // pauses this caller until data arrives. this is a blocking call that
197  // could potentially not return until the "timeout" elapses (measured in
198  // milliseconds). if "timeout" is zero, then this really doesn't do
199  // anything. if data is available, then OKAY is returned.
200 
201  basis::outcome await_writable(int timeout);
202  // pauses this caller until the socket can be written to again. could
203  // potentially not return until the "timeout" elapses (measured in
204  // milliseconds). if "timeout" is zero, then this really doesn't do
205  // anything. if the socket is able to send again, then OKAY is returned.
206  // otherwise NONE_READY is returned.
207 
208  tcpip_stack &stack() const;
209  // provides access to the spocket's tcpip stack to derivative objects.
210 
211  bool is_bogus() const { return _type == BOGUS_SOCK; }
213 
219 private:
220  sock_types _type; // records what kind of socket we'll create.
221  basis::un_int _socket; // our socket that we communicate on.
222  basis::un_int _server_socket; // our serving socket, if we're a root server.
223  bool _was_connected; // did we ever successfully connect?
224  bool _client; // true if we are acting as a client.
225  internet_address *_where; // our addressing info.
226  internet_address *_remote; // our addressing info.
227  raw_socket *_socks; // provides low-level socket functionality.
228  tcpip_stack *_stack; // provides access to socket facilities.
229  basis::mutex *_select_lock; // protects concurrent access to socket.
230  timely::time_stamp *_last_resolve;
231  // tracks when we last tried a resolve on our address. if they try to
232  // reconnect and we haven't done this in a while, we'll re-resolve the
233  // socket.
234  bool _client_bind;
235  internet_address *_cli_bind;
236 
237  // not allowed.
238  spocket(const spocket &);
239  spocket &operator =(const spocket &);
240 };
241 
242 } //namespace.
243 
244 #endif
245 
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
A very common template for a dynamic array of bytes.
Definition: byte_array.h:36
Outcomes describe the state of completion for an operation.
Definition: outcome.h:31
this type of address describes a destination out on the internet.
Abstraction for a higher-level BSD socket that is platform independent.
Definition: spocket.h:40
basis::outcome await_writable(int timeout)
Definition: spocket.cpp:256
bool was_connected() const
Definition: spocket.h:94
tcpip_stack & stack() const
Definition: spocket.cpp:150
bool client() const
Definition: spocket.h:152
bool server() const
Definition: spocket.h:153
spocket(const internet_address &where, sock_types type=CONNECTED)
Definition: spocket.cpp:99
basis::outcome send(const basis::abyte *buffer, int size, int &len_sent)
Definition: spocket.cpp:573
basis::astring text_form()
Definition: spocket.cpp:154
basis::outcome connect(int communication_wait=20 *basis::SECOND_ms)
Definition: spocket.cpp:274
static const char * outcome_name(const basis::outcome &to_name)
Definition: spocket.cpp:180
basis::un_int OS_socket()
Definition: spocket.h:108
basis::outcome receive_from(basis::abyte *buffer, int &size, internet_address &where_from)
Definition: spocket.cpp:713
bool is_root_server() const
Definition: spocket.h:106
basis::outcome send_to(const internet_address &where_to, const basis::abyte *buffer, int size, int &len_sent)
Definition: spocket.cpp:628
basis::outcome accept(spocket *&sock, bool wait)
Definition: spocket.cpp:460
bool is_server() const
Definition: spocket.h:105
const internet_address & remote() const
Definition: spocket.cpp:148
void bind_client(const internet_address &source)
when a client calls connect, this forces it to bind to "source".
Definition: spocket.cpp:174
basis::outcome disconnect()
Definition: spocket.cpp:188
basis::outcome await_readable(int timeout)
Definition: spocket.cpp:238
bool is_bogus() const
returns true when this object is bogus.
Definition: spocket.h:211
basis::un_int OS_root_socket()
Definition: spocket.h:113
DEFINE_CLASS_NAME("spocket")
bool connected()
Definition: spocket.cpp:209
const internet_address & where() const
Definition: spocket.cpp:147
basis::outcome receive(basis::abyte *buffer, int &size)
Definition: spocket.cpp:664
bool is_client() const
Definition: spocket.h:104
Helpful functions for interacting with TCP/IP stacks.
Definition: tcpip_stack.h:38
Represents a point in time relative to the operating system startup time.
Definition: time_stamp.h:38
unsigned char abyte
A fairly important unit which is seldom defined...
Definition: definitions.h:51
const int SECOND_ms
Number of milliseconds in a second.
Definition: definitions.h:120
unsigned int un_int
Abbreviated name for unsigned integers.
Definition: definitions.h:62
Provides access to the operating system's socket methods.
Definition: base_address.h:26