1 /** @file scim_socket.cpp
2 * @brief Implementation of Socket related classes.
5 /* ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. */
8 * Smart Common Input Method
10 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
11 * Copyright (c) 2012-2015 Samsung Electronics Co., Ltd.
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this program; if not, write to the
26 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
27 * Boston, MA 02111-1307 USA
29 * Modifications by Samsung Electronics Co., Ltd.
30 * 1. Add filter_event () and filter_exception_event () in SocketServer class
31 * 2. Add set_nonblock_mode () in Socket class
33 * $Id: scim_socket.cpp,v 1.44 2005/12/01 08:27:36 suzhe Exp $
37 #define Uses_SCIM_SOCKET
38 #define Uses_SCIM_TRANSACTION
39 #define Uses_SCIM_CONFIG_PATH
40 #include <sys/types.h>
41 #include <sys/socket.h>
50 #include <netinet/in.h>
52 #include <arpa/inet.h>
57 #include <sys/prctl.h>
60 #include "scim_private.h"
62 #include <systemd/sd-daemon.h>
67 #define LOG_TAG "ISF_SOCKET"
69 #define SCIM_SOCKET_SERVER_MAX_CLIENTS 256
74 __gethostname (const char *host)
76 struct in_addr addr = { 0 };
78 #if HAVE_GETHOSTBYNAME_R
79 struct hostent hostbuf, *hp;
86 /* Allocate buffer, remember to free it to avoid memory leakage. */
87 tmphstbuf = (char*) malloc (hstbuflen);
89 while ((res = gethostbyname_r (host, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr)) == ERANGE) {
90 /* Enlarge the buffer. */
92 char *hstbuf = (char*) realloc (tmphstbuf, hstbuflen);
99 void *pvoid = hp->h_addr_list [0];
100 addr = * ((struct in_addr *) pvoid);
105 struct hostent *hostinfo;
107 hostinfo = gethostbyname (host);
110 pvoid = hostinfo->h_addr_list [0];
111 addr = * ((struct in_addr *) pvoid);
117 class SocketAddress::SocketAddressImpl
119 struct sockaddr *m_data;
120 SocketFamily m_family;
124 SocketAddressImpl (const String &addr = String ())
125 : m_data (0), m_family (SCIM_SOCKET_UNKNOWN) {
126 if (addr.length ()) set_address (addr);
129 SocketAddressImpl (const SocketAddressImpl &other)
130 : m_data (0), m_family (other.m_family), m_address (other.m_address) {
134 case SCIM_SOCKET_LOCAL:
135 m_data = (struct sockaddr*) new struct sockaddr_un;
136 len = sizeof (sockaddr_un);
138 case SCIM_SOCKET_INET:
139 m_data = (struct sockaddr*) new struct sockaddr_in;
140 len = sizeof (sockaddr_in);
142 case SCIM_SOCKET_UNKNOWN:
148 if (len && m_data) memcpy (m_data, other.m_data, len);
152 ~SocketAddressImpl () {
153 struct sockaddr_un *un = 0;
154 struct sockaddr_in *in = 0;
158 case SCIM_SOCKET_LOCAL:
159 un = (struct sockaddr_un *)m_data;
162 case SCIM_SOCKET_INET:
163 in = (struct sockaddr_in *)m_data;
166 case SCIM_SOCKET_UNKNOWN:
175 SocketAddressImpl & operator = (const SocketAddressImpl &other) {
179 m_family = other.m_family;
180 m_address = other.m_address;
187 case SCIM_SOCKET_LOCAL:
188 m_data = (struct sockaddr*) new struct sockaddr_un;
189 len = sizeof (sockaddr_un);
191 case SCIM_SOCKET_INET:
192 m_data = (struct sockaddr*) new struct sockaddr_in;
193 len = sizeof (sockaddr_in);
195 case SCIM_SOCKET_UNKNOWN:
200 if (len && m_data) memcpy (m_data, other.m_data, len);
205 void swap (SocketAddressImpl &other) {
206 std::swap (m_data, other.m_data);
207 std::swap (m_family, other.m_family);
208 std::swap (m_address, other.m_address);
211 bool valid () const {
212 if (m_address.length () && m_data &&
213 (m_family == SCIM_SOCKET_LOCAL || m_family == SCIM_SOCKET_INET))
218 SocketFamily get_family () const {
222 bool set_address (const String &addr);
224 const String & get_address () const {
228 const void * get_data () const {
229 return (void *)m_data;
232 int get_data_length () const {
234 if (m_family == SCIM_SOCKET_LOCAL)
235 return SUN_LEN ((struct sockaddr_un*)(m_data));
236 else if (m_family == SCIM_SOCKET_INET)
237 return sizeof (struct sockaddr_in);
244 SocketAddress::SocketAddressImpl::set_address (const String &addr)
246 std::vector <String> varlist;
248 struct sockaddr *new_data = 0;
249 SocketFamily new_family = SCIM_SOCKET_UNKNOWN;
251 scim_split_string_list (varlist, addr, ':');
253 if (varlist.size () < 2)
256 if (varlist [0] == "local" || varlist [0] == "unix" || varlist [0] == "file") {
257 #ifdef DISABLE_MULTIPLE_SOCKETS
258 String real_addr = addr.substr (varlist [0].length ()+1);
260 String real_addr = addr.substr (varlist [0].length ()+1) +
262 scim_get_user_name ();
264 struct sockaddr_un *un = new struct sockaddr_un;
266 un->sun_family = AF_UNIX;
268 memset (un->sun_path, 0, sizeof (un->sun_path));
270 strncpy (un->sun_path, real_addr.c_str (), sizeof (un->sun_path) - 1);
272 un->sun_path[sizeof (un->sun_path) - 1] = '\0';
274 SCIM_DEBUG_SOCKET (3) << " local:" << un->sun_path << "\n";
276 new_family = SCIM_SOCKET_LOCAL;
277 new_data = (struct sockaddr *) un;
279 } else if ((varlist [0] == "tcp" || varlist [0] == "inet") &&
280 varlist.size () == 3) {
281 struct sockaddr_in *in = new struct sockaddr_in;
283 in->sin_addr = __gethostname (varlist [1].c_str ());
285 if (in->sin_addr.s_addr) {
286 in->sin_family = AF_INET;
287 in->sin_port = htons (atoi (varlist [2].c_str ()));
289 SCIM_DEBUG_SOCKET (3) << " inet:"
290 << inet_ntoa (in->sin_addr) << ":"
291 << ntohs (in->sin_port) << "\n";
293 new_family = SCIM_SOCKET_INET;
294 new_data = (struct sockaddr *) in;
301 struct sockaddr_un *un = 0;
302 struct sockaddr_in *in = 0;
306 case SCIM_SOCKET_LOCAL:
307 un = (struct sockaddr_un *)m_data;
310 case SCIM_SOCKET_INET:
311 in = (struct sockaddr_in *)m_data;
314 case SCIM_SOCKET_UNKNOWN:
323 m_family = new_family;
331 // Implementation of SocketAddress
332 SocketAddress::SocketAddress (const String &addr)
333 : m_impl (new SocketAddressImpl (addr))
337 SocketAddress::SocketAddress (const SocketAddress &addr)
338 : m_impl (new SocketAddressImpl (*addr.m_impl))
342 SocketAddress::~SocketAddress ()
348 SocketAddress::operator = (const SocketAddress &addr)
351 SocketAddressImpl new_impl (*addr.m_impl);
352 m_impl->swap (new_impl);
358 SocketAddress::valid () const
360 return m_impl->valid ();
364 SocketAddress::get_family () const
366 return m_impl->get_family ();
370 SocketAddress::set_address (const String &addr)
372 SCIM_DEBUG_SOCKET (2) << " SocketAddress::set_address (" << addr << ")\n";
373 return m_impl->set_address (addr);
377 SocketAddress::get_address () const
379 return m_impl->get_address ();
383 SocketAddress::get_data () const
385 return m_impl->get_data ();
389 SocketAddress::get_data_length () const
391 return m_impl->get_data_length ();
394 // Implementation of Socket
395 class Socket::SocketImpl
401 SocketFamily m_family;
402 SocketAddress m_address;
406 SocketImpl (int id = -1)
407 : m_id (id), m_err (0), m_binded (false), m_no_close (true),
408 m_family (SCIM_SOCKET_UNKNOWN) {
415 bool valid () const {
419 int read (void *buf, size_t size) {
420 if (!buf || !size) { m_err = EINVAL; return -1; }
421 if (m_id < 0) { m_err = EBADF; return -1; }
426 ret = ::read (m_id, buf, size);
436 int read_with_timeout (void *buf, size_t size, int timeout) {
437 if (!buf || !size) { m_err = EINVAL; return -1; }
438 if (m_id < 0) { m_err = EBADF; return -1; }
441 return read (buf, size);
445 char *cbuf = static_cast<char *> (buf);
448 ret = wait_for_data_internal (&timeout);
450 if (ret < 0) return ret;
451 if (ret == 0) return nbytes;
453 ret = read (cbuf, size);
455 if (ret < 0) return ret;
456 if (ret == 0) return nbytes;
465 int write (const void *buf, size_t size) {
466 if (!buf || !size) { m_err = EINVAL; return -1; }
467 if (m_id < 0) { m_err = EBADF; return -1; }
471 typedef void (*_scim_sighandler_t)(int);
472 _scim_sighandler_t orig_handler = signal (SIGPIPE, SIG_IGN);
476 const char *cbuf = static_cast<const char*> (buf);
479 ret = ::write (m_id, cbuf, size);
481 size -= (size_t) ret;
492 if (orig_handler != SIG_ERR)
493 signal (SIGPIPE, orig_handler);
495 signal (SIGPIPE, SIG_DFL);
500 int wait_for_data (int timeout = -1) {
501 if (m_id < 0) { m_err = EBADF; return -1; }
502 return wait_for_data_internal (&timeout);
505 int get_error_number () const {
509 String get_error_message () const {
512 return String (strerror_r (m_err, buf_err, sizeof (buf_err)));
517 int get_id () const {
521 int set_nonblock_mode () {
522 if (m_id < 0) { m_err = EBADF; return -1; }
526 ret = ::fcntl (m_id, F_SETFL, O_NONBLOCK);
530 bool connect (const SocketAddress &addr) {
531 SCIM_DEBUG_SOCKET (1) << "Socket: Connect to server: "
532 << addr.get_address () << " ...\n";
536 if (m_binded) return false;
538 if (addr.valid () && m_id >= 0 && m_family == addr.get_family ()) {
539 struct sockaddr * data = static_cast<sockaddr*> (const_cast<void*> (addr.get_data ()));
540 int len = addr.get_data_length ();
542 // Backup the current flag to restore after non-blocking connect() try
543 int flags = fcntl (m_id, F_GETFL, 0);
544 if (fcntl (m_id, F_SETFL, flags | O_NONBLOCK) == -1) {
547 LOGW ("ppid : %d fcntl() failed, %d %s", getppid (), m_err, strerror_r (m_err, buf_err, sizeof (buf_err)));
550 char proc_name[17] = {0}; /* the buffer provided shall at least be 16+1 bytes long */
551 if (-1 != prctl (PR_GET_NAME, proc_name, 0, 0, 0)) {
552 LOGI ("ppid:%d trying connect() to %s, %s", getppid (), addr.get_address ().c_str (), proc_name);
555 if ((m_err = ::connect (m_id, data, len)) == 0) {
556 if (fcntl (m_id, F_SETFL, flags) == -1) {
561 LOGI ("connect() succeeded");
566 // If still in progress, use select() to wait for the connection result
567 if (m_err == EINPROGRESS) {
568 const int nsec = scim_get_default_socket_timeout () / 1000;
573 FD_SET (m_id, &rset);
578 LOGW ("EINPROGRESS, select() with timeout %d", nsec);
580 if (select (m_id + 1, &rset, &wset, NULL, nsec ? &tval : NULL) == 0) {
583 LOGW ("timeout in select()");
585 // We've got something, connection succeeded
586 LOGI ("finally connected");
588 if (fcntl (m_id, F_SETFL, flags) == -1) {
597 LOGW ("connect() failed with %d (%s)", m_err, strerror_r (m_err, buf_err, sizeof (buf_err)));
599 if (fcntl (m_id, F_SETFL, flags) == -1) {
606 bool bind (const SocketAddress &addr) {
607 SCIM_DEBUG_SOCKET (1) << "Socket: Bind to address: "
608 << addr.get_address () << " ...\n";
612 if (m_binded) return false;
614 if (addr.valid () && m_id >= 0 && m_family == addr.get_family ()) {
615 const struct sockaddr_un * data_un = 0;
616 const struct sockaddr * data = static_cast <const struct sockaddr *>(addr.get_data ());
617 int len = addr.get_data_length ();
619 // Unlink the broken socket file.
620 if (m_family == SCIM_SOCKET_LOCAL) {
621 data_un = static_cast <const struct sockaddr_un *>(addr.get_data ());
622 // The file is already exist, check if it's broken
623 // by connecting to it.
624 SCIM_DEBUG_SOCKET (2) << "Try to remove the broken socket file: " << data_un->sun_path << "\n";
626 if (::access (data_un->sun_path, F_OK) == 0) {
627 SocketClient tmp_socket (addr);
629 if (!tmp_socket.is_connected ()) {
632 // If it's a socket file, then
634 if (::stat (data_un->sun_path, &statbuf) == 0 && S_ISSOCK (statbuf.st_mode))
635 ::unlink (data_un->sun_path);
642 if (::bind (m_id, data, len) == 0) {
647 // Set correct permission for the socket file
648 #ifdef DISABLE_MULTIPLE_SOCKETS
649 if (m_family == SCIM_SOCKET_LOCAL) {
650 if (::chmod (data_un->sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == -1)
654 if (m_family == SCIM_SOCKET_LOCAL) {
655 if (::chmod (data_un->sun_path, S_IRUSR | S_IWUSR) == -1)
668 bool listen (int queue_length = 5) {
669 if (m_id < 0) { m_err = EBADF; return -1; }
671 SCIM_DEBUG_SOCKET (1) << "Socket: Listen: "
672 << queue_length << " ...\n";
676 int ret = ::listen (m_id, queue_length);
678 if (ret < 0) m_err = errno;
684 if (m_id < 0) { m_err = EBADF; return -1; }
691 if (m_family == SCIM_SOCKET_LOCAL) {
692 struct sockaddr_un addr;
693 addrlen = sizeof (addr);
694 ret = ::accept (m_id, (struct sockaddr*) &addr, (socklen_t*) &addrlen);
695 } else if (m_family == SCIM_SOCKET_INET) {
696 struct sockaddr_in addr;
697 addrlen = sizeof (addr);
698 ret = ::accept (m_id, (struct sockaddr*) &addr, (socklen_t*) &addrlen);
701 if (ret < 0 && addrlen > 0)
705 int flag = fcntl (ret, F_GETFD, 0);
706 fcntl (ret, F_SETFD, flag|FD_CLOEXEC);
708 SCIM_DEBUG_SOCKET (1) << "Socket: Accept connection, ret: " << ret << "\n";
713 bool create (SocketFamily family) {
716 if (family == SCIM_SOCKET_LOCAL)
717 ret = ::socket (PF_UNIX, SOCK_STREAM, 0);
718 else if (family == SCIM_SOCKET_INET)
719 ret = ::socket (PF_INET, SOCK_STREAM, 0);
726 if (m_id >= 0) close ();
732 int flag = fcntl (ret, F_GETFD, 0);
733 fcntl (ret, F_SETFD, flag|FD_CLOEXEC);
738 SCIM_DEBUG_SOCKET (1) << "Socket: Socket created, family: "
739 << family << " ret: " << ret << "\n";
744 bool sd_socket (SocketFamily family, const SocketAddress &addr) {
748 snprintf(pid, sizeof(pid), "%d", getpid());
749 setenv("LISTEN_PID", pid, 1);
750 n = sd_listen_fds (0);
752 SCIM_DEBUG_SOCKET (1) << "Socket: Too many file descriptors received.\n";
760 ret = SD_LISTEN_FDS_START + 0;
761 int flag = fcntl (ret, F_GETFD, 0);
763 flag = fcntl (ret, F_SETFD, flag|FD_CLOEXEC);
766 LOGW ("fcntl() failed");
771 LOGW("No sd socket!!");
772 SCIM_DEBUG_SOCKET (1) << "%d returned.\n" << n;
779 if (m_id < 0) return;
782 SCIM_DEBUG_SOCKET (2) << " Closing the socket: " << m_id << " ...\n";
785 // Unlink the socket file.
787 if (m_binded && m_family == SCIM_SOCKET_LOCAL) {
788 const struct sockaddr_un * data = static_cast <const struct sockaddr_un *>(m_address.get_data ());
789 // FIXME: Don't unlink the socket file, because if the process is forked and child process exits
790 // the socket file will be unlinked by child process.
791 //SCIM_DEBUG_SOCKET(3) << " Unlinking socket file " << data->sun_path << "...\n";
792 ::unlink (data->sun_path);
801 m_family = SCIM_SOCKET_UNKNOWN;
802 m_address = SocketAddress ();
806 int wait_for_data_internal (int *timeout) {
809 struct timeval begin_tv;
813 gettimeofday (&begin_tv, 0);
814 tv.tv_sec = *timeout / 1000;
815 tv.tv_usec = ((unsigned long int)*timeout % 1000) * 1000;
824 ret = select (m_id + 1, &fds, NULL, NULL, (*timeout >= 0) ? &tv : NULL);
827 struct timeval cur_tv;
828 gettimeofday (&cur_tv, 0);
829 elapsed = (cur_tv.tv_sec - begin_tv.tv_sec) * 1000 +
830 (cur_tv.tv_usec - begin_tv.tv_usec) / 1000;
831 /* If somebody else calls settimeofday () after we set begin_tv value,
832 the elapsed time could be invalid */
836 *timeout = *timeout - elapsed;
839 tv.tv_sec = *timeout / 1000;
840 tv.tv_usec = ((unsigned long int)*timeout % 1000) * 1000;
849 } else if (ret == 0) {
865 Socket::Socket (int id)
866 : m_impl (new SocketImpl (id))
877 Socket::valid () const
879 return m_impl->valid ();
883 Socket::read (void *buf, size_t size) const
885 return m_impl->read (buf, size);
889 Socket::read_with_timeout (void *buf, size_t size, int timeout) const
891 return m_impl->read_with_timeout (buf, size, timeout);
895 Socket::write (const void *buf, size_t size) const
897 return m_impl->write (buf, size);
901 Socket::wait_for_data (int timeout) const
903 return m_impl->wait_for_data (timeout);
907 Socket::get_error_number () const
909 return m_impl->get_error_number ();
913 Socket::get_error_message () const
915 return m_impl->get_error_message ();
919 Socket::connect (const SocketAddress &addr) const
921 return m_impl->connect (addr);
925 Socket::bind (const SocketAddress &addr) const
927 return m_impl->bind (addr);
931 Socket::listen (int queue_length) const
933 return m_impl->listen (queue_length);
937 Socket::accept () const
939 return m_impl->accept ();
943 Socket::get_id () const
945 return m_impl->get_id ();
949 Socket::set_nonblock_mode ()
951 return m_impl->set_nonblock_mode ();
955 Socket::create (SocketFamily family)
957 return m_impl->create (family);
961 Socket::sd_socket (SocketFamily family, const SocketAddress &addr)
963 return m_impl->sd_socket (family, addr);
972 // Implementation of SocketServer
973 struct SocketServer::SocketServerImpl
983 std::vector <int> ext_fds;
985 SocketServerSignalSocket accept_signal;
986 SocketServerSignalSocket receive_signal;
987 SocketServerSignalSocket exception_signal;
989 SocketServerImpl (int mc)
990 : max_fd (0), err (0), running (false), created (false),
991 num_clients (0), max_clients (std::min (mc, SCIM_SOCKET_SERVER_MAX_CLIENTS)) {
992 FD_ZERO (&active_fds);
996 SocketServer::SocketServer (int max_clients)
997 : Socket (-1), m_impl (new SocketServerImpl (max_clients))
1001 SocketServer::SocketServer (const SocketAddress &address, int max_clients)
1002 : Socket (-1), m_impl (new SocketServerImpl (max_clients))
1007 SocketServer::~SocketServer ()
1013 SocketServer::valid () const
1015 return m_impl->created;
1019 SocketServer::create (const SocketAddress &address)
1021 m_impl->err = EBUSY;
1022 if (!m_impl->created) {
1023 SocketFamily family = address.get_family ();
1025 SCIM_DEBUG_SOCKET (1) << "Creating Socket Server, family: " << family << "\n";
1027 if (family != SCIM_SOCKET_UNKNOWN) {
1028 if (Socket::create (family) &&
1029 Socket::bind (address) &&
1030 Socket::listen ()) {
1031 m_impl->created = true;
1032 m_impl->max_fd = Socket::get_id ();
1033 FD_ZERO (&(m_impl->active_fds));
1034 FD_SET (m_impl->max_fd, &(m_impl->active_fds));
1037 #ifdef SOCKET_ACTIVATION
1038 } else if (Socket::sd_socket (family, address)) {
1039 m_impl->created = true;
1040 m_impl->max_fd = Socket::get_id ();
1041 FD_ZERO (&(m_impl->active_fds));
1042 FD_SET (m_impl->max_fd, &(m_impl->active_fds));
1047 m_impl->err = Socket::get_error_number ();
1050 m_impl->err = EBADF;
1057 SocketServer::run ()
1059 if (m_impl->created && !m_impl->running) {
1060 fd_set read_fds, exception_fds;
1064 m_impl->running = true;
1067 read_fds = m_impl->active_fds;
1068 exception_fds = m_impl->active_fds;
1070 SCIM_DEBUG_SOCKET (2) << " SocketServer: Watching socket...\n";
1072 if (select (m_impl->max_fd + 1, &read_fds, NULL, &exception_fds, NULL) < 0) {
1076 m_impl->err = errno;
1077 m_impl->running = false;
1078 SCIM_DEBUG_SOCKET (3) << " SocketServer: Error: "
1079 << get_error_message () << "\n";
1083 //The server has been shut down.
1084 if (!m_impl->running)
1087 for (i = 0; i < m_impl->max_fd + 1; i++) {
1088 if (FD_ISSET (i, &read_fds)) {
1090 if (i == Socket::get_id ()) {
1091 client = Socket::accept ();
1093 SCIM_DEBUG_SOCKET (3) << " SocketServer: Accept new connection:"
1097 m_impl->err = Socket::get_error_number ();
1098 m_impl->running = false;
1100 SCIM_DEBUG_SOCKET (4) << " SocketServer: Error occurred: "
1101 << Socket::get_error_message () << "\n";
1106 if (m_impl->max_clients > 0 &&
1107 m_impl->num_clients >= m_impl->max_clients) {
1108 SCIM_DEBUG_SOCKET (4) << " SocketServer: Too many clients.\n";
1111 m_impl->num_clients ++;
1113 //Store the new client
1114 FD_SET (client, &(m_impl->active_fds));
1115 if (m_impl->max_fd < client)
1116 m_impl->max_fd = client;
1118 Socket client_socket (client);
1120 m_impl->accept_signal.emit (this, client_socket);
1125 SCIM_DEBUG_SOCKET (3) << " SocketServer: Accept client reading...\n";
1127 Socket client_socket (i);
1129 m_impl->receive_signal.emit (this, client_socket);
1133 if (FD_ISSET (i, &exception_fds)) {
1134 //The server got an exception, return.
1135 if (i == Socket::get_id ()) {
1136 SCIM_DEBUG_SOCKET (3) << " SocketServer: Server got an exception, exiting...\n";
1142 SCIM_DEBUG_SOCKET (3) << " SocketServer: Client "
1144 << "got an exception, callbacking...\n";
1146 Socket client_socket (i);
1147 m_impl->exception_signal.emit (this, client_socket);
1151 if (!m_impl->running)
1155 //The server has been shut down.
1156 if (!m_impl->running)
1161 m_impl->err = EBADF;
1166 SocketServer::filter_event (int fd)
1169 static bool first_call = true;
1172 m_impl->running = true;
1176 if (fd == Socket::get_id ()) {
1177 client = Socket::accept ();
1179 SCIM_DEBUG_SOCKET (3) << " SocketServer: Accept new connection:"
1183 m_impl->err = Socket::get_error_number ();
1184 m_impl->running = false;
1186 SCIM_DEBUG_SOCKET (4) << " SocketServer: Error occurred: "
1187 << Socket::get_error_message () << "\n";
1192 if (m_impl->max_clients > 0 &&
1193 m_impl->num_clients >= m_impl->max_clients) {
1194 SCIM_DEBUG_SOCKET (4) << " SocketServer: Too many clients.\n";
1197 m_impl->num_clients ++;
1199 //Store the new client
1200 FD_SET (client, &(m_impl->active_fds));
1201 if (m_impl->max_fd < client)
1202 m_impl->max_fd = client;
1204 Socket client_socket (client);
1206 m_impl->accept_signal.emit (this, client_socket);
1209 SCIM_DEBUG_SOCKET (3) << " SocketServer: Accept client reading...\n";
1210 Socket client_socket (fd);
1211 m_impl->receive_signal.emit (this, client_socket);
1218 SocketServer::filter_exception_event (int fd)
1220 //The server got an exception, return.
1221 if (fd == Socket::get_id ()) {
1222 SCIM_DEBUG_SOCKET (3) << " SocketServer: Server got an exception, exiting...\n";
1226 SCIM_DEBUG_SOCKET (3) << " SocketServer: Client "
1228 << "got an exception, callbacking...\n";
1230 Socket client_socket (fd);
1231 m_impl->exception_signal.emit (this, client_socket);
1238 SocketServer::is_running () const
1240 return m_impl->running;
1244 SocketServer::shutdown ()
1246 if (m_impl->created) {
1247 SCIM_DEBUG_SOCKET (2) << " SocketServer: Shutting down the server...\n";
1249 m_impl->running = false;
1251 for (int i = 0; ((unsigned int)i) < m_impl->ext_fds.size (); i++)
1252 FD_CLR (m_impl->ext_fds [i], &m_impl->active_fds);
1254 for (int i = 0; i < m_impl->max_fd + 1; i++) {
1256 if (FD_ISSET (i, &(m_impl->active_fds)) && i != Socket::get_id ()) {
1257 SCIM_DEBUG_SOCKET (3) << " SocketServer: Closing client: "
1263 m_impl->created = false;
1265 m_impl->num_clients = 0;
1266 m_impl->ext_fds.clear ();
1267 FD_ZERO (&(m_impl->active_fds));
1274 SocketServer::close_connection (const Socket &socket)
1276 int id = socket.get_id ();
1277 if (m_impl->created && m_impl->running && id > 0 && FD_ISSET (id, &(m_impl->active_fds))) {
1278 SCIM_DEBUG_SOCKET (2) << " SocketServer: Closing the connection: " << id << "\n";
1280 m_impl->num_clients --;
1282 FD_CLR (id, &(m_impl->active_fds));
1284 std::vector <int>::iterator it = std::find (m_impl->ext_fds.begin (), m_impl->ext_fds.end (), id);
1285 if (it != m_impl->ext_fds.end ()) m_impl->ext_fds.erase (it);
1294 SocketServer::get_error_number () const
1299 return Socket::get_error_number ();
1303 SocketServer::get_error_message () const
1307 return String (strerror_r (m_impl->err, buf_err, sizeof (buf_err)));
1310 return Socket::get_error_message ();
1314 SocketServer::get_max_clients () const
1316 return m_impl->max_clients;
1320 SocketServer::set_max_clients (int max_clients)
1322 if (max_clients < SCIM_SOCKET_SERVER_MAX_CLIENTS)
1323 m_impl->max_clients = max_clients;
1327 SocketServer::insert_external_socket (const Socket &sock)
1329 int fd = sock.get_id ();
1331 if (valid () && sock.valid () && sock.wait_for_data (0) >= 0 &&
1332 m_impl->num_clients < m_impl->max_clients &&
1333 !FD_ISSET (fd, &m_impl->active_fds)) {
1334 m_impl->ext_fds.push_back (fd);
1335 FD_SET (fd, &m_impl->active_fds);
1336 if (m_impl->max_fd < fd) m_impl->max_fd = fd;
1337 m_impl->num_clients ++;
1344 SocketServer::remove_external_socket (const Socket &sock)
1346 int fd = sock.get_id ();
1348 if (valid () && FD_ISSET (fd, &m_impl->active_fds)) {
1349 FD_CLR (fd, &m_impl->active_fds);
1350 std::vector <int>::iterator it = std::find (m_impl->ext_fds.begin (), m_impl->ext_fds.end (), fd);
1351 if (it != m_impl->ext_fds.end ()) m_impl->ext_fds.erase (it);
1352 m_impl->num_clients --;
1359 SocketServer::signal_connect_accept (SocketServerSlotSocket *slot)
1361 return m_impl->accept_signal.connect (slot);
1365 SocketServer::signal_connect_receive (SocketServerSlotSocket *slot)
1367 return m_impl->receive_signal.connect (slot);
1371 SocketServer::signal_connect_exception (SocketServerSlotSocket *slot)
1373 return m_impl->exception_signal.connect (slot);
1376 //Implementation of SocketClient
1377 SocketClient::SocketClient ()
1378 : Socket (-1), m_connected (false)
1382 SocketClient::SocketClient (const SocketAddress &address)
1383 : Socket (-1), m_connected (false)
1388 SocketClient::~SocketClient ()
1393 SocketClient::is_connected () const
1395 return Socket::valid () && m_connected;
1399 SocketClient::connect (const SocketAddress &address)
1401 if (m_connected) close ();
1403 if (Socket::create (address.get_family ()) && Socket::connect (address)) {
1414 SocketClient::close ()
1417 m_connected = false;
1420 #define SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS "local:/run/.isf/scim-socket-frontend"
1421 #define SCIM_DEFAULT_PANEL_SOCKET_ADDRESS "local:/run/.isf/scim-panel-socket"
1422 #define SCIM_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS "local:/run/.isf/scim-socket-frontend"
1424 String scim_get_default_socket_frontend_address ()
1426 String address (SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS);
1428 address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_FRONTEND_ADDRESS, address);
1430 const char *env = getenv ("SCIM_SOCKET_ADDRESS");
1431 if (env && strlen (env) > 0) {
1432 address = String (env);
1434 env = getenv ("SCIM_FRONTEND_SOCKET_ADDRESS");
1435 if (env && strlen (env))
1436 address = String (env);
1439 if (address == "default")
1440 address = SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS;
1445 String scim_get_default_socket_imengine_address ()
1447 String address (SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS);
1449 address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_IMENGINE_ADDRESS, address);
1451 const char *env = getenv ("SCIM_SOCKET_ADDRESS");
1452 if (env && strlen (env) > 0) {
1453 address = String (env);
1455 env = getenv ("SCIM_IMENGINE_SOCKET_ADDRESS");
1456 if (env && strlen (env))
1457 address = String (env);
1460 if (address == "default")
1461 address = SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS;
1466 String scim_get_default_socket_config_address ()
1468 String address (SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS);
1470 address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_CONFIG_ADDRESS, address);
1472 const char *env = getenv ("SCIM_SOCKET_ADDRESS");
1473 if (env && strlen (env) > 0) {
1474 address = String (env);
1476 env = getenv ("SCIM_CONFIG_SOCKET_ADDRESS");
1477 if (env && strlen (env))
1478 address = String (env);
1481 if (address == "default")
1482 address = SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS;
1487 String scim_get_default_panel_socket_address (const String &display)
1489 String address (SCIM_DEFAULT_PANEL_SOCKET_ADDRESS);
1491 address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_PANEL_SOCKET_ADDRESS, address);
1493 const char *env = getenv ("SCIM_PANEL_SOCKET_ADDRESS");
1495 if (env && strlen (env) > 0) {
1496 address = String (env);
1499 if (address == "default")
1500 address = SCIM_DEFAULT_PANEL_SOCKET_ADDRESS;
1502 SocketAddress sockaddr (address);
1504 if (!sockaddr.valid ())
1508 String::size_type colon_pos = display.rfind (':');
1509 String disp_name = display;
1512 // Maybe It's a X11 DISPLAY name
1513 if (colon_pos != String::npos) {
1514 String::size_type dot_pos = display.find ('.', colon_pos+1);
1515 // It has screen number
1516 if (dot_pos != String::npos) {
1517 disp_name = display.substr (0, dot_pos);
1519 // FIXME: ignore remote X Server name.
1520 disp_num = atoi (display.substr (colon_pos + 1, dot_pos - colon_pos - 1).c_str ());
1523 if (sockaddr.get_family () == SCIM_SOCKET_LOCAL) {
1524 address = address + disp_name;
1525 } else if (sockaddr.get_family () == SCIM_SOCKET_INET) {
1526 std::vector <String> varlist;
1527 scim_split_string_list (varlist, address, ':');
1528 if (varlist.size () == 3) {
1529 int port = atoi (varlist [2].c_str ()) + disp_num;
1531 snprintf (buf, 10, "%d", port);
1532 varlist [2] = String (buf);
1533 address = scim_combine_string_list (varlist, ':');
1538 sockaddr.set_address (address);
1540 if (sockaddr.valid ())
1546 String scim_get_default_helper_manager_socket_address ()
1548 String address (SCIM_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS);
1550 address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS, address);
1552 const char *env = getenv ("SCIM_HELPER_MANAGER_SOCKET_ADDRESS");
1553 if (env && strlen (env) > 0) {
1554 address = String (env);
1557 if (address == "default")
1558 address = SCIM_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS;
1563 int scim_get_default_socket_timeout ()
1567 timeout = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_TIMEOUT, timeout);
1569 const char *env = getenv ("SCIM_SOCKET_TIMEOUT");
1571 if (env && strlen (env))
1572 timeout = atoi (env);
1574 if (timeout <= 0) timeout = -1;
1580 scim_socket_check_type (const String &types,
1581 const String &atype)
1583 std::vector <String> type_list;
1584 scim_split_string_list (type_list, types, ',');
1586 return std::find (type_list.begin (), type_list.end (), atype) != type_list.end ();
1590 scim_socket_open_connection (uint32 &key,
1591 const String &client_type,
1592 const String &server_type,
1593 const Socket &socket,
1596 if (!socket.valid () || !client_type.length () || !server_type.length ())
1601 trans.put_command (SCIM_TRANS_CMD_REQUEST);
1602 trans.put_command (SCIM_TRANS_CMD_OPEN_CONNECTION);
1603 trans.put_data (String (SCIM_BINARY_VERSION));
1604 trans.put_data (client_type);
1605 if (const_cast<Socket &>(socket).set_nonblock_mode () == -1)
1606 std::cerr << __func__ << "set_nonblock_mode () is failed!!!\n";
1607 if (trans.write_to_socket (socket)) {
1609 String server_types;
1610 if (trans.read_from_socket (socket, timeout) &&
1611 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
1612 trans.get_data (server_types) && scim_socket_check_type (server_types, server_type) &&
1613 trans.get_data (key)) {
1615 trans.put_command (SCIM_TRANS_CMD_REPLY);
1616 trans.put_command (SCIM_TRANS_CMD_OK);
1617 if (trans.write_to_socket (socket))
1620 LOGW ("write_to_socket() failed");
1622 LOGW ("read_from_socket() failed %d", timeout);
1625 trans.put_command (SCIM_TRANS_CMD_REPLY);
1626 trans.put_command (SCIM_TRANS_CMD_FAIL);
1627 trans.write_to_socket (socket);
1630 LOGW ("write_to_socket() failed");
1637 scim_socket_accept_connection (uint32 &key,
1638 const String &server_types,
1639 const String &client_types,
1640 const Socket &socket,
1643 if (!socket.valid () || !client_types.length () || !server_types.length ())
1647 if (const_cast<Socket &>(socket).set_nonblock_mode () == -1)
1648 std::cerr << __func__ << "set_nonblock_mode () is failed!!!\n";
1649 if (trans.read_from_socket (socket, timeout)) {
1653 if (trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REQUEST &&
1654 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OPEN_CONNECTION &&
1655 trans.get_data (version) && version == String (SCIM_BINARY_VERSION) &&
1656 trans.get_data (client_type) &&
1657 (scim_socket_check_type (client_types, client_type) || client_type == "ConnectionTester")) {
1658 unsigned int seed = (unsigned int)time (NULL);
1659 key = (uint32)rand_r (&seed);
1661 trans.put_command (SCIM_TRANS_CMD_REPLY);
1662 trans.put_data (server_types);
1663 trans.put_data (key);
1665 if (trans.write_to_socket (socket) &&
1666 trans.read_from_socket (socket, timeout) &&
1667 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
1668 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
1669 // Client is ok, return the client type.
1670 return (client_type == "ConnectionTester") ? String ("") : client_type;
1672 LOGW ("write_to_socket() failed");
1675 LOGW ("wrong format of SCIM_TRANS_CMD_OPEN_CONNECTION transaction");
1678 LOGW ("read_from_socket() failed %d", timeout);
1686 vi:ts=4:nowrap:ai:expandtab