Prepare for arbitrary object connection. The broken commits start.
[sfinx.git] / include / network.H
blobe1a85f672c5f03eca4feb83618a3b74bed57f57a
2  /*
3   *   Copyright (C) 2007, Rus V. Brushkoff, All rights reserved.
4   */
6 #ifndef _NETWORK_H_
7 #define _NETWORK_H_
9 #include <crypter.H>
10 #include <cc++/socket.h>
12 using namespace ost;
14 // ('s' + 'f' + 'i' + 'n' + 'x') << 5
15 #define SFINX_PORT              17664
16 #define SFINX_MAX_PACKET_SIZE   10240
17 #define SFINX_SERVER_BACKLOG    5
19 // TODO: kill this
20 #define SFINX_MAX_NETWORK_BUF_SIZE  7000000
22 class sfinx_stream {
24  protected:
26   u8_t *packet_buf, *parsed_buf;
27   sfinx_crypter *tx_packet_crypter, *rx_packet_crypter;
28   sfinx_crypter *plain, *crc32; // *aes, *rsa;
29   sfinx_elements rx_elements, tx_elements;
30   sfinx_8bit_vector_t *daemon_version, *packet_crypt_types, *min_auth_levels,
31     *md5_challenge;
33     virtual bool read_data(u8_t *buf, u32_t size, u32_t timeout = 0) = 0;
34     virtual bool send_data(u8_t *b, u32_t size) = 0;
36   public:
38     sfinx_stream() {
39       packet_buf = new u8_t[SFINX_MAX_NETWORK_BUF_SIZE];
40       plain = new sfinx_crypter_plain();
41       crc32 = new sfinx_crypter_crc32();
42       rx_packet_crypter = tx_packet_crypter = plain;
43       daemon_version = new sfinx_8bit_vector_t(SFINX_DAEMON_VERSION);
44       packet_crypt_types = new sfinx_8bit_vector_t(SFINX_PACKET_CRYPT_TYPES);
45       min_auth_levels = new sfinx_8bit_vector_t(SFINX_MIN_AUTH_LEVELS);
46       md5_challenge = new sfinx_8bit_vector_t(SFINX_MD5_SUM);
47    }
48     // ÞÉÔÁÅÍ ÐÁËÅÔ, ÐÒÏ×ÅÒÑÅÍ magic, ÒÁÓÛÉÆÒÏ×Ù×ÁÅÍ, ÐÁÒÓÉÍ
49     // TODO: return'Ù ÎÅ ÎÕÖÎÙ. ÐÅÒÅÄÅÌÁÔØ ÎÁ exception'Ù
50     bool send_packet() {
51       tx_packet_crypter->crypt(tx_elements);
52       int res = send_data(tx_packet_crypter->header(),
53         tx_packet_crypter->header_len());
54       if (!res)
55         res = send_data(tx_elements.buf(), tx_elements.size());
56       else {
57         debug("header send error %d", res);
58         return res;
59      }
60       if (res)
61         debug("elements send error %d", res);
62       return res;
63    }
64     bool read_packet() {
65       if (read_data(packet_buf, 7, 1000)) { // 5 magic + 1 type + 1 É ÂÏÌÅÅ packet_len
66         debug("Error reading Sfinx Magic");
67         return 1;
68      }
69       if (memcmp(packet_buf, "sfinx", 5)) {
70         debug("Bad Sfinx Magic");
71         return 1;
72      }
73       // 5 ÂÁÊÔ - ÔÉРÐÁËÅÔÁ
74       u8_t packet_type = packet_buf[5];
75       u32_t data_len_be32 = 0;
76       s8_t len_bytes_to_read = sfinx_elements::decoded_size(packet_buf[6]);
77       if (len_bytes_to_read < 1) {
78         debug("Bad decoded packet size");
79         return 1;
80      }
81       if (len_bytes_to_read - 1) {
82         if (read_data(packet_buf + 7, len_bytes_to_read - 1, 1000)) {
83           debug("Can't read packet len");
84           return 1;
85        }
86      }
87       memcpy(((u8_t *)&data_len_be32) + (sizeof(u32_t) - len_bytes_to_read), packet_buf + 6,
88         len_bytes_to_read);
89       u32_t data_len = sfinx_elements::decode(data_len_be32, len_bytes_to_read);
90       // debug("got packet header: type 0x%x, len - %d", packet_type, data_len);
91       if (data_len > SFINX_MAX_NETWORK_BUF_SIZE) {
92         debug("Too big data packet");
93         return 1;
94      }
95       // read rest of data
96       if (read_data(packet_buf, data_len, data_len * 10)) {
97         debug("Can't read packet data");
98         return 1;
99      }
100       switch (packet_type) {
101         case SFINX_PACKET_PLAIN:
102           // decrypt data
103           break;
104        case SFINX_PACKET_CRC32:
105        case SFINX_PACKET_CRYPTED_AES:
106         default:
107           debug("Unsupported packet type 0x%x !", packet_type);
108           return 1;
109      }
110       // parse packet
111       rx_elements.clear();
112       if (rx_elements.parse_from(packet_buf, data_len)) {
113         debug("Can't parse packet data");
114         return 1;
115      }
116       return 0;
117   }
118     virtual ~sfinx_stream() {
119       delete [] packet_buf;
120       delete plain;
121       delete crc32;
122       delete daemon_version;
123       delete packet_crypt_types;
124       delete min_auth_levels;
125       delete md5_challenge;
126   }
127     bool send(sfinx_t &el) { return send(&el); }
128     bool send(sfinx_t *el) {
129       tx_elements.clear();
130       int res = tx_elements.add(el);
131       if (res) {
132         debug("error adding element 0x%x (%d)", el->id(), res);
133         return 1;
134      }
135       return send_packet();
136    }
137     bool send(u32_t cmd_id, u8_t val = 0) {
138       tx_elements.clear();
139       sfinx_8bit_t cmd(cmd_id);
140       cmd.set(val);
141       int res = tx_elements.add(cmd);
142       if (res) {
143         debug("error adding element 0x%x (%d)", cmd_id, res);
144         return 1;
145      }
146       return send_packet();
147    }
148     bool send(u32_t cmd_id, u32_t val = 0) {
149       tx_elements.clear();
150       sfinx_32bit_t cmd(cmd_id);
151       cmd.set(val);
152       int res = tx_elements.add(cmd);
153       if (res) {
154         debug("error adding element 0x%x (%d)", cmd_id, res);
155         return 1;
156      }
157       return send_packet();
158    } 
159     friend class faraon_app;
162 class connection_to_sfinx : public sfinx_stream, public TCPStream {
164   bool connected_;
166 /*  bool is_waiting;
167   sfinx_t *wait_object;*/
169     bool read_data(u8_t *buf, u32_t size, u32_t timeout = 0) {
170      ssize_t nread;
171      u32_t total_read = 0;
172      while (total_read != size) {
173        nread = readData(buf + total_read, size - total_read, 0, timeout);
174        if (nread <= 0) {
175          if (!nread)
176            error(errInput, (char *)"read: EOF on stream");
177          else
178            error(errInput, (char *)"read: Input Error");
179          return 1;
180       }
181        total_read += nread;
182     }
183      return 0;
185     bool send_data(u8_t *b, u32_t size) {
186       int res = writeData((const char *)b, size, 0);
187       if (res != (s32_t)size) {
188         debug("Error sending raw data - %d", res);
189         return 1;
190       }
191       return 0;
192     }
193   public:
194     connection_to_sfinx() : sfinx_stream(), TCPStream() {
195       /*is_waiting =*/ connected_ = false;
196       //wait_object = 0;
197    }
198     bool pending() {
199       return isPending(pendingInput, 10);
200     }
201     bool connected() { return connected_; }
202     ~connection_to_sfinx() { }
203     void disconnect() {
204       /*is_waiting =*/ connected_ = false;
205       //wait_object = 0;
206       TCPStream::disconnect();
207     }
208     // client to server connect
209     bool connect(string &host) {
210        disconnect();
211        setError(1);
212        setNoDelay(1);
213        InetHostAddress sfinx(host.c_str());
214        TCPStream::connect(sfinx, SFINX_PORT, SFINX_MAX_PACKET_SIZE);
215        if (read_packet())
216          return 1;
217        // check version / crypt types / min_auth_levels
218        sfinx_t *val = rx_elements.get(SFINX_DAEMON_VERSION);
219        if (!val)
220          return 1;
221        daemon_version->copy((sfinx_8bit_vector_t *)val);
222        val = rx_elements.get(SFINX_PACKET_CRYPT_TYPES);
223        if (!val)
224          return 1;
225        packet_crypt_types->copy((sfinx_8bit_vector_t *)val);
226        val = rx_elements.get(SFINX_MIN_AUTH_LEVELS);
227        if (!val)
228          return 1;
229        min_auth_levels->copy((sfinx_8bit_vector_t *)val);
230        if (min_auth_levels->size() > 1) // unsupported auth levels
231          return 1;
232        if (min_auth_levels->get(0) != SFINX_AUTH_USERPASS) // unsupported auth type
233          return 1;
234        val = rx_elements.get(SFINX_MD5_SUM);
235        if (!val)
236          return 1;
237        md5_challenge->copy((sfinx_8bit_vector_t *)val);
238        // send auth_request
239        tx_elements.clear();
240        sfinx_8bit_t auth_req(SFINX_AUTH_REQUEST);
241        auth_req.set(SFINX_AUTH_USERPASS);
242        tx_elements.add(auth_req);
243        sfinx_8bit_vector_t auth_md5(SFINX_MD5_SUM);
244        auth_md5.copy(md5_challenge); // ÏÒÉÇÉÎÁÌØÎÙÊ challenge
245        // ask user_name / pass
246        // ...
247        // ÛÉÆÒÕÅÍ user_name
248        tx_elements.add(auth_md5); // user name md5'ed
249        // ÛÉÆÒÕÅÍ pass
250        tx_elements.add(auth_md5); // pass md5'ed
251        debug("sending auth request");
252        send_packet();
253        // read response
254        if (read_packet()) {
255          debug("Error reading response");
256          return 1;
257       }
258        val = rx_elements.get(SFINX_ACCESS_GRANTED);
259        if (!val) {
260          debug("Access denied");
261          return 1;
262       }
263        debug("connected ok");
264        connected_ = true;
265        return 0;        
269     void wait_for(sfinx_t *o) {
270     if (wait_object) {
271       log("wait_for:", "already waiting");
272       return;
273    }
274     wait_object = o;
275     is_waiting = true;
277   bool waiting(u32_t ms) {
278     while(ms) {
279       if (!is_waiting)
280         return 0;
281       Thread::sleep(10);
282       ms -= 10;
283    }
284     return 1;
286   void cancel_wait(void) { wait_for(0); }
291 #endif