Fix issue detected by static analysis tool
[platform/core/uifw/isf.git] / ism / src / scim_socket.cpp
1 /** @file scim_socket.cpp
2  *  @brief Implementation of Socket related classes.
3  */
4
5 /* ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. */
6
7 /*
8  * Smart Common Input Method
9  *
10  * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
11  * Copyright (c) 2012-2015 Samsung Electronics Co., Ltd.
12  *
13  *
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.
18  *
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.
23  *
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
28  *
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
32  *
33  * $Id: scim_socket.cpp,v 1.44 2005/12/01 08:27:36 suzhe Exp $
34  *
35  */
36
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>
42 #include <sys/stat.h>
43 #include <sys/un.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <stddef.h>
48 #include <stdio.h>
49 #include <errno.h>
50 #include <netinet/in.h>
51 #include <netdb.h>
52 #include <arpa/inet.h>
53 #include <errno.h>
54 #include <signal.h>
55 #include <sys/time.h>
56 #include <fcntl.h>
57 #include <sys/prctl.h>
58 #include <dlog.h>
59
60 #include "scim_private.h"
61 #include "scim.h"
62 #include <systemd/sd-daemon.h>
63
64 #ifdef LOG_TAG
65 # undef LOG_TAG
66 #endif
67 #define LOG_TAG "ISF_SOCKET"
68
69 #define SCIM_SOCKET_SERVER_MAX_CLIENTS  256
70
71 namespace scim {
72
73 static struct in_addr
74 __gethostname (const char *host)
75 {
76     struct in_addr addr = { 0 };
77
78 #if HAVE_GETHOSTBYNAME_R
79     struct hostent hostbuf, *hp;
80     size_t hstbuflen;
81     char *tmphstbuf;
82     int res;
83     int herr;
84
85     hstbuflen = 1024;
86     /* Allocate buffer, remember to free it to avoid memory leakage.  */
87     tmphstbuf = (char*) malloc (hstbuflen);
88
89     while ((res = gethostbyname_r (host, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr)) == ERANGE) {
90         /* Enlarge the buffer.  */
91         hstbuflen *= 2;
92         char *hstbuf = (char*) realloc (tmphstbuf, hstbuflen);
93         tmphstbuf = hstbuf;
94         hstbuf = NULL;
95     }
96
97     /* Found the host */
98     if (!res && hp) {
99         void *pvoid = hp->h_addr_list [0];
100         addr = * ((struct in_addr *) pvoid);
101     }
102
103     free (tmphstbuf);
104 #else
105     struct hostent *hostinfo;
106
107     hostinfo = gethostbyname (host);
108
109     if (hostinfo){
110         pvoid = hostinfo->h_addr_list [0];
111         addr = * ((struct in_addr *) pvoid);
112     }
113 #endif
114     return addr;
115 }
116
117 class SocketAddress::SocketAddressImpl
118 {
119     struct sockaddr *m_data;
120     SocketFamily     m_family;
121     String           m_address;
122
123 public:
124     SocketAddressImpl (const String &addr = String ())
125         : m_data (0), m_family (SCIM_SOCKET_UNKNOWN) {
126         if (addr.length ()) set_address (addr);
127     }
128
129     SocketAddressImpl (const SocketAddressImpl &other)
130         : m_data (0), m_family (other.m_family), m_address (other.m_address) {
131         if (other.m_data) {
132             size_t len = 0;
133             switch (m_family) {
134                 case SCIM_SOCKET_LOCAL:
135                     m_data = (struct sockaddr*) new struct sockaddr_un;
136                     len = sizeof (sockaddr_un);
137                     break;
138                 case SCIM_SOCKET_INET:
139                     m_data = (struct sockaddr*) new struct sockaddr_in;
140                     len = sizeof (sockaddr_in);
141                     break;
142                 case SCIM_SOCKET_UNKNOWN:
143                     break;
144                 default :
145                     break;
146             }
147
148             if (len && m_data) memcpy (m_data, other.m_data, len);
149         }
150     }
151
152     ~SocketAddressImpl () {
153         struct sockaddr_un *un = 0;
154         struct sockaddr_in *in = 0;
155
156         if (m_data) {
157             switch (m_family) {
158                 case SCIM_SOCKET_LOCAL:
159                     un = (struct sockaddr_un *)m_data;
160                     delete un;
161                     break;
162                 case SCIM_SOCKET_INET:
163                     in = (struct sockaddr_in *)m_data;
164                     delete in;
165                     break;
166                 case SCIM_SOCKET_UNKNOWN:
167                     delete m_data;
168                     break;
169                 default:
170                     break;
171             }
172         }
173     }
174
175     SocketAddressImpl & operator = (const SocketAddressImpl &other) {
176         if (this == &other)
177             return *this;
178
179         m_family = other.m_family;
180         m_address = other.m_address;
181         if (m_data)
182             delete (m_data);
183
184         if (other.m_data) {
185             size_t len = 0;
186             switch (m_family) {
187                 case SCIM_SOCKET_LOCAL:
188                     m_data = (struct sockaddr*) new struct sockaddr_un;
189                     len = sizeof (sockaddr_un);
190                     break;
191                 case SCIM_SOCKET_INET:
192                     m_data = (struct sockaddr*) new struct sockaddr_in;
193                     len = sizeof (sockaddr_in);
194                     break;
195                 case SCIM_SOCKET_UNKNOWN:
196                     break;
197                 default :
198                     break;
199             }
200             if (len && m_data) memcpy (m_data, other.m_data, len);
201         }
202         return *this;
203     }
204
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);
209     }
210
211     bool valid () const {
212         if (m_address.length () && m_data &&
213             (m_family == SCIM_SOCKET_LOCAL || m_family == SCIM_SOCKET_INET))
214             return true;
215         return false;
216     }
217
218     SocketFamily get_family () const {
219         return m_family;
220     }
221
222     bool set_address (const String &addr);
223
224     const String & get_address () const {
225         return m_address;
226     }
227
228     const void * get_data () const {
229         return (void *)m_data;
230     }
231
232     int get_data_length () const {
233         if (m_data) {
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);
238         }
239         return 0;
240     }
241 };
242
243 bool
244 SocketAddress::SocketAddressImpl::set_address (const String &addr)
245 {
246     std::vector <String> varlist;
247
248     struct sockaddr *new_data   = 0;
249     SocketFamily     new_family = SCIM_SOCKET_UNKNOWN;
250
251     scim_split_string_list (varlist, addr, ':');
252
253     if (varlist.size () < 2)
254         return false;
255
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);
259 #else
260         String real_addr = addr.substr (varlist [0].length ()+1) +
261                            String ("-") +
262                            scim_get_user_name ();
263 #endif
264         struct sockaddr_un *un = new struct sockaddr_un;
265
266         un->sun_family = AF_UNIX;
267
268         memset (un->sun_path, 0, sizeof (un->sun_path));
269
270         strncpy (un->sun_path, real_addr.c_str (), sizeof (un->sun_path) - 1);
271
272         un->sun_path[sizeof (un->sun_path) - 1] = '\0';
273
274         SCIM_DEBUG_SOCKET (3) << "  local:" << un->sun_path << "\n";
275
276         new_family = SCIM_SOCKET_LOCAL;
277         new_data = (struct sockaddr *) un;
278
279     } else if ((varlist [0] == "tcp" || varlist [0] == "inet") &&
280                 varlist.size () == 3) {
281         struct sockaddr_in *in = new struct sockaddr_in;
282
283         in->sin_addr = __gethostname (varlist [1].c_str ());
284
285         if (in->sin_addr.s_addr) {
286             in->sin_family = AF_INET;
287             in->sin_port = htons (atoi (varlist [2].c_str ()));
288
289             SCIM_DEBUG_SOCKET (3) << "  inet:"
290                 << inet_ntoa (in->sin_addr) << ":"
291                 << ntohs (in->sin_port) << "\n";
292
293             new_family = SCIM_SOCKET_INET;
294             new_data = (struct sockaddr *) in;
295         } else {
296             delete in;
297         }
298     }
299
300     if (new_data) {
301         struct sockaddr_un *un = 0;
302         struct sockaddr_in *in = 0;
303
304         if (m_data) {
305             switch (m_family) {
306                 case SCIM_SOCKET_LOCAL:
307                     un = (struct sockaddr_un *)m_data;
308                     delete un;
309                     break;
310                 case SCIM_SOCKET_INET:
311                     in = (struct sockaddr_in *)m_data;
312                     delete in;
313                     break;
314                 case SCIM_SOCKET_UNKNOWN:
315                     delete m_data;
316                     break;
317                 default:
318                     break;
319             }
320         }
321
322         m_data = new_data;
323         m_family = new_family;
324         m_address = addr;
325         return valid ();
326     }
327
328     return false;
329 }
330
331 // Implementation of SocketAddress
332 SocketAddress::SocketAddress (const String &addr)
333     : m_impl (new SocketAddressImpl (addr))
334 {
335 }
336
337 SocketAddress::SocketAddress (const SocketAddress &addr)
338     : m_impl (new SocketAddressImpl (*addr.m_impl))
339 {
340 }
341
342 SocketAddress::~SocketAddress ()
343 {
344     delete m_impl;
345 }
346
347 SocketAddress&
348 SocketAddress::operator = (const SocketAddress &addr)
349 {
350     if (this != &addr) {
351         SocketAddressImpl new_impl (*addr.m_impl);
352         m_impl->swap (new_impl);
353     }
354     return *this;
355 }
356
357 bool
358 SocketAddress::valid () const
359 {
360     return m_impl->valid ();
361 }
362
363 SocketFamily
364 SocketAddress::get_family () const
365 {
366     return m_impl->get_family ();
367 }
368
369 bool
370 SocketAddress::set_address (const String &addr)
371 {
372     SCIM_DEBUG_SOCKET (2) << " SocketAddress::set_address (" << addr << ")\n";
373     return m_impl->set_address (addr);
374 }
375
376 String
377 SocketAddress::get_address () const
378 {
379     return m_impl->get_address ();
380 }
381
382 const void *
383 SocketAddress::get_data () const
384 {
385     return m_impl->get_data ();
386 }
387
388 int
389 SocketAddress::get_data_length () const
390 {
391     return m_impl->get_data_length ();
392 }
393
394 // Implementation of Socket
395 class Socket::SocketImpl
396 {
397     int           m_id;
398     int           m_err;
399     bool          m_binded;
400     bool          m_no_close;
401     SocketFamily  m_family;
402     SocketAddress m_address;
403
404 public:
405
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) {
409     }
410
411     ~SocketImpl () {
412         close ();
413     }
414
415     bool valid () const {
416         return m_id >= 0;
417     }
418
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; }
422
423         m_err = 0;
424         int ret;
425         while (1) {
426             ret = ::read (m_id, buf, size);
427             if (ret >= 0)
428                 break;
429             if (errno == EINTR)
430                 continue;
431             m_err = errno;
432         }
433         return ret;
434     }
435
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; }
439
440         if (timeout < 0)
441             return read (buf, size);
442
443         int   ret;
444         int   nbytes = 0;
445         char *cbuf = static_cast<char *> (buf);
446
447         while (size > 0) {
448             ret = wait_for_data_internal (&timeout);
449
450             if (ret < 0) return ret;
451             if (ret == 0) return nbytes;
452
453             ret = read (cbuf, size);
454
455             if (ret < 0) return ret;
456             if (ret == 0) return nbytes;
457
458             cbuf += ret;
459             nbytes += ret;
460             size -= ret;
461         }
462         return nbytes;
463     }
464
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; }
468
469         int ret = -1;
470
471         typedef void (*_scim_sighandler_t)(int);
472         _scim_sighandler_t orig_handler = signal (SIGPIPE, SIG_IGN);
473
474         m_err = 0;
475
476         const char *cbuf = static_cast<const char*> (buf);
477
478         while (size > 0) {
479             ret = ::write (m_id, cbuf, size);
480             if (ret > 0) {
481                 size -= (size_t) ret;
482                 cbuf += ret;
483                 continue;
484             }
485             if (errno == EINTR)
486                 continue;
487             break;
488         }
489
490         m_err = errno;
491
492         if (orig_handler != SIG_ERR)
493             signal (SIGPIPE, orig_handler);
494         else
495             signal (SIGPIPE, SIG_DFL);
496
497         return ret;
498     }
499
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);
503     }
504
505     int get_error_number () const {
506         return m_err;
507     }
508
509     String get_error_message () const {
510         if (m_err > 0) {
511             char buf_err[256];
512             return String (strerror_r (m_err, buf_err, sizeof (buf_err)));
513         }
514         return String ();
515     }
516
517     int get_id () const {
518         return m_id;
519     }
520
521     int set_nonblock_mode () {
522         if (m_id < 0) { m_err = EBADF; return -1; }
523
524         int ret;
525
526         ret = ::fcntl (m_id, F_SETFL, O_NONBLOCK);
527         return ret;
528     }
529
530     bool connect (const SocketAddress &addr) {
531         SCIM_DEBUG_SOCKET (1) << "Socket: Connect to server: "
532                              << addr.get_address () << " ...\n";
533
534         m_err = EBADF;
535
536         if (m_binded) return false;
537
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 ();
541
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) {
545                 char buf_err[256];
546                 m_err = errno;
547                 LOGW ("ppid : %d fcntl() failed, %d %s", getppid (), m_err, strerror_r (m_err, buf_err, sizeof (buf_err)));
548             }
549
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);
553             }
554
555             if ((m_err = ::connect (m_id, data, len)) == 0) {
556                 if (fcntl (m_id, F_SETFL, flags) == -1) {
557                     m_err = errno;
558                 }
559                 m_address = addr;
560
561                 LOGI ("connect() succeeded");
562
563                 return true;
564             }
565
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;
569
570                 fd_set rset, wset;
571                 struct timeval tval;
572                 FD_ZERO (&rset);
573                 FD_SET (m_id, &rset);
574                 wset = rset;
575                 tval.tv_sec = nsec;
576                 tval.tv_usec = 0;
577
578                 LOGW ("EINPROGRESS, select() with timeout %d", nsec);
579
580                 if (select (m_id + 1, &rset, &wset, NULL, nsec ? &tval : NULL) == 0) {
581                     m_err = ETIMEDOUT;
582
583                     LOGW ("timeout in select()");
584                 } else {
585                     // We've got something, connection succeeded
586                     LOGI ("finally connected");
587
588                     if (fcntl (m_id, F_SETFL, flags) == -1) {
589                         m_err = errno;
590                     }
591                     m_address = addr;
592                     return true;
593                 }
594             } else {
595                 char buf_err[256];
596                 m_err = errno;
597                 LOGW ("connect() failed with %d (%s)", m_err, strerror_r (m_err, buf_err, sizeof (buf_err)));
598             }
599             if (fcntl (m_id, F_SETFL, flags) == -1) {
600                 m_err = errno;
601             }
602         }
603         return false;
604     }
605
606     bool bind (const SocketAddress &addr) {
607         SCIM_DEBUG_SOCKET (1) << "Socket: Bind to address: "
608                              << addr.get_address () << " ...\n";
609
610         m_err = EBADF;
611
612         if (m_binded) return false;
613
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 ();
618
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";
625
626                 if (::access (data_un->sun_path, F_OK) == 0) {
627                     SocketClient tmp_socket (addr);
628
629                     if (!tmp_socket.is_connected ()) {
630                         struct stat statbuf;
631
632                         // If it's a socket file, then
633                         // delete it.
634                         if (::stat (data_un->sun_path, &statbuf) == 0 && S_ISSOCK (statbuf.st_mode))
635                             ::unlink (data_un->sun_path);
636                     }
637
638                     tmp_socket.close ();
639                 }
640             }
641
642             if (::bind (m_id, data, len) == 0) {
643                 m_address = addr;
644                 m_binded = true;
645                 m_err = 0;
646
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)
651                         return false;
652                 }
653 #else
654                 if (m_family == SCIM_SOCKET_LOCAL) {
655                     if (::chmod (data_un->sun_path, S_IRUSR | S_IWUSR) == -1)
656                         return false;
657                 }
658 #endif
659
660                 return true;
661             }
662
663             m_err = errno;
664         }
665         return false;
666     }
667
668     bool listen (int queue_length = 5) {
669         if (m_id < 0) { m_err = EBADF; return -1; }
670
671         SCIM_DEBUG_SOCKET (1) << "Socket: Listen: "
672                              << queue_length << " ...\n";
673
674         m_err = 0;
675
676         int ret = ::listen (m_id, queue_length);
677
678         if (ret < 0) m_err = errno;
679
680         return ret >= 0;
681     }
682
683     int accept () {
684         if (m_id < 0) { m_err = EBADF; return -1; }
685
686         int ret = -1;
687         int addrlen = 0;
688
689         m_err = 0;
690
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);
699         }
700
701         if (ret < 0 && addrlen > 0)
702             m_err = errno;
703
704         if (ret >= 0) {
705             int flag = fcntl (ret, F_GETFD, 0);
706             fcntl (ret, F_SETFD, flag|FD_CLOEXEC);
707         }
708         SCIM_DEBUG_SOCKET (1) << "Socket: Accept connection, ret: " << ret << "\n";
709
710         return ret;
711     }
712
713     bool create (SocketFamily family) {
714         int ret = -1;
715
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);
720         else {
721             m_err = EINVAL;
722             return false;
723         }
724
725         if (ret >= 0) {
726             if (m_id >= 0) close ();
727             m_no_close = false;
728             m_binded = false;
729             m_err = 0;
730             m_family = family;
731             m_id = ret;
732             int flag = fcntl (ret, F_GETFD, 0);
733             fcntl (ret, F_SETFD, flag|FD_CLOEXEC);
734         } else {
735             m_err = errno;
736         }
737
738         SCIM_DEBUG_SOCKET (1) << "Socket: Socket created, family: "
739                              << family << " ret: " << ret << "\n";
740
741         return ret >= 0;
742     }
743
744     bool sd_socket (SocketFamily family, const SocketAddress &addr) {
745         int ret, n;
746         char pid[10];
747
748         snprintf(pid, sizeof(pid), "%d", getpid());
749         setenv("LISTEN_PID", pid, 1);
750         n = sd_listen_fds (0);
751         if (n > 1) {
752             SCIM_DEBUG_SOCKET (1) << "Socket: Too many file descriptors received.\n";
753             return false;
754         } else if (n == 1) {
755             m_no_close = false;
756             m_binded = true;
757             m_err = 0;
758             m_family = family;
759             m_address = addr;
760             ret = SD_LISTEN_FDS_START + 0;
761             int flag = fcntl (ret, F_GETFD, 0);
762             if (flag != -1)
763                 flag = fcntl (ret, F_SETFD, flag|FD_CLOEXEC);
764
765             if (flag == -1) {
766                 LOGW ("fcntl() failed");
767                 return false;
768             }
769             m_id = ret;
770         } else {
771             LOGW("No sd socket!!");
772             SCIM_DEBUG_SOCKET (1) << "%d returned.\n" << n;
773             return false;
774         }
775         return true;
776     }
777
778     void close () {
779         if (m_id < 0) return;
780
781         if (!m_no_close) {
782             SCIM_DEBUG_SOCKET (2) << "  Closing the socket: " << m_id << " ...\n";
783             ::close (m_id);
784
785             // Unlink the socket file.
786             #if 0
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);
793             }
794             #endif
795         }
796
797         m_id = -1;
798         m_err = 0;
799         m_binded = false;
800         m_no_close = false;
801         m_family = SCIM_SOCKET_UNKNOWN;
802         m_address = SocketAddress ();
803     }
804
805 private:
806     int wait_for_data_internal (int *timeout) {
807         fd_set fds;
808         struct timeval tv;
809         struct timeval begin_tv;
810         int ret;
811
812         if (*timeout >= 0) {
813             gettimeofday (&begin_tv, 0);
814             tv.tv_sec = *timeout / 1000;
815             tv.tv_usec = ((unsigned long int)*timeout % 1000) * 1000;
816         }
817
818         m_err = 0;
819
820         while (1) {
821             FD_ZERO (&fds);
822             FD_SET (m_id, &fds);
823
824             ret = select (m_id + 1, &fds, NULL, NULL, (*timeout >= 0) ? &tv : NULL);
825             if (*timeout > 0) {
826                 int elapsed;
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 */
833                 if (elapsed < 0) {
834                     *timeout = 0;
835                 } else {
836                     *timeout = *timeout - elapsed;
837                 }
838                 if (*timeout > 0) {
839                     tv.tv_sec = *timeout / 1000;
840                     tv.tv_usec = ((unsigned long int)*timeout % 1000) * 1000;
841                 } else {
842                     tv.tv_sec = 0;
843                     tv.tv_usec = 0;
844                     *timeout = 0;
845                 }
846             }
847             if (ret > 0) {
848                 return ret;
849             } else if (ret == 0) {
850                 if (*timeout == 0)
851                     return ret;
852                 else
853                     continue;
854             }
855
856             if (errno == EINTR)
857                 continue;
858
859             m_err = errno;
860             return ret;
861         }
862     }
863 };
864
865 Socket::Socket (int id)
866     : m_impl (new SocketImpl (id))
867 {
868 }
869
870 Socket::~Socket ()
871 {
872     m_impl->close ();
873     delete m_impl;
874 }
875
876 bool
877 Socket::valid () const
878 {
879     return m_impl->valid ();
880 }
881
882 int
883 Socket::read (void *buf, size_t size) const
884 {
885     return m_impl->read (buf, size);
886 }
887
888 int
889 Socket::read_with_timeout (void *buf, size_t size, int timeout) const
890 {
891     return m_impl->read_with_timeout (buf, size, timeout);
892 }
893
894 int
895 Socket::write (const void *buf, size_t size) const
896 {
897     return m_impl->write (buf, size);
898 }
899
900 int
901 Socket::wait_for_data (int timeout) const
902 {
903     return m_impl->wait_for_data (timeout);
904 }
905
906 int
907 Socket::get_error_number () const
908 {
909     return m_impl->get_error_number ();
910 }
911
912 String
913 Socket::get_error_message () const
914 {
915     return m_impl->get_error_message ();
916 }
917
918 bool
919 Socket::connect (const SocketAddress &addr) const
920 {
921     return m_impl->connect (addr);
922 }
923
924 bool
925 Socket::bind (const SocketAddress &addr) const
926 {
927     return m_impl->bind (addr);
928 }
929
930 bool
931 Socket::listen (int queue_length) const
932 {
933     return m_impl->listen (queue_length);
934 }
935
936 int
937 Socket::accept () const
938 {
939     return m_impl->accept ();
940 }
941
942 int
943 Socket::get_id () const
944 {
945     return m_impl->get_id ();
946 }
947
948 int
949 Socket::set_nonblock_mode ()
950 {
951     return m_impl->set_nonblock_mode ();
952 }
953
954 bool
955 Socket::create (SocketFamily family)
956 {
957     return m_impl->create (family);
958 }
959
960 bool
961 Socket::sd_socket (SocketFamily family, const SocketAddress &addr)
962 {
963     return m_impl->sd_socket (family, addr);
964 }
965
966 void
967 Socket::close ()
968 {
969     m_impl->close ();
970 }
971
972 // Implementation of SocketServer
973 struct SocketServer::SocketServerImpl
974 {
975     fd_set   active_fds;
976     int      max_fd;
977     int      err;
978     bool     running;
979     bool     created;
980     int      num_clients;
981     int      max_clients;
982
983     std::vector <int> ext_fds;
984
985     SocketServerSignalSocket accept_signal;
986     SocketServerSignalSocket receive_signal;
987     SocketServerSignalSocket exception_signal;
988
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);
993     }
994 };
995
996 SocketServer::SocketServer (int max_clients)
997     : Socket (-1), m_impl (new SocketServerImpl (max_clients))
998 {
999 }
1000
1001 SocketServer::SocketServer (const SocketAddress &address, int max_clients)
1002     : Socket (-1), m_impl (new SocketServerImpl (max_clients))
1003 {
1004     create (address);
1005 }
1006
1007 SocketServer::~SocketServer ()
1008 {
1009     delete m_impl;
1010 }
1011
1012 bool
1013 SocketServer::valid () const
1014 {
1015     return m_impl->created;
1016 }
1017
1018 bool
1019 SocketServer::create (const SocketAddress &address)
1020 {
1021     m_impl->err = EBUSY;
1022     if (!m_impl->created) {
1023         SocketFamily family = address.get_family ();
1024
1025         SCIM_DEBUG_SOCKET (1) << "Creating Socket Server, family: " << family << "\n";
1026
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));
1035                 m_impl->err = 0;
1036                 return true;
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));
1043                 m_impl->err = 0;
1044                 return true;
1045 #endif
1046             }
1047             m_impl->err = Socket::get_error_number ();
1048             Socket::close ();
1049         } else {
1050             m_impl->err = EBADF;
1051         }
1052     }
1053     return false;
1054 }
1055
1056 bool
1057 SocketServer::run ()
1058 {
1059     if (m_impl->created && !m_impl->running) {
1060         fd_set read_fds, exception_fds;
1061         int client;
1062         int i;
1063
1064         m_impl->running = true;
1065         m_impl->err = 0;
1066         while (1) {
1067             read_fds = m_impl->active_fds;
1068             exception_fds = m_impl->active_fds;
1069
1070             SCIM_DEBUG_SOCKET (2) << " SocketServer: Watching socket...\n";
1071
1072             if (select (m_impl->max_fd + 1, &read_fds, NULL, &exception_fds, NULL) < 0) {
1073                 if (errno == EINTR)
1074                     continue;
1075
1076                 m_impl->err = errno;
1077                 m_impl->running = false;
1078                 SCIM_DEBUG_SOCKET (3) << "  SocketServer: Error: "
1079                                       << get_error_message () << "\n";
1080                 return false;
1081             }
1082
1083             //The server has been shut down.
1084             if (!m_impl->running)
1085                 return true;
1086
1087             for (i = 0; i < m_impl->max_fd + 1; i++) {
1088                 if (FD_ISSET (i, &read_fds)) {
1089                     //New connection
1090                     if (i == Socket::get_id ()) {
1091                         client = Socket::accept ();
1092
1093                         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Accept new connection:"
1094                                               << client << "\n";
1095
1096                         if (client < 0) {
1097                             m_impl->err = Socket::get_error_number ();
1098                             m_impl->running = false;
1099
1100                             SCIM_DEBUG_SOCKET (4) << "   SocketServer: Error occurred: "
1101                                 << Socket::get_error_message () << "\n";
1102
1103                             return false;
1104                         }
1105
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";
1109                             ::close (client);
1110                         } else {
1111                             m_impl->num_clients ++;
1112
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;
1117
1118                             Socket client_socket (client);
1119                             //emit the signal.
1120                             m_impl->accept_signal.emit (this, client_socket);
1121                         }
1122
1123                     //Client reading
1124                     } else {
1125                         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Accept client reading...\n";
1126
1127                         Socket client_socket (i);
1128                         //emit the signal.
1129                         m_impl->receive_signal.emit (this, client_socket);
1130                     }
1131                 }
1132
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";
1137
1138                         shutdown ();
1139                         return true;
1140
1141                     } else {
1142                         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Client "
1143                                               << i
1144                                               << "got an exception, callbacking...\n";
1145
1146                         Socket client_socket (i);
1147                         m_impl->exception_signal.emit (this, client_socket);
1148                     }
1149                 }
1150
1151                 if (!m_impl->running)
1152                     break;
1153             }
1154
1155             //The server has been shut down.
1156             if (!m_impl->running)
1157                 return true;
1158         }
1159     }
1160
1161     m_impl->err = EBADF;
1162     return false;
1163 }
1164
1165 bool
1166 SocketServer::filter_event (int fd)
1167 {
1168     int client;
1169     static bool first_call = true;
1170
1171     if (first_call) {
1172         m_impl->running = true;
1173         first_call = false;
1174     }
1175
1176     if (fd == Socket::get_id ()) {
1177         client = Socket::accept ();
1178
1179         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Accept new connection:"
1180                               << client << "\n";
1181
1182         if (client < 0) {
1183             m_impl->err = Socket::get_error_number ();
1184             m_impl->running = false;
1185
1186             SCIM_DEBUG_SOCKET (4) << "   SocketServer: Error occurred: "
1187                 << Socket::get_error_message () << "\n";
1188
1189             return false;
1190         }
1191
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";
1195             ::close (client);
1196         } else {
1197             m_impl->num_clients ++;
1198
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;
1203
1204             Socket client_socket (client);
1205             //emit the signal.
1206             m_impl->accept_signal.emit (this, client_socket);
1207         }
1208     } else {
1209         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Accept client reading...\n";
1210         Socket client_socket (fd);
1211         m_impl->receive_signal.emit (this, client_socket);
1212     }
1213
1214     return true;
1215 }
1216
1217 bool
1218 SocketServer::filter_exception_event (int fd)
1219 {
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";
1223
1224         shutdown ();
1225     } else {
1226         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Client "
1227                               << fd
1228                               << "got an exception, callbacking...\n";
1229
1230         Socket client_socket (fd);
1231         m_impl->exception_signal.emit (this, client_socket);
1232     }
1233
1234     return true;
1235 }
1236
1237 bool
1238 SocketServer::is_running () const
1239 {
1240     return m_impl->running;
1241 }
1242
1243 void
1244 SocketServer::shutdown ()
1245 {
1246     if (m_impl->created) {
1247         SCIM_DEBUG_SOCKET (2) << " SocketServer: Shutting down the server...\n";
1248
1249         m_impl->running = false;
1250
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);
1253
1254         for (int i = 0; i < m_impl->max_fd + 1; i++) {
1255             //Close all client
1256             if (FD_ISSET (i, &(m_impl->active_fds)) && i != Socket::get_id ()) {
1257                 SCIM_DEBUG_SOCKET (3) << "  SocketServer: Closing client: "
1258                                       << i << "\n";
1259                 ::close (i);
1260             }
1261         }
1262         m_impl->max_fd = 0;
1263         m_impl->created = false;
1264         m_impl->err = 0;
1265         m_impl->num_clients = 0;
1266         m_impl->ext_fds.clear ();
1267         FD_ZERO (&(m_impl->active_fds));
1268
1269         Socket::close ();
1270     }
1271 }
1272
1273 bool
1274 SocketServer::close_connection (const Socket &socket)
1275 {
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";
1279
1280         m_impl->num_clients --;
1281
1282         FD_CLR (id, &(m_impl->active_fds));
1283
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);
1286
1287         ::close (id);
1288         return true;
1289     }
1290     return false;
1291 }
1292
1293 int
1294 SocketServer::get_error_number () const
1295 {
1296     if (m_impl->err)
1297         return m_impl->err;
1298
1299     return Socket::get_error_number ();
1300 }
1301
1302 String
1303 SocketServer::get_error_message () const
1304 {
1305     if (m_impl->err) {
1306         char buf_err[256];
1307         return String (strerror_r (m_impl->err, buf_err, sizeof (buf_err)));
1308     }
1309
1310     return Socket::get_error_message ();
1311 }
1312
1313 int
1314 SocketServer::get_max_clients () const
1315 {
1316     return m_impl->max_clients;
1317 }
1318
1319 void
1320 SocketServer::set_max_clients (int max_clients)
1321 {
1322     if (max_clients < SCIM_SOCKET_SERVER_MAX_CLIENTS)
1323         m_impl->max_clients = max_clients;
1324 }
1325
1326 bool
1327 SocketServer::insert_external_socket (const Socket &sock)
1328 {
1329     int fd = sock.get_id ();
1330
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 ++;
1338         return true;
1339     }
1340     return false;
1341 }
1342
1343 bool
1344 SocketServer::remove_external_socket (const Socket &sock)
1345 {
1346     int fd = sock.get_id ();
1347
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 --;
1353         return true;
1354     }
1355     return false;
1356 }
1357
1358 Connection
1359 SocketServer::signal_connect_accept (SocketServerSlotSocket *slot)
1360 {
1361     return m_impl->accept_signal.connect (slot);
1362 }
1363
1364 Connection
1365 SocketServer::signal_connect_receive (SocketServerSlotSocket *slot)
1366 {
1367     return m_impl->receive_signal.connect (slot);
1368 }
1369
1370 Connection
1371 SocketServer::signal_connect_exception (SocketServerSlotSocket *slot)
1372 {
1373     return m_impl->exception_signal.connect (slot);
1374 }
1375
1376 //Implementation of SocketClient
1377 SocketClient::SocketClient ()
1378     : Socket (-1), m_connected (false)
1379 {
1380 }
1381
1382 SocketClient::SocketClient (const SocketAddress &address)
1383     : Socket (-1), m_connected (false)
1384 {
1385     connect (address);
1386 }
1387
1388 SocketClient::~SocketClient ()
1389 {
1390 }
1391
1392 bool
1393 SocketClient::is_connected () const
1394 {
1395     return Socket::valid () && m_connected;
1396 }
1397
1398 bool
1399 SocketClient::connect (const SocketAddress &address)
1400 {
1401     if (m_connected) close ();
1402
1403     if (Socket::create (address.get_family ()) && Socket::connect (address)) {
1404         m_connected = true;
1405         return true;
1406     } else {
1407         close ();
1408     }
1409
1410     return false;
1411 }
1412
1413 void
1414 SocketClient::close ()
1415 {
1416     Socket::close ();
1417     m_connected = false;
1418 }
1419
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"
1423
1424 String scim_get_default_socket_frontend_address ()
1425 {
1426     String address (SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS);
1427
1428     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_FRONTEND_ADDRESS, address);
1429
1430     const char *env = getenv ("SCIM_SOCKET_ADDRESS");
1431     if (env && strlen (env) > 0) {
1432         address = String (env);
1433     } else {
1434         env = getenv ("SCIM_FRONTEND_SOCKET_ADDRESS");
1435         if (env && strlen (env))
1436             address = String (env);
1437     }
1438
1439     if (address == "default")
1440         address = SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS;
1441
1442     return address;
1443 }
1444
1445 String scim_get_default_socket_imengine_address ()
1446 {
1447     String address (SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS);
1448
1449     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_IMENGINE_ADDRESS, address);
1450
1451     const char *env = getenv ("SCIM_SOCKET_ADDRESS");
1452     if (env && strlen (env) > 0) {
1453         address = String (env);
1454     } else {
1455         env = getenv ("SCIM_IMENGINE_SOCKET_ADDRESS");
1456         if (env && strlen (env))
1457             address = String (env);
1458     }
1459
1460     if (address == "default")
1461         address = SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS;
1462
1463     return address;
1464 }
1465
1466 String scim_get_default_socket_config_address ()
1467 {
1468     String address (SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS);
1469
1470     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_CONFIG_ADDRESS, address);
1471
1472     const char *env = getenv ("SCIM_SOCKET_ADDRESS");
1473     if (env && strlen (env) > 0) {
1474         address = String (env);
1475     } else {
1476         env = getenv ("SCIM_CONFIG_SOCKET_ADDRESS");
1477         if (env && strlen (env))
1478             address = String (env);
1479     }
1480
1481     if (address == "default")
1482         address = SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS;
1483
1484     return address;
1485 }
1486
1487 String scim_get_default_panel_socket_address (const String &display)
1488 {
1489     String address (SCIM_DEFAULT_PANEL_SOCKET_ADDRESS);
1490
1491     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_PANEL_SOCKET_ADDRESS, address);
1492
1493     const char *env = getenv ("SCIM_PANEL_SOCKET_ADDRESS");
1494
1495     if (env && strlen (env) > 0) {
1496         address = String (env);
1497     }
1498
1499     if (address == "default")
1500         address = SCIM_DEFAULT_PANEL_SOCKET_ADDRESS;
1501
1502     SocketAddress sockaddr (address);
1503
1504     if (!sockaddr.valid ())
1505         return String ();
1506
1507 #ifndef WAYLAND
1508     String::size_type colon_pos = display.rfind (':');
1509     String disp_name = display;
1510     int    disp_num  = 0;
1511
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);
1518         }
1519         // FIXME: ignore remote X Server name.
1520         disp_num = atoi (display.substr (colon_pos + 1, dot_pos - colon_pos - 1).c_str ());
1521     }
1522
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;
1530             char buf [10];
1531             snprintf (buf, 10, "%d", port);
1532             varlist [2] = String (buf);
1533             address = scim_combine_string_list (varlist, ':');
1534         }
1535     }
1536 #endif
1537
1538     sockaddr.set_address (address);
1539
1540     if (sockaddr.valid ())
1541         return address;
1542
1543     return String ();
1544 }
1545
1546 String scim_get_default_helper_manager_socket_address ()
1547 {
1548     String address (SCIM_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS);
1549
1550     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS, address);
1551
1552     const char *env = getenv ("SCIM_HELPER_MANAGER_SOCKET_ADDRESS");
1553     if (env && strlen (env) > 0) {
1554         address = String (env);
1555     }
1556
1557     if (address == "default")
1558         address = SCIM_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS;
1559
1560     return address;
1561 }
1562
1563 int scim_get_default_socket_timeout ()
1564 {
1565     int timeout = 5000;
1566
1567     timeout = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_TIMEOUT, timeout);
1568
1569     const char *env = getenv ("SCIM_SOCKET_TIMEOUT");
1570
1571     if (env && strlen (env))
1572         timeout = atoi (env);
1573
1574     if (timeout <= 0) timeout = -1;
1575
1576     return timeout;
1577 }
1578
1579 static bool
1580 scim_socket_check_type (const String &types,
1581                         const String &atype)
1582 {
1583     std::vector <String> type_list;
1584     scim_split_string_list (type_list, types, ',');
1585
1586     return std::find (type_list.begin (), type_list.end (), atype) != type_list.end ();
1587 }
1588
1589 bool
1590 scim_socket_open_connection   (uint32       &key,
1591                                const String &client_type,
1592                                const String &server_type,
1593                                const Socket &socket,
1594                                int           timeout)
1595 {
1596     if (!socket.valid () || !client_type.length () || !server_type.length ())
1597         return false;
1598
1599     Transaction trans;
1600
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)) {
1608         int cmd;
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)) {
1614             trans.clear ();
1615             trans.put_command (SCIM_TRANS_CMD_REPLY);
1616             trans.put_command (SCIM_TRANS_CMD_OK);
1617             if (trans.write_to_socket (socket))
1618                 return true;
1619             else
1620                 LOGW ("write_to_socket() failed");
1621         } else {
1622             LOGW ("read_from_socket() failed %d", timeout);
1623
1624             trans.clear ();
1625             trans.put_command (SCIM_TRANS_CMD_REPLY);
1626             trans.put_command (SCIM_TRANS_CMD_FAIL);
1627             trans.write_to_socket (socket);
1628         }
1629     } else {
1630         LOGW ("write_to_socket() failed");
1631     }
1632
1633     return false;
1634 }
1635
1636 String
1637 scim_socket_accept_connection (uint32       &key,
1638                                const String &server_types,
1639                                const String &client_types,
1640                                const Socket &socket,
1641                                int           timeout)
1642 {
1643     if (!socket.valid () || !client_types.length () || !server_types.length ())
1644         return String ("");
1645
1646     Transaction trans;
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)) {
1650         int cmd;
1651         String version;
1652         String client_type;
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);
1660             trans.clear ();
1661             trans.put_command (SCIM_TRANS_CMD_REPLY);
1662             trans.put_data (server_types);
1663             trans.put_data (key);
1664
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;
1671             } else {
1672                 LOGW ("write_to_socket() failed");
1673             }
1674         } else {
1675             LOGW ("wrong format of SCIM_TRANS_CMD_OPEN_CONNECTION transaction");
1676         }
1677     } else {
1678         LOGW ("read_from_socket() failed %d", timeout);
1679     }
1680     return String ("");
1681 }
1682
1683 } // namespace scim
1684
1685 /*
1686 vi:ts=4:nowrap:ai:expandtab
1687 */
1688