1 /** @file scim_socket_config.cpp
2 * implementation of SocketConfig class.
4 /* ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. */
7 * Smart Common Input Method
9 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
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.
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.
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
27 * $Id: scim_socket_config.cpp,v 1.23 2005/12/16 11:12:26 suzhe Exp $
30 #define Uses_SCIM_CONFIG_BASE
31 #define Uses_SCIM_CONFIG_PATH
32 #define Uses_SCIM_SOCKET
33 #define Uses_SCIM_TRANSACTION
37 #include "scim_private.h"
39 #include "scim_socket_config.h"
42 #include "isf_debug.h"
47 #define LOG_TAG "ISF_SOCKET_CONFIG"
50 #define scim_module_init socket_LTX_scim_module_init
51 #define scim_module_exit socket_LTX_scim_module_exit
52 #define scim_config_module_init socket_LTX_scim_config_module_init
53 #define scim_config_module_create_config socket_LTX_scim_config_module_create_config
58 EXAPI void scim_module_init (void)
60 SCIM_DEBUG_CONFIG(1) << "Initializing Socket Config module...\n";
63 EXAPI void scim_module_exit (void)
65 SCIM_DEBUG_CONFIG(1) << "Exiting Socket Config module...\n";
68 EXAPI void scim_config_module_init ()
70 SCIM_DEBUG_CONFIG(1) << "Initializing Socket Config module (more)...\n";
73 EXAPI ConfigPointer scim_config_module_create_config ()
75 SCIM_DEBUG_CONFIG(1) << "Creating a Socket Config instance...\n";
76 return new SocketConfig ();
82 SocketConfig::SocketConfig ()
83 : m_socket_address (scim_get_default_socket_config_address ()),
84 m_socket_timeout (scim_get_default_socket_timeout ()),
88 SCIM_DEBUG_CONFIG (2) << " Construct SocketConfig object.\n";
92 const char *p = getenv ("DISPLAY");
93 if (p) display_name = String (p);
95 m_socket_address = scim_get_default_panel_socket_address (display_name);
97 m_valid = open_connection ();
100 SocketConfig::~SocketConfig ()
102 m_socket_client.close ();
106 SocketConfig::valid () const
108 return ConfigBase::valid() && m_valid;
112 SocketConfig::get_name () const
119 SocketConfig::read (const String& key, String *pStr) const
122 if (!valid () || !pStr || key.empty()) return false;
123 if (!m_connected && !open_connection ()) return false;
129 for (int retry = 0; retry < 3; ++retry) {
130 init_transaction (trans);
131 trans.put_command (SCIM_TRANS_CMD_GET_CONFIG_STRING);
132 trans.put_data (key);
134 if (trans.write_to_socket (m_socket_client) &&
135 trans.read_from_socket (m_socket_client, m_socket_timeout)) {
136 if (trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
137 trans.get_data (*pStr) &&
138 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK)
143 LOGW ("Failed, reconnect again");
144 if (!open_connection ())
154 SocketConfig::read (const String& key, int *pl) const
157 if (!valid () || !pl || key.empty()) return false;
158 if (!m_connected && !open_connection ()) return false;
163 for (int retry = 0; retry < 3; ++retry) {
164 init_transaction (trans);
165 trans.put_command (SCIM_TRANS_CMD_GET_CONFIG_INT);
166 trans.put_data (key);
168 if (trans.write_to_socket (m_socket_client) &&
169 trans.read_from_socket (m_socket_client, m_socket_timeout)) {
171 if (trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
172 trans.get_data (val) &&
173 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
180 LOGW ("Failed, reconnect again");
181 if (!open_connection ())
191 SocketConfig::read (const String& key, double* val) const
194 if (!valid () || !val || key.empty()) return false;
195 if (!m_connected && !open_connection ()) return false;
200 for (int retry = 0; retry < 3; ++retry) {
201 init_transaction (trans);
202 trans.put_command (SCIM_TRANS_CMD_GET_CONFIG_DOUBLE);
203 trans.put_data (key);
205 if (trans.write_to_socket (m_socket_client) &&
206 trans.read_from_socket (m_socket_client, m_socket_timeout)) {
208 if (trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
209 trans.get_data (str) &&
210 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
211 sscanf (str.c_str (), "%lE", val);
217 LOGW ("Failed, reconnect again");
218 if (!open_connection ())
228 SocketConfig::read (const String& key, bool* val) const
231 if (!valid () || !val || key.empty()) return false;
232 if (!m_connected && !open_connection ()) return false;
237 for (int retry = 0; retry < 3; ++retry) {
238 init_transaction (trans);
239 trans.put_command (SCIM_TRANS_CMD_GET_CONFIG_BOOL);
240 trans.put_data (key);
242 if (trans.write_to_socket (m_socket_client) &&
243 trans.read_from_socket (m_socket_client, m_socket_timeout)) {
245 if (trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
246 trans.get_data (tmp) &&
247 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
254 LOGW ("Failed, reconnect again");
255 if (!open_connection ())
265 SocketConfig::read (const String& key, std::vector <String>* val) const
268 if (!valid () || !val || key.empty()) return false;
269 if (!m_connected && !open_connection ()) return false;
276 for (int retry = 0; retry < 3; ++retry) {
277 init_transaction (trans);
278 trans.put_command (SCIM_TRANS_CMD_GET_CONFIG_VECTOR_STRING);
279 trans.put_data (key);
281 if (trans.write_to_socket (m_socket_client) &&
282 trans.read_from_socket (m_socket_client, m_socket_timeout)) {
283 if (trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
284 trans.get_data (*val) &&
285 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
291 LOGW ("Failed, reconnect again");
292 if (!open_connection ())
301 SocketConfig::read (const String& key, std::vector <int>* val) const
304 if (!valid () || !val || key.empty()) return false;
305 if (!m_connected && !open_connection ()) return false;
312 for (int retry = 0; retry < 3; ++retry) {
313 init_transaction (trans);
314 trans.put_command (SCIM_TRANS_CMD_GET_CONFIG_VECTOR_INT);
315 trans.put_data (key);
317 if (trans.write_to_socket (m_socket_client) &&
318 trans.read_from_socket (m_socket_client, m_socket_timeout)) {
319 std::vector<uint32> vec;
320 if (trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
321 trans.get_data (vec) &&
322 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
323 for (uint32 i=0; i<vec.size (); ++i)
324 val->push_back ((int) vec[i]);
330 LOGW ("Failed, reconnect again");
331 if (!open_connection ())
338 // write the value (return true on success)
340 SocketConfig::write (const String& key, const String& value)
343 if (!valid () || key.empty()) return false;
344 if (!m_connected && !open_connection ()) return false;
348 for (int retry = 0; retry < 3; ++retry) {
349 init_transaction (trans);
350 trans.put_command (SCIM_TRANS_CMD_SET_CONFIG_STRING);
351 trans.put_data (key);
352 trans.put_data (value);
354 if (trans.write_to_socket (m_socket_client)) {
357 LOGW ("Failed, reconnect again");
358 if (!open_connection ())
366 SocketConfig::write (const String& key, int value)
369 if (!valid () || key.empty()) return false;
370 if (!m_connected && !open_connection ()) return false;
374 for (int retry = 0; retry < 3; ++retry) {
375 init_transaction (trans);
376 trans.put_command (SCIM_TRANS_CMD_SET_CONFIG_INT);
377 trans.put_data (key);
378 trans.put_data ((uint32)value);
380 if (trans.write_to_socket (m_socket_client)) {
383 LOGW ("Failed, reconnect again");
384 if (!open_connection ())
392 SocketConfig::write (const String& key, double value)
395 if (!valid () || key.empty()) return false;
396 if (!m_connected && !open_connection ()) return false;
399 snprintf (buf, 255, "%lE", value);
403 for (int retry = 0; retry < 3; ++retry) {
404 init_transaction (trans);
405 trans.put_command (SCIM_TRANS_CMD_SET_CONFIG_DOUBLE);
406 trans.put_data (key);
407 trans.put_data (String (buf));
409 if (trans.write_to_socket (m_socket_client)) {
412 LOGW ("Failed, reconnect again");
413 if (!open_connection ())
421 SocketConfig::write (const String& key, bool value)
424 if (!valid () || key.empty()) return false;
425 if (!m_connected && !open_connection ()) return false;
429 for (int retry = 0; retry < 3; ++retry) {
430 init_transaction (trans);
431 trans.put_command (SCIM_TRANS_CMD_SET_CONFIG_BOOL);
432 trans.put_data (key);
433 trans.put_data ((uint32)value);
435 if (trans.write_to_socket (m_socket_client)) {
438 LOGW ("Failed, reconnect again");
439 if (!open_connection ())
447 SocketConfig::write (const String& key, const std::vector <String>& value)
450 if (!valid () || key.empty()) return false;
451 if (!m_connected && !open_connection ()) return false;
455 for (int retry = 0; retry < 3; ++retry) {
456 init_transaction (trans);
457 trans.put_command (SCIM_TRANS_CMD_SET_CONFIG_VECTOR_STRING);
458 trans.put_data (key);
459 trans.put_data (value);
461 if (trans.write_to_socket (m_socket_client)) {
464 LOGW ("Failed, reconnect again");
465 if (!open_connection ())
473 SocketConfig::write (const String& key, const std::vector <int>& value)
476 if (!valid () || key.empty()) return false;
477 if (!m_connected && !open_connection ()) return false;
479 std::vector <uint32> vec;
481 for (uint32 i=0; i<value.size (); ++i)
482 vec.push_back ((uint32) value [i]);
486 for (int retry = 0; retry < 3; ++retry) {
487 init_transaction (trans);
488 trans.put_command (SCIM_TRANS_CMD_SET_CONFIG_VECTOR_INT);
489 trans.put_data (key);
490 trans.put_data (vec);
492 if (trans.write_to_socket (m_socket_client)) {
495 LOGW ("Failed, reconnect again");
496 if (!open_connection ())
503 // permanently writes all changes
505 SocketConfig::flush ()
508 if (!valid ()) return false;
509 if (!m_connected && !open_connection ()) return false;
513 for (int retry = 0; retry < 3; ++retry) {
514 init_transaction (trans);
515 trans.put_command (SCIM_TRANS_CMD_FLUSH_CONFIG);
517 if (trans.write_to_socket (m_socket_client)) {
518 gettimeofday (&m_update_timestamp, 0);
521 LOGW ("Failed, reconnect again");
522 if (!open_connection ())
531 SocketConfig::erase (const String& key)
534 if (!valid ()) return false;
535 if (!m_connected && !open_connection ()) return false;
539 for (int retry = 0; retry < 3; ++retry) {
540 init_transaction (trans);
541 trans.put_command (SCIM_TRANS_CMD_ERASE_CONFIG);
542 trans.put_data (key);
544 if (trans.write_to_socket (m_socket_client)) {
547 LOGW ("Failed, reconnect again");
548 if (!open_connection ())
556 SocketConfig::reload ()
559 if (!valid ()) return false;
560 if (!m_connected && !open_connection ()) return false;
565 for (int retry = 0; retry < 3; ++retry) {
566 init_transaction (trans);
567 trans.put_command (SCIM_TRANS_CMD_RELOAD_CONFIG);
569 // The reload process may take very long time, so wait a little longer time.
570 if (trans.write_to_socket (m_socket_client) &&
571 trans.read_from_socket (m_socket_client, m_socket_timeout * 10)) {
572 if (trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
573 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
575 if (read (String (SCIM_CONFIG_UPDATE_TIMESTAMP), &str)) {
576 std::vector <String> strs;
577 if (scim_split_string_list (strs, str, ':') == 2) {
578 time_t sec = (time_t) strtol (strs [0].c_str (), 0, 10);
579 suseconds_t usec = (suseconds_t) strtol (strs [1].c_str (), 0, 10);
581 // The config file is newer, so load it.
582 if (m_update_timestamp.tv_sec < sec ||
583 (m_update_timestamp.tv_sec == sec && m_update_timestamp.tv_usec < usec)) {
584 m_update_timestamp.tv_sec = sec;
585 m_update_timestamp.tv_usec = usec;
586 return ConfigBase::reload ();
593 LOGW ("Failed reconnect again");
594 if (!open_connection ())
602 SocketConfig::init_transaction (Transaction &trans) const
605 trans.put_command (SCIM_TRANS_CMD_REQUEST);
606 trans.put_data (m_socket_magic_key);
610 SocketConfig::open_connection () const
612 SocketAddress socket_address (m_socket_address);
616 // Connect to SocketServer.
617 if (!m_socket_client.connect (socket_address)) {
618 /* Retry connecting considering the ANR timeout */
619 for (int i = 0; i < 3; ++i) {
620 if (m_socket_client.connect (socket_address))
622 scim_usleep (100000);
623 LOGW (" Re-connecting to ISF(scim) server. SocketConfig connect count : %d\n", i+1);
627 if (!m_socket_client.is_connected ()) {
628 LOGW (" Cannot connect to SocketServer (%s).\n", m_socket_address.c_str ());
632 // Init the connection,
633 if (!scim_socket_open_connection (m_socket_magic_key,
634 String ("SocketConfig"),
638 m_socket_client.close ();
639 LOGE (" Connect to SocketServer (%s) failed.\n", m_socket_address.c_str ());
643 LOGD (" Connect to SocketServer (%s).\n", m_socket_address.c_str ());
645 gettimeofday (&m_update_timestamp, 0);
652 vi:ts=4:nowrap:ai:expandtab