예제 #1
0
static void
notify_status_cb(InfTcpConnection* connection,
                 const gchar* property,
		 gpointer user_data)
{
  InfTcpConnectionStatus status;
  InfIpAddress* addr;
  guint port;
  gchar* addr_str;

  g_object_get(
    G_OBJECT(connection),
    "status", &status,
    "remote-address", &addr,
    "remote-port", &port,
    NULL
  );

  addr_str = inf_ip_address_to_string(addr);
  inf_ip_address_free(addr);

  switch(status)
  {
  case INF_TCP_CONNECTION_CONNECTING:
    printf("Connecting to %s:%u\n", addr_str, port);
    break;
  case INF_TCP_CONNECTION_CONNECTED:
    printf("Connected to %s:%u\n", addr_str, port);

    g_object_get(
      G_OBJECT(connection),
      "local-address", &addr,
      "local-port", &port,
      NULL
    );

    g_free(addr_str);
    addr_str = inf_ip_address_to_string(addr);
    inf_ip_address_free(addr);

    printf("Connected from %s:%u\n", addr_str, port);
    inf_tcp_connection_send(connection, "Hello, World!\n", 14);
    break;
  case INF_TCP_CONNECTION_CLOSED:
    printf("Connection to %s:%u closed\n", addr_str, port);
    if(inf_standalone_io_loop_running(INF_STANDALONE_IO(user_data)))
      inf_standalone_io_loop_quit(INF_STANDALONE_IO(user_data));
    break;
  default:
    g_assert_not_reached();
    break;
  }

  g_free(addr_str);
}
예제 #2
0
/* Creates a new TCP connection from an accepted socket. This is only used
 * by InfdTcpServer and should not be considered regular API. Do not call
 * this function. Language bindings should not wrap it. */
