1 #ifndef CROMP_COMMON_CLASS
2 #define CROMP_COMMON_CLASS
6 * Author : Chris Koeritz
7 *******************************************************************************
8 * Copyright (c) 2000-$now By Author. This program is free software; you can *
9 * redistribute it and/or modify it under the terms of the GNU General Public *
10 * License as published by the Free Software Foundation; either version 2 of *
11 * the License or (at your option) any later version. This is online at: *
12 * http://www.fsf.org/copyleft/gpl.html *
13 * Please send any updates to: fred@gruntose.com *
14 \*****************************************************************************/
16 #include <crypto/rsa_crypto.h>
17 #include <octopus/octopus.h>
18 #include <octopus/entity_defs.h>
19 #include <octopus/entity_data_bin.h>
20 #include <octopus/infoton.h>
21 #include <sockets/internet_address.h>
22 #include <sockets/machine_uid.h>
23 #include <sockets/spocket.h>
24 #include <sockets/tcpip_stack.h>
28 const int DEFAULT_MAX_ENTITY_QUEUE = 14 * basis::MEGABYTE;
29 //!< the default size we allow per each entity.
30 /*!< note that if there are many entities and they're all getting full, the total allowed
31 will be this number multiplied by the number of entities. */
33 //! A few common features used by both CROMP clients and servers.
35 class cromp_common : public virtual basis::root_object
38 cromp_common(const basis::astring &host, int max_per_ent);
39 // constructs a normal common object. open_common() must be invoked before
40 // this object becomes useful. the "host" should be the actual TCPIP host
41 // that this program is running on. the "max_per_ent" is the maximum
42 // allowed size (in bytes) of pending items per entity.
44 cromp_common(sockets::spocket *preexisting, octopi::octopus *singleton);
45 // uses a "preexisting" spocket object for the communications needed here.
46 // the "singleton" octopus is used instead of our base class for restoring
47 // any data. note that "singleton" is not dealt with in the destructor;
48 // it is considered owned externally. however, the "preexisting" spocket
49 // is considered to be owned by this class now. also note that if a NULL_POINTER
50 // "preexisting" socket is passed, then socket creation occurs by the
53 virtual ~cromp_common();
55 static int default_port();
56 // returns the default port used by cromp and octopus. this is not
57 // appropriate for most derived apps; they should use their own ports.
59 DEFINE_CLASS_NAME("cromp_common");
61 basis::outcome open_common(const sockets::internet_address &where);
62 // opens the object to begin communication. this is the first point at
63 // which the socket is opened.
65 basis::outcome close_common();
66 // shuts down our presence on the network.
68 sockets::spocket *spock() const;
69 // allows external access to our socket object. do not abuse this.
70 // also keep in mind that in some stages of construction, this can return
71 // NULL_POINTER. do not assume it is non-null.
73 sockets::internet_address other_side() const;
74 // returns the location that we're connected to, if any.
76 virtual basis::outcome add_tentacle(octopi::tentacle *to_add, bool filter = false);
77 // allows customization of the processing that the cromp object performs.
80 OKAY = basis::common::OKAY,
81 DISALLOWED = basis::common::DISALLOWED,
82 BAD_INPUT = basis::common::BAD_INPUT,
83 NOT_FOUND = basis::common::NOT_FOUND,
84 TIMED_OUT = basis::common::TIMED_OUT,
85 GARBAGE = basis::common::GARBAGE,
86 NO_HANDLER = basis::common::NO_HANDLER,
87 PARTIAL = basis::common::PARTIAL,
88 ENCRYPTION_MISMATCH = basis::common::ENCRYPTION_MISMATCH,
90 NO_SERVER = sockets::communication_commons::NO_SERVER,
91 NO_CONNECTION = sockets::communication_commons::NO_CONNECTION,
93 DEFINE_OUTCOME(TOO_FULL, -40, "The request cannot be processed yet")
96 static const char *outcome_name(const basis::outcome &to_name);
98 static basis::astring chew_hostname(const sockets::internet_address &addr,
99 sockets::internet_address *resolved = NULL_POINTER);
100 // resolves the hostname in "addr" and returns the resolved hostname as
101 // a machine_uid compact_form(). the "resolved" form of the address is
102 // also stored if the pointer is non-null.
104 basis::astring responses_text_form() const;
105 // returns a textual form of the responses awaiting pickup.
107 bool buffer_clog(int clog_point = 1 * basis::MEGABYTE) const;
108 // returns true if the buffer is bigger than a certain "clog_point".
110 basis::outcome pack_and_ship(const octopi::infoton &request,
111 const octopi::octopus_request_id &item_id, int max_tries);
112 // requests a transaction from the other side, specified by the "request".
113 // the return value is OKAY if the request was successfully sent or it
114 // will be another outcome that indicates a failure of transmission.
115 // the "item_id" must be set ahead of time to identify the request and
116 // sender. the "max_tries" limits how many times the sending is
117 // reattempted on failure.
119 basis::outcome pack_and_ship(const octopi::infoton_list &requests, int max_tries);
120 // sends a batch of "requests" in one blast.
122 basis::outcome retrieve_and_restore(octopi::infoton * &item,
123 const octopi::octopus_request_id &req_id, int timeout);
124 // attempts to pull down data from our spocket and process it back into
125 // an infoton in "item". only the specific object for the "req_id"
126 // will be provided. if the "timeout" is non-zero, then data will be
127 // awaited that long. if "timeout" is zero, the method will return
128 // immediately if the data is not already available.
130 basis::outcome retrieve_and_restore_any(octopi::infoton * &item, octopi::octopus_request_id &req_id,
132 // returns the first infoton that becomes available. the "req_id" is set
133 // to the identifier from the transaction. this is useful more for the
134 // server side than for the client side.
136 basis::outcome push_outgoing(int max_tries);
137 // composes calls to grab_anything and send_buffer into an attempt to
138 // get all of the data out that is waiting while not ignoring the incoming
139 // data from the other side.
141 void grab_anything(bool wait);
142 // attempts to locate any data waiting for our socket. any infotons
143 // found get stuffed into the requests bin. this is never needed for
144 // cromp_clients; the retrieve methods will automatically invoke this
145 // as appropriate. if "wait" is true, then a data pause will occur
146 // on the socket to await data.
148 basis::outcome send_buffer();
149 // pushes out any pending data waiting for the other side. the returns
150 // can range the gamut, but OKAY and PARTIAL are both successful outcomes.
151 // OKAY means that everything was sent successfully (or there was nothing
152 // to send). PARTIAL means that not all the data was sent, but some got
153 // out successfully. any other errors probably indicate a major problem.
155 // these adjust the storage sizes allowed internally.
156 int max_bytes_per_entity() const;
157 void max_bytes_per_entity(int max_bytes_per_entity);
159 // provides information on the overall number of bytes encountered by all
160 // cromp clients in this program. these are only intended for testing
161 // purposes and might in fact roll over for a busy client app.
162 static double total_bytes_sent() { return _bytes_sent_total; }
163 static double total_bytes_received() { return _bytes_received_total; }
165 static const int HOSTCHOP;
166 // this is the number of characters from the host's name that go into the
167 // octopus identity. the portion after that many characters is a compacted
168 // form of the machine_uid.
170 static bool decode_host(const basis::astring &coded_host, basis::astring &hostname,
171 sockets::machine_uid &machine);
172 // takes the "coded_host" from an entity and returns the "hostname" and
173 // "machine" information that was encoded in it. those will be gibberish
174 // unless true is returned.
176 octopi::octopus *octo() const { return _octopus; }
177 // returns our octopus support object. this should always exist when this
178 // object is constructed properly.
180 static const crypto::rsa_crypto &localhost_only_key();
181 // this key should *only* be used for speeding up encryption on the local
182 // host. it is generated when the first caller needs it but then is
183 // a constant key during the program's runtime. this object can be used
184 // for initializing services when it is _known_ that they are connecting
185 // only on the localhost; that's the only place it should be used because
186 // re-using the key on the network provides less security than using
187 // the randomized encryption startup in cromp.
189 int pending_sends() const;
190 //!< returns the number of bytes still unsent.
192 int accumulated_bytes() const;
193 //!< returns the number of bytes pending processing from the other side.
196 octopi::octopus *singleton() const { return _singleton; }
197 // returns the singleton octopus passed to the constructor earlier.
198 // this will return NULL_POINTER if it was not constructed that way.
201 sockets::spocket *_commlink; // transceiver for data.
202 octopi::octopus *_octopus; // main octopus; might be same as singleton.
203 octopi::octopus *_singleton; // used for dependent cromp server objects.
204 octopi::entity_data_bin *_requests; // where the incoming requests are stored.
205 basis::mutex *_accum_lock; // protects the accumulator and other data below.
206 timely::time_stamp *_last_data_seen; // last time we got anything on socket.
207 basis::byte_array *_accumulator; // accumulates data for this object.
208 basis::byte_array *_sendings; // accumulates outgoing sends when socket is full.
209 basis::byte_array *_receive_buffer; // temporary buffer.
210 basis::byte_array *_still_flat; // another temporary buffer.
211 timely::time_stamp *_last_cleanup; // when we last cleaned out our bin.
213 // helps for testing; not used for operation.
214 static double _bytes_sent_total;
215 static double _bytes_received_total;
217 void snarf_from_socket(bool wait);
218 // retrieves data waiting on the socket and adds to the accumulator.
219 // if "wait" is true, then the presence of data is awaited first.
221 void process_accumulator();
222 // chews on the accumulated data to seek any commands that are present.
224 void conditional_cleaning();
225 // flushes out any old items if they haven't been cleaned in a bit.
227 basis::outcome retrieve_and_restore_root(bool get_anything, octopi::infoton * &item,
228 octopi::octopus_request_id &req_id, int timeout);
229 // used for both types of retrieval; if "get_anything" is true, then
230 // any old item will be returned. if "get_anything" is false, then only
231 // the item with "req_id" is returned.