Merge branch 'master' of feistymeow.org:feisty_meow
[feisty_meow.git] / octopi / library / cromp / cromp_client.h
1 #ifndef CROMP_CLIENT_CLASS
2 #define CROMP_CLIENT_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : cromp_client                                                      *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *  Purpose:                                                                   *
10 *                                                                             *
11 *    Supplies primitive operations for requesting services of a CROMP-based   *
12 *  server application.  Tentacles in cromp clients are only used for          *
13 *  restoring original objects, but they are required for that.  Keep in mind  *
14 *  that for communication to be possible, a cromp server and its cromp client *
15 *  must possess tentacles that grok the same infotons.  They do not need to   *
16 *  be the same objects and probably shouldn't be.  It makes sense to          *
17 *  implement an unpacking / cloning tentacle and then derive the full-service *
18 *  request processing tentacle from it.                                       *
19 *                                                                             *
20 *******************************************************************************
21 * Copyright (c) 2000-$now By Author.  This program is free software; you can  *
22 * redistribute it and/or modify it under the terms of the GNU General Public  *
23 * License as published by the Free Software Foundation; either version 2 of   *
24 * the License or (at your option) any later version.  This is online at:      *
25 *     http://www.fsf.org/copyleft/gpl.html                                    *
26 * Please send any updates to: fred@gruntose.com                               *
27 \*****************************************************************************/
28
29 #include "cromp_common.h"
30
31 #include <crypto/blowfish_crypto.h>
32 #include <sockets/internet_address.h>
33 #include <structures/roller.h>
34 #include <tentacles/encryption_tentacle.h>
35 #include <tentacles/encryption_wrapper.h>
36 #include <tentacles/entity_registry.h>
37 #include <timely/time_stamp.h>
38
39 namespace cromp {
40
41 // forward:
42 class asynch_connection_thread;
43
44 class cromp_client : public cromp_common
45 {
46 public:
47   enum constraints {
48     DEFAULT_MAX_CONNECT_WAIT = 28 * basis::SECOND_ms,
49       // the server had better connect within this time limit or it will
50       // be considered missing in action.
51     DEFAULT_MAX_RESPONSE_WAIT = 4 * basis::MINUTE_ms
52       // a server should be able to answer in this interval or something is
53       // really wrong with the system.
54   };
55
56   cromp_client(const sockets::internet_address &destination,
57           int connection_wait = DEFAULT_MAX_CONNECT_WAIT,
58           int max_per_ent = DEFAULT_MAX_ENTITY_QUEUE);
59     // will connect to a cromp_server on the host specified by "destination".
60
61   virtual ~cromp_client();
62
63   DEFINE_CLASS_NAME("cromp_client");
64
65   basis::astring instance_name() const {
66     return basis::astring(class_name()) + ": " + entity().text_form();
67   }
68
69   const octopi::octopus_entity &entity() const;
70     // returns our identity within the octopus server.
71
72   void enable_encryption();
73     // this turns on the encryption.  this should be done before the first
74     // connect or login invocations.  once it's enabled, it stays enabled.
75
76   void reset(const sockets::internet_address &destination,
77           int connection_wait = DEFAULT_MAX_CONNECT_WAIT,
78           int max_per_ent = DEFAULT_MAX_ENTITY_QUEUE);
79     // disconnects from any previous server and reconstructs this client.
80     // the client will be left in an unconnected and unauthenticated state.
81     // any pre-existing tentacles will still be hooked up to the object.
82     // use connect() to re-establish the connection to the server.
83
84   basis::outcome connect(const basis::byte_array &verification = blank_verification());
85     // attempts to connect to the server.  OKAY is returned if this succeeds.
86
87   static const basis::byte_array &blank_verification();  // empty verification.
88
89   basis::outcome asynch_connect();
90     // this is a non-blocking connect.  it behaves like connect(), but should
91     // never take more than a few milliseconds to return.  if the client is
92     // already connected, then nothing is done.  otherwise no operations will
93     // be permitted until the reconnection has succeeded.  a call to regular
94     // connect() cancels the asynchronous connect.
95
96   bool connected() const;
97     // returns true if we think we are connected to the server.
98
99   basis::outcome disconnect();
100     // disconnects from the cromp server and releases all connection resources.
101
102   virtual basis::outcome login();
103     // attempts to log in to the server.  we must already have connected
104     // when this is called.  the "verification" is a protocol specific
105     // package of info that can be used to validate the login.
106
107   //////////////
108
109   basis::outcome submit(const octopi::infoton &request, octopi::octopus_request_id &item_id,
110           int max_tries = 80);
111     // requests a transaction from the cromp_server described by "request".
112     // the return value is OKAY if the request was successfully sent or it
113     // will be another outcome that indicates a failure of transmission.
114     // the "max_tries" is the number of times to try getting the send out;
115     // if asynchronous sends are allowed to accumulate, then 1 works here.
116
117   basis::outcome acquire(octopi::infoton * &response, const octopi::octopus_request_id &cmd_id,
118           int timeout = DEFAULT_MAX_RESPONSE_WAIT);
119     // attempts to receive a "response" to a previously submitted request
120     // with the "cmd_id".  if "timeout" is non-zero, then the response will
121     // be awaited for "timeout" milliseconds.  otherwise the function returns
122     // immediately.  note that "response" will only be generated properly given
123     // a tentacle that knows the infoton type received.  this requires the
124     // cromp_client to have tentacles registered for all of the types to be
125     // exchanged.  this can be used for asynchronous retrieval if the timeout
126     // is zero and one knows a previously requested "cmd_id".
127
128   //////////////
129
130   // grittier functions...
131
132   basis::outcome synchronous_request(const octopi::infoton &to_send, octopi::infoton * &received,
133           octopi::octopus_request_id &item_id,
134           int timeout = DEFAULT_MAX_RESPONSE_WAIT);
135     // submits the infoton "to_send" and waits for the reply.  if there is
136     // a reply in the allotted time, then "received" is set to that.  the
137     // "item_id" is set to the request id assigned to the request.
138
139   basis::outcome acquire_any(octopi::infoton * &response, octopi::octopus_request_id &cmd_id,
140           int timeout = DEFAULT_MAX_RESPONSE_WAIT);
141     // a request to retrieve any waiting data for the client.  similar to
142     // acquire above, but does not require one to know the command id.
143
144   octopi::octopus_request_id next_id();
145     // generates the next identifier.  this can be used as a unique identifier
146     // for derived objects since the id is issued from our server.  it is
147     // not unique across different types of cromp servers though, nor across
148     // cromp servers running on different hosts.
149
150   void decrypt_package_as_needed(basis::outcome &to_return, octopi::infoton * &response,
151           const octopi::octopus_request_id &cmd_id);
152     // this ensures that if the "response" is encrypted, it will be decrypted
153     // and replaced with the real object intended.  this method is invoked
154     // automatically by acquire(), but if the cromp_common retrieve methods are
155     // used directly, this should be done to the response before using it.
156
157   void keep_alive_pause(int duration = 0, int interval = 40);
158     // pauses this thread but keeps calling into the cromp support to ensure
159     // items get delivered or received when possible.  the call will snooze
160     // for at least "duration" milliseconds with individual sleeps being
161     // allowed the "interval" milliseconds.
162
163   const basis::byte_array &verification() const;
164     // returns the verification token held currently, if it's been set.
165
166 private:
167   bool _encrypting;  // true if this connection should be encrypted.
168   int _connection_wait;  // the length of time we'll allow a connection.
169   basis::mutex *_lock;  // protects our data members below.
170   octopi::octopus_entity *_ent;  // our identity within the octopus server.
171   structures::int_roller *_req_id;  // the numbering of our nth request is depicted here.
172   bool _identified;  // true if our initial identifier verification succeeded.
173   bool _authorized;  // true if our login was successful.
174   bool _disallowed;  // nothing is allowed right now except asynch connecting.
175   friend class asynch_connection_thread;  // solely so it can use r_p_c method.
176   asynch_connection_thread *_asynch_connector;  // b-ground connection thread.
177   bool _channel_secured;  // true if an encrypted connection has been made.
178   crypto::blowfish_crypto *_crypto;  // tracks our key, once we have one.
179   octopi::encryption_tentacle *_encrypt_arm;  // processes encryption for us.
180   octopi::blank_entity_registry *_guardian;  // simple security support.
181   basis::byte_array *c_verification;  // verification token we were given.
182
183   void stop_asynch_thread();  // stops the background connector.
184
185   basis::outcome locked_connect();
186     // called by the other types of connection processes to get the work done.
187
188   octopi::octopus_entity randomize_entity() const;
189     // provides a junk entity for our temporary identifier that we'll use
190     // until the server gives us a new one.
191
192   basis::outcome locked_disconnect();
193     // assumes that the client is locked.  this is the real disconnect.
194
195   bool wrap_infoton(const octopi::infoton &request, octopi::encryption_wrapper &wrapped);
196     // wraps an infoton for sending over an encrypted connection.
197 };
198
199 } //namespace.
200
201 #endif
202