Fixed prevent defects
[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-2013 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
58 #include "scim_private.h"
59 #include "scim.h"
60
61 /* Experimental modification for avoiding multiple scim process problem */
62 #define DISABLE_MULTIPLE_SOCKETS
63
64 #define SCIM_SOCKET_SERVER_MAX_CLIENTS  256
65
66 namespace scim {
67
68 static struct in_addr
69 __gethostname (const char *host)
70 {
71     struct in_addr addr = { 0 };
72
73 #if HAVE_GETHOSTBYNAME_R
74     struct hostent hostbuf, *hp;
75     size_t hstbuflen;
76     char *tmphstbuf;
77     int res;
78     int herr;
79
80     hstbuflen = 1024;
81     /* Allocate buffer, remember to free it to avoid memory leakage.  */
82     tmphstbuf = (char*) malloc (hstbuflen);
83
84     while ((res = gethostbyname_r (host, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr)) == ERANGE) {
85         /* Enlarge the buffer.  */
86         hstbuflen *= 2;
87         tmphstbuf = (char*) realloc (tmphstbuf, hstbuflen);
88     }
89
90     /* Found the host */
91     if (!res && hp) {
92         addr = * ((struct in_addr *)hp->h_addr_list [0]);
93     }
94
95     free (tmphstbuf);
96 #else
97     struct hostent *hostinfo;
98
99     hostinfo = gethostbyname (host);
100
101     if (hostinfo)
102         addr = * ((struct in_addr *) hostinfo->h_addr_list [0]);
103 #endif
104     return addr;
105 }
106
107 class SocketAddress::SocketAddressImpl
108 {
109     struct sockaddr *m_data;
110     SocketFamily     m_family;
111     String           m_address;
112
113 public:
114     SocketAddressImpl (const String &addr = String ())
115         : m_data (0), m_family (SCIM_SOCKET_UNKNOWN) {
116         if (addr.length ()) set_address (addr);
117     }
118
119     SocketAddressImpl (const SocketAddressImpl &other)
120         : m_data (0), m_family (other.m_family), m_address (other.m_address) {
121         if (other.m_data) {
122             size_t len = 0;
123             switch (m_family) {
124                 case SCIM_SOCKET_LOCAL:
125                     m_data = (struct sockaddr*) new struct sockaddr_un;
126                     len = sizeof (sockaddr_un);
127                     break;
128                 case SCIM_SOCKET_INET:
129                     m_data = (struct sockaddr*) new struct sockaddr_in;
130                     len = sizeof (sockaddr_in);
131                     break;
132                 case SCIM_SOCKET_UNKNOWN:
133                     break;
134             }
135
136             if (len && m_data) memcpy (m_data, other.m_data, len);
137         }
138     }
139
140     ~SocketAddressImpl () {
141         if (m_data) delete m_data;
142     }
143
144     void swap (SocketAddressImpl &other) {
145         std::swap (m_data, other.m_data);
146         std::swap (m_family, other.m_family);
147         std::swap (m_address, other.m_address);
148     }
149
150     bool valid () const {
151         if (m_address.length () && m_data &&
152             (m_family == SCIM_SOCKET_LOCAL || m_family == SCIM_SOCKET_INET))
153             return true;
154         return false;
155     }
156
157     SocketFamily get_family () const {
158         return m_family;
159     }
160
161     bool set_address (const String &addr);
162
163     const String & get_address () const {
164         return m_address;
165     }
166
167     const void * get_data () const {
168         return (void *)m_data;
169     }
170
171     int get_data_length () const {
172         if (m_data) {
173             if (m_family == SCIM_SOCKET_LOCAL)
174                 return SUN_LEN ((struct sockaddr_un*)(m_data));
175             else if (m_family == SCIM_SOCKET_INET)
176                 return sizeof (struct sockaddr_in);
177         }
178         return 0;
179     }
180 };
181
182 bool
183 SocketAddress::SocketAddressImpl::set_address (const String &addr)
184 {
185     std::vector <String> varlist;
186
187     struct sockaddr *new_data   = 0;
188     SocketFamily     new_family = SCIM_SOCKET_UNKNOWN;
189
190     scim_split_string_list (varlist, addr, ':');
191
192     if (varlist.size () < 2)
193         return false;
194
195     if (varlist [0] == "local" || varlist [0] == "unix" || varlist [0] == "file") {
196 #ifdef DISABLE_MULTIPLE_SOCKETS
197         String real_addr = addr.substr (varlist [0].length ()+1);
198 #else
199         String real_addr = addr.substr (varlist [0].length ()+1) +
200                            String ("-") +
201                            scim_get_user_name ();
202 #endif
203         struct sockaddr_un *un = new struct sockaddr_un;
204
205         un->sun_family = AF_UNIX;
206
207         memset (un->sun_path, 0, sizeof (un->sun_path));
208
209         strncpy (un->sun_path, real_addr.c_str (), sizeof (un->sun_path));
210
211         un->sun_path[sizeof (un->sun_path) - 1] = '\0';
212
213         SCIM_DEBUG_SOCKET(3) << "  local:" << un->sun_path << "\n";
214
215         new_family = SCIM_SOCKET_LOCAL;
216         new_data = (struct sockaddr *) un;
217
218     } else if ((varlist [0] == "tcp" || varlist [0] == "inet") &&
219                 varlist.size () == 3) {
220
221         struct sockaddr_in *in = new struct sockaddr_in;
222
223         in->sin_addr = __gethostname (varlist [1].c_str ());
224
225         if (in->sin_addr.s_addr) {
226             in->sin_family = AF_INET;
227             in->sin_port = htons (atoi (varlist [2].c_str ()));
228
229             SCIM_DEBUG_SOCKET(3) << "  inet:"
230                 << inet_ntoa (in->sin_addr) << ":"
231                 << ntohs (in->sin_port) << "\n";
232
233             new_family = SCIM_SOCKET_INET;
234             new_data = (struct sockaddr *) in;
235         } else {
236             delete in;
237         }
238     }
239
240     if (new_data) {
241         if (m_data) delete m_data;
242
243         m_data = new_data;
244         m_family = new_family;
245         m_address = addr;
246         return valid ();
247     }
248
249     return false;
250 }
251
252 // Implementation of SocketAddress
253 SocketAddress::SocketAddress (const String &addr)
254     : m_impl (new SocketAddressImpl (addr))
255 {
256 }
257
258 SocketAddress::SocketAddress (const SocketAddress &addr)
259     : m_impl (new SocketAddressImpl (*addr.m_impl))
260 {
261 }
262
263 SocketAddress::~SocketAddress ()
264 {
265     delete m_impl;
266 }
267
268 const SocketAddress&
269 SocketAddress::operator = (const SocketAddress &addr)
270 {
271     if (this != &addr) {
272         SocketAddressImpl new_impl (*addr.m_impl);
273         m_impl->swap (new_impl);
274     }
275     return *this;
276 }
277
278 bool
279 SocketAddress::valid () const
280 {
281     return m_impl->valid ();
282 }
283
284 SocketFamily
285 SocketAddress::get_family () const
286 {
287     return m_impl->get_family ();
288 }
289
290 bool
291 SocketAddress::set_address (const String &addr)
292 {
293     SCIM_DEBUG_SOCKET(2) << " SocketAddress::set_address (" << addr << ")\n";
294     return m_impl->set_address (addr);
295 }
296
297 String
298 SocketAddress::get_address () const
299 {
300     return m_impl->get_address ();
301 }
302
303 const void *
304 SocketAddress::get_data () const
305 {
306     return m_impl->get_data ();
307 }
308
309 int
310 SocketAddress::get_data_length () const
311 {
312     return m_impl->get_data_length ();
313 }
314
315 // Implementation of Socket
316 class Socket::SocketImpl
317 {
318     int           m_id;
319     int           m_err;
320     bool          m_binded;
321     bool          m_no_close;
322     SocketFamily  m_family;
323     SocketAddress m_address;
324
325 public:
326
327     SocketImpl (int id = -1)
328         : m_id (id), m_err (0), m_binded (false), m_no_close (true),
329           m_family (SCIM_SOCKET_UNKNOWN) {
330     }
331
332     ~SocketImpl () {
333         close ();
334     }
335
336     bool valid () const {
337         return m_id >= 0;
338     }
339
340     int read (void *buf, size_t size) {
341         if (!buf || !size) { m_err = EINVAL; return -1; }
342         if (m_id < 0) { m_err = EBADF; return -1; }
343
344         m_err = 0;
345         int ret;
346         while (1) {
347             ret = ::read (m_id, buf, size);
348             if (ret >= 0)
349                 break;
350             if (errno == EINTR)
351                 continue;
352             m_err = errno;
353         }
354         return ret;
355     }
356
357     int read_with_timeout (void *buf, size_t size, int timeout) {
358         if (!buf || !size) { m_err = EINVAL; return -1; }
359         if (m_id < 0) { m_err = EBADF; return -1; }
360
361         if (timeout < 0)
362             return read (buf, size);
363
364         int   ret;
365         int   nbytes = 0;
366         char *cbuf = static_cast<char *> (buf);
367
368         while (size > 0) {
369             ret = wait_for_data_internal (&timeout);
370
371             if (ret < 0) return ret;
372             if (ret == 0) return nbytes;
373
374             ret = read (cbuf, size);
375
376             if (ret < 0) return ret;
377             if (ret == 0) return nbytes;
378
379             cbuf += ret;
380             nbytes += ret;
381             size -= ret;
382         }
383         return nbytes;
384     }
385
386     int write (const void *buf, size_t size) {
387         if (!buf || !size) { m_err = EINVAL; return -1; }
388         if (m_id < 0) { m_err = EBADF; return -1; }
389
390         int ret = -1;
391
392         typedef void (*_scim_sighandler_t)(int);
393         _scim_sighandler_t orig_handler = signal (SIGPIPE, SIG_IGN);
394
395         m_err = 0;
396
397         const char *cbuf = static_cast<const char*> (buf);
398
399         while (size > 0) {
400             ret = ::write (m_id, cbuf, size);
401             if (ret > 0) {
402                 size -= (size_t) ret;
403                 cbuf += ret;
404                 continue;
405             }
406             if (errno == EINTR)
407                 continue;
408             break;
409         }
410
411         m_err = errno;
412
413         if (orig_handler != SIG_ERR)
414             signal (SIGPIPE, orig_handler);
415         else
416             signal (SIGPIPE, SIG_DFL);
417
418         return ret;
419     }
420
421     int wait_for_data (int timeout = -1) {
422         if (m_id < 0) { m_err = EBADF; return -1; }
423         return wait_for_data_internal (&timeout);
424     }
425
426     int get_error_number () const {
427         return m_err;
428     }
429
430     String get_error_message () const {
431         if (m_err > 0)
432             return String (strerror (m_err));
433         return String ();
434     }
435
436     int get_id () const {
437         return m_id;
438     }
439
440     int set_nonblock_mode () {
441         if (m_id < 0) { m_err = EBADF; return -1; }
442
443         int ret;
444
445         ret = ::fcntl(m_id, F_SETFL, O_NONBLOCK);
446         return ret;
447     }
448
449     bool connect (const SocketAddress &addr) {
450         SCIM_DEBUG_SOCKET(1) << "Socket: Connect to server: "
451                              << addr.get_address () << " ...\n";
452
453         m_err = EBADF;
454
455         if (m_binded) return false;
456
457         if (addr.valid () && m_id >= 0 && m_family == addr.get_family ()) {
458             struct sockaddr * data = (sockaddr *) addr.get_data ();
459             int len = addr.get_data_length ();
460
461             // Backup the current flag to restore after non-blocking connect() try
462             int flags = fcntl (m_id, F_GETFL, 0);
463             fcntl (m_id, F_SETFL, flags | O_NONBLOCK);
464
465             char buf[256] = {0};
466             snprintf (buf, sizeof (buf), "time:%ld  pid:%d  ppid:%d  %s  %s  trying connect() to %s\n",
467                 time (0), getpid (), getppid (), __FILE__, __func__, addr.get_address ().c_str ());
468             isf_save_log (buf);
469
470             if ((m_err = ::connect (m_id, data, len)) == 0) {
471                 if (fcntl (m_id, F_SETFL, flags) == -1) {
472                     m_err = errno;
473                 }
474                 m_address = addr;
475
476                 snprintf (buf, sizeof (buf), "time:%ld  pid:%d  %s  %s  connect() succeeded\n",
477                     time (0), getpid (), __FILE__, __func__);
478                 isf_save_log (buf);
479
480                 return true;
481             }
482
483             // If still in progress, use select() to wait for the connection result
484             if (m_err == EINPROGRESS) {
485                 const int nsec = scim_get_default_socket_timeout () / 1000;
486
487                 fd_set rset, wset;
488                 struct timeval tval;
489                 FD_ZERO(&rset);
490                 FD_SET(m_id, &rset);
491                 wset = rset;
492                 tval.tv_sec = nsec;
493                 tval.tv_usec = 0;
494
495                 snprintf (buf, sizeof (buf), "time:%ld  pid:%d  %s  %s  EINPROGRESS, select() with timeout %d\n",
496                     time (0), getpid (), __FILE__, __func__, nsec);
497                 isf_save_log (buf);
498
499                 if (select (m_id + 1, &rset, &wset, NULL, nsec ? &tval : NULL) == 0) {
500                     m_err = ETIMEDOUT;
501
502                     snprintf (buf, sizeof (buf), "time:%ld  pid:%d  %s  %s  timeout in select()\n",
503                         time (0), getpid (), __FILE__, __func__);
504                     isf_save_log (buf);
505                 } else {
506                     // We've got something, connection succeeded
507                     snprintf (buf, sizeof (buf), "time:%ld  pid:%d  %s  %s  finally connected\n",
508                         time (0), getpid (), __FILE__, __func__);
509                     isf_save_log (buf);
510
511                     if (fcntl (m_id, F_SETFL, flags) == -1) {
512                         m_err = errno;
513                     }
514                     m_address = addr;
515                     return true;
516                 }
517             } else {
518                 m_err = errno;
519                 snprintf (buf, sizeof (buf), "time:%ld  pid:%d  %s  %s  connect() failed with %d\n",
520                         time (0), getpid (), __FILE__, __func__, errno);
521                 isf_save_log (buf);
522             }
523             if (fcntl (m_id, F_SETFL, flags) == -1) {
524                 m_err = errno;
525             }
526         }
527         return false;
528     }
529
530     bool bind (const SocketAddress &addr) {
531         SCIM_DEBUG_SOCKET(1) << "Socket: Bind to address: "
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             const struct sockaddr_un * data_un = 0;
540             const struct sockaddr * data = static_cast <const struct sockaddr *>(addr.get_data ());
541             int len = addr.get_data_length ();
542
543             // Unlink the broken socket file.
544             if (m_family == SCIM_SOCKET_LOCAL) {
545                 data_un = static_cast <const struct sockaddr_un *>(addr.get_data ());
546                 // The file is already exist, check if it's broken
547                 // by connecting to it.
548                 SCIM_DEBUG_SOCKET(2) << "Try to remove the broken socket file: " << data_un->sun_path << "\n";
549
550                 if (::access (data_un->sun_path, F_OK) == 0) {
551                     SocketClient tmp_socket (addr);
552
553                     if (!tmp_socket.is_connected ()) {
554                         struct stat statbuf;
555
556                         // If it's a socket file, then
557                         // delete it.
558                         if (::stat (data_un->sun_path, &statbuf) == 0 && S_ISSOCK (statbuf.st_mode))
559                             ::unlink (data_un->sun_path);
560                     }
561
562                     tmp_socket.close ();
563                 }
564             }
565
566             if (::bind (m_id, data, len) == 0) {
567                 m_address = addr;
568                 m_binded = true;
569                 m_err = 0;
570
571                 // Set correct permission for the socket file
572 #ifdef DISABLE_MULTIPLE_SOCKETS
573                 if (m_family == SCIM_SOCKET_LOCAL) {
574                     ::chmod (data_un->sun_path, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
575                 }
576 #else
577                 if (m_family == SCIM_SOCKET_LOCAL) {
578                     ::chmod (data_un->sun_path, S_IRUSR | S_IWUSR);
579                 }
580 #endif
581
582                 return true;
583             }
584
585             m_err = errno;
586         }
587         return false;
588     }
589
590     bool listen (int queue_length = 5) {
591         if (m_id < 0) { m_err = EBADF; return -1; }
592
593         SCIM_DEBUG_SOCKET(1) << "Socket: Listen: "
594                              << queue_length << " ...\n";
595
596         m_err = 0;
597
598         int ret = ::listen (m_id, queue_length);
599
600         if (ret < 0) m_err = errno;
601
602         return ret >= 0;
603     }
604
605     int accept () {
606         if (m_id < 0) { m_err = EBADF; return -1; }
607
608         int ret = -1;
609         int addrlen = 0;
610
611         m_err = 0;
612
613         if (m_family == SCIM_SOCKET_LOCAL) {
614             struct sockaddr_un addr;
615             addrlen = sizeof (addr);
616             ret = ::accept (m_id, (struct sockaddr*) &addr, (socklen_t*) &addrlen);
617         } else if (m_family == SCIM_SOCKET_INET) {
618             struct sockaddr_in addr;
619             addrlen = sizeof (addr);
620             ret = ::accept (m_id, (struct sockaddr*) &addr, (socklen_t*) &addrlen);
621         }
622
623         if (ret < 0 && addrlen > 0)
624             m_err = errno;
625
626         SCIM_DEBUG_SOCKET(1) << "Socket: Accept connection, ret: " << ret << "\n";
627
628         return ret;
629     }
630
631     bool create (SocketFamily family) {
632         int ret = -1;
633
634         if (family == SCIM_SOCKET_LOCAL)
635             ret = ::socket (PF_UNIX, SOCK_STREAM, 0);
636         else if (family == SCIM_SOCKET_INET)
637             ret = ::socket (PF_INET, SOCK_STREAM, 0);
638         else {
639             m_err = EINVAL;
640             return false;
641         }
642
643         if (ret > 0) {
644             if (m_id >= 0) close ();
645             m_no_close = false;
646             m_binded = false;
647             m_err = 0;
648             m_family = family;
649             m_id = ret;
650         } else {
651             m_err = errno;
652         }
653
654         SCIM_DEBUG_SOCKET(1) << "Socket: Socket created, family: "
655                              << family << " ret: " << ret << "\n";
656
657         return ret >= 0;
658     }
659
660     void close () {
661         if (m_id < 0) return;
662
663         if (!m_no_close) {
664             SCIM_DEBUG_SOCKET(2) << "  Closing the socket: " << m_id << " ...\n";
665             ::close (m_id);
666
667             // Unlink the socket file.
668             #if 0
669             if (m_binded && m_family == SCIM_SOCKET_LOCAL) {
670                 const struct sockaddr_un * data = static_cast <const struct sockaddr_un *>(m_address.get_data ());
671                 // FIXME: Don't unlink the socket file, because if the process is forked and child process exits
672                 // the socket file will be unlinked by child process.
673                 //SCIM_DEBUG_SOCKET(3) << "  Unlinking socket file " << data->sun_path << "...\n";
674                 ::unlink (data->sun_path);
675             }
676             #endif
677         }
678
679         m_id = -1;
680         m_err = 0;
681         m_binded = false;
682         m_no_close = false;
683         m_family = SCIM_SOCKET_UNKNOWN;
684         m_address = SocketAddress ();
685     }
686
687 private:
688     int wait_for_data_internal (int *timeout) {
689         fd_set fds;
690         struct timeval tv;
691         struct timeval begin_tv;
692         int ret;
693
694         if (*timeout >= 0) {
695             gettimeofday(&begin_tv, 0);
696             tv.tv_sec = *timeout / 1000;
697             tv.tv_usec = (*timeout % 1000) * 1000;
698         }
699
700         m_err = 0;
701
702         while (1) {
703             FD_ZERO(&fds);
704             FD_SET(m_id, &fds);
705
706             ret = select(m_id + 1, &fds, NULL, NULL, (*timeout >= 0) ? &tv : NULL);
707             if (*timeout > 0) {
708                 int elapsed;
709                 struct timeval cur_tv;
710                 gettimeofday (&cur_tv, 0);
711                 elapsed = (cur_tv.tv_sec - begin_tv.tv_sec) * 1000 +
712                           (cur_tv.tv_usec - begin_tv.tv_usec) / 1000;
713                 *timeout = *timeout - elapsed;
714                 if (*timeout > 0) {
715                     tv.tv_sec = *timeout / 1000;
716                     tv.tv_usec = (*timeout % 1000) * 1000;
717                 } else {
718                     tv.tv_sec = 0;
719                     tv.tv_usec = 0;
720                     *timeout = 0;
721                 }
722             }
723             if (ret > 0) {
724                 return ret;
725             } else if (ret == 0) {
726                 if (*timeout == 0)
727                     return ret;
728                 else
729                     continue;
730             }
731
732             if (errno == EINTR)
733                 continue;
734
735             m_err = errno;
736             return ret;
737         }
738     }
739 };
740
741 Socket::Socket (int id)
742     : m_impl (new SocketImpl (id))
743 {
744 }
745
746 Socket::~Socket ()
747 {
748     m_impl->close ();
749     delete m_impl;
750 }
751
752 bool
753 Socket::valid () const
754 {
755     return m_impl->valid ();
756 }
757
758 int
759 Socket::read (void *buf, size_t size) const
760 {
761     return m_impl->read (buf, size);
762 }
763
764 int
765 Socket::read_with_timeout (void *buf, size_t size, int timeout) const
766 {
767     return m_impl->read_with_timeout (buf, size, timeout);
768 }
769
770 int
771 Socket::write (const void *buf, size_t size) const
772 {
773     return m_impl->write (buf, size);
774 }
775
776 int
777 Socket::wait_for_data (int timeout) const
778 {
779     return m_impl->wait_for_data (timeout);
780 }
781
782 int
783 Socket::get_error_number () const
784 {
785     return m_impl->get_error_number ();
786 }
787
788 String
789 Socket::get_error_message () const
790 {
791     return m_impl->get_error_message ();
792 }
793
794 bool
795 Socket::connect (const SocketAddress &addr) const
796 {
797     return m_impl->connect (addr);
798 }
799
800 bool
801 Socket::bind (const SocketAddress &addr) const
802 {
803     return m_impl->bind (addr);
804 }
805
806 bool
807 Socket::listen (int queue_length) const
808 {
809     return m_impl->listen (queue_length);
810 }
811
812 int
813 Socket::accept () const
814 {
815     return m_impl->accept ();
816 }
817
818 int
819 Socket::get_id () const
820 {
821     return m_impl->get_id ();
822 }
823
824 int
825 Socket::set_nonblock_mode ()
826 {
827     return m_impl->set_nonblock_mode ();
828 }
829
830 bool
831 Socket::create (SocketFamily family)
832 {
833     return m_impl->create (family);
834 }
835
836 void
837 Socket::close ()
838 {
839     m_impl->close ();
840 }
841
842 // Implementation of SocketServer
843 struct SocketServer::SocketServerImpl
844 {
845     fd_set   active_fds;
846     int      max_fd;
847     int      err;
848     bool     running;
849     bool     created;
850     int      num_clients;
851     int      max_clients;
852
853     std::vector <int> ext_fds;
854
855     SocketServerSignalSocket accept_signal;
856     SocketServerSignalSocket receive_signal;
857     SocketServerSignalSocket exception_signal;
858
859     SocketServerImpl (int mc)
860         : max_fd (0), err (0), running (false), created (false),
861           num_clients (0), max_clients (std::min (mc, SCIM_SOCKET_SERVER_MAX_CLIENTS)) {
862         FD_ZERO (&active_fds);
863     }
864 };
865
866 SocketServer::SocketServer (int max_clients)
867     : Socket (-1), m_impl (new SocketServerImpl (max_clients))
868 {
869 }
870
871 SocketServer::SocketServer (const SocketAddress &address, int max_clients)
872     : Socket (-1), m_impl (new SocketServerImpl (max_clients))
873 {
874     create (address);
875 }
876
877 SocketServer::~SocketServer ()
878 {
879     delete m_impl;
880 }
881
882 bool
883 SocketServer::valid () const
884 {
885     return m_impl->created;
886 }
887
888 bool
889 SocketServer::create (const SocketAddress &address)
890 {
891     m_impl->err = EBUSY;
892     if (!m_impl->created) {
893         SocketFamily family = address.get_family ();
894
895         SCIM_DEBUG_SOCKET (1) << "Creating Socket Server, family: " << family << "\n";
896
897         if (family != SCIM_SOCKET_UNKNOWN) {
898             if (Socket::create (family) &&
899                 Socket::bind (address) &&
900                 Socket::listen ()) {
901                 m_impl->created = true;
902                 m_impl->max_fd = Socket::get_id ();
903                 FD_ZERO (&(m_impl->active_fds));
904                 FD_SET (m_impl->max_fd, &(m_impl->active_fds));
905                 m_impl->err = 0;
906                 return true;
907             }
908             m_impl->err = Socket::get_error_number ();
909             Socket::close ();
910         } else {
911             m_impl->err = EBADF;
912         }
913     }
914     return false;
915 }
916
917 bool
918 SocketServer::run ()
919 {
920     if (m_impl->created && !m_impl->running) {
921         fd_set read_fds, exception_fds;
922         int client;
923         int i;
924
925         m_impl->running = true;
926         m_impl->err = 0;
927         while (1) {
928             read_fds = m_impl->active_fds;
929             exception_fds = m_impl->active_fds;
930
931             SCIM_DEBUG_SOCKET (2) << " SocketServer: Watching socket...\n";
932
933             if (select (m_impl->max_fd + 1, &read_fds, NULL, &exception_fds, NULL) < 0) {
934                 if (errno == EINTR)
935                     continue;
936
937                 m_impl->err = errno;
938                 m_impl->running = false;
939                 SCIM_DEBUG_SOCKET (3) << "  SocketServer: Error: "
940                                       << get_error_message () << "\n";
941                 return false;
942             }
943
944             //The server has been shut down.
945             if (!m_impl->running)
946                 return true;
947
948             for (i = 0; i<m_impl->max_fd + 1; i++) {
949                 if (FD_ISSET (i, &read_fds)) {
950
951                     //New connection
952                     if (i == Socket::get_id ()) {
953                         client = Socket::accept ();
954
955                         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Accept new connection:"
956                                               << client << "\n";
957
958                         if (client < 0) {
959                             m_impl->err = Socket::get_error_number ();
960                             m_impl->running = false;
961
962                             SCIM_DEBUG_SOCKET (4) << "   SocketServer: Error occurred: "
963                                 << Socket::get_error_message () << "\n";
964
965                             return false;
966                         }
967
968                         if (m_impl->max_clients > 0 &&
969                             m_impl->num_clients >= m_impl->max_clients) {
970                             SCIM_DEBUG_SOCKET (4) << "   SocketServer: Too many clients.\n";
971                             ::close (client);
972                         } else {
973                             m_impl->num_clients ++;
974
975                             //Store the new client
976                             FD_SET (client, &(m_impl->active_fds));
977                             if (m_impl->max_fd < client)
978                                 m_impl->max_fd = client;
979
980                             Socket client_socket (client);
981                             //emit the signal.
982                             m_impl->accept_signal.emit (this, client_socket);
983                         }
984
985                     //Client reading
986                     } else {
987                         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Accept client reading...\n";
988
989                         Socket client_socket (i);
990                         //emit the signal.
991                         m_impl->receive_signal.emit (this, client_socket);
992                     }
993                 }
994
995                 if (FD_ISSET (i, &exception_fds)) {
996
997                     //The server got an exception, return.
998                     if (i == Socket::get_id ()) {
999
1000                         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Server got an exception, exiting...\n";
1001
1002                         shutdown ();
1003                         return true;
1004
1005                     } else {
1006                         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Client "
1007                                               << i
1008                                               << "got an exception, callbacking...\n";
1009
1010                         Socket client_socket (i);
1011                         m_impl->exception_signal.emit (this, client_socket);
1012                     }
1013                 }
1014
1015                 if (!m_impl->running)
1016                     break;
1017             }
1018
1019             //The server has been shut down.
1020             if (!m_impl->running)
1021                 return true;
1022         }
1023     }
1024
1025     m_impl->err = EBADF;
1026     return false;
1027 }
1028
1029 bool
1030 SocketServer::filter_event (int fd)
1031 {
1032     int client;
1033     static bool first_call = true;
1034
1035     if (first_call) {
1036         m_impl->running = true;
1037         first_call = false;
1038     }
1039
1040     if (fd == Socket::get_id ()) {
1041         client = Socket::accept ();
1042
1043         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Accept new connection:"
1044                               << client << "\n";
1045
1046         if (client < 0) {
1047             m_impl->err = Socket::get_error_number ();
1048             m_impl->running = false;
1049
1050             SCIM_DEBUG_SOCKET (4) << "   SocketServer: Error occurred: "
1051                 << Socket::get_error_message () << "\n";
1052
1053             return false;
1054         }
1055
1056         if (m_impl->max_clients > 0 &&
1057             m_impl->num_clients >= m_impl->max_clients) {
1058             SCIM_DEBUG_SOCKET (4) << "   SocketServer: Too many clients.\n";
1059             ::close (client);
1060         } else {
1061             m_impl->num_clients ++;
1062
1063             //Store the new client
1064             FD_SET (client, &(m_impl->active_fds));
1065             if (m_impl->max_fd < client)
1066                 m_impl->max_fd = client;
1067
1068             Socket client_socket (client);
1069             //emit the signal.
1070             m_impl->accept_signal.emit (this, client_socket);
1071         }
1072     }else {
1073         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Accept client reading...\n";
1074         Socket client_socket (fd);
1075         m_impl->receive_signal.emit (this, client_socket);
1076     }
1077
1078     return true;
1079 }
1080
1081 bool
1082 SocketServer::filter_exception_event (int fd)
1083 {
1084     //The server got an exception, return.
1085     if (fd == Socket::get_id ()) {
1086
1087         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Server got an exception, exiting...\n";
1088
1089         shutdown ();
1090     } else {
1091         SCIM_DEBUG_SOCKET (3) << "  SocketServer: Client "
1092                               << fd
1093                               << "got an exception, callbacking...\n";
1094
1095         Socket client_socket (fd);
1096         m_impl->exception_signal.emit (this, client_socket);
1097     }
1098
1099     return true;
1100 }
1101
1102 bool
1103 SocketServer::is_running () const
1104 {
1105     return m_impl->running;
1106 }
1107
1108 void
1109 SocketServer::shutdown ()
1110 {
1111     if (m_impl->created) {
1112         SCIM_DEBUG_SOCKET (2) << " SocketServer: Shutting down the server...\n";
1113
1114         m_impl->running = false;
1115
1116         for (int i = 0; ((unsigned int)i) < m_impl->ext_fds.size (); i++)
1117             FD_CLR (m_impl->ext_fds [i], &m_impl->active_fds);
1118
1119         for (int i = 0; i<m_impl->max_fd + 1; i++) {
1120             //Close all client
1121             if (FD_ISSET (i, &(m_impl->active_fds)) && i != Socket::get_id ()) {
1122                 SCIM_DEBUG_SOCKET (3) << "  SocketServer: Closing client: "
1123                                       << i << "\n";
1124                 ::close (i);
1125             }
1126         }
1127         m_impl->max_fd = 0;
1128         m_impl->created = false;
1129         m_impl->err = 0;
1130         m_impl->num_clients = 0;
1131         m_impl->ext_fds.clear ();
1132         FD_ZERO (&(m_impl->active_fds));
1133
1134         Socket::close ();
1135     }
1136 }
1137
1138 bool
1139 SocketServer::close_connection (const Socket &socket)
1140 {
1141     int id = socket.get_id ();
1142     if (m_impl->created && m_impl->running && id > 0 && FD_ISSET (id, &(m_impl->active_fds))) {
1143
1144         SCIM_DEBUG_SOCKET (2) << " SocketServer: Closing the connection: " << id << "\n";
1145
1146         m_impl->num_clients --;
1147
1148         FD_CLR (id, &(m_impl->active_fds));
1149
1150         std::vector <int>::iterator it = std::find (m_impl->ext_fds.begin (), m_impl->ext_fds.end (), id);
1151         if (it != m_impl->ext_fds.end ()) m_impl->ext_fds.erase (it);
1152
1153         ::close (id);
1154         return true;
1155     }
1156     return false;
1157 }
1158
1159 int
1160 SocketServer::get_error_number () const
1161 {
1162     if (m_impl->err)
1163         return m_impl->err;
1164
1165     return Socket::get_error_number ();
1166 }
1167
1168 String
1169 SocketServer::get_error_message () const
1170 {
1171     if (m_impl->err)
1172         return String (strerror (m_impl->err));
1173
1174     return Socket::get_error_message ();
1175 }
1176
1177 int
1178 SocketServer::get_max_clients () const
1179 {
1180     return m_impl->max_clients;
1181 }
1182
1183 void
1184 SocketServer::set_max_clients (int max_clients)
1185 {
1186     if (max_clients < SCIM_SOCKET_SERVER_MAX_CLIENTS)
1187         m_impl->max_clients = max_clients;
1188 }
1189
1190 bool
1191 SocketServer::insert_external_socket (const Socket &sock)
1192 {
1193     int fd = sock.get_id ();
1194
1195     if (valid () && sock.valid () && sock.wait_for_data (0) >= 0 &&
1196         m_impl->num_clients < m_impl->max_clients &&
1197         !FD_ISSET (fd, &m_impl->active_fds)) {
1198         m_impl->ext_fds.push_back (fd);
1199         FD_SET (fd, &m_impl->active_fds);
1200         if (m_impl->max_fd < fd) m_impl->max_fd = fd;
1201         m_impl->num_clients ++;
1202         return true;
1203     }
1204     return false;
1205 }
1206
1207 bool
1208 SocketServer::remove_external_socket (const Socket &sock)
1209 {
1210     int fd = sock.get_id ();
1211
1212     if (valid () && FD_ISSET (fd, &m_impl->active_fds)) {
1213         FD_CLR (fd, &m_impl->active_fds);
1214         std::vector <int>::iterator it = std::find (m_impl->ext_fds.begin (), m_impl->ext_fds.end (), fd);
1215         if (it != m_impl->ext_fds.end ()) m_impl->ext_fds.erase (it);
1216         m_impl->num_clients --;
1217         return true;
1218     }
1219     return false;
1220 }
1221
1222 Connection
1223 SocketServer::signal_connect_accept (SocketServerSlotSocket *slot)
1224 {
1225     return m_impl->accept_signal.connect (slot);
1226 }
1227
1228 Connection
1229 SocketServer::signal_connect_receive (SocketServerSlotSocket *slot)
1230 {
1231     return m_impl->receive_signal.connect (slot);
1232 }
1233
1234 Connection
1235 SocketServer::signal_connect_exception (SocketServerSlotSocket *slot)
1236 {
1237     return m_impl->exception_signal.connect (slot);
1238 }
1239
1240 //Implementation of SocketClient
1241 SocketClient::SocketClient ()
1242     : Socket (-1), m_connected (false)
1243 {
1244 }
1245
1246 SocketClient::SocketClient (const SocketAddress &address)
1247     : Socket (-1), m_connected (false)
1248 {
1249     connect (address);
1250 }
1251
1252 SocketClient::~SocketClient ()
1253 {
1254 }
1255
1256 bool
1257 SocketClient::is_connected () const
1258 {
1259     return Socket::valid () && m_connected;
1260 }
1261
1262 bool
1263 SocketClient::connect (const SocketAddress &address)
1264 {
1265     if (m_connected) close ();
1266
1267     if (Socket::create (address.get_family ()) && Socket::connect (address)) {
1268         m_connected = true;
1269         return true;
1270     } else {
1271         close ();
1272     }
1273
1274     return false;
1275 }
1276
1277 void
1278 SocketClient::close ()
1279 {
1280     Socket::close ();
1281     m_connected = false;
1282 }
1283
1284 #define SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS        "local:/tmp/scim-socket-frontend"
1285 #define SCIM_DEFAULT_PANEL_SOCKET_ADDRESS           "local:/tmp/scim-panel-socket"
1286 #define SCIM_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS  "local:/tmp/scim-socket-frontend"
1287
1288 String scim_get_default_socket_frontend_address ()
1289 {
1290     String address (SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS);
1291
1292     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_FRONTEND_ADDRESS, address);
1293
1294     const char *env = getenv ("SCIM_SOCKET_ADDRESS");
1295     if (env && strlen (env) > 0) {
1296         address = String (env);
1297     } else {
1298         env = getenv ("SCIM_FRONTEND_SOCKET_ADDRESS");
1299         if (env && strlen (env))
1300             address = String (env);
1301     }
1302
1303     if (address == "default")
1304         address = SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS;
1305
1306     return address;
1307 }
1308
1309 String scim_get_default_socket_imengine_address ()
1310 {
1311     String address (SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS);
1312
1313     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_IMENGINE_ADDRESS, address);
1314
1315     const char *env = getenv ("SCIM_SOCKET_ADDRESS");
1316     if (env && strlen (env) > 0) {
1317         address = String (env);
1318     } else {
1319         env = getenv ("SCIM_IMENGINE_SOCKET_ADDRESS");
1320         if (env && strlen (env))
1321             address = String (env);
1322     }
1323
1324     if (address == "default")
1325         address = SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS;
1326
1327     return address;
1328 }
1329
1330 String scim_get_default_socket_config_address ()
1331 {
1332     String address (SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS);
1333
1334     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_CONFIG_ADDRESS, address);
1335
1336     const char *env = getenv ("SCIM_SOCKET_ADDRESS");
1337     if (env && strlen (env) > 0) {
1338         address = String (env);
1339     } else {
1340         env = getenv ("SCIM_CONFIG_SOCKET_ADDRESS");
1341         if (env && strlen (env))
1342             address = String (env);
1343     }
1344
1345     if (address == "default")
1346         address = SCIM_DEFAULT_SOCKET_FRONTEND_ADDRESS;
1347
1348     return address;
1349 }
1350
1351 String scim_get_default_panel_socket_address (const String &display)
1352 {
1353     String address (SCIM_DEFAULT_PANEL_SOCKET_ADDRESS);
1354
1355     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_PANEL_SOCKET_ADDRESS, address);
1356
1357     const char *env = getenv ("SCIM_PANEL_SOCKET_ADDRESS");
1358
1359     if (env && strlen (env) > 0) {
1360         address = String (env);
1361     }
1362
1363     if (address == "default")
1364         address = SCIM_DEFAULT_PANEL_SOCKET_ADDRESS;
1365
1366     SocketAddress sockaddr (address);
1367
1368     if (!sockaddr.valid ())
1369         return String ();
1370
1371     String::size_type colon_pos = display.rfind (':');
1372     String disp_name = display;
1373     int    disp_num  = 0;
1374
1375     // Maybe It's a X11 DISPLAY name
1376     if (colon_pos != String::npos) {
1377         String::size_type dot_pos = display.find ('.', colon_pos+1);
1378         // It has screen number
1379         if (dot_pos != String::npos) {
1380             disp_name = display.substr (0, dot_pos);
1381         }
1382         // FIXME: ignore remote X Server name.
1383         disp_num = atoi (display.substr (colon_pos + 1, dot_pos - colon_pos - 1).c_str ());
1384     }
1385
1386     if (sockaddr.get_family () == SCIM_SOCKET_LOCAL) {
1387         address = address + disp_name;
1388     } else if (sockaddr.get_family () == SCIM_SOCKET_INET) {
1389         std::vector <String> varlist;
1390         scim_split_string_list (varlist, address, ':');
1391         if (varlist.size () == 3) {
1392             int port = atoi (varlist [2].c_str ()) + disp_num;
1393             char buf [10];
1394             snprintf (buf, 10, "%d", port);
1395             varlist [2] = String (buf);
1396             address = scim_combine_string_list (varlist, ':');
1397         }
1398     }
1399
1400     sockaddr.set_address (address);
1401
1402     if (sockaddr.valid ())
1403         return address;
1404
1405     return String ();
1406 }
1407
1408 String scim_get_default_helper_manager_socket_address ()
1409 {
1410     String address (SCIM_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS);
1411
1412     address = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS, address);
1413
1414     const char *env = getenv ("SCIM_HELPER_MANAGER_SOCKET_ADDRESS");
1415     if (env && strlen (env) > 0) {
1416         address = String (env);
1417     }
1418
1419     if (address == "default")
1420         address = SCIM_DEFAULT_HELPER_MANAGER_SOCKET_ADDRESS;
1421
1422     return address;
1423 }
1424
1425 int scim_get_default_socket_timeout ()
1426 {
1427     int timeout = 5000;
1428
1429     timeout = scim_global_config_read (SCIM_GLOBAL_CONFIG_DEFAULT_SOCKET_TIMEOUT, timeout);
1430
1431     const char *env = getenv ("SCIM_SOCKET_TIMEOUT");
1432
1433     if (env && strlen (env))
1434         timeout = atoi (env);
1435
1436     if (timeout <= 0) timeout = -1;
1437
1438     return timeout;
1439 }
1440
1441 static bool
1442 scim_socket_check_type (const String &types,
1443                         const String &atype)
1444 {
1445     std::vector <String> type_list;
1446     scim_split_string_list (type_list, types, ',');
1447
1448     return std::find (type_list.begin (), type_list.end (), atype) != type_list.end ();
1449 }
1450
1451 bool
1452 scim_socket_open_connection   (uint32       &key,
1453                                const String &client_type,
1454                                const String &server_type,
1455                                const Socket &socket,
1456                                int           timeout)
1457 {
1458     if (!socket.valid () || !client_type.length () || !server_type.length ())
1459         return false;
1460
1461     Transaction trans;
1462
1463     trans.put_command (SCIM_TRANS_CMD_REQUEST);
1464     trans.put_command (SCIM_TRANS_CMD_OPEN_CONNECTION);
1465     trans.put_data (String (SCIM_BINARY_VERSION));
1466     trans.put_data (client_type);
1467     if (const_cast<Socket &>(socket).set_nonblock_mode () == -1)
1468         std::cerr << __func__ << "set_nonblock_mode () is failed!!!\n";
1469     if (trans.write_to_socket (socket)) {
1470         int cmd;
1471         String server_types;
1472         if (trans.read_from_socket (socket, timeout) &&
1473             trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
1474             trans.get_data (server_types) && scim_socket_check_type (server_types, server_type) &&
1475             trans.get_data (key)) {
1476             trans.clear ();
1477             trans.put_command (SCIM_TRANS_CMD_REPLY);
1478             trans.put_command (SCIM_TRANS_CMD_OK);
1479             if (trans.write_to_socket (socket))
1480                 return true;
1481         } else {
1482             trans.clear ();
1483             trans.put_command (SCIM_TRANS_CMD_REPLY);
1484             trans.put_command (SCIM_TRANS_CMD_FAIL);
1485             trans.write_to_socket (socket);
1486         }
1487     }
1488
1489     return false;
1490 }
1491
1492 String
1493 scim_socket_accept_connection (uint32       &key,
1494                                const String &server_types,
1495                                const String &client_types,
1496                                const Socket &socket,
1497                                int           timeout)
1498 {
1499     if (!socket.valid () || !client_types.length () || !server_types.length ())
1500         return String ("");
1501
1502     Transaction trans;
1503     if (const_cast<Socket &>(socket).set_nonblock_mode () == -1)
1504         std::cerr << __func__ << "set_nonblock_mode () is failed!!!\n";
1505     if (trans.read_from_socket (socket, timeout)) {
1506         int cmd;
1507         String version;
1508         String client_type;
1509         if (trans.get_command (cmd)  && cmd == SCIM_TRANS_CMD_REQUEST &&
1510             trans.get_command (cmd)  && cmd == SCIM_TRANS_CMD_OPEN_CONNECTION &&
1511             trans.get_data (version) && version == String (SCIM_BINARY_VERSION) &&
1512             trans.get_data (client_type) &&
1513             (scim_socket_check_type (client_types, client_type) || client_type == "ConnectionTester")) {
1514             key = (uint32) rand ();
1515             trans.clear ();
1516             trans.put_command (SCIM_TRANS_CMD_REPLY);
1517             trans.put_data (server_types);
1518             trans.put_data (key);
1519
1520             if (trans.write_to_socket (socket) &&
1521                 trans.read_from_socket (socket, timeout) &&
1522                 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_REPLY &&
1523                 trans.get_command (cmd) && cmd == SCIM_TRANS_CMD_OK) {
1524
1525                 // Client is ok, return the client type.
1526                 return (client_type == "ConnectionTester") ? String ("") : client_type;
1527             }
1528         }
1529     }
1530     return String ("");
1531 }
1532
1533 } // namespace scim
1534
1535 /*
1536 vi:ts=4:nowrap:ai:expandtab
1537 */
1538