static void
infinoted_plugin_document_stream_add_stream(
  InfinotedPluginDocumentStream* plugin,
  InfNativeSocket new_socket)
{
  InfinotedPluginDocumentStreamStream* stream;
  stream = g_slice_new(InfinotedPluginDocumentStreamStream);

  stream->plugin = plugin;
  stream->socket = new_socket;
  stream->watch = inf_io_add_watch(
    infinoted_plugin_manager_get_io(plugin->manager),
    &stream->socket,
    INF_IO_INCOMING,
    infinoted_plugin_document_stream_io_func,
    stream,
    NULL
  );

  stream->username = NULL;

  stream->status = INFINOTED_PLUGIN_DOCUMENT_STREAM_NORMAL;
  infinoted_plugin_document_stream_queue_initialize(&stream->send_queue);
  infinoted_plugin_document_stream_queue_initialize(&stream->recv_queue);

  stream->navigate_handle = NULL;
  stream->subscribe_request = NULL;
  stream->user_request = NULL;
  stream->proxy = NULL;
  stream->user = NULL;
  stream->buffer = NULL;

  plugin->streams = g_slist_prepend(plugin->streams, stream);
}
Пример #2
0
static void
inf_tcp_connection_connected(InfTcpConnection* connection)
{
  InfTcpConnectionPrivate* priv;
  priv = INF_TCP_CONNECTION_PRIVATE(connection);

  priv->status = INF_TCP_CONNECTION_CONNECTED;
  priv->front_pos = 0;
  priv->back_pos = 0;

  priv->events = INF_IO_INCOMING | INF_IO_ERROR;

  if(priv->watch == NULL)
  {
    priv->watch = inf_io_add_watch(
      priv->io,
      &priv->socket,
      priv->events,
      inf_tcp_connection_io,
      connection,
      NULL
    );
  }
  else
  {
    inf_io_update_watch(priv->io, priv->watch, priv->events);
  }

  g_object_freeze_notify(G_OBJECT(connection));

  /* Update adresses from resolver */
  if(priv->resolver != NULL)
  {
    if(priv->remote_address != NULL)
      inf_ip_address_free(priv->remote_address);

    priv->remote_address = inf_ip_address_copy(
      inf_name_resolver_get_address(priv->resolver, priv->resolver_index)
    );

    priv->remote_port =
      inf_name_resolver_get_port(priv->resolver, priv->resolver_index);

    g_object_notify(G_OBJECT(connection), "remote-address");
    g_object_notify(G_OBJECT(connection), "remote-port");

    priv->resolver_index = 0;
  }

  g_object_notify(G_OBJECT(connection), "status");
  g_object_notify(G_OBJECT(connection), "local-address");
  g_object_notify(G_OBJECT(connection), "local-port");
  g_object_thaw_notify(G_OBJECT(connection));
}
Пример #3
0
/**
 * infinoted_signal_register:
 * @run: A #InfinotedRun.
 *
 * Registers signal handlers for SIGINT and SIGTERM that terminate the given
 * infinote server. When you don't need the signal handlers anymore, you
 * must unregister them again using infinoted_signal_unregister().
 *
 * Returns: A #InfinotedSignal to unregister the signal handlers again later.
 */
InfinotedSignal*
infinoted_signal_register(InfinotedRun* run)
{
  InfinotedSignal* sig;
  sig = g_slice_new(InfinotedSignal);

#ifdef LIBINFINITY_HAVE_LIBDAEMON
  sig->run = run;

  /* TODO: Should we report when this fails? Should ideally happen before
   * actually forking then - are signal connections kept in fork()'s child? */
  if(daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) == 0)
  {
    sig->signal_fd = daemon_signal_fd();

    sig->watch = inf_io_add_watch(
      INF_IO(run->io),
      &sig->signal_fd,
      INF_IO_INCOMING | INF_IO_ERROR,
      infinoted_signal_sig_func,
      sig,
      NULL
    );
  }

#else
  sig->previous_sigint_handler =
    signal(SIGINT, &infinoted_signal_sigint_handler);
  sig->previous_sigterm_handler =
    signal(SIGTERM, &infinoted_signal_sigterm_handler);
  sig->previous_sigquit_handler =
