10
#include <sys/socket.h>
12
#include <sys/types.h>
15
#include "scim-bridge-client-kernel-protected.h"
16
#include "scim-bridge-client-messenger.h"
17
#include "scim-bridge-exception.h"
18
#include "scim-bridge-environment.h"
19
#include "scim-bridge-keyevent.h"
20
#include "scim-bridge-message.h"
21
#include "scim-bridge-messenger.h"
22
#include "scim-bridge-output.h"
23
#include "scim-bridge-string.h"
25
/* Private static variables */
26
static const int CONNECTION_TRY_MAX_COUNT = 3;
28
/* Private variables */
32
static ScimBridgeMessengerID messenger_id = -1;
34
static pthread_t messenger_thread;
36
/* Private functions */
37
static int launch_agent ();
38
static int open_connection (ScimBridgeException *except);
39
static int start_thread (ScimBridgeException *except);
40
static void *run_thread ();
42
static int received_message_unknown (ScimBridgeException *except, ScimBridgeMessageCode code);
43
static int received_message_commit (ScimBridgeException *except);
44
static int received_message_update_preedit (ScimBridgeException *except);
45
static int received_message_set_preedit_string (ScimBridgeException *except);
46
static int received_message_set_preedit_attributes (ScimBridgeException *except);
47
static int received_message_set_preedit_cursor_position (ScimBridgeException *except);
48
static int received_message_set_preedit_shown (ScimBridgeException *except);
49
static int received_message_forward_keyevent (ScimBridgeException *except);
50
static int received_message_beep (ScimBridgeException *except);
51
static int received_message_get_surrounding_string (ScimBridgeException *except);
52
static int received_message_delete_surrounding_string (ScimBridgeException *except);
55
int scim_bridge_client_initialize_messenger (ScimBridgeException *except)
61
for (retry_count = 0; retry_count < CONNECTION_TRY_MAX_COUNT; ++retry_count) {
62
if (open_connection (except)) {
63
if (retry_count == 0) {
72
if (input_fd < 0 || output_fd < 0) return -1;
74
if (scim_bridge_initialize_messenger (except, &messenger_id, input_fd, output_fd))
77
return start_thread (except);
81
int scim_bridge_client_finalize_messenger (ScimBridgeException *except)
83
if (input_fd > 0 && output_fd > 0) {
88
if (messenger_id >= 0) {
89
scim_bridge_finalize_messenger (except, messenger_id);
97
/* Helper functions */
100
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT, 1, "Invoking the agent...");
101
if (system ("scim-bridge-agent")) {
102
scim_bridge_perrorln ("Failed to invoking the agent: %s", strerror (errno));
110
int open_connection (ScimBridgeException *except)
112
int output_socket_fd = socket (PF_UNIX, SOCK_STREAM, 0);
113
if (output_socket_fd < 0) {
114
scim_bridge_exception_set_errno (except, errno);
115
scim_bridge_exception_set_message (except, "Failed to create the output socket");
119
struct sockaddr_un output_socket_addr;
120
memset (&output_socket_addr, 0, sizeof (struct sockaddr_un));
121
output_socket_addr.sun_family = AF_UNIX;
122
strcpy (output_socket_addr.sun_path, scim_bridge_environment_get_client_to_agent_socket_path ());
124
if (connect (output_socket_fd, (struct sockaddr*)&output_socket_addr, sizeof (struct sockaddr_un)) != 0) {
125
scim_bridge_exception_set_errno (except, errno);
126
scim_bridge_exception_set_message (except, "Failed to open the output socket");
130
int input_socket_fd = socket (PF_UNIX, SOCK_STREAM, 0);
131
if (input_socket_fd < 0) {
132
scim_bridge_exception_set_errno (except, errno);
133
scim_bridge_exception_set_message (except, "Failed to create the input socket");
137
struct sockaddr_un input_socket_addr;
138
memset (&input_socket_addr, 0, sizeof (struct sockaddr_un));
139
input_socket_addr.sun_family = AF_UNIX;
140
strcpy (input_socket_addr.sun_path, scim_bridge_environment_get_agent_to_client_socket_path ());
142
if (connect (input_socket_fd, (struct sockaddr*)&input_socket_addr, sizeof (struct sockaddr_un)) != 0) {
143
scim_bridge_exception_set_errno (except, errno);
144
scim_bridge_exception_set_message (except, "Failed to open the input socket");
148
input_fd = input_socket_fd;
149
output_fd = output_socket_fd;
155
int start_thread (ScimBridgeException *except)
157
if (pthread_create (&messenger_thread, NULL, &run_thread, NULL) || pthread_detach (messenger_thread)) {
158
scim_bridge_exception_set_errno (except, errno);
159
scim_bridge_exception_set_message (except, "Failed to create new thread");
169
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 1, "run_messenger");
171
int connection_broken = 0;
172
ScimBridgeException except;
173
scim_bridge_exception_initialize (&except);
174
while (!connection_broken && input_fd > 0 && output_fd > 0) {
175
if (scim_bridge_messenger_open_input (&except, messenger_id)) {
176
connection_broken = 1;
180
ScimBridgeMessageCode code;
181
if (scim_bridge_messenger_read_input (&except, messenger_id, &code, sizeof (code))) {
182
connection_broken = 1;
186
case SCIM_BRIDGE_MESSAGE_COMMIT:
187
if (received_message_commit (&except)) connection_broken = 1;
189
case SCIM_BRIDGE_MESSAGE_SET_PREEDIT_STRING:
190
if (received_message_set_preedit_string (&except)) connection_broken = 1;
192
case SCIM_BRIDGE_MESSAGE_SET_PREEDIT_ATTRIBUTES:
193
if (received_message_set_preedit_attributes (&except)) connection_broken = 1;
195
case SCIM_BRIDGE_MESSAGE_SET_PREEDIT_CURSOR_POSITION:
196
if (received_message_set_preedit_cursor_position (&except)) connection_broken = 1;
198
case SCIM_BRIDGE_MESSAGE_SET_PREEDIT_SHOWN:
199
if (received_message_set_preedit_shown (&except)) connection_broken = 1;
201
case SCIM_BRIDGE_MESSAGE_UPDATE_PREEDIT:
202
if (received_message_update_preedit (&except)) connection_broken = 1;
204
case SCIM_BRIDGE_MESSAGE_FORWARD_KEYEVENT:
205
if (received_message_forward_keyevent (&except)) connection_broken = 1;
207
case SCIM_BRIDGE_MESSAGE_BEEP:
208
if (received_message_beep (&except)) connection_broken = 1;
210
case SCIM_BRIDGE_MESSAGE_GET_SURROUNDING_STRING:
211
if (received_message_get_surrounding_string (&except)) connection_broken = 1;
213
case SCIM_BRIDGE_MESSAGE_DELETE_SURROUNDING_STRING:
214
if (received_message_delete_surrounding_string (&except)) connection_broken = 1;
217
if (received_message_unknown (&except, code)) {
218
connection_broken = 1;
224
if (input_fd > 0 || output_fd > 0) {
225
scim_bridge_client_kernel_exception_occured (&except);
227
scim_bridge_client_kernel_cleanup (&except);
229
scim_bridge_exception_finalize (&except);
235
/* Received message handler */
237
int received_message_unknown (ScimBridgeException *except, ScimBridgeMessageCode code)
239
scim_bridge_perrorln ("Unknown message received: %d", code);
240
scim_bridge_exception_set_errno (except, EBADRQC);
241
scim_bridge_exception_set_message (except, "Unknwon message received");
243
if (scim_bridge_messenger_close_input (except, messenger_id))
250
int received_message_commit (ScimBridgeException *except)
252
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'Commit' message");
254
ScimBridgeIMContextID id;
255
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
258
scim_bridge_client_kernel_commit (id);
260
if (scim_bridge_messenger_close_input (except, messenger_id))
267
int received_message_set_preedit_shown (ScimBridgeException *except)
269
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'Set preedit shown' message");
271
ScimBridgeIMContextID id;
272
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
276
if (scim_bridge_messenger_read_input (except, messenger_id, &shown, sizeof (shown)))
279
scim_bridge_client_kernel_set_preedit_shown (id, shown);
281
if (scim_bridge_messenger_close_input (except, messenger_id))
288
int received_message_set_preedit_string (ScimBridgeException *except)
290
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'Set preedit string' message");
292
ScimBridgeIMContextID id;
293
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
297
if (scim_bridge_messenger_read_input (except, messenger_id, &wstr_len, sizeof (wstr_len)))
301
wstr = malloc (sizeof (ucs4_t) * (wstr_len + 1));
302
if (scim_bridge_messenger_read_input (except, messenger_id, wstr, sizeof (ucs4_t) * (wstr_len + 1)))
305
scim_bridge_client_kernel_set_preedit_string (id, wstr, wstr_len);
307
if (scim_bridge_messenger_close_input (except, messenger_id))
313
int received_message_set_preedit_attributes (ScimBridgeException *except)
315
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'Set preedit attributes' message");
317
ScimBridgeIMContextID id;
318
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
322
if (scim_bridge_messenger_read_input (except, messenger_id, &attr_count, sizeof (attr_count)))
325
ScimBridgeAttribute *attrs;
326
if (attr_count != 0) attrs = malloc (sizeof (ScimBridgeAttribute) * attr_count);
328
if (scim_bridge_messenger_read_input (except, messenger_id, attrs, sizeof (ScimBridgeAttribute) * (attr_count)))
331
scim_bridge_client_kernel_set_preedit_attributes (id, attrs, attr_count);
333
if (scim_bridge_messenger_close_input (except, messenger_id))
339
int received_message_set_preedit_cursor_position (ScimBridgeException *except)
341
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'Set preedit cursor position' message");
343
ScimBridgeIMContextID id;
344
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
348
if (scim_bridge_messenger_read_input (except, messenger_id, &cur_pos, sizeof (cur_pos)))
351
if (scim_bridge_messenger_close_input (except, messenger_id))
354
scim_bridge_client_kernel_set_preedit_cursor_position (id, cur_pos);
359
int received_message_update_preedit (ScimBridgeException *except)
361
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'Update preedit' message");
363
ScimBridgeIMContextID id;
364
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
367
scim_bridge_client_kernel_update_preedit (id);
369
if (scim_bridge_messenger_close_input (except, messenger_id))
376
int received_message_forward_keyevent (ScimBridgeException *except)
378
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'forward keyevent' message");
380
ScimBridgeIMContextID id;
381
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
384
ScimBridgeKeyEvent keyevent;
385
if (scim_bridge_messenger_read_input (except, messenger_id, &keyevent, sizeof (ScimBridgeKeyEvent)))
388
scim_bridge_client_kernel_forward_keyevent (id, &keyevent);
390
if (scim_bridge_messenger_close_input (except, messenger_id))
397
int received_message_beep (ScimBridgeException *except)
399
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'beep' message");
401
ScimBridgeIMContextID id;
402
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
405
if (scim_bridge_messenger_close_input (except, messenger_id))
408
scim_bridge_client_kernel_beep (id);
414
int received_message_get_surrounding_string (ScimBridgeException *except)
416
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'Get surrounding text' message");
418
ScimBridgeIMContextID id;
419
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
422
size_t buffer_length;
423
if (scim_bridge_messenger_read_input (except, messenger_id, &buffer_length, sizeof (buffer_length)))
426
ucs4_t wstr[buffer_length + 1];
431
scim_bridge_client_kernel_get_surrounding_string (id, wstr, buffer_length, &wstr_len, &cursor_position);
433
if (scim_bridge_messenger_write_input (except, messenger_id, &wstr_len, sizeof (wstr_len)))
436
if (scim_bridge_messenger_write_input (except, messenger_id, wstr, sizeof (ucs4_t) * (wstr_len + 1)))
439
if (scim_bridge_messenger_write_input (except, messenger_id, &cursor_position, sizeof (cursor_position)))
442
if (scim_bridge_messenger_close_input (except, messenger_id))
449
int received_message_delete_surrounding_string (ScimBridgeException *except)
451
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Received 'Delete surrounding text' message");
453
ScimBridgeIMContextID id;
454
if (scim_bridge_messenger_read_input (except, messenger_id, &id, sizeof (id)))
458
if (scim_bridge_messenger_read_input (except, messenger_id, &offset, sizeof (offset)))
462
if (scim_bridge_messenger_read_input (except, messenger_id, &length, sizeof (length)))
466
scim_bridge_client_kernel_delete_surrounding_string (id, offset, length, &retval);
468
if (scim_bridge_messenger_write_input (except, messenger_id, &retval, sizeof (retval)))
471
if (scim_bridge_messenger_close_input (except, messenger_id))
478
/* Remote functions */
479
int scim_bridge_client_call_alloc_imcontext (ScimBridgeException *except, ScimBridgeIMContextID id, ScimBridgeIMContextID *opponent_id)
481
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Sending 'alloc imcontext' message...");
483
if (scim_bridge_messenger_open_output (except, messenger_id))
486
const ScimBridgeMessageCode code = SCIM_BRIDGE_MESSAGE_ALLOC_IMCONTEXT;
487
if (scim_bridge_messenger_write_output (except, messenger_id, &code, sizeof (code)))
490
if (scim_bridge_messenger_write_output (except, messenger_id, &id, sizeof (id)))
493
if (scim_bridge_messenger_read_output (except, messenger_id, opponent_id, sizeof (*opponent_id)))
496
if (scim_bridge_messenger_close_output (except, messenger_id))
503
int scim_bridge_client_call_free_imcontext (ScimBridgeException *except, ScimBridgeIMContextID opponent_id)
505
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Sending 'free imcontext' message...");
507
if (scim_bridge_messenger_open_output (except, messenger_id))
510
const ScimBridgeMessageCode code = SCIM_BRIDGE_MESSAGE_FREE_IMCONTEXT;
511
if (scim_bridge_messenger_write_output (except, messenger_id, &code, sizeof (code)))
514
if (scim_bridge_messenger_write_output (except, messenger_id, &opponent_id, sizeof (opponent_id)))
517
if (scim_bridge_messenger_close_output (except, messenger_id))
524
int scim_bridge_client_call_reset_imcontext (ScimBridgeException *except, ScimBridgeIMContextID opponent_id)
526
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Sending 'reset imcontext' message...");
528
if (scim_bridge_messenger_open_output (except, messenger_id))
531
const ScimBridgeMessageCode code = SCIM_BRIDGE_MESSAGE_RESET_IMCONTEXT;
532
if (scim_bridge_messenger_write_output (except, messenger_id, &code, sizeof (code)))
535
if (scim_bridge_messenger_write_output (except, messenger_id, &opponent_id, sizeof (opponent_id)))
538
if (scim_bridge_messenger_close_output (except, messenger_id))
545
int scim_bridge_client_call_cursor_location_changed (ScimBridgeException *except, ScimBridgeIMContextID opponent_id, int cursor_x, int cursor_y)
547
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Sending 'cursor location changed' message");
549
if (scim_bridge_messenger_open_output (except, messenger_id))
552
const ScimBridgeMessageCode code = SCIM_BRIDGE_MESSAGE_CURSOR_LOCATION_CHANGED;
553
if (scim_bridge_messenger_write_output (except, messenger_id, &code, sizeof (code)))
556
if (scim_bridge_messenger_write_output (except, messenger_id, &opponent_id, sizeof (opponent_id)))
559
if (scim_bridge_messenger_write_output (except, messenger_id, &cursor_x, sizeof (cursor_x)))
562
if (scim_bridge_messenger_write_output (except, messenger_id, &cursor_y, sizeof (cursor_y)))
565
if (scim_bridge_messenger_close_output (except, messenger_id))
572
int scim_bridge_client_call_focus_changed (ScimBridgeException *except, ScimBridgeIMContextID opponent_id, int focus_in)
574
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Sending 'focus changed' message...");
576
if (scim_bridge_messenger_open_output (except, messenger_id))
579
const ScimBridgeMessageCode code = SCIM_BRIDGE_MESSAGE_FOCUS_CHANGED;
580
if (scim_bridge_messenger_write_output (except, messenger_id, &code, sizeof (code)))
583
if (scim_bridge_messenger_write_output (except, messenger_id, &opponent_id, sizeof (opponent_id)))
586
if (scim_bridge_messenger_write_output (except, messenger_id, &focus_in, sizeof (focus_in)))
589
if (scim_bridge_messenger_close_output (except, messenger_id))
596
int scim_bridge_client_call_keyevent_occured (ScimBridgeException *except, ScimBridgeIMContextID opponent_id, const ScimBridgeKeyEvent *keyevent, int *consumed)
598
scim_bridge_pdebugln (SCIM_BRIDGE_DEBUG_CLIENT | SCIM_BRIDGE_DEBUG_MESSENGER, 3, "Sending 'keyevent occured' message...");
600
if (scim_bridge_messenger_open_output (except, messenger_id))
603
const ScimBridgeMessageCode code = SCIM_BRIDGE_MESSAGE_KEYEVENT_OCCURED;
604
if (scim_bridge_messenger_write_output (except, messenger_id, &code, sizeof (code)))
607
if (scim_bridge_messenger_write_output (except, messenger_id, &opponent_id, sizeof (opponent_id)))
610
if (scim_bridge_messenger_write_output (except, messenger_id, keyevent, sizeof (ScimBridgeKeyEvent)))
613
if (scim_bridge_messenger_read_output (except, messenger_id, consumed, sizeof (*consumed)))
616
if (scim_bridge_messenger_close_output (except, messenger_id))