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
33namespace scim {
34
35/**
36 * @addtogroup SocketCommunication
37 * @{
38 */
39
40class Socket;
41class SocketAddress;
42class SocketServer;
43class SocketClient;
44
45typedef Slot2<void, SocketServer *, const Socket &>
46 SocketServerSlotSocket;
47
48typedef 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 */
57class SocketError: public Exception
58{
59public:
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 */
69enum 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 */
94class SocketAddress
95{
96 class SocketAddressImpl;
97 SocketAddressImpl *m_impl;
98
99public:
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 */
178class Socket
179{
180 class SocketImpl;
181
182 SocketImpl *m_impl;
183
184 Socket (const Socket&);
185 const Socket& operator = (const Socket&);
186
187public:
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
270protected:
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 */
327class SocketServer : private Socket
328{
329 class SocketServerImpl;
330
331 SocketServerImpl *m_impl;
332
333public:
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
441public:
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 */
488class SocketClient : public Socket
489{
490 bool m_connected;
491
492public:
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 */
537String 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 */
544String 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 */
551String 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 */
559String 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 */
564String 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 */
571int 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 */
599bool 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 */
629String 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/*
641vi:ts=4:nowrap:ai:expandtab
642*/
643
644