1 | /** |
2 | * @file scim_socket.h |
3 | * @brief Socket interfaces. |
4 | */ |
5 | |
6 | /* |
7 | * Smart Common Input Method |
8 | * |
9 | * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn> |
10 | * |
11 | * |
12 | * This library is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU Lesser General Public |
14 | * License as published by the Free Software Foundation; either |
15 | * version 2 of the License, or (at your option) any later version. |
16 | * |
17 | * This library is distributed in the hope that it will be useful, |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | * GNU Lesser General Public License for more details. |
21 | * |
22 | * You should have received a copy of the GNU Lesser General Public |
23 | * License along with this program; if not, write to the |
24 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
25 | * Boston, MA 02111-1307 USA |
26 | * |
27 | * $Id: scim_socket.h,v 1.25 2005/01/25 15:13:15 suzhe Exp $ |
28 | */ |
29 | |
30 | #ifndef __SCIM_SOCKET_H |
31 | #define __SCIM_SOCKET_H |
32 | |
33 | namespace scim { |
34 | |
35 | /** |
36 | * @addtogroup SocketCommunication |
37 | * @{ |
38 | */ |
39 | |
40 | class Socket; |
41 | class SocketAddress; |
42 | class SocketServer; |
43 | class SocketClient; |
44 | |
45 | typedef Slot2<void, SocketServer *, const Socket &> |
46 | SocketServerSlotSocket; |
47 | |
48 | typedef Signal2<void, SocketServer *, const Socket &> |
49 | SocketServerSignalSocket; |
50 | |
51 | /** |
52 | * @brief An exception class to hold Socket related errors. |
53 | * |
54 | * scim::Socket and its derived classes must throw |
55 | * scim::SocketError object when error. |
56 | */ |
57 | class SocketError: public Exception |
58 | { |
59 | public: |
60 | SocketError (const String& what_arg) |
61 | : Exception (String("scim::Socket: " ) + what_arg) { } |
62 | }; |
63 | |
64 | /** |
65 | * @brief The vaild socket address/protocol family, |
66 | * |
67 | * Corresponding to libc PF_LOCAL/AF_LOCAL and PF_INET/AF_INET |
68 | */ |
69 | enum SocketFamily |
70 | { |
71 | SCIM_SOCKET_UNKNOWN, /**< Unknown or invalid socket address/protocol */ |
72 | SCIM_SOCKET_LOCAL, /**< Unix local socket address/protocol */ |
73 | SCIM_SOCKET_INET /**< Internet (ipv4) socket address/protocol */ |
74 | }; |
75 | |
76 | /** |
77 | * @brief The class to hold a socket address. |
78 | * |
79 | * Class SocketAddress encapsulates the details of |
80 | * socket address, like socketaddr_un and socketaddr_in. |
81 | * |
82 | * A SocketAddress object can be constructed from an |
83 | * address string, which must start with one of the |
84 | * following prefixes: |
85 | * - inet: or tcp: |
86 | * A internet address (ipv4). This kind of address must |
87 | * include two parts, separated by a colon. The first part |
88 | * is the ip address, the second part is the port. For example: |
89 | * inet:127.0.0.1:12345 |
90 | * - local: or unix: or file: |
91 | * A unix or local socket address. It's a full path of a socket file. |
92 | * For example: local:/tmp/scim-socket-frontend |
93 | */ |
94 | class SocketAddress |
95 | { |
96 | class SocketAddressImpl; |
97 | SocketAddressImpl *m_impl; |
98 | |
99 | public: |
100 | /** |
101 | * @brief Constructor. |
102 | * |
103 | * @param addr the address string. |
104 | */ |
105 | SocketAddress (const String &addr = String ()); |
106 | |
107 | /** |
108 | * @brief Copy constructor. |
109 | */ |
110 | SocketAddress (const SocketAddress &addr); |
111 | |
112 | /** |
113 | * @brief Destructor. |
114 | */ |
115 | ~SocketAddress (); |
116 | |
117 | /** |
118 | * @brief Copy operator. |
119 | */ |
120 | const SocketAddress& operator = (const SocketAddress &addr); |
121 | |
122 | /** |
123 | * @brief Check if this address is valid. |
124 | * |
125 | * @return true if this address is valid. |
126 | */ |
127 | bool valid () const; |
128 | |
129 | /** |
130 | * @brief Get the family of this socket address. |
131 | * |
132 | * @return the family enum value of this address. |
133 | * |
134 | * @sa SocketFamily |
135 | */ |
136 | SocketFamily get_family () const; |
137 | |
138 | /** |
139 | * @brief Set a new address. |
140 | * |
141 | * @param addr the new address string. |
142 | */ |
143 | bool set_address (const String &addr); |
144 | |
145 | /** |
146 | * @brief Get the address string. |
147 | * |
148 | * @return the address string. |
149 | */ |
150 | String get_address () const; |
151 | |
152 | /** |
153 | * @brief Get the internal data of this socket address, |
154 | * used by class Socket. |
155 | * |
156 | * @return the pointer to the data, usually a sockaddr struct. |
157 | */ |
158 | const void * get_data () const; |
159 | |
160 | /** |
161 | * @brief Get the size of the internall data. |
162 | * |
163 | * @return the size of the internall data returned by get_data (); |
164 | */ |
165 | int get_data_length () const; |
166 | }; |
167 | |
168 | /** |
169 | * @brief Socket communication class. |
170 | * |
171 | * Class Socket provides basic operation of socket, |
172 | * such as bind connect, read, write etc. |
173 | * |
174 | * This class object cannot be created directly by user. |
175 | * Only the object of its derived classes SocketServer and SocketClient |
176 | * can be created directly. |
177 | */ |
178 | class Socket |
179 | { |
180 | class SocketImpl; |
181 | |
182 | SocketImpl *m_impl; |
183 | |
184 | Socket (const Socket&); |
185 | const Socket& operator = (const Socket&); |
186 | |
187 | public: |
188 | /** |
189 | * @brief Create a Socket object from an already created socket_id. |
190 | * |
191 | * @param id an file id of an existing socket. |
192 | */ |
193 | Socket (int id = -1); |
194 | |
195 | /** |
196 | * @brief Destructor |
197 | */ |
198 | ~Socket (); |
199 | |
200 | /** |
201 | * @brief Check if the socket is valid. |
202 | * |
203 | * @return true if the socket is ready to read and write. |
204 | */ |
205 | bool valid () const; |
206 | |
207 | /** |
208 | * @brief Read data from socket. |
209 | * |
210 | * @param buf the buffer to store the data. |
211 | * @param size size of the buffer. |
212 | * |
213 | * @return the amount of data actually read, -1 means error occurred. |
214 | */ |
215 | int read (void *buf, size_t size) const; |
216 | |
217 | /** |
218 | * @brief read data from socket with a timeout. |
219 | * |
220 | * @param buf the buffer to store the data. |
221 | * @param size size of the buffer, and the amount of data to be read. |
222 | * @param timeout time out in millisecond (1/1000 second), -1 means infinity. |
223 | * |
224 | * @return the amount of data actually read, |
225 | * 0 means the connection is closed, |
226 | * -1 means error occurred. |
227 | */ |
228 | int read_with_timeout (void *buf, size_t size, int timeout) const; |
229 | |
230 | /** |
231 | * @brief Write data to socket. |
232 | * |
233 | * @param buf the buffer stores the data. |
234 | * @param size size of the data to be sent. |
235 | * |
236 | * @return the amount of data acutally sent, or -1 if an error occurred. |
237 | */ |
238 | int write (const void *buf, size_t size) const; |
239 | |
240 | /** |
241 | * @brief Wait until there are some data ready to read. |
242 | * |
243 | * @param timeout time out in millisecond (1/1000 second), -1 means infinity. |
244 | * |
245 | * @return > 0 if data is OK, == 0 if time is out, < 0 if an error occurred. |
246 | */ |
247 | int wait_for_data (int timeout = -1) const; |
248 | |
249 | /** |
250 | * @brief Get the number of the last occurred error. |
251 | * |
252 | * @return the standard errno value. |
253 | */ |
254 | int get_error_number () const; |
255 | |
256 | /** |
257 | * @brief Get the message of the last occurred error. |
258 | * |
259 | * @return the error message of the last occurred error. |
260 | */ |
261 | String get_error_message () const; |
262 | |
263 | /** |
264 | * @brief Get the socket id. |
265 | * |
266 | * @return the file id of this socket object. |
267 | */ |
268 | int get_id () const; |
269 | |
270 | protected: |
271 | |
272 | /** |
273 | * @brief Initiate a connection on a socket. |
274 | * |
275 | * @param addr the address to be connected to. |
276 | * |
277 | * @return true if success. |
278 | */ |
279 | bool connect (const SocketAddress &addr) const; |
280 | |
281 | /** |
282 | * @brief Bind a socket to an address, used by SocketServer. |
283 | * |
284 | * @param addr the address to be binded to. |
285 | * |
286 | * @return true if success. |
287 | */ |
288 | bool bind (const SocketAddress &addr) const; |
289 | |
290 | /** |
291 | * @brief Listen for connections on a socket. |
292 | * |
293 | * @param queue_length the length of the waiting queue. |
294 | * |
295 | * @return true if success. |
296 | */ |
297 | bool listen (int queue_length = 5) const; |
298 | |
299 | /** |
300 | * @brief Accept a connection on the socket, used by SocketServer. |
301 | * |
302 | * @return the id of the accepted client socket, or -1 if an error is occurred. |
303 | */ |
304 | int accept () const; |
305 | |
306 | /** |
307 | * @brief Create a socket for specific family. |
308 | * |
309 | * @param family the family type. |
310 | * |
311 | * @return true if success. |
312 | */ |
313 | bool create (SocketFamily family); |
314 | |
315 | /** |
316 | * @brief Close the socket. |
317 | */ |
318 | void close (); |
319 | }; |
320 | |
321 | /** |
322 | * @brief Socket Server class. |
323 | * |
324 | * Class SocketServer provides basic operations to create a Socket Server, |
325 | * such as create, run etc. |
326 | */ |
327 | class SocketServer : private Socket |
328 | { |
329 | class SocketServerImpl; |
330 | |
331 | SocketServerImpl *m_impl; |
332 | |
333 | public: |
334 | /** |
335 | * @brief Default constructor, do nothing. |
336 | */ |
337 | SocketServer (int max_clients = -1); |
338 | |
339 | /** |
340 | * @brief Constructor. |
341 | * |
342 | * @param address create a server on this address. |
343 | * @param max_clients the max number of socket clients, -1 means unlimited. |
344 | */ |
345 | SocketServer (const SocketAddress &address, int max_clients = -1); |
346 | |
347 | /** |
348 | * @brief Destructor. |
349 | */ |
350 | ~SocketServer (); |
351 | |
352 | /** |
353 | * @brief Test if the server is valid. |
354 | * |
355 | * @return true if the socket server is valid and ready to run. |
356 | */ |
357 | bool valid () const; |
358 | |
359 | /** |
360 | * @brief Create a socket on an address. |
361 | * |
362 | * @param address the address to be listen. |
363 | * |
364 | * @return true if OK. |
365 | */ |
366 | bool create (const SocketAddress &address); |
367 | |
368 | /** |
369 | * @brief Run the server. |
370 | * |
371 | * @return true if it ran successfully. |
372 | */ |
373 | bool run (); |
374 | |
375 | /** |
376 | * @brief Check if the server is running. |
377 | * |
378 | * @return true if it's running. |
379 | */ |
380 | bool is_running () const; |
381 | |
382 | /** |
383 | * @brief Shutdown the server. |
384 | */ |
385 | void shutdown (); |
386 | |
387 | /** |
388 | * @brief Close a client connection. |
389 | * |
390 | * @param socket the client socket object to be closed. |
391 | * @return true if the socket was closed successfully. |
392 | */ |
393 | bool close_connection (const Socket &socket); |
394 | |
395 | /** |
396 | * @brief Get the number of the last occurred error. |
397 | * |
398 | * @return the standard errno value. |
399 | */ |
400 | int get_error_number () const; |
401 | |
402 | /** |
403 | * @brief Get the message of the last occurred error. |
404 | * |
405 | * @return the error message corresponding to the errno. |
406 | */ |
407 | String get_error_message () const; |
408 | |
409 | /** |
410 | * @brief Get the max number of socket clients. |
411 | * |
412 | * @return the max number of socket clients allowed to connect this server. |
413 | */ |
414 | int get_max_clients () const; |
415 | |
416 | /** |
417 | * @brief Set the max number of clients. |
418 | * |
419 | * @param max_clients the max number of socket clients allowed to connect this server. |
420 | */ |
421 | void set_max_clients (int max_clients); |
422 | |
423 | /** |
424 | * @brief Insert an external socket into the main loop. |
425 | * |
426 | * If data is available on this socket, then the receive signal will be emitted. |
427 | * |
428 | * @param sock The external socket to be inserted. |
429 | * @return true if the socket is valid. |
430 | */ |
431 | bool insert_external_socket (const Socket &sock); |
432 | |
433 | /** |
434 | * @brief Remove an external socket which was inserted by insert_external_socket (). |
435 | * |
436 | * @param sock The external socket to be removed. |
437 | * @return true if the socket is valid and has been removed successfully. |
438 | */ |
439 | bool remove_external_socket (const Socket &sock); |
440 | |
441 | public: |
442 | /** |
443 | * @brief Connect a slot to socket accept signal. |
444 | * |
445 | * Connect a slot to socket accept signal, if a client connection is accepted, |
446 | * this signal will be emitted. |
447 | * |
448 | * @param slot the slot to be connected to this signal. |
449 | * |
450 | * @return the Connection object of this slot-signal connection, can be used |
451 | * to disconnect the slot later. |
452 | */ |
453 | Connection signal_connect_accept (SocketServerSlotSocket *slot); |
454 | |
455 | /** |
456 | * @brief Connect a slot to socket receive signal. |
457 | * |
458 | * Connect a slot to socket receive signal, if a client send data to this server, |
459 | * this signal will be emitted. |
460 | * |
461 | * @param slot the slot to be connected to this signal. |
462 | * |
463 | * @return the Connection object of this slot-signal connection, can be used |
464 | * to disconnect the slot later. |
465 | */ |
466 | Connection signal_connect_receive (SocketServerSlotSocket *slot); |
467 | |
468 | /** |
469 | * @brief Connect a slot to socket exception signal. |
470 | * |
471 | * Connect a slot to socket exception signal, if an exception was occurred |
472 | * to a client connection, this signal will be emitted. |
473 | * |
474 | * @param slot the slot to be connected to this signal. |
475 | * |
476 | * @return the Connection object of this slot-signal connection, can be used |
477 | * to disconnect the slot later. |
478 | */ |
479 | Connection signal_connect_exception (SocketServerSlotSocket *slot); |
480 | }; |
481 | |
482 | /** |
483 | * @brief Socket client class. |
484 | * |
485 | * Class SocketClient provides basic operations to create a Socket Client, |
486 | * such as connect, read, write, etc. |
487 | */ |
488 | class SocketClient : public Socket |
489 | { |
490 | bool m_connected; |
491 | |
492 | public: |
493 | /** |
494 | * @brief Constructor. |
495 | */ |
496 | SocketClient (); |
497 | |
498 | /** |
499 | * @brief Constructor. |
500 | * |
501 | * @param address the server address to be connected. |
502 | */ |
503 | SocketClient (const SocketAddress &address); |
504 | |
505 | /** |
506 | * @brief Destructor. |
507 | */ |
508 | ~SocketClient (); |
509 | |
510 | /** |
511 | * @brief Check if the socket is connected. |
512 | * |
513 | * @return true if the socket client is connected to a server. |
514 | */ |
515 | bool is_connected () const; |
516 | |
517 | /** |
518 | * @brief Connect to a server. |
519 | * |
520 | * @param address the server socket address to be connected to. |
521 | * |
522 | * @return true if connected successfully. |
523 | */ |
524 | bool connect (const SocketAddress &address); |
525 | |
526 | /** |
527 | * @brief Close the client. |
528 | */ |
529 | void close (); |
530 | }; |
531 | |
532 | /** |
533 | * @brief Get the default socket address of SocketFrontEnd |
534 | * |
535 | * SocketFrontEnd should listen on this address by default. |
536 | */ |
537 | String scim_get_default_socket_frontend_address (); |
538 | |
539 | /** |
540 | * @brief Get the default socket address of SocketIMEngine |
541 | * |
542 | * SocketIMEngine should connect to this address by default. |
543 | */ |
544 | String scim_get_default_socket_imengine_address (); |
545 | |
546 | /** |
547 | * @brief Get the default socket address of SocketConfig |
548 | * |
549 | * SocketConfig should connect to this address by default. |
550 | */ |
551 | String scim_get_default_socket_config_address (); |
552 | |
553 | /** |
554 | * @brief Get the default socket address of the Panel running on localhost. |
555 | * |
556 | * The panel running on local host should listen on this address by default. |
557 | * All FrontEnds which need panel should connect to this address by default. |
558 | */ |
559 | String scim_get_default_panel_socket_address (const String &display); |
560 | |
561 | /** |
562 | * @brief Get the default socket address of Helper Manager Server running on localhost. |
563 | */ |
564 | String scim_get_default_helper_manager_socket_address (); |
565 | |
566 | /** |
567 | * @brief Get the default socket timeout value. |
568 | * |
569 | * All socket connection should use this timeout value. |
570 | */ |
571 | int scim_get_default_socket_timeout (); |
572 | |
573 | /** |
574 | * @brief Helper function to open a connection to a socket server |
575 | * with a standard hand shake protocol. |
576 | * |
577 | * This function is used by a socket client to establish a connection |
578 | * between a socket server with a standard hand shake protocol. |
579 | * |
580 | * The communication between Panel and FrontEnd, SocketFrontEnd and SocketIMEngine, |
581 | * SocketFrontEnd and SocketConfig all uses this hand shake protocol. |
582 | * |
583 | * @param key A random magic key sent from the socket server |
584 | * to identify this client in later communications. |
585 | * @param client_type The type of this socket client, for example: |
586 | * "FrontEnd", "GUI", "SocketIMEngine", "SocketConfig" etc. |
587 | * If the type is "ConnectionTester" then this call just |
588 | * test if the connection can be established. The client |
589 | * should close this socket just after the call. |
590 | * @param server_type The request socket server type, for example: |
591 | * "Panel", "SocketFrontEnd" etc. |
592 | * @param socket The reference to the client socket which has been |
593 | * connected to the socket server. |
594 | * @param timeout The socket read timeout in millisecond, -1 means unlimited. |
595 | * |
596 | * @return true if the connection was established successfully, otherwise |
597 | * return false, and the client should close the socket. |
598 | */ |
599 | bool scim_socket_open_connection (uint32 &key, |
600 | const String &client_type, |
601 | const String &server_type, |
602 | const Socket &socket, |
603 | int timeout = -1); |
604 | |
605 | /** |
606 | * @brief Helper function to accept a connection request from a socket client |
607 | * with a standard hand shake protocol. |
608 | * |
609 | * This function is used by a socket server to accept a connection request |
610 | * from a socket client which is calling scim_socket_open_connection (). |
611 | * |
612 | * If a client with type "ConnectionTester" connected to this socket server, then |
613 | * this function will return an empty string, but tell the client the connection |
614 | * was established successfully. |
615 | * |
616 | * @param key A random magic key to identify the socket client in later |
617 | * communications. |
618 | * @param server_types The type of this server, for example: |
619 | * "SocketFrontEnd", "Panel" etc. |
620 | * One server can have multiple types, separated by comma. |
621 | * @param client_types A list of acceptable client types, separated by comma. |
622 | * The client type maybe: "FrontEnd", "GUI", "SocketIMEngine" etc. |
623 | * @param socket The socket connected to the client. |
624 | * @param timeout the socket read timeout in millisecond, -1 means unlimited. |
625 | * |
626 | * @return The type of the accepted socket client, or an empty string if the |
627 | * connection could not be established. |
628 | */ |
629 | String scim_socket_accept_connection (uint32 &key, |
630 | const String &server_types, |
631 | const String &client_types, |
632 | const Socket &socket, |
633 | int timeout = -1); |
634 | /** @} */ |
635 | |
636 | } // namespace scim |
637 | |
638 | #endif //__SCIM_SOCKET_H |
639 | |
640 | /* |
641 | vi:ts=4:nowrap:ai:expandtab |
642 | */ |
643 | |
644 | |