sctp: Clean up association state handling and go into error/disconnected state in more circumstances
This commit is contained in:
parent
8612da865e
commit
6d22e80f30
@ -856,12 +856,13 @@ on_sctp_association_state_changed (GstSctpAssociation * sctp_association,
|
|||||||
TRUE);
|
TRUE);
|
||||||
break;
|
break;
|
||||||
case GST_SCTP_ASSOCIATION_STATE_DISCONNECTING:
|
case GST_SCTP_ASSOCIATION_STATE_DISCONNECTING:
|
||||||
|
case GST_SCTP_ASSOCIATION_STATE_DISCONNECTED:
|
||||||
g_signal_emit (self, signals[SIGNAL_SCTP_ASSOCIATION_ESTABLISHED], 0,
|
g_signal_emit (self, signals[SIGNAL_SCTP_ASSOCIATION_ESTABLISHED], 0,
|
||||||
FALSE);
|
FALSE);
|
||||||
break;
|
break;
|
||||||
case GST_SCTP_ASSOCIATION_STATE_DISCONNECTED:
|
|
||||||
break;
|
|
||||||
case GST_SCTP_ASSOCIATION_STATE_ERROR:
|
case GST_SCTP_ASSOCIATION_STATE_ERROR:
|
||||||
|
GST_ELEMENT_ERROR (self, RESOURCE, WRITE, (NULL),
|
||||||
|
("SCTP association went into error state"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ static void handle_message (GstSctpAssociation * self, guint8 * data,
|
|||||||
guint32 datalen, guint16 stream_id, guint32 ppid);
|
guint32 datalen, guint16 stream_id, guint32 ppid);
|
||||||
|
|
||||||
static void maybe_set_state_to_ready (GstSctpAssociation * self);
|
static void maybe_set_state_to_ready (GstSctpAssociation * self);
|
||||||
static void gst_sctp_association_change_state (GstSctpAssociation * self,
|
static gboolean gst_sctp_association_change_state (GstSctpAssociation * self,
|
||||||
GstSctpAssociationState new_state, gboolean notify);
|
GstSctpAssociationState new_state, gboolean notify);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -281,18 +281,14 @@ maybe_set_state_to_ready (GstSctpAssociation * self)
|
|||||||
if ((self->state == GST_SCTP_ASSOCIATION_STATE_NEW) &&
|
if ((self->state == GST_SCTP_ASSOCIATION_STATE_NEW) &&
|
||||||
(self->local_port != 0 && self->remote_port != 0)
|
(self->local_port != 0 && self->remote_port != 0)
|
||||||
&& (self->packet_out_cb != NULL) && (self->packet_received_cb != NULL)) {
|
&& (self->packet_out_cb != NULL) && (self->packet_received_cb != NULL)) {
|
||||||
signal_ready_state = TRUE;
|
signal_ready_state =
|
||||||
gst_sctp_association_change_state (self, GST_SCTP_ASSOCIATION_STATE_READY,
|
gst_sctp_association_change_state (self,
|
||||||
FALSE);
|
GST_SCTP_ASSOCIATION_STATE_READY, FALSE);
|
||||||
}
|
}
|
||||||
g_rec_mutex_unlock (&self->association_mutex);
|
g_rec_mutex_unlock (&self->association_mutex);
|
||||||
|
|
||||||
/* The reason the state is changed twice is that we do not want to change state with
|
|
||||||
* notification while the association_mutex is locked. If someone listens
|
|
||||||
* on property change and call this object a deadlock might occur.*/
|
|
||||||
if (signal_ready_state)
|
if (signal_ready_state)
|
||||||
gst_sctp_association_change_state (self, GST_SCTP_ASSOCIATION_STATE_READY,
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE]);
|
||||||
TRUE);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,6 +355,7 @@ gboolean
|
|||||||
gst_sctp_association_start (GstSctpAssociation * self)
|
gst_sctp_association_start (GstSctpAssociation * self)
|
||||||
{
|
{
|
||||||
gchar *thread_name;
|
gchar *thread_name;
|
||||||
|
gboolean signal_state = FALSE;
|
||||||
|
|
||||||
g_rec_mutex_lock (&self->association_mutex);
|
g_rec_mutex_lock (&self->association_mutex);
|
||||||
if (self->state != GST_SCTP_ASSOCIATION_STATE_READY) {
|
if (self->state != GST_SCTP_ASSOCIATION_STATE_READY) {
|
||||||
@ -370,21 +367,18 @@ gst_sctp_association_start (GstSctpAssociation * self)
|
|||||||
if ((self->sctp_ass_sock = create_sctp_socket (self)) == NULL)
|
if ((self->sctp_ass_sock = create_sctp_socket (self)) == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
gst_sctp_association_change_state (self,
|
signal_state |= gst_sctp_association_change_state (self,
|
||||||
GST_SCTP_ASSOCIATION_STATE_CONNECTING, FALSE);
|
GST_SCTP_ASSOCIATION_STATE_CONNECTING, FALSE);
|
||||||
g_rec_mutex_unlock (&self->association_mutex);
|
g_rec_mutex_unlock (&self->association_mutex);
|
||||||
|
|
||||||
/* The reason the state is changed twice is that we do not want to change state with
|
|
||||||
* notification while the association_mutex is locked. If someone listens
|
|
||||||
* on property change and call this object a deadlock might occur.*/
|
|
||||||
gst_sctp_association_change_state (self,
|
|
||||||
GST_SCTP_ASSOCIATION_STATE_CONNECTING, TRUE);
|
|
||||||
|
|
||||||
thread_name = g_strdup_printf ("connection_thread_%u", self->association_id);
|
thread_name = g_strdup_printf ("connection_thread_%u", self->association_id);
|
||||||
self->connection_thread = g_thread_new (thread_name,
|
self->connection_thread = g_thread_new (thread_name,
|
||||||
(GThreadFunc) connection_thread_func, self);
|
(GThreadFunc) connection_thread_func, self);
|
||||||
g_free (thread_name);
|
g_free (thread_name);
|
||||||
|
|
||||||
|
if (signal_state)
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE]);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
error:
|
error:
|
||||||
g_rec_mutex_unlock (&self->association_mutex);
|
g_rec_mutex_unlock (&self->association_mutex);
|
||||||
@ -525,6 +519,8 @@ gst_sctp_association_force_close (GstSctpAssociation * self)
|
|||||||
|
|
||||||
}
|
}
|
||||||
g_rec_mutex_unlock (&self->association_mutex);
|
g_rec_mutex_unlock (&self->association_mutex);
|
||||||
|
gst_sctp_association_change_state (self,
|
||||||
|
GST_SCTP_ASSOCIATION_STATE_DISCONNECTED, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct socket *
|
static struct socket *
|
||||||
@ -636,7 +632,10 @@ static gpointer
|
|||||||
connection_thread_func (GstSctpAssociation * self)
|
connection_thread_func (GstSctpAssociation * self)
|
||||||
{
|
{
|
||||||
/* TODO: Support both server and client role */
|
/* TODO: Support both server and client role */
|
||||||
client_role_connect (self);
|
if (!client_role_connect (self))
|
||||||
|
gst_sctp_association_change_state (self, GST_SCTP_ASSOCIATION_STATE_ERROR,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,13 +730,16 @@ handle_notification (GstSctpAssociation * self,
|
|||||||
GST_DEBUG_OBJECT (self, "Event: SCTP_PEER_ADDR_CHANGE");
|
GST_DEBUG_OBJECT (self, "Event: SCTP_PEER_ADDR_CHANGE");
|
||||||
break;
|
break;
|
||||||
case SCTP_REMOTE_ERROR:
|
case SCTP_REMOTE_ERROR:
|
||||||
GST_ERROR_OBJECT (self, "Event: SCTP_REMOTE_ERROR");
|
GST_ERROR_OBJECT (self, "Event: SCTP_REMOTE_ERROR (%u)",
|
||||||
|
notification->sn_remote_error.sre_error);
|
||||||
break;
|
break;
|
||||||
case SCTP_SEND_FAILED:
|
case SCTP_SEND_FAILED:
|
||||||
GST_ERROR_OBJECT (self, "Event: SCTP_SEND_FAILED");
|
GST_ERROR_OBJECT (self, "Event: SCTP_SEND_FAILED");
|
||||||
break;
|
break;
|
||||||
case SCTP_SHUTDOWN_EVENT:
|
case SCTP_SHUTDOWN_EVENT:
|
||||||
GST_DEBUG_OBJECT (self, "Event: SCTP_SHUTDOWN_EVENT");
|
GST_DEBUG_OBJECT (self, "Event: SCTP_SHUTDOWN_EVENT");
|
||||||
|
gst_sctp_association_change_state (self,
|
||||||
|
GST_SCTP_ASSOCIATION_STATE_DISCONNECTING, TRUE);
|
||||||
break;
|
break;
|
||||||
case SCTP_ADAPTATION_INDICATION:
|
case SCTP_ADAPTATION_INDICATION:
|
||||||
GST_DEBUG_OBJECT (self, "Event: SCTP_ADAPTATION_INDICATION");
|
GST_DEBUG_OBJECT (self, "Event: SCTP_ADAPTATION_INDICATION");
|
||||||
@ -765,7 +767,8 @@ handle_notification (GstSctpAssociation * self,
|
|||||||
GST_DEBUG_OBJECT (self, "Event: SCTP_STREAM_CHANGE_EVENT");
|
GST_DEBUG_OBJECT (self, "Event: SCTP_STREAM_CHANGE_EVENT");
|
||||||
break;
|
break;
|
||||||
case SCTP_SEND_FAILED_EVENT:
|
case SCTP_SEND_FAILED_EVENT:
|
||||||
GST_ERROR_OBJECT (self, "Event: SCTP_SEND_FAILED_EVENT");
|
GST_ERROR_OBJECT (self, "Event: SCTP_SEND_FAILED_EVENT (%u)",
|
||||||
|
notification->sn_send_failed_event.ssfe_error);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -796,17 +799,21 @@ handle_association_changed (GstSctpAssociation * self,
|
|||||||
break;
|
break;
|
||||||
case SCTP_COMM_LOST:
|
case SCTP_COMM_LOST:
|
||||||
GST_WARNING_OBJECT (self, "SCTP event SCTP_COMM_LOST received");
|
GST_WARNING_OBJECT (self, "SCTP event SCTP_COMM_LOST received");
|
||||||
/* TODO: Tear down association and signal that this has happend */
|
change_state = TRUE;
|
||||||
|
new_state = GST_SCTP_ASSOCIATION_STATE_ERROR;
|
||||||
break;
|
break;
|
||||||
case SCTP_RESTART:
|
case SCTP_RESTART:
|
||||||
GST_DEBUG_OBJECT (self, "SCTP event SCTP_RESTART received");
|
GST_DEBUG_OBJECT (self, "SCTP event SCTP_RESTART received");
|
||||||
break;
|
break;
|
||||||
case SCTP_SHUTDOWN_COMP:
|
case SCTP_SHUTDOWN_COMP:
|
||||||
GST_WARNING_OBJECT (self, "SCTP event SCTP_SHUTDOWN_COMP received");
|
GST_DEBUG_OBJECT (self, "SCTP event SCTP_SHUTDOWN_COMP received");
|
||||||
/* TODO: Tear down association and signal that this has happend */
|
change_state = TRUE;
|
||||||
|
new_state = GST_SCTP_ASSOCIATION_STATE_DISCONNECTED;
|
||||||
break;
|
break;
|
||||||
case SCTP_CANT_STR_ASSOC:
|
case SCTP_CANT_STR_ASSOC:
|
||||||
GST_WARNING_OBJECT (self, "SCTP event SCTP_CANT_STR_ASSOC received");
|
GST_WARNING_OBJECT (self, "SCTP event SCTP_CANT_STR_ASSOC received");
|
||||||
|
change_state = TRUE;
|
||||||
|
new_state = GST_SCTP_ASSOCIATION_STATE_ERROR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -851,11 +858,21 @@ handle_message (GstSctpAssociation * self, guint8 * data, guint32 datalen,
|
|||||||
g_rec_mutex_unlock (&self->association_mutex);
|
g_rec_mutex_unlock (&self->association_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* Returns TRUE if notify==FALSE and notification is needed later */
|
||||||
|
static gboolean
|
||||||
gst_sctp_association_change_state (GstSctpAssociation * self,
|
gst_sctp_association_change_state (GstSctpAssociation * self,
|
||||||
GstSctpAssociationState new_state, gboolean notify)
|
GstSctpAssociationState new_state, gboolean notify)
|
||||||
{
|
{
|
||||||
self->state = new_state;
|
if (self->state != new_state
|
||||||
if (notify)
|
&& self->state != GST_SCTP_ASSOCIATION_STATE_ERROR) {
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE]);
|
self->state = new_state;
|
||||||
|
if (notify) {
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE]);
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user