2 * Copyright (c) 2012 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
28 #include <Ecore_IMF.h>
31 #include "websocket.h"
36 #include <libwebsockets.h>
38 pthread_t g_ws_server_thread = (pthread_t)NULL;
39 pthread_mutex_t g_ws_server_mutex = PTHREAD_MUTEX_INITIALIZER;
41 pthread_cond_t g_ws_query_condition = PTHREAD_COND_INITIALIZER;
42 pthread_mutex_t g_ws_query_mutex = PTHREAD_MUTEX_INITIALIZER;
44 bool g_ws_server_exit = false;
45 struct lws_context *g_ws_server_context = NULL;
47 CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::m_current_instance = NULL;
61 struct per_session_data__http {
65 static int callback_http(struct lws *wsi,
66 enum lws_callback_reasons reason,
67 void *user, void *in, size_t len)
72 struct per_session_data__keyboard {
77 static int callback_keyboard(struct lws *wsi,
78 enum lws_callback_reasons reason,
79 void *user, void *in, size_t len);
81 static struct lws_protocols protocols[] = {
85 sizeof(struct per_session_data__http),
91 sizeof(struct per_session_data__keyboard),
97 static int callback_keyboard(struct lws *wsi,
98 enum lws_callback_reasons reason,
99 void *user, void *in, size_t len)
101 static int last_session_id = 0;
102 const int bufsize = 512;
104 unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + bufsize +
105 LWS_SEND_BUFFER_POST_PADDING];
106 unsigned char *p = &buf[LWS_SEND_BUFFER_PRE_PADDING];
107 struct per_session_data__keyboard *pss = (struct per_session_data__keyboard *)user;
108 CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance();
112 case LWS_CALLBACK_ESTABLISHED:
113 pss->session_id = ++last_session_id;
114 LOGD("LWS_CALLBACK_ESTABLISHED : %p %d", g_ws_server_context, pss->session_id);
116 if (g_ws_server_context) {
117 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
121 case LWS_CALLBACK_CLOSED:
122 LOGD("LWS_CALLBACK_CLOSED : %d", pss->session_id);
125 case LWS_CALLBACK_SERVER_WRITEABLE:
127 /* We allow data tranmission only if this client is guaranteed to be valid */
129 pthread_mutex_lock(&g_ws_server_mutex);
130 std::queue<ISE_MESSAGE>& messages = agent->get_send_message_queue();
131 while (messages.size() > 0) {
132 ISE_MESSAGE &message = messages.front();
133 std::string str = CISEMessageSerializer::serialize(message);
134 LOGD("SEND_WEBSOCKET_MESSAGE : %s", str.c_str());
135 n = snprintf((char *)p, bufsize, "%s", str.c_str());
136 /* too small for partial */
137 n = lws_write(wsi, p, n, LWS_WRITE_TEXT);
140 pthread_mutex_unlock(&g_ws_server_mutex);
143 lwsl_err("ERROR %d writing to di socket\n", n);
147 LOGD("Rejecting data transmission since client is not valid");
152 case LWS_CALLBACK_RECEIVE:
154 std::string str = (const char *)in;
155 ISE_MESSAGE message = CISEMessageSerializer::deserialize(str);
157 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOGIN]) == 0) {
159 if (message.values.at(0).compare(CMagicKeyManager::get_magic_key()) == 0) {
160 LOGD("LOGIN successful, validating client");
163 LOGD("LOGIN failed, invalidating client");
171 pthread_mutex_lock(&g_ws_server_mutex);
172 std::queue<ISE_MESSAGE>& messages = agent->get_recv_message_queue();
173 messages.push(message);
174 pthread_mutex_unlock(&g_ws_server_mutex);
176 const char *recved_message = "recved";
177 ecore_pipe_write(agent->get_recv_message_pipe(), recved_message, strlen(recved_message));
179 /* If we received reply message, let's send signal to wake up our main thread */
180 if (message.type.compare(ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]) == 0) {
181 pthread_mutex_lock(&g_ws_query_mutex);
182 pthread_cond_signal(&g_ws_query_condition);
183 pthread_mutex_unlock(&g_ws_query_mutex);
186 LOGD("Ignoring data received since client is not valid");
198 void *process_ws_server(void *data)
200 while (!force_exit && !g_ws_server_exit) {
202 gettimeofday(&tv, NULL);
204 if (g_ws_server_context) {
205 lws_service(g_ws_server_context, 50);
207 LOGD("WARNING : g_ws_server_context is NULL");
213 void log_func(int level, const char *line)
216 LOGD("LEVEL : %d , %s", level, line);
220 CWebHelperAgentWebSocket::CWebHelperAgentWebSocket()
222 if (m_current_instance != NULL) {
223 LOGD("WARNING : m_current_instance is NOT NULL");
225 m_current_instance = this;
226 m_recv_message_pipe = NULL;
229 CWebHelperAgentWebSocket::~CWebHelperAgentWebSocket()
231 if (m_current_instance == this) {
232 m_current_instance = NULL;
235 if (m_recv_message_pipe) {
236 ecore_pipe_del(m_recv_message_pipe);
237 m_recv_message_pipe = NULL;
241 static void recv_message_pipe_handler(void *data, void *buffer, unsigned int nbyte)
243 CWebHelperAgentWebSocket *agent = CWebHelperAgentWebSocket::get_current_instance();
245 agent->process_recved_messages();
249 bool CWebHelperAgentWebSocket::init()
253 struct lws_context_creation_info info;
255 memset(&info, 0, sizeof info);
258 int debug_level = LLL_DEBUG;
259 lws_set_log_level(debug_level, log_func);
262 info.protocols = protocols;
263 info.extensions = NULL;
264 info.ssl_cert_filepath = NULL;
265 info.ssl_private_key_filepath = NULL;
272 /* The WebSocket server is running on a separate thread, and let the thread send a message
273 through this pipe to guarantee thread safety */
274 m_recv_message_pipe = ecore_pipe_add(recv_message_pipe_handler, NULL);
276 /* Let's retry creating server context for a certain number of times */
277 const int max_retry_num = 10;
281 g_ws_server_context = lws_create_context(&info);
282 LOGD("libwebsocket context : %p", g_ws_server_context);
284 } while (g_ws_server_context == NULL && retry_num++ < max_retry_num);
286 pthread_mutex_init(&g_ws_server_mutex, NULL);
288 pthread_mutex_init(&g_ws_query_mutex, NULL);
289 pthread_cond_init(&g_ws_query_condition, NULL);
291 if (g_ws_server_context) {
292 if (pthread_create(&g_ws_server_thread, NULL, &process_ws_server, NULL) != 0) {
293 g_ws_server_thread = (pthread_t)NULL;
305 bool CWebHelperAgentWebSocket::exit()
309 g_ws_server_exit = true;
311 if (m_recv_message_pipe) {
312 ecore_pipe_del(m_recv_message_pipe);
313 m_recv_message_pipe = NULL;
316 if (g_ws_server_thread) {
317 pthread_join(g_ws_server_thread, NULL);
320 pthread_cond_destroy(&g_ws_query_condition);
321 pthread_mutex_destroy(&g_ws_query_mutex);
323 pthread_mutex_destroy(&g_ws_server_mutex);
325 if (g_ws_server_context) {
326 lws_context_destroy(g_ws_server_context);
327 g_ws_server_context = NULL;
335 void CWebHelperAgentWebSocket::signal(int sig)
341 std::string to_string(T i)
343 std::stringstream ss;
351 void CWebHelperAgentWebSocket::on_init()
354 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
355 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_INIT];
357 pthread_mutex_lock(&g_ws_server_mutex);
358 m_send_message_queue.push(message);
359 pthread_mutex_unlock(&g_ws_server_mutex);
361 if (g_ws_server_context) {
362 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
364 LOGD("WARNING : g_ws_server_context is NULL");
368 void CWebHelperAgentWebSocket::on_exit()
371 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
372 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_EXIT];
374 pthread_mutex_lock(&g_ws_server_mutex);
375 m_send_message_queue.push(message);
376 pthread_mutex_unlock(&g_ws_server_mutex);
378 if (g_ws_server_context) {
379 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
381 LOGD("WARNING : g_ws_server_context is NULL");
385 void CWebHelperAgentWebSocket::on_focus_in(int ic)
388 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
389 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_FOCUS_IN];
390 message.values.push_back(to_string(ic));
392 pthread_mutex_lock(&g_ws_server_mutex);
393 m_send_message_queue.push(message);
394 pthread_mutex_unlock(&g_ws_server_mutex);
396 if (g_ws_server_context) {
397 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
399 LOGD("WARNING : g_ws_server_context is NULL");
403 void CWebHelperAgentWebSocket::on_focus_out(int ic)
406 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
407 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_FOCUS_OUT];
408 message.values.push_back(to_string(ic));
410 pthread_mutex_lock(&g_ws_server_mutex);
411 m_send_message_queue.push(message);
412 pthread_mutex_unlock(&g_ws_server_mutex);
414 if (g_ws_server_context) {
415 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
417 LOGD("WARNING : g_ws_server_context is NULL");
421 void CWebHelperAgentWebSocket::on_show(int ic)
424 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
425 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SHOW];
426 message.values.push_back(to_string(ic));
428 pthread_mutex_lock(&g_ws_server_mutex);
429 m_send_message_queue.push(message);
430 pthread_mutex_unlock(&g_ws_server_mutex);
432 if (g_ws_server_context) {
433 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
435 LOGD("WARNING : g_ws_server_context is NULL");
438 LOGD("put into send message buffer");
441 void CWebHelperAgentWebSocket::on_hide(int ic)
444 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
445 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_HIDE];
446 message.values.push_back(to_string(ic));
448 pthread_mutex_lock(&g_ws_server_mutex);
449 m_send_message_queue.push(message);
450 pthread_mutex_unlock(&g_ws_server_mutex);
452 if (g_ws_server_context) {
453 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
455 LOGD("WARNING : g_ws_server_context is NULL");
459 void CWebHelperAgentWebSocket::on_set_rotation(int degree)
462 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
463 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_ROTATION];
464 message.values.push_back(to_string(degree));
466 pthread_mutex_lock(&g_ws_server_mutex);
467 m_send_message_queue.push(message);
468 pthread_mutex_unlock(&g_ws_server_mutex);
470 if (g_ws_server_context) {
471 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
473 LOGD("WARNING : g_ws_server_context is NULL");
477 void CWebHelperAgentWebSocket::on_update_cursor_position(int ic, int cursor_pos)
480 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
481 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_CURSOR_POSITION];
482 message.values.push_back(to_string(ic));
483 message.values.push_back(to_string(cursor_pos));
485 pthread_mutex_lock(&g_ws_server_mutex);
486 m_send_message_queue.push(message);
487 pthread_mutex_unlock(&g_ws_server_mutex);
489 if (g_ws_server_context) {
490 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
492 LOGD("WARNING : g_ws_server_context is NULL");
496 void CWebHelperAgentWebSocket::on_update_surrounding_text(int ic, const char *text, int cursor)
499 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY];
500 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_SURROUNDING_TEXT];
501 message.values.push_back(to_string(cursor));
502 message.values.push_back(text);
504 pthread_mutex_lock(&g_ws_server_mutex);
505 m_send_message_queue.push(message);
506 pthread_mutex_unlock(&g_ws_server_mutex);
508 if (g_ws_server_context) {
509 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
511 LOGD("WARNING : g_ws_server_context is NULL");
515 void CWebHelperAgentWebSocket::on_update_selection(int ic, const char *text)
518 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY];
519 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_SELECTION];
520 message.values.push_back(text);
522 pthread_mutex_lock(&g_ws_server_mutex);
523 m_send_message_queue.push(message);
524 pthread_mutex_unlock(&g_ws_server_mutex);
526 if (g_ws_server_context) {
527 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
529 LOGD("WARNING : g_ws_server_context is NULL");
533 void CWebHelperAgentWebSocket::on_set_language(unsigned int language)
536 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
537 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_LANGUAGE];
540 for (unsigned int loop = 0;loop < sizeof(ISE_LANGUAGE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
541 if (language == (unsigned int)ISE_LANGUAGE_TYPES[loop].type_value) {
542 message.values.push_back(ISE_LANGUAGE_TYPES[loop].type_string);
548 pthread_mutex_lock(&g_ws_server_mutex);
549 m_send_message_queue.push(message);
550 pthread_mutex_unlock(&g_ws_server_mutex);
552 if (g_ws_server_context) {
553 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
555 LOGD("WARNING : g_ws_server_context is NULL");
560 void CWebHelperAgentWebSocket::on_set_imdata(char *buf, unsigned int len)
563 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
564 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_IMDATA];
565 message.values.push_back(buf);
567 pthread_mutex_lock(&g_ws_server_mutex);
568 m_send_message_queue.push(message);
569 pthread_mutex_unlock(&g_ws_server_mutex);
571 if (g_ws_server_context) {
572 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
574 LOGD("WARNING : g_ws_server_context is NULL");
578 void CWebHelperAgentWebSocket::on_get_imdata(char **buf, unsigned int *len)
581 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
582 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_IMDATA];
584 pthread_mutex_lock(&g_ws_server_mutex);
585 m_send_message_queue.push(message);
586 pthread_mutex_unlock(&g_ws_server_mutex);
588 if (g_ws_server_context) {
589 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
591 LOGD("WARNING : g_ws_server_context is NULL");
594 wait_for_reply_message();
596 std::vector<std::string> values;
597 /* Check if we received reply for GET_IMDATA message */
598 if (process_recved_messages_until_reply_found(
599 ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_IMDATA], values)) {
600 if (values.size() > 0 && buf && len) {
601 int string_length = values.at(0).length();
602 (*buf) = new char[string_length + 1];
604 strncpy(*buf, values.at(0).c_str(), string_length);
605 /* Make sure this is a null-terminated string */
606 *(*buf + string_length) = '\0';
607 *len = string_length;
611 LOGD("process_recved_messages_until_reply_found returned FALSE");
613 /* Now process the rest in the recv buffer */
614 process_recved_messages();
617 void CWebHelperAgentWebSocket::on_set_return_key_type(unsigned int type)
620 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
621 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_RETURN_KEY_TYPE];
624 for (unsigned int loop = 0;loop < sizeof(ISE_RETURN_KEY_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
625 if (type == (unsigned int)ISE_RETURN_KEY_TYPES[loop].type_value) {
626 message.values.push_back(ISE_RETURN_KEY_TYPES[loop].type_string);
632 pthread_mutex_lock(&g_ws_server_mutex);
633 m_send_message_queue.push(message);
634 pthread_mutex_unlock(&g_ws_server_mutex);
636 if (g_ws_server_context) {
637 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
639 LOGD("WARNING : g_ws_server_context is NULL");
644 void CWebHelperAgentWebSocket::on_get_return_key_type(unsigned int *type)
647 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
648 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE];
650 pthread_mutex_lock(&g_ws_server_mutex);
651 m_send_message_queue.push(message);
652 pthread_mutex_unlock(&g_ws_server_mutex);
654 if (g_ws_server_context) {
655 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
657 LOGD("WARNING : g_ws_server_context is NULL");
660 wait_for_reply_message();
662 /* Since we are accessing recved buffer, lock the server mutex again */
663 pthread_mutex_lock(&g_ws_server_mutex);
664 std::vector<std::string> values;
665 /* Check if we received reply for GET_RETURN_KEY_TYPE message */
666 if (process_recved_messages_until_reply_found(
667 ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_TYPE], values)) {
669 for (unsigned int loop = 0;loop < sizeof(ISE_RETURN_KEY_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
670 if (values.at(0).compare(ISE_RETURN_KEY_TYPES[loop].type_string) == 0) {
671 *type = ISE_RETURN_KEY_TYPES[loop].type_value;
676 /* Now process the rest in the recv buffer */
677 process_recved_messages();
678 pthread_mutex_unlock(&g_ws_server_mutex);
681 void CWebHelperAgentWebSocket::on_set_return_key_disable(unsigned int disabled)
684 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
685 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_RETURN_KEY_DISABLE];
688 for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
689 if (disabled == (unsigned int)ISE_TRUEFALSE_TYPES[loop].type_value) {
690 message.values.push_back(ISE_TRUEFALSE_TYPES[loop].type_string);
696 pthread_mutex_lock(&g_ws_server_mutex);
697 m_send_message_queue.push(message);
698 pthread_mutex_unlock(&g_ws_server_mutex);
700 if (g_ws_server_context) {
701 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
703 LOGD("WARNING : g_ws_server_context is NULL");
708 void CWebHelperAgentWebSocket::on_get_return_key_disable(unsigned int *disabled)
711 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
712 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE];
714 pthread_mutex_lock(&g_ws_server_mutex);
715 m_send_message_queue.push(message);
716 pthread_mutex_unlock(&g_ws_server_mutex);
718 if (g_ws_server_context) {
719 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
721 LOGD("WARNING : g_ws_server_context is NULL");
724 wait_for_reply_message();
726 /* Since we are accessing recved buffer, lock the server mutex again */
727 pthread_mutex_lock(&g_ws_server_mutex);
728 std::vector<std::string> values;
729 /* Check if we received reply for GET_RETURN_KEY_DISABLE message */
730 if (process_recved_messages_until_reply_found(
731 ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_RETURN_KEY_DISABLE], values)) {
733 for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
734 if (values.at(0).compare(ISE_TRUEFALSE_TYPES[loop].type_string) == 0) {
735 *disabled = ISE_TRUEFALSE_TYPES[loop].type_value;
740 /* Now process the rest in the recv buffer */
741 process_recved_messages();
742 pthread_mutex_unlock(&g_ws_server_mutex);
745 void CWebHelperAgentWebSocket::on_set_layout(unsigned int layout)
748 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
749 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_LAYOUT];
752 for (unsigned int loop = 0;loop < sizeof(ISE_LAYOUT_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
753 if (layout == (unsigned int)ISE_LAYOUT_TYPES[loop].type_value) {
754 message.values.push_back(ISE_LAYOUT_TYPES[loop].type_string);
760 pthread_mutex_lock(&g_ws_server_mutex);
761 m_send_message_queue.push(message);
762 pthread_mutex_unlock(&g_ws_server_mutex);
764 if (g_ws_server_context) {
765 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
767 LOGD("WARNING : g_ws_server_context is NULL");
772 void CWebHelperAgentWebSocket::on_get_layout(unsigned int *layout)
775 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
776 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_LAYOUT];
778 pthread_mutex_lock(&g_ws_server_mutex);
779 m_send_message_queue.push(message);
780 pthread_mutex_unlock(&g_ws_server_mutex);
782 if (g_ws_server_context) {
783 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
785 LOGD("WARNING : g_ws_server_context is NULL");
788 wait_for_reply_message();
790 /* Since we are accessing recved buffer, lock the server mutex again */
791 pthread_mutex_lock(&g_ws_server_mutex);
792 std::vector<std::string> values;
793 /* Check if we received reply for GET_LAYOUT message */
794 if (process_recved_messages_until_reply_found(
795 ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_LAYOUT], values)) {
797 for (unsigned int loop = 0;loop < sizeof(ISE_LAYOUT_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
798 if (values.at(0).compare(ISE_LAYOUT_TYPES[loop].type_string) == 0) {
799 *layout = ISE_LAYOUT_TYPES[loop].type_value;
804 /* Now process the rest in the recv buffer */
805 process_recved_messages();
806 pthread_mutex_unlock(&g_ws_server_mutex);
809 void CWebHelperAgentWebSocket::on_reset_input_context(int ic)
812 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_PLAIN];
813 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_RESET_INPUT_CONTEXT];
814 message.values.push_back(to_string(ic));
816 pthread_mutex_lock(&g_ws_server_mutex);
817 m_send_message_queue.push(message);
818 pthread_mutex_unlock(&g_ws_server_mutex);
820 if (g_ws_server_context) {
821 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
823 LOGD("WARNING : g_ws_server_context is NULL");
827 void CWebHelperAgentWebSocket::on_process_key_event(unsigned int code, unsigned int mask, unsigned int layout, unsigned int *ret)
830 message.type = ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_QUERY];
831 message.command = ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT];
832 message.values.push_back(to_string(code));
833 message.values.push_back(to_string(mask));
834 message.values.push_back(to_string(layout));
836 pthread_mutex_lock(&g_ws_server_mutex);
837 m_send_message_queue.push(message);
838 pthread_mutex_unlock(&g_ws_server_mutex);
840 if (g_ws_server_context) {
841 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
843 LOGD("WARNING : g_ws_server_context is NULL");
846 wait_for_reply_message();
848 /* Since we are accessing recved buffer, lock the server mutex again */
849 pthread_mutex_lock(&g_ws_server_mutex);
850 std::vector<std::string> values;
851 /* Check if we received reply for PROCESS_KEY_EVENT message */
852 if (process_recved_messages_until_reply_found(
853 ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_PROCESS_KEY_EVENT], values)) {
855 for (unsigned int loop = 0;loop < sizeof(ISE_TRUEFALSE_TYPES) / sizeof(ISE_TYPE_VALUE_STRING);loop++) {
856 if (values.at(0).compare(ISE_TRUEFALSE_TYPES[loop].type_string) == 0) {
857 *ret = ISE_TRUEFALSE_TYPES[loop].type_value;
862 /* Now process the rest in the recv buffer */
863 process_recved_messages();
864 pthread_mutex_unlock(&g_ws_server_mutex);
867 CWebHelperAgentWebSocket* CWebHelperAgentWebSocket::get_current_instance()
869 return m_current_instance;
872 std::queue<ISE_MESSAGE>& CWebHelperAgentWebSocket::get_send_message_queue()
874 return m_send_message_queue;
877 std::queue<ISE_MESSAGE>& CWebHelperAgentWebSocket::get_recv_message_queue()
879 return m_recv_message_queue;
882 Ecore_Pipe* CWebHelperAgentWebSocket::get_recv_message_pipe()
884 return m_recv_message_pipe;
887 void CWebHelperAgentWebSocket::wait_for_reply_message()
889 /* Let's wait for at most REPLY_TIMEOUT */
891 struct timespec timeout;
892 gettimeofday(&now, NULL);
893 timeout.tv_sec = now.tv_sec + REPLY_TIMEOUT.tv_sec;
894 timeout.tv_nsec = (now.tv_usec + REPLY_TIMEOUT.tv_usec) * 1000;
895 pthread_mutex_lock(&g_ws_query_mutex);
896 pthread_cond_timedwait(&g_ws_query_condition, &g_ws_query_mutex, &timeout);
897 pthread_mutex_unlock(&g_ws_query_mutex);
901 void CWebHelperAgentWebSocket::process_recved_messages()
903 pthread_mutex_lock(&g_ws_server_mutex);
905 while (m_recv_message_queue.size() > 0) {
906 ISE_MESSAGE &message = m_recv_message_queue.front();
908 handle_recved_message(message);
910 m_recv_message_queue.pop();
913 pthread_mutex_unlock(&g_ws_server_mutex);
916 bool CWebHelperAgentWebSocket::process_recved_messages_until_reply_found(std::string command, std::vector<std::string> &values)
920 pthread_mutex_lock(&g_ws_server_mutex);
922 while (ret == false && m_recv_message_queue.size() > 0) {
923 ISE_MESSAGE &message = m_recv_message_queue.front();
925 if (message.command.compare(command) == 0 &&
926 message.type.compare(ISE_MESSAGE_TYPE_STRINGS[ISE_MESSAGE_TYPE_REPLY]) == 0) {
928 values = message.values;
930 handle_recved_message(message);
932 m_recv_message_queue.pop();
935 pthread_mutex_unlock(&g_ws_server_mutex);
940 void CWebHelperAgentWebSocket::handle_recved_message(ISE_MESSAGE &message)
942 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOG]) == 0) {
943 std::string str = "";
944 for (unsigned int loop = 0;loop < message.values.size();loop++) {
945 str += message.values.at(loop).c_str();
946 if (loop < message.values.size() - 1) {
952 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_COMMIT_STRING]) == 0) {
953 send_key_event(0xff6b, 0); // Temporarily reset keyboard engine
955 std::string str = "";
956 for (unsigned int loop = 0;loop < message.values.size();loop++) {
957 str += message.values.at(loop).c_str();
958 if (loop < message.values.size() - 1) {
962 commit_string(str.c_str());
964 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_UPDATE_PREEDIT_STRING]) == 0) {
965 std::string str = "";
966 for (unsigned int loop = 0;loop < message.values.size();loop++) {
967 str += message.values.at(loop).c_str();
968 if (loop < message.values.size() - 1) {
972 update_preedit_string(str.c_str());
974 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SEND_KEY_EVENT]) == 0) {
975 if (message.values.size() == 1) {
976 send_key_event(atoi(message.values.at(0).c_str()), 0);
979 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES]) == 0) {
980 LOGD("ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES");
981 if (message.values.size() == 4) {
982 LOGD("ISE_MESSAGE_COMMAND_SET_KEYBOARD_SIZES : %d %d %d %d",
983 atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()),
984 atoi(message.values.at(2).c_str()), atoi(message.values.at(3).c_str()));
986 atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()),
987 atoi(message.values.at(2).c_str()), atoi(message.values.at(3).c_str()));
990 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_SET_SELECTION]) == 0) {
991 LOGD("ISE_MESSAGE_COMMAND_SET_SELECTION");
992 if (message.values.size() == 2) {
993 LOGD("ISE_MESSAGE_COMMAND_SET_SELECTION : %d %d",
994 atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
996 atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
999 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_SELECTION]) == 0) {
1000 if (message.values.size() == 0) {
1004 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT]) == 0) {
1005 LOGD("ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT");
1006 if (message.values.size() == 2) {
1007 LOGD("ISE_MESSAGE_COMMAND_GET_SURROUNDING_TEXT : %d %d",
1008 atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
1009 get_surrounding_text(
1010 atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
1013 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT]) == 0) {
1014 LOGD("ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT");
1015 if (message.values.size() == 2) {
1016 LOGD("ISE_MESSAGE_COMMAND_DELETE_SURROUNDING_TEXT : %d %d",
1017 atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
1018 delete_surrounding_text(
1019 atoi(message.values.at(0).c_str()), atoi(message.values.at(1).c_str()));
1022 if (message.command.compare(ISE_MESSAGE_COMMAND_STRINGS[ISE_MESSAGE_COMMAND_LOGIN]) == 0) {
1023 if (g_ws_server_context) {
1024 lws_callback_on_writable_all_protocol(g_ws_server_context, &protocols[PROTOCOL_KEYBOARD]);
1026 LOGD("WARNING : g_ws_server_context is NULL");