Exemplo n.º 1
0
static gboolean
on_new_connection (GSocketService    *service,
                   GSocketConnection *socket_connection,
                   GObject           *source_object,
                   DasomServer       *server)
{
  g_debug (G_STRLOC ": %s", G_STRFUNC);

  /* TODO: simple authentication using GCredentials */

  GSocket *socket = g_socket_connection_get_socket (socket_connection);

  DasomMessage *message;
  message = dasom_recv_message (socket);

  if (message->header->type == DASOM_MESSAGE_CONNECT)
    dasom_send_message (socket, DASOM_MESSAGE_CONNECT_REPLY, NULL, 0, NULL);
  else
  {
    /* TODO: error handling */
    dasom_send_message (socket, DASOM_MESSAGE_ERROR, NULL, 0, NULL);
    return TRUE; /* TODO: what happened if return value is FALSE */
  }

  DasomConnection *connection;
  connection = dasom_connection_new (*(DasomConnectionType *) message->data,
                                     dasom_server_get_default_engine (server), NULL);
  dasom_message_unref (message);
  connection->socket = socket;
  dasom_server_add_connection (server, connection);

  if (connection->type == DASOM_CONNECTION_DASOM_AGENT)
    server->agents_list = g_list_prepend (server->agents_list, connection);

  connection->source = g_socket_create_source (socket, G_IO_IN, NULL);
  connection->socket_connection = g_object_ref (socket_connection);
  g_source_set_can_recurse (connection->source, TRUE);
  g_source_set_callback (connection->source,
                         (GSourceFunc) on_incoming_message_dasom,
                         connection, NULL);
  g_source_attach (connection->source, server->main_context);

  return TRUE;
}
Exemplo n.º 2
0
static void
dasom_connection_finalize (GObject *object)
{
  g_debug (G_STRLOC ": %s", G_STRFUNC);

  DasomConnection *connection = DASOM_CONNECTION (object);
  dasom_message_unref (connection->reply);

  if (connection->source)
  {
    g_source_destroy (connection->source);
    g_source_unref   (connection->source);
  }

  if (connection->socket_connection)
    g_object_unref (connection->socket_connection);

  G_OBJECT_CLASS (dasom_connection_parent_class)->finalize (object);
}
Exemplo n.º 3
0
static gboolean
on_incoming_message (GSocket      *socket,
                     GIOCondition  condition,
                     gpointer      user_data)
{
  g_debug (G_STRLOC ": %s: socket fd:%d", G_STRFUNC, g_socket_get_fd (socket));

  DasomIM *im = DASOM_IM (user_data);
  dasom_message_unref (im->result->reply);
  im->result->is_dispatched = TRUE;

  if (condition & (G_IO_HUP | G_IO_ERR))
  {
    /* Because two GSource is created over one socket,
     * when G_IO_HUP | G_IO_ERR, callback can run two times.
     * the following code avoid that callback runs two times. */
    GSource *source = g_main_current_source ();

    if (source == im->default_context_source)
      g_source_destroy (im->sockets_context_source);
    else if (source == im->sockets_context_source)
      g_source_destroy (im->default_context_source);

    if (!g_socket_is_closed (socket))
      g_socket_close (socket, NULL);

    im->result->reply    = NULL;

    g_critical (G_STRLOC ": %s: G_IO_HUP | G_IO_ERR", G_STRFUNC);

    return G_SOURCE_REMOVE;
  }

  DasomMessage *message;
  message = dasom_recv_message (socket);
  im->result->reply = message;
  gboolean retval;

  if (G_UNLIKELY (message == NULL))
  {
    g_critical (G_STRLOC ": NULL message");
    return G_SOURCE_CONTINUE;
  }

  switch (message->header->type)
  {
    /* reply */
    case DASOM_MESSAGE_FILTER_EVENT_REPLY:
    case DASOM_MESSAGE_RESET_REPLY:
    case DASOM_MESSAGE_FOCUS_IN_REPLY:
    case DASOM_MESSAGE_FOCUS_OUT_REPLY:
    case DASOM_MESSAGE_SET_SURROUNDING_REPLY:
    case DASOM_MESSAGE_GET_SURROUNDING_REPLY:
    case DASOM_MESSAGE_SET_CURSOR_LOCATION_REPLY:
    case DASOM_MESSAGE_SET_USE_PREEDIT_REPLY:
      break;
    /* signals */
    case DASOM_MESSAGE_PREEDIT_START:
      g_signal_emit_by_name (im, "preedit-start");
      dasom_send_message (socket, DASOM_MESSAGE_PREEDIT_START_REPLY, NULL, 0, NULL);
      break;
    case DASOM_MESSAGE_PREEDIT_END:
      g_signal_emit_by_name (im, "preedit-end");
      dasom_send_message (socket, DASOM_MESSAGE_PREEDIT_END_REPLY, NULL, 0, NULL);
      break;
    case DASOM_MESSAGE_PREEDIT_CHANGED:
      g_free (im->preedit_string);
      im->preedit_string = g_strndup (message->data,
                                      message->header->data_len - 1 - sizeof (gint));
      im->cursor_pos = *(gint *) (message->data +
                                  message->header->data_len - sizeof (gint));
      g_signal_emit_by_name (im, "preedit-changed");
      dasom_send_message (socket,
                          DASOM_MESSAGE_PREEDIT_CHANGED_REPLY,
                          NULL, 0, NULL);
      break;
    case DASOM_MESSAGE_COMMIT:
      dasom_message_ref (message);
      g_signal_emit_by_name (im, "commit", (const gchar *) message->data);
      dasom_message_unref (message);
      dasom_send_message (socket, DASOM_MESSAGE_COMMIT_REPLY, NULL, 0, NULL);
      break;
    case DASOM_MESSAGE_RETRIEVE_SURROUNDING:
      g_signal_emit_by_name (im, "retrieve-surrounding", &retval);
      dasom_send_message (socket, DASOM_MESSAGE_RETRIEVE_SURROUNDING_REPLY,
                          &retval, sizeof (gboolean), NULL);
      break;
    case DASOM_MESSAGE_DELETE_SURROUNDING:
      dasom_message_ref (message);
      g_signal_emit_by_name (im, "delete-surrounding",
                             ((gint *) message->data)[0],
                             ((gint *) message->data)[1], &retval);
      dasom_message_unref (message);
      dasom_send_message (socket, DASOM_MESSAGE_DELETE_SURROUNDING_REPLY,
                          &retval, sizeof (gboolean), NULL);
      break;
    default:
      g_warning (G_STRLOC ": %s: Unknown message type: %d", G_STRFUNC, message->header->type);
      break;
  }

  return G_SOURCE_CONTINUE;
}
Exemplo n.º 4
0
static void
dasom_im_init (DasomIM *im)
{
  g_debug (G_STRLOC ": %s", G_STRFUNC);

  GSocketClient  *client;
  GSocketAddress *address;
  GSocket        *socket;
  GError         *error = NULL;

  address = g_unix_socket_address_new_with_type (DASOM_ADDRESS, -1,
                                                 G_UNIX_SOCKET_ADDRESS_ABSTRACT);
  client = g_socket_client_new ();
  im->connection = g_socket_client_connect (client,
                                            G_SOCKET_CONNECTABLE (address),
                                            NULL, &error);
  g_object_unref (address);
  g_object_unref (client);

  if (im->connection == NULL)
  {
    g_critical (G_STRLOC ": %s: %s", G_STRFUNC, error->message);
    g_clear_error (&error);
    return;
  }

  socket = g_socket_connection_get_socket (im->connection);

  if (!socket)
  {
    g_critical (G_STRLOC ": %s: %s", G_STRFUNC, "Can't get socket");
    return;
  }

  DasomMessage *message;

  DasomConnectionType type = DASOM_CONNECTION_DASOM_IM;

  dasom_send_message (socket, DASOM_MESSAGE_CONNECT, &type, sizeof (DasomConnectionType), NULL);
  g_socket_condition_wait (socket, G_IO_IN, NULL, NULL);
  message = dasom_recv_message (socket);

  if (G_UNLIKELY (message == NULL ||
                  message->header->type != DASOM_MESSAGE_CONNECT_REPLY))
  {
    dasom_message_unref (message);
    g_error ("Couldn't connect to dasom daemon");
  }

  dasom_message_unref (message);

  im->result = g_slice_new0 (DasomResult);
  im->preedit_string = g_strdup ("");

  GMutex mutex;

  g_mutex_init (&mutex);
  g_mutex_lock (&mutex);

  if (G_UNLIKELY (dasom_im_sockets_context == NULL))
  {
    dasom_im_sockets_context = g_main_context_new ();
    dasom_im_sockets_context_ref_count++;
  }
  else
  {
    dasom_im_sockets_context = g_main_context_ref (dasom_im_sockets_context);
    dasom_im_sockets_context_ref_count++;
  }

  g_mutex_unlock (&mutex);

  /* when g_main_context_iteration(), iterate only sockets */
  im->sockets_context_source = g_socket_create_source (socket, G_IO_IN, NULL);
  g_source_set_can_recurse (im->sockets_context_source, TRUE);
  g_source_attach (im->sockets_context_source, dasom_im_sockets_context);
  g_source_set_callback (im->sockets_context_source,
                         (GSourceFunc) on_incoming_message,
                         im, NULL);

  im->default_context_source = g_socket_create_source (socket, G_IO_IN, NULL);
  g_source_set_can_recurse (im->default_context_source, TRUE);
  g_source_set_callback (im->default_context_source,
                         (GSourceFunc) on_incoming_message, im, NULL);
  g_source_attach (im->default_context_source, NULL);
}
Exemplo n.º 5
0
DasomMessage *dasom_recv_message (GSocket *socket)
{
  g_debug (G_STRLOC ": %s", G_STRFUNC);

  DasomMessage *message = dasom_message_new ();
  GError *error = NULL;
  gssize n_read = 0;

  n_read = g_socket_receive (socket,
                             (gchar *) message->header,
                             dasom_message_get_header_size (),
                             NULL, &error);

  if (G_UNLIKELY (n_read < dasom_message_get_header_size ()))
  {
    g_critical (G_STRLOC ": %s: received %"G_GSSIZE_FORMAT" less than %d",
                G_STRFUNC, n_read, dasom_message_get_header_size ());

    if (error)
    {
      g_critical (G_STRLOC ": %s: %s", G_STRFUNC, error->message);
      g_error_free (error);
    }

    dasom_message_unref (message);

    return NULL;
  }

  if (message->header->data_len > 0)
  {
    dasom_message_set_body (message,
                            g_malloc0 (message->header->data_len),
                            message->header->data_len,
                            g_free);

    n_read = g_socket_receive (socket,
                               message->data,
                               message->header->data_len,
                               NULL, &error);

    if (G_UNLIKELY (n_read < message->header->data_len))
    {
      g_critical (G_STRLOC ": %s: received %"G_GSSIZE_FORMAT" less than %d",
                  G_STRFUNC, n_read, message->header->data_len);

      if (error)
      {
        g_critical (G_STRLOC ": %s: %s", G_STRFUNC, error->message);
        g_error_free (error);
      }

      dasom_message_unref (message);

      return NULL;
    }
  }

  /* debug message */
  const gchar *name = dasom_message_get_name (message);
  if (name)
    g_debug ("recv: %s, fd: %d", name, g_socket_get_fd (socket));
  else
    g_error (G_STRLOC ": unknown message type");

  return message;
}
Exemplo n.º 6
0
void
dasom_send_message (GSocket          *socket,
                    DasomMessageType  type,
                    gpointer          data,
                    guint16           data_len,
                    GDestroyNotify    data_destroy_func)
{
  g_debug (G_STRLOC ": %s: fd = %d", G_STRFUNC, g_socket_get_fd (socket));

  DasomMessage *message;
  const DasomMessageHeader *header;
  GError *error = NULL;
  gssize n_written;

  message = dasom_message_new_full (type, data, data_len, data_destroy_func);
  header  = dasom_message_get_header (message);

  n_written = g_socket_send (socket,
                             (gchar *) header,
                             dasom_message_get_header_size (),
                             NULL, &error);

  if (G_UNLIKELY (n_written < dasom_message_get_header_size ()))
  {
    g_critical (G_STRLOC ": %s: sent %"G_GSSIZE_FORMAT" less than %d",
                G_STRFUNC, n_written, dasom_message_get_header_size ());
    if (error)
    {
      g_critical (G_STRLOC ": %s: %s", G_STRFUNC, error->message);
      g_error_free (error);
    }

    dasom_message_unref (message);

    return;
  }

  if (G_LIKELY (message->header->data_len > 0))
  {
    n_written = g_socket_send (socket,
                               message->data,
                               message->header->data_len,
                               NULL, &error);

    if (G_UNLIKELY (n_written < message->header->data_len))
    {
      g_critical (G_STRLOC ": %s: sent %"G_GSSIZE_FORMAT" less than %d",
                  G_STRFUNC, n_written, message->header->data_len);

      if (error)
      {
        g_critical (G_STRLOC ": %s: %s", G_STRFUNC, error->message);
        g_error_free (error);
      }

      dasom_message_unref (message);

      return;
    }
  }

  /* debug message */
  const gchar *name = dasom_message_get_name (message);
  if (name)
    g_debug ("send: %s, fd: %d", name, g_socket_get_fd(socket));
  else
    g_error (G_STRLOC ": unknown message type");

  dasom_message_unref (message);
}
Exemplo n.º 7
0
static gboolean
on_incoming_message_dasom (GSocket         *socket,
                           GIOCondition     condition,
                           DasomConnection *connection)
{
  g_debug (G_STRLOC ": %s", G_STRFUNC);

  DasomMessage *message;
  gboolean      retval;

  if (condition & (G_IO_HUP | G_IO_ERR))
  {
    g_debug (G_STRLOC ": condition & (G_IO_HUP | G_IO_ERR)");

    g_socket_close (socket, NULL);

    dasom_message_unref (connection->reply);
    connection->reply = NULL;

    if (G_UNLIKELY (connection->type == DASOM_CONNECTION_DASOM_AGENT))
      connection->server->agents_list =
        g_list_remove (connection->server->agents_list, connection);

    g_hash_table_remove (connection->server->connections,
                         GUINT_TO_POINTER (dasom_connection_get_id (connection)));

    return G_SOURCE_REMOVE;
  }

  if (connection->type == DASOM_CONNECTION_DASOM_IM)
    dasom_engine_set_english_mode (connection->engine,
                                   connection->is_english_mode);

  message = dasom_recv_message (socket);
  dasom_message_unref (connection->reply);
  connection->reply = message;
  connection->is_dispatched = TRUE;

  switch (message->header->type)
  {
    case DASOM_MESSAGE_FILTER_EVENT:
      dasom_message_ref (message);
      retval = dasom_connection_filter_event (connection,
                                              (DasomEvent *) message->data);
      dasom_message_unref (message);
      dasom_send_message (socket, DASOM_MESSAGE_FILTER_EVENT_REPLY, &retval,
                          sizeof (gboolean), NULL);
      break;
    case DASOM_MESSAGE_GET_PREEDIT_STRING:
      {
        gchar *data = NULL;
        gint   cursor_pos;
        gint   str_len = 0;

        dasom_connection_get_preedit_string (connection, &data, &cursor_pos);

        str_len = strlen (data);
        data = g_realloc (data, str_len + 1 + sizeof (gint));
        *(gint *) (data + str_len + 1) = cursor_pos;

        dasom_send_message (socket, DASOM_MESSAGE_GET_PREEDIT_STRING_REPLY,
                            data,
                            str_len + 1 + sizeof (gint),
                            NULL);
        g_free (data);
      }
      break;
    case DASOM_MESSAGE_RESET:
      dasom_connection_reset (connection);
      dasom_send_message (socket, DASOM_MESSAGE_RESET_REPLY, NULL, 0, NULL);
      break;
    case DASOM_MESSAGE_FOCUS_IN:
      dasom_connection_focus_in (connection);
      dasom_send_message (socket, DASOM_MESSAGE_FOCUS_IN_REPLY, NULL, 0, NULL);
      break;
    case DASOM_MESSAGE_FOCUS_OUT:
      dasom_connection_focus_out (connection);
      dasom_send_message (socket, DASOM_MESSAGE_FOCUS_OUT_REPLY, NULL, 0, NULL);
      break;
    case DASOM_MESSAGE_SET_SURROUNDING:
      {
        dasom_message_ref (message);
        gchar   *data     = message->data;
        guint16  data_len = message->header->data_len;

        gint   str_len      = data_len - 1 - 2 * sizeof (gint);
        gint   cursor_index = *(gint *) (data + data_len - sizeof (gint));

        dasom_connection_set_surrounding (connection, data, str_len,
                                          cursor_index);
        dasom_message_unref (message);
        dasom_send_message (socket, DASOM_MESSAGE_SET_SURROUNDING_REPLY, NULL, 0, NULL);
      }
      break;
    case DASOM_MESSAGE_GET_SURROUNDING:
      {
        gchar *data;
        gint   cursor_index;
        gint   str_len = 0;

        retval = dasom_connection_get_surrounding (connection, &data,
                                                   &cursor_index);
        str_len = strlen (data);
        data = g_realloc (data, str_len + 1 + sizeof (gint) + sizeof (gboolean));
        *(gint *) (data + str_len + 1) = cursor_index;
        *(gboolean *) (data + str_len + 1 + sizeof (gint)) = retval;

        dasom_send_message (socket, DASOM_MESSAGE_GET_SURROUNDING_REPLY,
                            data,
                            str_len + 1 + sizeof (gint) + sizeof (gboolean),
                            NULL);
        g_free (data);
      }
      break;
    case DASOM_MESSAGE_SET_CURSOR_LOCATION:
      dasom_message_ref (message);
      dasom_connection_set_cursor_location (connection,
                                            (DasomRectangle *) message->data);
      dasom_message_unref (message);
      dasom_send_message (socket, DASOM_MESSAGE_SET_CURSOR_LOCATION_REPLY,
                          NULL, 0, NULL);
      break;
    case DASOM_MESSAGE_SET_USE_PREEDIT:
      dasom_message_ref (message);
      dasom_connection_set_use_preedit (connection, *(gboolean *) message->data);
      dasom_message_unref (message);
      dasom_send_message (socket, DASOM_MESSAGE_SET_USE_PREEDIT_REPLY,
                          NULL, 0, NULL);
      break;
    case DASOM_MESSAGE_PREEDIT_START_REPLY:
    case DASOM_MESSAGE_PREEDIT_CHANGED_REPLY:
    case DASOM_MESSAGE_PREEDIT_END_REPLY:
    case DASOM_MESSAGE_COMMIT_REPLY:
    case DASOM_MESSAGE_RETRIEVE_SURROUNDING_REPLY:
    case DASOM_MESSAGE_DELETE_SURROUNDING_REPLY:
      break;
    default:
      g_warning ("Unknown message type: %d", message->header->type);
      break;
  }

  if (connection->type == DASOM_CONNECTION_DASOM_IM)
    connection->is_english_mode =
      dasom_engine_get_english_mode (connection->engine);

  return G_SOURCE_CONTINUE;
}