InfTcpConnection*
_inf_tcp_connection_accepted(InfIo* io,
                             InfNativeSocket socket,
                             InfIpAddress* address,
                             guint port,
                             const InfKeepalive* keepalive,
                             GError** error)
{
  InfTcpConnection* connection;
  InfTcpConnectionPrivate* priv;
  int errcode;

  g_return_val_if_fail(INF_IS_IO(io), NULL);
  g_return_val_if_fail(socket != INVALID_SOCKET, NULL);
  g_return_val_if_fail(address != NULL, NULL);
  g_return_val_if_fail(keepalive != NULL, NULL);

  if(inf_tcp_connection_configure_socket(socket, keepalive, error) != TRUE)
    return NULL;

  g_return_val_if_fail(address != NULL, NULL);
  g_return_val_if_fail(port != 0, NULL);

  connection = inf_tcp_connection_new(io, address, port);

  inf_ip_address_free(address);

  priv = INF_TCP_CONNECTION_PRIVATE(connection);
  priv->socket = socket;
  priv->keepalive = *keepalive;

  inf_tcp_connection_connected(connection);
  return connection;
}
예제 #3
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));
}
예제 #4
0
static void
conn_received_cb(InfTcpConnection* connection,
                 gconstpointer data,
                 guint len,
                 gpointer user_data)
{
  InfIpAddress* addr;
  gchar* str;
  g_object_get(G_OBJECT(connection), "remote-address", &addr, NULL);
  str = inf_ip_address_to_string(addr);
  inf_ip_address_free(addr);

  printf("Data from %s: %.*s\n", str, (int)len, (const char*)data);
  g_free(str);
}
예제 #5
0
static void
conn_error_cb(InfTcpConnection* connection,
              GError* error,
              gpointer user_data)
{
  InfIpAddress* addr;
  gchar* str;
  g_object_get(G_OBJECT(connection), "remote-address", &addr, NULL);
  str = inf_ip_address_to_string(addr);
  inf_ip_address_free(addr);

  printf("Error from %s: %s\n", str, error->message);
  g_free(str);

  g_object_unref(G_OBJECT(connection));
}
예제 #6
0
static void
infd_xmpp_server_new_connection_cb(InfdTcpServer* tcp_server,
                                   InfTcpConnection* tcp_connection,
                                   gpointer user_data)
{
  InfdXmppServer* xmpp_server;
  InfdXmppServerPrivate* priv;
  InfXmppConnection* xmpp_connection;
  InfIpAddress* addr;
  gchar* addr_str;

  xmpp_server = INFD_XMPP_SERVER(user_data);
  priv = INFD_XMPP_SERVER_PRIVATE(xmpp_server);

  /* TODO: We could perform a reverse DNS lookup to find the client hostname
   * here. */
  g_object_get(G_OBJECT(tcp_connection), "remote-address", &addr, NULL);
  addr_str = inf_ip_address_to_string(addr);
  inf_ip_address_free(addr);

  xmpp_connection = inf_xmpp_connection_new(
    tcp_connection,
    INF_XMPP_CONNECTION_SERVER,
    priv->local_hostname,
    addr_str,
    priv->security_policy,
    priv->tls_creds,
    priv->sasl_context,
    priv->sasl_own_context != NULL ? "ANONYMOUS" : priv->sasl_mechanisms
  );

  g_free(addr_str);

  /* We could, alternatively, keep the connection around until authentication
   * has completed and emit the new_connection signal after that, to guarantee
   * that the connection is open when new_connection is emitted. */
  infd_xml_server_new_connection(
    INFD_XML_SERVER(xmpp_server),
    INF_XML_CONNECTION(xmpp_connection)
  );

  g_object_unref(G_OBJECT(xmpp_connection));
}
예제 #7
0
static void
inf_tcp_connection_finalize(GObject* object)
{
  InfTcpConnection* connection;
  InfTcpConnectionPrivate* priv;

  connection = INF_TCP_CONNECTION(object);
  priv = INF_TCP_CONNECTION_PRIVATE(connection);

  if(priv->remote_address != NULL)
    inf_ip_address_free(priv->remote_address);

  if(priv->socket != INVALID_SOCKET)
    closesocket(priv->socket);

  g_free(priv->queue);

  G_OBJECT_CLASS(inf_tcp_connection_parent_class)->finalize(object);
}
예제 #8
0
static void
new_connection_cb(InfdTcpServer* server,
                  InfTcpConnection* connection,
                  gpointer user_data)
{
  InfIpAddress* addr;
  gchar* str;
  g_object_get(G_OBJECT(connection), "remote-address", &addr, NULL);
  str = inf_ip_address_to_string(addr);
  inf_ip_address_free(addr);

  printf("Connection from %s\n", str);
  g_free(str);

  g_signal_connect(
    G_OBJECT(connection),
    "received",
    G_CALLBACK(conn_received_cb),
    NULL
  );

  g_signal_connect(
    G_OBJECT(connection),
    "error",
    G_CALLBACK(conn_error_cb),
    NULL
  );

  g_signal_connect(
    G_OBJECT(connection),
    "notify::status",
    G_CALLBACK(conn_notify_status_cb),
    NULL
  );

  g_object_ref(G_OBJECT(connection));
}
예제 #9
0
static void
notify_status_cb(InfdTcpServer* server,
                 GParamSpec* pspec,
                 gpointer user_data)
{
  InfdTcpServerStatus status;
  InfIpAddress* addr;
  guint port;
  gchar* addr_str;

  g_object_get(
    G_OBJECT(server),
    "status", &status,
    "local-address", &addr,
    "local-port", &port,
    NULL
  );

  addr_str = inf_ip_address_to_string(addr);
  inf_ip_address_free(addr);

  switch(status)
  {
  case INFD_TCP_SERVER_CLOSED:
    printf("Server closed\n");
    break;
  case INFD_TCP_SERVER_OPEN:
    printf("Server listening on %s:%u\n", addr_str, port);
    break;
  default:
    g_assert_not_reached();
    break;
  }

  g_free(addr_str);
}
예제 #10
0
static void
conn_notify_status_cb(InfTcpConnection* connection,
                      GParamSpec* spec,
                      gpointer user_data)
{
  InfIpAddress* addr;
  InfTcpConnectionStatus status;
  gchar* str;

  g_object_get(
    G_OBJECT(connection),
    "remote-address", &addr,
    "status", &status,
    NULL
  );

  str = inf_ip_address_to_string(addr);
  inf_ip_address_free(addr);

  if(status == INF_TCP_CONNECTION_CLOSED)
    printf("Connection close from %s\n", str);

  g_free(str);
}
static void
bookmark_added (GeditCollaborationWindowHelper *helper,
                GeditCollaborationBookmark     *bookmark)
{
	GResolver *resolver = g_resolver_get_default ();
	GList *addresses;
	InfTcpConnection *tcp;
	InfIpAddress *ipaddress;
	InfXmppConnection *connection;
	gchar *ipaddr;
	NameInfo *info;
	GeditCollaborationUser *user;

	/* TODO: make this asynchronous and be smarter about it */
	addresses = g_resolver_lookup_by_name (resolver,
	                                       gedit_collaboration_bookmark_get_host (bookmark),
	                                       NULL,
	                                       NULL);

	if (!addresses)
	{
		return;
	}

	ipaddr = g_inet_address_to_string ((GInetAddress *)addresses->data);
	g_resolver_free_addresses (addresses);

	ipaddress = inf_ip_address_new_from_string (ipaddr);
	g_free (ipaddr);

	tcp = inf_tcp_connection_new (helper->priv->io,
	                              ipaddress,
	                              (guint)gedit_collaboration_bookmark_get_port (bookmark));

	user = gedit_collaboration_bookmark_get_user (bookmark);
	connection = inf_xmpp_connection_new (tcp,
	                                      INF_XMPP_CONNECTION_CLIENT,
	                                      NULL,
	                                      gedit_collaboration_bookmark_get_host (bookmark),
	                                      INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS,
	                                      helper->priv->certificate_credentials,
	                                      gedit_collaboration_user_get_sasl_context (user),
	                                      "ANONYMOUS PLAIN");

	g_signal_connect (user,
	                  "request-password",
	                  G_CALLBACK (user_request_password),
	                  helper);

	inf_gtk_browser_store_add_connection (helper->priv->browser_store,
	                                      INF_XML_CONNECTION (connection),
	                                      gedit_collaboration_bookmark_get_name (bookmark));

	g_object_set_data (G_OBJECT (connection), BOOKMARK_DATA_KEY, bookmark);

	inf_ip_address_free (ipaddress);
	g_object_unref (tcp);

	info = g_slice_new (NameInfo);
	info->helper = helper;
	info->connection = INF_XML_CONNECTION (connection);

	g_signal_connect_data (bookmark,
	                       "notify::name",
	                       G_CALLBACK (on_bookmark_name_changed),
	                       info,
	                       (GClosureNotify)name_info_free,
	                       0);
}
예제 #12
0
static void
inf_tcp_connection_set_property(GObject* object,
                                guint prop_id,
                                const GValue* value,
                                GParamSpec* pspec)
{
  InfTcpConnection* connection;
  InfTcpConnectionPrivate* priv;
#ifndef G_OS_WIN32
  const gchar* device_string;
  unsigned int new_index;
#endif
  GError* error;

  connection = INF_TCP_CONNECTION(object);
  priv = INF_TCP_CONNECTION_PRIVATE(connection);

  switch(prop_id)
  {
  case PROP_IO:
    g_assert(priv->status == INF_TCP_CONNECTION_CLOSED);
    if(priv->io != NULL) g_object_unref(G_OBJECT(priv->io));
    priv->io = INF_IO(g_value_dup_object(value));
    break;
  case PROP_RESOLVER:
    g_assert(priv->status == INF_TCP_CONNECTION_CLOSED);

    inf_tcp_connection_set_resolver(
      connection,
      INF_NAME_RESOLVER(g_value_get_object(value))
    );

    break;
  case PROP_KEEPALIVE:
    error = NULL;

    inf_tcp_connection_set_keepalive(
      connection,
      (InfKeepalive*)g_value_get_boxed(value),
      &error
    );
    
    if(error != NULL)
    {
      g_warning("Failed to set keepalive settings: %s\n", error->message);
      g_error_free(error);
    }

    break;
  case PROP_REMOTE_ADDRESS:
    g_assert(priv->status == INF_TCP_CONNECTION_CLOSED);
    if(priv->remote_address != NULL)
      inf_ip_address_free(priv->remote_address);
    priv->remote_address = (InfIpAddress*)g_value_dup_boxed(value);
    break;
  case PROP_REMOTE_PORT:
    g_assert(priv->status == INF_TCP_CONNECTION_CLOSED);
    priv->remote_port = g_value_get_uint(value);
    break;
  case PROP_DEVICE_INDEX:
    g_assert(priv->status == INF_TCP_CONNECTION_CLOSED);
    /* TODO: Verify that such a device exists */
    priv->device_index = g_value_get_uint(value);
    g_object_notify(G_OBJECT(object), "device-name");
    break;
  case PROP_DEVICE_NAME:
#ifdef G_OS_WIN32
    /* TODO: We can probably implement this using GetInterfaceInfo() */
    g_warning("The device-name property is not implemented on Win32");
#else
    g_assert(priv->status == INF_TCP_CONNECTION_CLOSED);
    device_string = g_value_get_string(value);
    if(device_string == NULL) priv->device_index = 0;

    new_index = if_nametoindex(device_string);
    if(new_index == 0)
    {
      g_warning(_("Interface `%s' does not exist"), device_string);
    }
    else
    {
      priv->device_index = new_index;
      g_object_notify(G_OBJECT(object), "device-index");
    }
#endif
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    break;
  }
}
예제 #13
0
int main(int argc, char* argv[])
{
  InfIpAddress* addr;
  InfStandaloneIo* io;
  InfTcpConnection* connection;
  GError* error;

  g_type_init();

  addr = inf_ip_address_new_loopback4();
  io = inf_standalone_io_new();
  error = NULL;

  connection = g_object_new(
    INF_TYPE_TCP_CONNECTION,
    "io", io,
    "remote-address", addr,
    "remote-port", 5223,
    NULL
  );

  inf_ip_address_free(addr);

  g_signal_connect(
    G_OBJECT(connection),
    "received",
    G_CALLBACK(received_cb),
    io
  );

  g_signal_connect(
    G_OBJECT(connection),
    "sent",
    G_CALLBACK(sent_cb),
    io
  );

  g_signal_connect(
    G_OBJECT(connection),
    "error",
    G_CALLBACK(error_cb),
    io
  );

  g_signal_connect(
    G_OBJECT(connection),
    "notify::status",
    G_CALLBACK(notify_status_cb),
    io
  );

  if(inf_tcp_connection_open(connection, &error) == FALSE)
  {
    fprintf(stderr, "Could not open connection: %s\n", error->message);
    g_error_free(error);
  }
  else
  {
    inf_standalone_io_loop(io);
  }

  g_object_unref(G_OBJECT(io));
  g_object_unref(G_OBJECT(connection));

  return 0;
}
예제 #14
0
static void
inf_test_mass_join_connect(InfTestMassJoin* massjoin,
                           const char* hostname,
                           guint port,
                           const char* document,
                           const char* username)
{
    InfIpAddress* addr;
    InfTcpConnection* tcp;
    InfXmppConnection* xmpp;
    InfTestMassJoiner* joiner;
    InfXmlConnection* xml;
    GError* error;

    addr = inf_ip_address_new_from_string(hostname);
    tcp = inf_tcp_connection_new(massjoin->io, addr, port);
    xmpp = inf_xmpp_connection_new(
               tcp,
               INF_XMPP_CONNECTION_CLIENT,
               g_get_host_name(),
               hostname,
               INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS,
               NULL,
               NULL,
               NULL
           );

    joiner = g_slice_new(InfTestMassJoiner);
    joiner->communication_manager = inf_communication_manager_new();
    joiner->browser = infc_browser_new(
                          massjoin->io,
                          joiner->communication_manager,
                          INF_XML_CONNECTION(xmpp)
                      );
    joiner->session = NULL;
    joiner->document = g_strdup(document);
    joiner->username = g_strdup(username);

    g_object_unref(xmpp);
    g_object_unref(tcp);
    inf_ip_address_free(addr);

    massjoin->joiners = g_slist_prepend(massjoin->joiners, joiner);
    infc_browser_add_plugin(joiner->browser, &INF_TEST_MASS_JOIN_TEXT_PLUGIN);

    g_signal_connect(
        G_OBJECT(joiner->browser),
        "notify::status",
        G_CALLBACK(inf_test_mass_join_browser_notify_status_cb),
        massjoin
    );

    error = NULL;
    xml = infc_browser_get_connection(joiner->browser);
    if(inf_xml_connection_open(xml, &error) == FALSE)
    {
        fprintf(
            stderr,
            "Joiner %s: Failed to connect to %s: %s\n",
            joiner->username,
            hostname,
            error->message
        );

        g_error_free(error);
        massjoin->joiners = g_slist_remove(massjoin->joiners, joiner);

        if(massjoin->joiners == NULL)
            inf_standalone_io_loop_quit(INF_STANDALONE_IO(massjoin->io));
    }
}
static InfXmppConnection*
inf_test_certificate_validate_setup_client(InfIo* io,
                                           const gchar* ca_file,
                                           const gchar* remote_hostname,
                                           GError** error)
{
  InfIpAddress* addr;
  InfTcpConnection* conn;
  InfXmppConnection* xmpp;

  InfCertificateCredentials* creds;
  GPtrArray* cas;
  int res;
  guint i;

  creds = inf_certificate_credentials_new();
  if(ca_file != NULL)
  {
    cas = inf_cert_util_read_certificate(ca_file, NULL, error);
    if(cas == NULL)
    {
      inf_certificate_credentials_unref(creds);
      return NULL;
    }

    res = gnutls_certificate_set_x509_trust(
      inf_certificate_credentials_get(creds),
      (gnutls_x509_crt_t*)cas->pdata,
      cas->len
    );

    for(i = 0; i < cas->len; ++i)
      gnutls_x509_crt_deinit(cas->pdata[i]);
    g_ptr_array_free(cas, TRUE);
  }

  addr = inf_ip_address_new_loopback4();
  conn = inf_tcp_connection_new(io, addr, 6524);
  inf_ip_address_free(addr);

  xmpp = inf_xmpp_connection_new(
    conn,
    INF_XMPP_CONNECTION_CLIENT,
    g_get_host_name(),
    remote_hostname,
    INF_XMPP_CONNECTION_SECURITY_ONLY_TLS,
    creds,
    NULL,
    NULL
  );

  inf_certificate_credentials_unref(creds);
  if(inf_tcp_connection_open(conn, error) == FALSE)
  {
    g_object_unref(conn);
    g_object_unref(xmpp);
    return NULL;
  }

  g_object_unref(conn);
  return xmpp;
}
예제 #16
0
int
main(int argc, char* argv[])
{
  InfTestBrowser test;
  InfIpAddress* address;
  InfCommunicationManager* manager;
  InfTcpConnection* tcp_conn;
  GError* error;

  gnutls_global_init();
  g_type_init();

  test.io = inf_standalone_io_new();
#ifndef G_OS_WIN32
  test.input_fd = STDIN_FILENO;
#endif
  address = inf_ip_address_new_loopback4();

  error = NULL;
  tcp_conn =
    inf_tcp_connection_new_and_open(INF_IO(test.io), address, inf_protocol_get_default_port(), &error);

  inf_ip_address_free(address);

  if(tcp_conn == NULL)
  {
    fprintf(stderr, "Could not open TCP connection: %s\n", error->message);
    g_error_free(error);
  }
  else
  {
    test.conn = inf_xmpp_connection_new(
      tcp_conn,
      INF_XMPP_CONNECTION_CLIENT,
      NULL,
      "localhost",
      INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS,
      NULL,
      NULL,
      NULL
    );

    g_object_unref(G_OBJECT(tcp_conn));

    manager = inf_communication_manager_new();
    test.browser = INF_BROWSER(
      infc_browser_new(
        INF_IO(test.io),
        manager,
        INF_XML_CONNECTION(test.conn)
      )
    );

    g_signal_connect_after(
      G_OBJECT(test.browser),
      "notify::status",
      G_CALLBACK(inf_test_browser_notify_status_cb),
      &test
    );

    g_signal_connect(
      G_OBJECT(test.browser),
      "error",
      G_CALLBACK(inf_test_browser_error_cb),
      &test
    );

    inf_standalone_io_loop(test.io);
    g_object_unref(G_OBJECT(manager));
    g_object_unref(G_OBJECT(test.browser));

    /* TODO: Wait until the XMPP connection is in status closed */
    g_object_unref(G_OBJECT(test.conn));
  }

  g_object_unref(G_OBJECT(test.io));
  return 0;
}
예제 #17
0
static void
notify_status_cb(InfTcpConnection* connection,
                 GParamSpec* pspec,
                 gpointer user_data)
{
  InfTcpConnectionStatus status;
  InfIpAddress* addr;
  guint port;
  InfNameResolver* resolver;
  gchar* addr_str_tmp;
  gchar* addr_str;

  g_object_get(
    G_OBJECT(connection),
    "status", &status,
    "remote-address", &addr,
    "remote-port", &port,
    "resolver", &resolver,
    NULL
  );

  if(addr != NULL)
  {
    addr_str_tmp = inf_ip_address_to_string(addr);
    addr_str = g_strdup_printf("%s:%u", addr_str_tmp, port);
    g_free(addr_str_tmp);
  }
  else
  {
    g_object_get(G_OBJECT(resolver), "hostname", &addr_str, NULL);
  }

  if(addr != NULL)
    inf_ip_address_free(addr);
  if(resolver != NULL)
    g_object_unref(resolver);

  switch(status)
  {
  case INF_TCP_CONNECTION_CONNECTING:
    printf("Connecting to %s\n", addr_str);
    break;
  case INF_TCP_CONNECTION_CONNECTED:
    printf("Connected to %s\n", addr_str);

    g_object_get(
      G_OBJECT(connection),
      "local-address", &addr,
      "local-port", &port,
      NULL
    );

    g_free(addr_str);
    addr_str = inf_ip_address_to_string(addr);
    inf_ip_address_free(addr);

    printf("Connected from %s:%u\n", addr_str, port);
    inf_tcp_connection_send(connection, "Hello, World!\n", 14);
    break;
  case INF_TCP_CONNECTION_CLOSED:
    printf("Connection to %s closed\n", addr_str);
    if(inf_standalone_io_loop_running(INF_STANDALONE_IO(user_data)))
      inf_standalone_io_loop_quit(INF_STANDALONE_IO(user_data));
    break;
  default:
    g_assert_not_reached();
    break;
  }

  g_free(addr_str);
}
예제 #18
0
파일: server.cpp 프로젝트: aburgm/gobby
void Gobby::Server::open(unsigned int port,
                         InfXmppConnectionSecurityPolicy security_policy,
                         InfCertificateCredentials* creds,
                         InfSaslContext* context,
                         const char* sasl_mechanisms)
{
	// If we can open one of tcp4 or tcp6 that's a success.
	InfdTcpServer* tcp4;
	InfdTcpServer* tcp6;

	// If the server is already open and we do not need to change the
	// port, then just change the credentials and SASL context without
	// doing anything else.
	if(is_open() && get_port() == port)
	{
		set_credentials(security_policy, creds);
		set_sasl_context(context, sasl_mechanisms);
		return;
	}

	static const guint8 ANY6_ADDR[16] =
		{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
	InfIpAddress* any6 = inf_ip_address_new_raw6(ANY6_ADDR);

	tcp4 = INFD_TCP_SERVER(g_object_new(
		INFD_TYPE_TCP_SERVER,
		"io", m_io, "local-address", NULL,
		"local-port", port,
		NULL));
	tcp6 = INFD_TCP_SERVER(g_object_new(
		INFD_TYPE_TCP_SERVER,
		"io", m_io, "local-address", any6,
		"local-port", port,
		NULL));
	inf_ip_address_free(any6);

	if(!infd_tcp_server_open(tcp6, NULL))
	{
		g_object_unref(tcp6);
		tcp6 = NULL;

		GError* error = NULL;
		if(!infd_tcp_server_open(tcp4, &error))
		{
			g_object_unref(tcp4);

			const std::string message = error->message;
			g_error_free(error);

			throw std::runtime_error(message);
		}
	}
	else
	{
		if(!infd_tcp_server_open(tcp4, NULL))
		{
			g_object_unref(tcp4);
			tcp4 = NULL;
		}
	}

	// We have the new server open, from this point on there is nothing
	// that can go wrong anymore. Therefore, close the old server and
	// take over the new one.
	if(is_open()) close();

	InfXmppConnectionSecurityPolicy policy =
		INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED;
	if(creds != NULL) policy = security_policy;

	if(tcp4)
	{
		m_xmpp4 = infd_xmpp_server_new(
			tcp4, security_policy, creds,
			context, sasl_mechanisms);
		g_object_unref(tcp4);
	}

	if(tcp6)
	{
		m_xmpp6 = infd_xmpp_server_new(
			tcp6, security_policy, creds,
			context, sasl_mechanisms);
		g_object_unref(tcp6);
	}

	if(m_pool)
	{
		if(m_xmpp4 != NULL)
		{
			infd_server_pool_add_server(
				m_pool, INFD_XML_SERVER(m_xmpp4));
			infd_server_pool_add_local_publisher(
				m_pool, m_xmpp4, m_publisher);
		}

		if(m_xmpp6 != NULL)
		{
			infd_server_pool_add_server(
				m_pool, INFD_XML_SERVER(m_xmpp6));
			infd_server_pool_add_local_publisher(
				m_pool, m_xmpp6, m_publisher);
		}
	}
}