#ifndef G_OS_WIN32
    signal(SIGQUIT, &infinoted_signal_sigquit_handler);
  sig->previous_sighup_handler =
    signal(SIGHUP, &infinoted_signal_sighup_handler);
#endif /* !G_OS_WIN32 */
  _infinoted_signal_server = run;
#endif /* !LIBINFINITY_HAVE_LIBDAEMON */

#ifdef G_OS_WIN32
  SetConsoleCtrlHandler(infinoted_signal_console_handler, TRUE);
#endif

  return sig;
}
Пример #4
0
static void
inf_test_chat_userjoin_finished_cb(InfcRequest* request,
                                   InfUser* user,
                                   gpointer user_data)
{
  InfTestChat* test;
  test = (InfTestChat*)user_data;

  printf("User join complete. Start chatting!\n");

#ifndef G_OS_WIN32
  inf_io_add_watch(
    INF_IO(test->io),
    &test->input_fd,
    INF_IO_INCOMING | INF_IO_ERROR,
    inf_test_chat_input_cb,
    test,
    NULL
  );
#endif

  test->self = user;
}
Пример #5
0
static void
inf_test_browser_notify_status_cb(GObject* object,
                                  GParamSpec* pspec,
                                  gpointer user_data)
{
  InfTestBrowser* test;
  InfBrowserStatus status;

  test = (InfTestBrowser*)user_data;
  g_object_get(G_OBJECT(test->browser), "status", &status, NULL);

  if(status == INF_BROWSER_OPEN)
  {
    printf("Connection established\n");

#ifndef G_OS_WIN32
    inf_io_add_watch(
      INF_IO(test->io),
      &test->input_fd,
      INF_IO_INCOMING | INF_IO_ERROR,
      inf_test_browser_input_cb,
      test,
      NULL
    );
#endif

    /* Explore root node */
    inf_browser_get_root(test->browser, &test->cwd);
    inf_browser_explore(test->browser, &test->cwd, NULL, NULL);
  }

  if(status == INF_BROWSER_CLOSED)
  {
    if(inf_standalone_io_loop_running(test->io))
      inf_standalone_io_loop_quit(test->io);
  }
}
static gboolean
infinoted_plugin_document_stream_initialize(InfinotedPluginManager* manager,
                                            gpointer plugin_info,
                                            GError** error)
{
  static const char ADDRESS_NAME[] = "org.infinote.infinoted";
  struct sockaddr_un addr;

  InfinotedPluginDocumentStream* plugin;
  plugin = (InfinotedPluginDocumentStream*)plugin_info;

  plugin->manager = manager;

  plugin->socket = socket(AF_UNIX, SOCK_STREAM, 0);
  if(plugin->socket == -1)
  {
    infinoted_plugin_document_stream_make_system_error(errno, error);
    return FALSE;
  }

  /* TODO: Make the address configurable -- note that abstract paths
   * are a Linux extension. */
  addr.sun_family = AF_UNIX;
  addr.sun_path[0] = '\0';
  memcpy(&addr.sun_path[1], ADDRESS_NAME, sizeof(ADDRESS_NAME) - 1);

  memset(
    &addr.sun_path[1] + sizeof(ADDRESS_NAME) - 1,
    '\0',
    sizeof(addr.sun_path) - 1 - (sizeof(ADDRESS_NAME) - 1)
  );

  if(!infinoted_plugin_document_stream_set_nonblock(plugin->socket, error))
    return FALSE;

  if(bind(plugin->socket, (struct sockaddr*)&addr, sizeof(addr)) == -1)
  {
    infinoted_plugin_document_stream_make_system_error(errno, error);
    return FALSE;
  }

  if(listen(plugin->socket, 5) == -1)
  {
    infinoted_plugin_document_stream_make_system_error(errno, error);
    return FALSE;
  }

  plugin->watch = inf_io_add_watch(
    infinoted_plugin_manager_get_io(plugin->manager),
    &plugin->socket,
    INF_IO_INCOMING,
    infinoted_plugin_manager_socket_accept_func,
    plugin,
    NULL
  );

  g_signal_connect(
    G_OBJECT(infinoted_plugin_manager_get_directory(plugin->manager)),
    "node-removed",
    G_CALLBACK(infinoted_plugin_document_stream_node_removed_cb),
    plugin
  );

  return TRUE;
}
Пример #7
0
static gboolean
inf_tcp_connection_open_real(InfTcpConnection* connection,
                             const InfIpAddress* address,
                             guint port,
                             GError** error)
{
  InfTcpConnectionPrivate* priv;

  union {
    struct sockaddr_in in;
    struct sockaddr_in6 in6;
  } native_address;

  struct sockaddr* addr;
  socklen_t addrlen;
  int result;
  int errcode;
  const InfKeepalive* keepalive;
  GError* local_error;

  priv = INF_TCP_CONNECTION_PRIVATE(connection);

  g_assert(priv->status == INF_TCP_CONNECTION_CLOSED ||
           priv->status == INF_TCP_CONNECTION_CONNECTING);

  /* Close previous socket */
  if(priv->socket != INVALID_SOCKET)
    closesocket(priv->socket);

  switch(inf_ip_address_get_family(address))
  {
  case INF_IP_ADDRESS_IPV4:
    priv->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    addr = (struct sockaddr*)&native_address.in;
    addrlen = sizeof(struct sockaddr_in);

    memcpy(
      &native_address.in.sin_addr,
      inf_ip_address_get_raw(address),
      sizeof(struct in_addr)
    );

    native_address.in.sin_family = AF_INET;
    native_address.in.sin_port = htons(port);

    break;
  case INF_IP_ADDRESS_IPV6:
    priv->socket = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
    addr = (struct sockaddr*)&native_address.in6;
    addrlen = sizeof(struct sockaddr_in6);

    memcpy(
      &native_address.in6.sin6_addr,
      inf_ip_address_get_raw(address),
      sizeof(struct in6_addr)
    );

    native_address.in6.sin6_family = AF_INET6;
    native_address.in6.sin6_port = htons(port);
    native_address.in6.sin6_flowinfo = 0;
    native_address.in6.sin6_scope_id = priv->device_index;

    break;
  default:
    g_assert_not_reached();
    break;
  }

  if(priv->socket == INVALID_SOCKET)
  {
    inf_native_socket_make_error(INF_NATIVE_SOCKET_LAST_ERROR, error);
    return FALSE;
  }

  /* Set socket non-blocking and keepalive */
  keepalive = &priv->keepalive;
  if(!inf_tcp_connection_configure_socket(priv->socket, keepalive, error))
  {
    closesocket(priv->socket);
    priv->socket = INVALID_SOCKET;
    return FALSE;
  }

  /* Connect */
  do
  {
    result = connect(priv->socket, addr, addrlen);
    errcode = INF_NATIVE_SOCKET_LAST_ERROR;
    if(result == -1 &&
       errcode != INF_NATIVE_SOCKET_EINTR &&
       errcode != INF_NATIVE_SOCKET_EINPROGRESS)
    {
      local_error = NULL;
      inf_native_socket_make_error(errcode, &local_error);
      if(inf_tcp_connection_connection_error(connection, local_error) == TRUE)
      {
        /* In this case, we could recover from the error by connecting to a
         * different address. */
        g_error_free(local_error);
        return TRUE;
      }

      g_propagate_error(error, local_error);
      return FALSE;
    }
  } while(result == -1 && errcode != INF_NATIVE_SOCKET_EINPROGRESS);

  if(result == 0)
  {
    /* Connection fully established */
    inf_tcp_connection_connected(connection);
  }
  else
  {
    g_assert(priv->watch == NULL);

    /* Connection establishment in progress */
    priv->events = INF_IO_OUTGOING | INF_IO_ERROR;

    priv->watch = inf_io_add_watch(
      priv->io,
      &priv->socket,
      priv->events,
      inf_tcp_connection_io,
      connection,
      NULL
    );

    if(priv->status != INF_TCP_CONNECTION_CONNECTING)
    {
      priv->status = INF_TCP_CONNECTION_CONNECTING;
      g_object_notify(G_OBJECT(connection), "status");
    }
  }

  return TRUE;
}