summaryrefslogtreecommitdiff
path: root/gst/fsmsnconference/fs-msn-connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/fsmsnconference/fs-msn-connection.c')
-rw-r--r--gst/fsmsnconference/fs-msn-connection.c1134
1 files changed, 0 insertions, 1134 deletions
diff --git a/gst/fsmsnconference/fs-msn-connection.c b/gst/fsmsnconference/fs-msn-connection.c
deleted file mode 100644
index 0acf8c33..00000000
--- a/gst/fsmsnconference/fs-msn-connection.c
+++ /dev/null
@@ -1,1134 +0,0 @@
-/*
- * Farstream - Farstream MSN Connection
- *
- * Copyright 2008 Richard Spiers <richard.spiers@gmail.com>
- * Copyright 2007 Nokia Corp.
- * Copyright 2007-2009 Collabora Ltd.
- * @author: Olivier Crete <olivier.crete@collabora.co.uk>
- * @author: Youness Alaoui <youness.alaoui@collabora.co.uk>
- *
- * fs-msn-connection.c - A MSN Connection gobject
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "fs-msn-connection.h"
-
-#include <arpa/inet.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <stdio.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#include <gst/gst.h>
-#include <nice/interfaces.h>
-
-#define GST_CAT_DEFAULT fsmsnconference_debug
-
-/* Signals */
-enum
-{
- SIGNAL_NEW_LOCAL_CANDIDATE,
- SIGNAL_LOCAL_CANDIDATES_PREPARED,
- SIGNAL_CONNECTED,
- SIGNAL_CONNECTION_FAILED,
- N_SIGNALS
-};
-
-
-static guint signals[N_SIGNALS];
-
-/* props */
-enum
-{
- PROP_0,
- PROP_SESSION_ID
-};
-
-
-typedef enum {
- FS_MSN_STATUS_AUTH,
- FS_MSN_STATUS_CONNECTED,
- FS_MSN_STATUS_CONNECTED2,
- FS_MSN_STATUS_SEND_RECEIVE,
- FS_MSN_STATUS_PAUSED,
-} FsMsnStatus;
-
-typedef struct _FsMsnPollFD FsMsnPollFD;
-typedef void (*PollFdCallback) (FsMsnConnection *self, FsMsnPollFD *pollfd);
-
-struct _FsMsnPollFD {
- GstPollFD pollfd;
- FsMsnStatus status;
- gboolean server;
- gboolean want_read;
- gboolean want_write;
- PollFdCallback callback;
-};
-
-#define FS_MSN_CONNECTION_LOCK(conn) g_rec_mutex_lock(&(conn)->mutex)
-#define FS_MSN_CONNECTION_UNLOCK(conn) g_rec_mutex_unlock(&(conn)->mutex)
-
-
-G_DEFINE_TYPE(FsMsnConnection, fs_msn_connection, G_TYPE_OBJECT);
-
-static void fs_msn_connection_dispose (GObject *object);
-static void fs_msn_connection_finalize (GObject *object);
-static void fs_msn_connection_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void fs_msn_connection_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-
-
-static gboolean fs_msn_connection_attempt_connection_locked (
- FsMsnConnection *connection,
- FsCandidate *candidate,
- GError **error);
-static gboolean fs_msn_open_listening_port_unlock (FsMsnConnection *connection,
- guint16 port,
- GError **error);
-
-static void successful_connection_cb (FsMsnConnection *self, FsMsnPollFD *fd);
-static void accept_connection_cb (FsMsnConnection *self, FsMsnPollFD *fd);
-static void connection_cb (FsMsnConnection *self, FsMsnPollFD *fd);
-
-static gpointer connection_polling_thread (gpointer data);
-static void shutdown_fd (FsMsnConnection *self, FsMsnPollFD *pollfd,
- gboolean equal);
-static void shutdown_fd_locked (FsMsnConnection *self, FsMsnPollFD *pollfd,
- gboolean equal);
-static FsMsnPollFD * add_pollfd_locked (FsMsnConnection *self, int fd,
- PollFdCallback callback, gboolean read, gboolean write, gboolean server);
-
-static void
-fs_msn_connection_class_init (FsMsnConnectionClass *klass)
-{
- GObjectClass *gobject_class = (GObjectClass *) klass;
-
- gobject_class->dispose = fs_msn_connection_dispose;
- gobject_class->finalize = fs_msn_connection_finalize;
- gobject_class->get_property = fs_msn_connection_get_property;
- gobject_class->set_property = fs_msn_connection_set_property;
-
- signals[SIGNAL_NEW_LOCAL_CANDIDATE] = g_signal_new
- ("new-local-candidate",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, FS_TYPE_CANDIDATE);
-
- signals[SIGNAL_LOCAL_CANDIDATES_PREPARED] = g_signal_new
- ("local-candidates-prepared",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- signals[SIGNAL_CONNECTED] = g_signal_new
- ("connected",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__UINT,
- G_TYPE_NONE, 1, G_TYPE_UINT);
-
- signals[SIGNAL_CONNECTION_FAILED] = g_signal_new
- ("connection-failed",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_object_class_install_property (gobject_class,
- PROP_SESSION_ID,
- g_param_spec_uint ("session-id",
- "The session-id of the session",
- "This is the session-id of the MSN session",
- 1, 9999, 1,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-}
-
-static void
-fs_msn_connection_init (FsMsnConnection *self)
-{
- /* member init */
-
- self->poll_timeout = GST_CLOCK_TIME_NONE;
- self->poll = gst_poll_new (TRUE);
- gst_poll_set_flushing (self->poll, FALSE);
- self->pollfds = g_ptr_array_new ();
-
- g_rec_mutex_init (&self->mutex);
-}
-
-static void
-fs_msn_connection_dispose (GObject *object)
-{
- FsMsnConnection *self = FS_MSN_CONNECTION (object);
-
- FS_MSN_CONNECTION_LOCK(self);
-
- if (self->polling_thread)
- {
- GThread *polling_thread = g_thread_ref (self->polling_thread);
- gst_poll_set_flushing (self->poll, TRUE);
- FS_MSN_CONNECTION_UNLOCK(self);
- g_thread_join (polling_thread);
- FS_MSN_CONNECTION_LOCK(self);
- g_thread_unref (polling_thread);
- self->polling_thread = NULL;
- }
-
- FS_MSN_CONNECTION_UNLOCK(self);
-
- G_OBJECT_CLASS (fs_msn_connection_parent_class)->dispose (object);
-}
-
-static void
-fs_msn_connection_finalize (GObject *object)
-{
- FsMsnConnection *self = FS_MSN_CONNECTION (object);
- gint i;
-
- g_free (self->local_recipient_id);
- g_free (self->remote_recipient_id);
-
- gst_poll_free (self->poll);
-
- for (i = 0; i < self->pollfds->len; i++)
- {
- FsMsnPollFD *p = g_ptr_array_index(self->pollfds, i);
- close (p->pollfd.fd);
- g_slice_free (FsMsnPollFD, p);
- }
- g_ptr_array_free (self->pollfds, TRUE);
-
- g_rec_mutex_clear (&self->mutex);
-
- G_OBJECT_CLASS (fs_msn_connection_parent_class)->finalize (object);
-}
-
-/**
- * fs_msn_connection_new:
- * @session: The #FsMsnSession this connection is a child of
- * @participant: The #FsMsnParticipant this connection is for
- * @direction: the initial #FsDirection for this connection
- *
- *
- * This function create a new connection
- *
- * Returns: the newly created string or NULL on error
- */
-
-FsMsnConnection *
-fs_msn_connection_new (guint session_id, gboolean producer, guint initial_port)
-{
- FsMsnConnection *self = g_object_new (FS_TYPE_MSN_CONNECTION, NULL);
-
- if (self) {
- self->session_id = session_id;
- self->initial_port = initial_port;
- self->producer = producer;
- }
-
- return self;
-}
-
-static void
-fs_msn_connection_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- FsMsnConnection *self = FS_MSN_CONNECTION (object);
-
- FS_MSN_CONNECTION_LOCK (self);
- switch (prop_id)
- {
- case PROP_SESSION_ID:
- g_value_set_uint (value, self->session_id);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
- FS_MSN_CONNECTION_UNLOCK (self);
-}
-
-static void
-fs_msn_connection_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- FsMsnConnection *self = FS_MSN_CONNECTION (object);
-
- FS_MSN_CONNECTION_LOCK (self);
- switch (prop_id)
- {
- case PROP_SESSION_ID:
- self->session_id = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
- FS_MSN_CONNECTION_LOCK (self);
-
-}
-
-gboolean
-fs_msn_connection_gather_local_candidates (FsMsnConnection *self,
- GError **error)
-{
- gboolean ret;
-
- FS_MSN_CONNECTION_LOCK(self);
-
- self->polling_thread = g_thread_try_new ("msn polling thread",
- connection_polling_thread, self, error);
-
- if (!self->polling_thread)
- {
- FS_MSN_CONNECTION_UNLOCK(self);
- return FALSE;
- }
-
- ret = fs_msn_open_listening_port_unlock (self, self->initial_port, error);
-
- g_signal_emit (self, signals[SIGNAL_LOCAL_CANDIDATES_PREPARED], 0);
-
- return ret;
-}
-
-
-/**
- * fs_msn_connection_add_remote_candidate:
- */
-gboolean
-fs_msn_connection_add_remote_candidates (FsMsnConnection *self,
- GList *candidates, GError **error)
-{
- GList *item = NULL;
- gchar *recipient_id = NULL;
- gboolean ret = FALSE;
- guint session_id = 0;
-
- if (!candidates)
- {
- g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
- "Candidate list can no be empty");
- return FALSE;
- }
-
- FS_MSN_CONNECTION_LOCK(self);
-
- recipient_id = self->remote_recipient_id;
-
- for (item = candidates; item; item = g_list_next (item))
- {
- FsCandidate *candidate = item->data;
-
- if (!candidate->ip || !candidate->port)
- {
- g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
- "The candidate passed does not contain a valid ip or port");
- goto out;
- }
- if (!candidate->foundation)
- {
- g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
- "The candidate passed does not have a foundation (MSN recipient ID)");
- goto out;
- }
- if (recipient_id)
- {
- if (g_strcmp0 (candidate->foundation, recipient_id) != 0)
- {
- g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
- "The candidates do not have the same recipient ID");
- goto out;
- }
- }
- else
- {
- recipient_id = candidate->foundation;
- }
-
- if (candidate->username)
- {
- gint sid = atoi (candidate->username);
-
- if (sid < 1 || sid > 9999)
- {
- g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
- "The session ID (in the username) must be between 1 and 9999,"
- " %d is invalid", sid);
- goto out;
- }
-
- if (session_id)
- {
- if (session_id != sid)
- {
- g_set_error (error, FS_ERROR, FS_ERROR_INVALID_ARGUMENTS,
- "The candidates do not have the same session ID"
- " (in the username)");
- goto out;
- }
- }
- else
- {
- session_id = sid;
- }
- }
- }
-
- self->remote_recipient_id = g_strdup (recipient_id);
- self->session_id = session_id;
- ret = TRUE;
- for (item = candidates; item; item = g_list_next (item))
- {
- FsCandidate *candidate = item->data;
- if (!fs_msn_connection_attempt_connection_locked (self, candidate, error))
- {
- ret = FALSE;
- break;
- }
- }
-
- out:
- FS_MSN_CONNECTION_UNLOCK(self);
- return ret;
-}
-
-
-
-static GList *
-filter_ips_ipv4 (GList *ips)
-{
- GList *item;
-
- for (item = ips; item;)
- {
- gchar *ip = item->data;
- GList *next = item->next;
-
- if (!strchr (ip, '.'))
- {
- g_free (ip);
- ips = g_list_delete_link (ips, item);
- }
- item = next;
- }
-
- return ips;
-}
-
-static gboolean
-fs_msn_open_listening_port_unlock (FsMsnConnection *self, guint16 port,
- GError **error)
-{
- gint fd = -1;
- struct sockaddr_in myaddr;
- guint myaddr_len = sizeof (struct sockaddr_in);
- FsCandidate * candidate = NULL;
- GList *addresses = nice_interfaces_get_local_ips (FALSE);
- GList *item = NULL;
- gchar *session_id;
-
- addresses = filter_ips_ipv4 (addresses);
-
-
- GST_DEBUG ("Attempting to listen on port %d.....",port);
-
- if ( (fd = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- g_set_error (error, FS_ERROR, FS_ERROR_NETWORK,
- "Could not create socket: %s", error_str);
- goto error;
- }
-
- // set non-blocking mode
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
- for (;;) {
- GST_DEBUG ("Attempting to listen on port %d.....",port);
- memset(&myaddr, 0, sizeof(myaddr));
- myaddr.sin_family = AF_INET;
- myaddr.sin_port = htons (port);
- // bind
- if (bind(fd, (struct sockaddr *) &myaddr, sizeof(myaddr)) != 0)
- {
- if (port != 0 && errno == EADDRINUSE)
- {
- port++;
- }
- else
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- g_set_error (error, FS_ERROR, FS_ERROR_NETWORK,
- "Could not bind socket: %s", error_str);
- goto error;
- }
- } else {
- /* Listen */
- if (listen(fd, 3) != 0)
- {
- if (port != 0 && errno == EADDRINUSE)
- {
- port++;
- }
- else
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- g_set_error (error, FS_ERROR, FS_ERROR_NETWORK,
- "Could not listen on socket: %s", error_str);
- goto error;
- }
- }
- else
- {
- goto done;
- }
- }
- }
-
- done:
-
- if (getsockname (fd, (struct sockaddr *) &myaddr, &myaddr_len) < 0) {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- g_set_error (error, FS_ERROR, FS_ERROR_NETWORK,
- "Could not get the socket name: %s", error_str);
- goto error;
- }
- port = ntohs (myaddr.sin_port);
- add_pollfd_locked (self, fd, accept_connection_cb, TRUE, TRUE, FALSE);
-
- GST_DEBUG ("Listening on port %d", port);
-
- self->local_recipient_id = g_strdup_printf ("%d",
- g_random_int_range (100, 199));
- session_id = g_strdup_printf ("%u", self->session_id);
-
- FS_MSN_CONNECTION_UNLOCK (self);
-
- for (item = addresses;
- item;
- item = g_list_next (item))
- {
- candidate = fs_candidate_new (self->local_recipient_id, 1,
- FS_CANDIDATE_TYPE_HOST, FS_NETWORK_PROTOCOL_TCP, item->data, port);
- candidate->username = g_strdup (session_id);
-
- g_signal_emit (self, signals[SIGNAL_NEW_LOCAL_CANDIDATE], 0, candidate);
-
- fs_candidate_destroy (candidate);
- }
-
- g_free (session_id);
-
- g_list_foreach (addresses, (GFunc) g_free, NULL);
- g_list_free (addresses);
-
- return TRUE;
-
- error:
- if (fd >= 0)
- close (fd);
- g_list_foreach (addresses, (GFunc) g_free, NULL);
- g_list_free (addresses);
- FS_MSN_CONNECTION_UNLOCK (self);
- return FALSE;
-}
-
-static gboolean
-fs_msn_connection_attempt_connection_locked (FsMsnConnection *connection,
- FsCandidate *candidate,
- GError **error)
-{
- FsMsnConnection *self = FS_MSN_CONNECTION (connection);
- gint fd = -1;
- gint ret;
- struct sockaddr_in theiraddr;
- memset(&theiraddr, 0, sizeof(theiraddr));
-
-
- if ( (fd = socket(PF_INET, SOCK_STREAM, 0)) == -1 )
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- g_set_error (error, FS_ERROR, FS_ERROR_NETWORK,
- "Could not create socket: %s", error_str);
- return FALSE;
- }
-
- // set non-blocking mode
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
-
- theiraddr.sin_family = AF_INET;
- theiraddr.sin_addr.s_addr = inet_addr (candidate->ip);
- theiraddr.sin_port = htons (candidate->port);
-
- GST_DEBUG ("Attempting connection to %s %d on socket %d", candidate->ip,
- candidate->port, fd);
- // this is non blocking, the return value isn't too usefull
- ret = connect (fd, (struct sockaddr *) &theiraddr, sizeof (theiraddr));
- if (ret < 0 && errno != EINPROGRESS)
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- g_set_error (error, FS_ERROR, FS_ERROR_NETWORK,
- "Could not connect socket: %s", error_str);
- close (fd);
- return FALSE;
- }
-
- FS_MSN_CONNECTION_LOCK (self);
- add_pollfd_locked (self, fd, successful_connection_cb, TRUE, TRUE, FALSE);
- FS_MSN_CONNECTION_UNLOCK (self);
-
- return TRUE;
-}
-
-static void
-accept_connection_cb (FsMsnConnection *self, FsMsnPollFD *pollfd)
-{
- struct sockaddr_in in;
- int fd = -1;
- socklen_t n = sizeof (in);
-
- if (gst_poll_fd_has_error (self->poll, &pollfd->pollfd) ||
- gst_poll_fd_has_closed (self->poll, &pollfd->pollfd))
- {
- GST_WARNING ("Error in accept socket : %d", pollfd->pollfd.fd);
- goto error;
- }
-
- if ((fd = accept(pollfd->pollfd.fd,
- (struct sockaddr*) &in, &n)) == -1)
- {
- GST_ERROR ("Error while running accept() %d", errno);
- return;
- }
-
- FS_MSN_CONNECTION_LOCK (self);
- add_pollfd_locked (self, fd, connection_cb, TRUE, FALSE, TRUE);
- FS_MSN_CONNECTION_UNLOCK (self);
-
- return;
-
- /* Error */
- error:
- GST_WARNING ("Got error from fd %d, closing", fd);
- // find, shutdown and remove channel from fdlist
- shutdown_fd (self, pollfd, TRUE);
-
- return;
-}
-
-
-static void
-successful_connection_cb (FsMsnConnection *self, FsMsnPollFD *pollfd)
-{
- gint error;
- socklen_t option_len;
-
- GST_DEBUG ("handler called on fd %d", pollfd->pollfd.fd);
-
- errno = 0;
- if (gst_poll_fd_has_error (self->poll, &pollfd->pollfd) ||
- gst_poll_fd_has_closed (self->poll, &pollfd->pollfd))
- {
- GST_WARNING ("connecton closed or error");
- goto error;
- }
-
- option_len = sizeof(error);
-
- /* Get the error option */
- if (getsockopt(pollfd->pollfd.fd, SOL_SOCKET, SO_ERROR, (void*) &error, &option_len) < 0)
- {
- g_warning ("getsockopt() failed");
- goto error;
- }
-
- /* Check if there is an error */
- if (error)
- {
- GST_WARNING ("getsockopt gave an error : %d", error);
- goto error;
- }
-
- pollfd->callback = connection_cb;
-
- GST_DEBUG ("connection succeeded on socket %p", pollfd);
- return;
-
- /* Error */
- error:
- GST_WARNING ("Got error from fd %d, closing", pollfd->pollfd.fd);
- // find, shutdown and remove channel from fdlist
- shutdown_fd (self, pollfd, TRUE);
-
- return;
-}
-
-
-static void
-connection_cb (FsMsnConnection *self, FsMsnPollFD *pollfd)
-{
- gboolean success = FALSE;
-
- GST_DEBUG ("handler called on fd:%d server: %d status:%d r:%d w:%d",
- pollfd->pollfd.fd,
- pollfd->server, pollfd->status,
- gst_poll_fd_can_read (self->poll, &pollfd->pollfd),
- gst_poll_fd_can_write (self->poll, &pollfd->pollfd));
-
- if (gst_poll_fd_has_error (self->poll, &pollfd->pollfd) ||
- gst_poll_fd_has_closed (self->poll, &pollfd->pollfd))
- {
- GST_WARNING ("connecton closed or error (error: %d closed: %d)",
- gst_poll_fd_has_error (self->poll, &pollfd->pollfd),
- gst_poll_fd_has_closed (self->poll, &pollfd->pollfd));
- goto error;
- }
-
- if (gst_poll_fd_can_read (self->poll, &pollfd->pollfd))
- {
- switch (pollfd->status)
- {
- case FS_MSN_STATUS_AUTH:
- if (pollfd->server)
- {
- gchar str[35] = {0};
- gchar check[35] = {0};
-
- if (recv (pollfd->pollfd.fd, str, 34, 0) == 34)
- {
- GST_DEBUG ("Got %s, checking if it's auth", str);
- FS_MSN_CONNECTION_LOCK(self);
- snprintf(check, 35, "recipientid=%s&sessionid=%d\r\n\r\n",
- self->local_recipient_id, self->session_id);
- FS_MSN_CONNECTION_UNLOCK(self);
- if (strncmp (str, check, 35) == 0)
- {
- GST_DEBUG ("Authentication successful");
- pollfd->status = FS_MSN_STATUS_CONNECTED;
- pollfd->want_write = TRUE;
- gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, TRUE);
- }
- else
- {
- GST_WARNING ("Authentication failed check=%s", check);
- goto error;
- }
- }
- else
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- GST_WARNING ("auth: %s", error_str);
- goto error;
- }
-
- } else {
- GST_ERROR ("shouldn't receive data when client on AUTH state");
- goto error;
- }
- break;
- case FS_MSN_STATUS_CONNECTED:
- if (!pollfd->server)
- {
- gchar str[14] = {0};
- ssize_t size;
-
- size = recv (pollfd->pollfd.fd, str, 13, MSG_PEEK);
- if (size > 0)
- {
- GST_DEBUG ("Got %s, checking if it's connected", str);
- if (size == 13 && strcmp (str, "connected\r\n\r\n") == 0)
- {
- GST_DEBUG ("connection successful");
- if (recv (pollfd->pollfd.fd, str, 13, 0) != 13)
- {
- GST_WARNING ("Could not read 13 bytes that had previously"
- " been peeked at!");
- goto error;
- }
- pollfd->status = FS_MSN_STATUS_CONNECTED2;
- pollfd->want_write = TRUE;
- gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, TRUE);
- }
- else if (!self->producer)
- {
- GST_DEBUG ("connection successful");
- pollfd->status = FS_MSN_STATUS_SEND_RECEIVE;
- success = TRUE;
- }
- else
- {
- GST_WARNING ("connected failed");
- goto error;
- }
- }
- else
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- GST_WARNING ("recv: %s", error_str);
- goto error;
- }
- } else {
- GST_ERROR ("shouldn't receive data when server on CONNECTED state");
- goto error;
- }
- break;
- case FS_MSN_STATUS_CONNECTED2:
- if (pollfd->server)
- {
- gchar str[14] = {0};
- ssize_t size;
-
- size = recv (pollfd->pollfd.fd, str, 13, MSG_PEEK);
- if (size > 0)
- {
- GST_DEBUG ("Got %s, checking if it's connected", str);
- if (size == 13 && strcmp (str, "connected\r\n\r\n") == 0)
- {
- GST_DEBUG ("connection successful");
- if (recv (pollfd->pollfd.fd, str, 13, 0) != 13)
- {
- GST_WARNING ("Could not read 13 bytes that had previously"
- " been peeked at!");
-
- goto error;
- }
- pollfd->status = FS_MSN_STATUS_SEND_RECEIVE;
- success = TRUE;
- }
- else if (!self->producer)
- {
- GST_DEBUG ("connection successful");
- pollfd->status = FS_MSN_STATUS_SEND_RECEIVE;
- success = TRUE;
- }
- else
- {
- GST_WARNING ("connected failed");
- goto error;
- }
- }
- else
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- GST_WARNING ("recv: %s", error_str);
- goto error;
- }
-
- } else {
- GST_ERROR ("shouldn't receive data when client on CONNECTED2 state");
- goto error;
- }
- break;
- default:
- GST_ERROR ("Invalid status %d", pollfd->status);
- goto error;
- break;
-
- }
- }
- else if (gst_poll_fd_can_write (self->poll, &pollfd->pollfd))
- {
- pollfd->want_write = FALSE;
- gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, FALSE);
- switch (pollfd->status)
- {
- case FS_MSN_STATUS_AUTH:
- if (!pollfd->server)
- {
- gchar *str;
- FS_MSN_CONNECTION_LOCK(self);
- str = g_strdup_printf("recipientid=%s&sessionid=%d\r\n\r\n",
- self->remote_recipient_id, self->session_id);
- FS_MSN_CONNECTION_UNLOCK(self);
- if (send(pollfd->pollfd.fd, str, strlen (str), 0) != -1)
- {
- GST_DEBUG ("Sent %s", str);
- pollfd->status = FS_MSN_STATUS_CONNECTED;
- g_free (str);
- }
- else
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- GST_WARNING ("auth send: %s", error_str);
- g_free (str);
- goto error;
- }
-
- }
- break;
- case FS_MSN_STATUS_CONNECTED:
- if (pollfd->server)
- {
-
- if (send(pollfd->pollfd.fd, "connected\r\n\r\n", 13, 0) != -1)
- {
- GST_DEBUG ("sent connected");
- if (self->producer)
- {
- pollfd->status = FS_MSN_STATUS_SEND_RECEIVE;
- success = TRUE;
- }
- else
- {
- pollfd->status = FS_MSN_STATUS_CONNECTED2;
- }
- }
- else
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- GST_WARNING ("sending connected: %s", error_str);
- goto error;
- }
- } else {
- GST_DEBUG ("shouldn't receive data when server on CONNECTED state");
- goto error;
- }
- break;
- case FS_MSN_STATUS_CONNECTED2:
- if (!pollfd->server)
- {
-
- if (send(pollfd->pollfd.fd, "connected\r\n\r\n", 13, 0) != -1)
- {
- GST_DEBUG ("sent connected");
- pollfd->status = FS_MSN_STATUS_SEND_RECEIVE;
- success = TRUE;
- }
- else
- {
- gchar error_str[256];
- strerror_r (errno, error_str, 256);
- GST_WARNING ("sending connected: %s", error_str);
- goto error;
- }
- } else {
- GST_ERROR ("shouldn't receive data when client on CONNECTED2 state");
- goto error;
- }
- break;
- default:
- GST_ERROR ("Invalid status %d", pollfd->status);
- goto error;
- break;
- }
- }
-
- if (success) {
- // success! we need to shutdown/close all other channels
- shutdown_fd (self, pollfd, FALSE);
-
- g_signal_emit (self, signals[SIGNAL_CONNECTED], 0, pollfd->pollfd.fd);
-
- pollfd->want_read = FALSE;
- pollfd->want_write = FALSE;
- gst_poll_fd_ctl_read (self->poll, &pollfd->pollfd, FALSE);
- gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, FALSE);
- }
-
- return;
- error:
- /* Error */
- GST_WARNING ("Got error from fd %d, closing", pollfd->pollfd.fd);
- shutdown_fd (self, pollfd, TRUE);
-
- FS_MSN_CONNECTION_LOCK (self);
- success = (self->pollfds->len > 1);
- FS_MSN_CONNECTION_UNLOCK (self);
-
- if (!success)
- g_signal_emit (self, signals[SIGNAL_CONNECTION_FAILED], 0);
-
- return;
-}
-
-static gpointer
-connection_polling_thread (gpointer data)
-{
- FsMsnConnection *self = data;
- gint ret;
- GstClockTime timeout;
- GstPoll * poll;
-
- FS_MSN_CONNECTION_LOCK(self);
- timeout = self->poll_timeout;
- poll = self->poll;
- GST_DEBUG ("poll waiting %d", self->pollfds->len);
- FS_MSN_CONNECTION_UNLOCK(self);
-
- while ((ret = gst_poll_wait (poll, timeout)) >= 0)
- {
- GST_DEBUG ("gst_poll_wait returned : %d", ret);
- FS_MSN_CONNECTION_LOCK(self);
- if (ret > 0)
- {
- gint i;
-
- for (i = 0; i < self->pollfds->len; i++)
- {
- FsMsnPollFD *pollfd = NULL;
-
- pollfd = g_ptr_array_index(self->pollfds, i);
-
- GST_DEBUG ("ret %d - i = %d, len = %d", ret, i, self->pollfds->len);
-
- GST_DEBUG ("%p - error %d, close %d, read %d-%d, write %d-%d",
- pollfd,
- gst_poll_fd_has_error (poll, &pollfd->pollfd),
- gst_poll_fd_has_closed (poll, &pollfd->pollfd),
- pollfd->want_read,
- gst_poll_fd_can_read (poll, &pollfd->pollfd),
- pollfd->want_write,
- gst_poll_fd_can_write (poll, &pollfd->pollfd));
-
- if (gst_poll_fd_has_error (poll, &pollfd->pollfd) ||
- gst_poll_fd_has_closed (poll, &pollfd->pollfd))
- {
- pollfd->callback (self, pollfd);
- shutdown_fd_locked (self, pollfd, TRUE);
- i--;
- continue;
- }
- if ((pollfd->want_read &&
- gst_poll_fd_can_read (poll, &pollfd->pollfd)) ||
- (pollfd->want_write &&
- gst_poll_fd_can_write (poll, &pollfd->pollfd)))
- {
- pollfd->callback (self, pollfd);
- }
-
- }
- }
- timeout = self->poll_timeout;
- FS_MSN_CONNECTION_UNLOCK(self);
- }
-
- return NULL;
-}
-
-
-static void
-shutdown_fd (FsMsnConnection *self, FsMsnPollFD *pollfd, gboolean equal)
-{
- FS_MSN_CONNECTION_LOCK (self);
- shutdown_fd_locked (self, pollfd, equal);
- FS_MSN_CONNECTION_UNLOCK (self);
-}
-
-static void
-shutdown_fd_locked (FsMsnConnection *self, FsMsnPollFD *pollfd, gboolean equal)
-{
- gint i;
- guint closed = 0;
-
- for (i = 0; i < self->pollfds->len; i++)
- {
- FsMsnPollFD *p = g_ptr_array_index(self->pollfds, i);
- if ((equal && p == pollfd) || (!equal && p != pollfd))
- {
- GST_DEBUG ("Shutting down p %p (fd %d)", p, p->pollfd.fd);
-
- if (!gst_poll_fd_has_closed (self->poll, &p->pollfd))
- close (p->pollfd.fd);
- if (!gst_poll_remove_fd (self->poll, &p->pollfd))
- GST_WARNING ("Could not remove pollfd %p", p);
- g_ptr_array_remove_index_fast (self->pollfds, i);
- g_slice_free (FsMsnPollFD, p);
- closed++;
- i--;
- }
- }
-
- if (closed)
- gst_poll_restart (self->poll);
- else
- GST_WARNING ("Could find pollfd to remove");
-}
-
-static FsMsnPollFD *
-add_pollfd_locked (FsMsnConnection *self, int fd, PollFdCallback callback,
- gboolean read, gboolean write, gboolean server)
-{
- FsMsnPollFD *pollfd = g_slice_new0 (FsMsnPollFD);
- gst_poll_fd_init (&pollfd->pollfd);
- pollfd->pollfd.fd = fd;
- pollfd->server = server;
- pollfd->want_read = read;
- pollfd->want_write = write;
- pollfd->status = FS_MSN_STATUS_AUTH;
-
- gst_poll_add_fd (self->poll, &pollfd->pollfd);
-
- gst_poll_fd_ctl_read (self->poll, &pollfd->pollfd, read);
- gst_poll_fd_ctl_write (self->poll, &pollfd->pollfd, write);
- pollfd->callback = callback;
-
- GST_DEBUG ("ADD_POLLFD %p (%p) - error %d, close %d, read %d-%d, write %d-%d",
- self->pollfds, pollfd,
- gst_poll_fd_has_error (self->poll, &pollfd->pollfd),
- gst_poll_fd_has_closed (self->poll, &pollfd->pollfd),
- pollfd->want_read,
- gst_poll_fd_can_read (self->poll, &pollfd->pollfd),
- pollfd->want_write,
- gst_poll_fd_can_write (self->poll, &pollfd->pollfd));
-
- g_ptr_array_add (self->pollfds, pollfd);
- gst_poll_restart (self->poll);
- return pollfd;
-}