diff options
Diffstat (limited to 'lib/gibber/gibber-oob-file-transfer.c')
-rw-r--r-- | lib/gibber/gibber-oob-file-transfer.c | 206 |
1 files changed, 142 insertions, 64 deletions
diff --git a/lib/gibber/gibber-oob-file-transfer.c b/lib/gibber/gibber-oob-file-transfer.c index b811f8b9..323b6456 100644 --- a/lib/gibber/gibber-oob-file-transfer.c +++ b/lib/gibber/gibber-oob-file-transfer.c @@ -27,6 +27,7 @@ #include <libsoup/soup-message.h> #include <wocky/wocky-stanza.h> +#include <wocky/wocky-meta-porter.h> #include "gibber-oob-file-transfer.h" #include "gibber-fd-transport.h" #include "gibber-namespaces.h" @@ -177,7 +178,8 @@ gibber_oob_file_transfer_is_file_offer (WockyStanza *stanza) GibberFileTransfer * gibber_oob_file_transfer_new_from_stanza_with_from ( WockyStanza *stanza, - GibberXmppConnection *connection, + WockyPorter *porter, + WockyContact *contact, const gchar *peer_id, GError **error) { @@ -303,7 +305,8 @@ gibber_oob_file_transfer_new_from_stanza_with_from ( "self-id", self_id, "peer-id", peer_id, "filename", filename, - "connection", connection, + "porter", porter, + "contact", contact, "direction", GIBBER_FILE_TRANSFER_DIRECTION_INCOMING, "description", description, "content-type", content_type, @@ -470,12 +473,15 @@ static WockyStanza * create_transfer_offer (GibberOobFileTransfer *self, GError **error) { - GibberXmppConnection *connection; + WockyMetaPorter *porter; + WockyContact *contact; + GSocketConnection *conn; + GSocketAddress *address; + GInetAddress *addr; + GSocketFamily family; /* local host name */ - gchar host_name[NI_MAXHOST]; - struct sockaddr_storage name_addr; - socklen_t name_addr_len = sizeof (name_addr); + gchar *host_name; gchar *host_escaped; WockyStanza *stanza; @@ -490,21 +496,32 @@ create_transfer_offer (GibberOobFileTransfer *self, guint64 size; - g_object_get (GIBBER_FILE_TRANSFER (self), "connection", &connection, NULL); - if (connection->transport == NULL) + g_object_get (GIBBER_FILE_TRANSFER (self), + "porter", &porter, + "contact", &contact, + NULL); + + conn = wocky_meta_porter_borrow_connection (porter, contact); + + g_object_unref (porter); + g_object_unref (contact); + + if (conn == NULL) { g_set_error (error, GIBBER_FILE_TRANSFER_ERROR, GIBBER_FILE_TRANSFER_ERROR_NOT_CONNECTED, "Null transport"); return NULL; } - gibber_transport_get_sockaddr (connection->transport, &name_addr, - &name_addr_len); - g_object_unref (connection); - getnameinfo ((struct sockaddr *) &name_addr, name_addr_len, host_name, - sizeof (host_name), NULL, 0, NI_NUMERICHOST); + address = g_socket_connection_get_local_address (conn, NULL); + addr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address)); + family = g_socket_address_get_family (address); + + host_name = g_inet_address_to_string (addr); - if (name_addr.ss_family == AF_INET6) + g_object_unref (address); + + if (family == SOUP_ADDRESS_FAMILY_IPV6) { /* put brackets around the IP6 */ host_escaped = g_strdup_printf ("[%s]", host_name); @@ -515,6 +532,8 @@ create_transfer_offer (GibberOobFileTransfer *self, host_escaped = g_strdup (host_name); } + g_free (host_name); + filename_escaped = g_uri_escape_string (GIBBER_FILE_TRANSFER (self)->filename, NULL, FALSE); url = g_strdup_printf ("http://%s:%d/%s/%s", host_escaped, @@ -718,58 +737,10 @@ http_server_cb (SoupServer *server, } static void -gibber_oob_file_transfer_offer (GibberFileTransfer *ft) +create_and_send_transfer_offer (GibberOobFileTransfer *self) { - GibberOobFileTransfer *self = GIBBER_OOB_FILE_TRANSFER (ft); - WockyStanza *stanza; GError *error = NULL; - - /* start the server if not running */ - /* FIXME we should have only a single server */ - if (self->priv->server == NULL) - { - /* FIXME: libsoup can't listen on IPv4 and IPv6 interfaces at the same - * time. http://bugzilla.gnome.org/show_bug.cgi?id=522519 - * We have to check which IP will be send when creating the stanza. */ - GibberXmppConnection *connection; - struct sockaddr_storage name_addr; - socklen_t name_addr_len = sizeof (name_addr); - - g_object_get (GIBBER_FILE_TRANSFER (self), "connection", &connection, - NULL); - if (connection->transport == NULL) - { - g_set_error (&error, GIBBER_FILE_TRANSFER_ERROR, - GIBBER_FILE_TRANSFER_ERROR_NOT_CONNECTED, "Null transport"); - gibber_file_transfer_emit_error (GIBBER_FILE_TRANSFER (self), - error); - g_error_free (error); - return; - } - - gibber_transport_get_peeraddr (connection->transport, &name_addr, - &name_addr_len); - g_object_unref (connection); - - if (name_addr.ss_family == AF_INET6) - { - /* IPv6 server */ - SoupAddress *addr; - - addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV6, 0); - self->priv->server = soup_server_new (SOUP_SERVER_INTERFACE, - addr, NULL); - - g_object_unref (addr); - } - else - { - /* IPv4 server */ - self->priv->server = soup_server_new (NULL, NULL); - } - - soup_server_run_async (self->priv->server); - } + WockyStanza *stanza; stanza = create_transfer_offer (self, &error); if (stanza == NULL) @@ -791,6 +762,113 @@ gibber_oob_file_transfer_offer (GibberFileTransfer *ft) } static void +porter_open_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + WockyMetaPorter *porter = WOCKY_META_PORTER (source_object); + GibberOobFileTransfer *self = GIBBER_OOB_FILE_TRANSFER (user_data); + GError *error = NULL; + + WockyContact *contact; + + GSocketConnection *conn; + GSocketAddress *address; + GSocketFamily family; + + if (!wocky_meta_porter_open_finish (porter, result, &error)) + { + DEBUG ("Failed to open connection: %s", error->message); + g_clear_error (&error); + + g_set_error (&error, GIBBER_FILE_TRANSFER_ERROR, + GIBBER_FILE_TRANSFER_ERROR_NOT_CONNECTED, "Couldn't open connection"); + gibber_file_transfer_emit_error (GIBBER_FILE_TRANSFER (self), + error); + g_error_free (error); + return; + } + + g_object_get (GIBBER_FILE_TRANSFER (self), + "contact", &contact, + NULL); + + /* FIXME we should have only a single server */ + + /* FIXME: libsoup can't listen on IPv4 and IPv6 interfaces at the same + * time. http://bugzilla.gnome.org/show_bug.cgi?id=522519 + * We have to check which IP will be send when creating the stanza. */ + + conn = wocky_meta_porter_borrow_connection (porter, contact); + + if (conn == NULL) + { + g_set_error (&error, GIBBER_FILE_TRANSFER_ERROR, + GIBBER_FILE_TRANSFER_ERROR_NOT_CONNECTED, "Null transport"); + gibber_file_transfer_emit_error (GIBBER_FILE_TRANSFER (self), + error); + g_error_free (error); + goto out; + } + + address = g_socket_connection_get_remote_address (conn, NULL); + family = g_socket_address_get_family (address); + g_object_unref (address); + + if (family == G_SOCKET_FAMILY_IPV6) + { + /* IPv6 server */ + SoupAddress *addr; + + addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV6, 0); + self->priv->server = soup_server_new (SOUP_SERVER_INTERFACE, + addr, NULL); + + g_object_unref (addr); + } + else + { + /* IPv4 server */ + self->priv->server = soup_server_new (NULL, NULL); + } + + soup_server_run_async (self->priv->server); + + create_and_send_transfer_offer (self); + +out: + /* this was reffed when calling open_async */ + wocky_meta_porter_unref (porter, contact); + g_object_unref (contact); +} + +static void +gibber_oob_file_transfer_offer (GibberFileTransfer *ft) +{ + GibberOobFileTransfer *self = GIBBER_OOB_FILE_TRANSFER (ft); + WockyMetaPorter *porter; + WockyContact *contact; + + if (self->priv->server != NULL) + { + create_and_send_transfer_offer (self); + return; + } + + /* we need to create the soup server */ + + g_object_get (ft, + "porter", &porter, + "contact", &contact, + NULL); + + wocky_meta_porter_open_async (porter, contact, NULL, porter_open_cb, ft); + + g_object_unref (contact); + g_object_unref (porter); +} + +static void http_server_wrote_chunk_cb (SoupMessage *msg, gpointer user_data) { |