2 * Copyright (c) 2015, Collabora Ltd.
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or other
12 * materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30 #include "sctpassociation.h"
36 #define GST_SCTP_ASSOCIATION_STATE_TYPE (gst_sctp_association_state_get_type())
38 gst_sctp_association_state_get_type (void)
40 static const GEnumValue values[] = {
41 {GST_SCTP_ASSOCIATION_STATE_NEW, "state-new", "state-new"},
42 {GST_SCTP_ASSOCIATION_STATE_READY, "state-ready", "state-ready"},
43 {GST_SCTP_ASSOCIATION_STATE_CONNECTING, "state-connecting",
45 {GST_SCTP_ASSOCIATION_STATE_CONNECTED, "state-connected",
47 {GST_SCTP_ASSOCIATION_STATE_DISCONNECTING, "state-disconnecting",
48 "state-disconnecting"},
49 {GST_SCTP_ASSOCIATION_STATE_DISCONNECTED, "state-disconnected",
50 "state-disconnected"},
51 {GST_SCTP_ASSOCIATION_STATE_ERROR, "state-error", "state-error"},
54 static volatile GType id = 0;
56 if (g_once_init_enter ((gsize *) & id)) {
58 _id = g_enum_register_static ("GstSctpAssociationState", values);
59 g_once_init_leave ((gsize *) & id, _id);
65 G_DEFINE_TYPE (GstSctpAssociation, gst_sctp_association, G_TYPE_OBJECT);
87 static guint signals[LAST_SIGNAL] = { 0 };
89 static GParamSpec *properties[NUM_PROPERTIES];
91 #define DEFAULT_NUMBER_OF_SCTP_STREAMS 10
92 #define DEFAULT_LOCAL_SCTP_PORT 0
93 #define DEFAULT_REMOTE_SCTP_PORT 0
95 static GHashTable *associations = NULL;
96 G_LOCK_DEFINE_STATIC (associations_lock);
97 static guint32 number_of_associations = 0;
99 /* Interface implementations */
100 static void gst_sctp_association_finalize (GObject * object);
101 static void gst_sctp_association_set_property (GObject * object, guint prop_id,
102 const GValue * value, GParamSpec * pspec);
103 static void gst_sctp_association_get_property (GObject * object, guint prop_id,
104 GValue * value, GParamSpec * pspec);
106 static struct socket *create_sctp_socket (GstSctpAssociation *
107 gst_sctp_association);
108 static struct sockaddr_conn get_sctp_socket_address (GstSctpAssociation *
109 gst_sctp_association, guint16 port);
110 static gpointer connection_thread_func (GstSctpAssociation * self);
111 static gboolean client_role_connect (GstSctpAssociation * self);
112 static int sctp_packet_out (void *addr, void *buffer, size_t length, guint8 tos,
114 static int receive_cb (struct socket *sock, union sctp_sockstore addr,
115 void *data, size_t datalen, struct sctp_rcvinfo rcv_info, gint flags,
117 static void handle_notification (GstSctpAssociation * self,
118 const union sctp_notification *notification, size_t length);
119 static void handle_association_changed (GstSctpAssociation * self,
120 const struct sctp_assoc_change *sac);
121 static void handle_stream_reset_event (GstSctpAssociation * self,
122 const struct sctp_stream_reset_event *ssr);
123 static void handle_message (GstSctpAssociation * self, guint8 * data,
124 guint32 datalen, guint16 stream_id, guint32 ppid);
126 static void maybe_set_state_to_ready (GstSctpAssociation * self);
127 static void gst_sctp_association_change_state (GstSctpAssociation * self,
128 GstSctpAssociationState new_state, gboolean notify);
131 gst_sctp_association_class_init (GstSctpAssociationClass * klass)
133 GObjectClass *gobject_class;
135 gobject_class = (GObjectClass *) klass;
137 gobject_class->finalize = gst_sctp_association_finalize;
138 gobject_class->set_property = gst_sctp_association_set_property;
139 gobject_class->get_property = gst_sctp_association_get_property;
141 signals[SIGNAL_STREAM_RESET] =
142 g_signal_new ("stream-reset", G_OBJECT_CLASS_TYPE (klass),
143 G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstSctpAssociationClass,
144 on_sctp_stream_reset), NULL, NULL, g_cclosure_marshal_generic,
145 G_TYPE_NONE, 1, G_TYPE_UINT);
147 properties[PROP_ASSOCIATION_ID] = g_param_spec_uint ("association-id",
148 "The SCTP association-id", "The SCTP association-id.", 0, G_MAXUSHORT,
149 DEFAULT_LOCAL_SCTP_PORT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
151 properties[PROP_LOCAL_PORT] = g_param_spec_uint ("local-port", "Local SCTP",
152 "The local SCTP port for this association", 0, G_MAXUSHORT,
153 DEFAULT_LOCAL_SCTP_PORT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
155 properties[PROP_REMOTE_PORT] =
156 g_param_spec_uint ("remote-port", "Remote SCTP",
157 "The remote SCTP port for this association", 0, G_MAXUSHORT,
158 DEFAULT_LOCAL_SCTP_PORT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
160 properties[PROP_STATE] = g_param_spec_enum ("state", "SCTP Association state",
161 "The state of the SCTP association", GST_SCTP_ASSOCIATION_STATE_TYPE,
162 GST_SCTP_ASSOCIATION_STATE_NEW,
163 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
165 properties[PROP_USE_SOCK_STREAM] =
166 g_param_spec_boolean ("use-sock-stream", "Use sock-stream",
167 "When set to TRUE, a sequenced, reliable, connection-based connection is used."
168 "When TRUE the partial reliability parameters of the channel is ignored.",
169 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
171 g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
175 gst_sctp_association_init (GstSctpAssociation * self)
177 /* No need to lock mutex here as long as the function is only called from gst_sctp_association_get */
178 if (number_of_associations == 0) {
179 usrsctp_init (0, sctp_packet_out, g_print);
181 /* Explicit Congestion Notification */
182 usrsctp_sysctl_set_sctp_ecn_enable (0);
184 usrsctp_sysctl_set_sctp_nr_outgoing_streams_default
185 (DEFAULT_NUMBER_OF_SCTP_STREAMS);
187 number_of_associations++;
189 self->local_port = DEFAULT_LOCAL_SCTP_PORT;
190 self->remote_port = DEFAULT_REMOTE_SCTP_PORT;
191 self->sctp_ass_sock = NULL;
193 self->connection_thread = NULL;
194 g_mutex_init (&self->association_mutex);
196 self->state = GST_SCTP_ASSOCIATION_STATE_NEW;
198 self->use_sock_stream = FALSE;
200 usrsctp_register_address ((void *) self);
204 gst_sctp_association_finalize (GObject * object)
206 GstSctpAssociation *self = GST_SCTP_ASSOCIATION (object);
208 G_LOCK (associations_lock);
210 g_hash_table_remove (associations, GUINT_TO_POINTER (self->association_id));
212 usrsctp_deregister_address ((void *) self);
213 number_of_associations--;
214 if (number_of_associations == 0) {
217 G_UNLOCK (associations_lock);
219 if (self->connection_thread)
220 g_thread_join (self->connection_thread);
222 G_OBJECT_CLASS (gst_sctp_association_parent_class)->finalize (object);
226 gst_sctp_association_set_property (GObject * object, guint prop_id,
227 const GValue * value, GParamSpec * pspec)
229 GstSctpAssociation *self = GST_SCTP_ASSOCIATION (object);
231 g_mutex_lock (&self->association_mutex);
232 if (self->state != GST_SCTP_ASSOCIATION_STATE_NEW) {
234 case PROP_LOCAL_PORT:
235 case PROP_REMOTE_PORT:
236 g_warning ("These properties cannot be set in this state");
242 case PROP_ASSOCIATION_ID:
243 self->association_id = g_value_get_uint (value);
245 case PROP_LOCAL_PORT:
246 self->local_port = g_value_get_uint (value);
248 case PROP_REMOTE_PORT:
249 self->remote_port = g_value_get_uint (value);
252 self->state = g_value_get_enum (value);
254 case PROP_USE_SOCK_STREAM:
255 self->use_sock_stream = g_value_get_boolean (value);
258 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
262 g_mutex_unlock (&self->association_mutex);
263 if (prop_id == PROP_LOCAL_PORT || prop_id == PROP_REMOTE_PORT)
264 maybe_set_state_to_ready (self);
269 g_mutex_unlock (&self->association_mutex);
273 maybe_set_state_to_ready (GstSctpAssociation * self)
275 gboolean signal_ready_state = FALSE;
277 g_mutex_lock (&self->association_mutex);
278 if ((self->state == GST_SCTP_ASSOCIATION_STATE_NEW) &&
279 (self->local_port != 0 && self->remote_port != 0)
280 && (self->packet_out_cb != NULL) && (self->packet_received_cb != NULL)) {
281 signal_ready_state = TRUE;
282 gst_sctp_association_change_state (self, GST_SCTP_ASSOCIATION_STATE_READY,
285 g_mutex_unlock (&self->association_mutex);
287 /* The reason the state is changed twice is that we do not want to change state with
288 * notification while the association_mutex is locked. If someone listens
289 * on property change and call this object a deadlock might occur.*/
290 if (signal_ready_state)
291 gst_sctp_association_change_state (self, GST_SCTP_ASSOCIATION_STATE_READY,
297 gst_sctp_association_get_property (GObject * object, guint prop_id,
298 GValue * value, GParamSpec * pspec)
300 GstSctpAssociation *self = GST_SCTP_ASSOCIATION (object);
303 case PROP_ASSOCIATION_ID:
304 g_value_set_uint (value, self->association_id);
306 case PROP_LOCAL_PORT:
307 g_value_set_uint (value, self->local_port);
309 case PROP_REMOTE_PORT:
310 g_value_set_uint (value, self->remote_port);
313 g_value_set_enum (value, self->state);
315 case PROP_USE_SOCK_STREAM:
316 g_value_set_boolean (value, self->use_sock_stream);
319 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
324 /* Public functions */
327 gst_sctp_association_get (guint32 association_id)
329 GstSctpAssociation *association;
331 G_LOCK (associations_lock);
334 g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
338 g_hash_table_lookup (associations, GUINT_TO_POINTER (association_id));
341 g_object_new (GST_SCTP_TYPE_ASSOCIATION, "association-id",
342 association_id, NULL);
343 g_hash_table_insert (associations, GUINT_TO_POINTER (association_id),
346 g_object_ref (association);
348 G_UNLOCK (associations_lock);
353 gst_sctp_association_start (GstSctpAssociation * self)
357 g_mutex_lock (&self->association_mutex);
358 if (self->state != GST_SCTP_ASSOCIATION_STATE_READY) {
359 g_warning ("SCTP association is in wrong state and cannot be started");
360 goto configure_required;
363 if ((self->sctp_ass_sock = create_sctp_socket (self)) == NULL)
366 gst_sctp_association_change_state (self,
367 GST_SCTP_ASSOCIATION_STATE_CONNECTING, FALSE);
368 g_mutex_unlock (&self->association_mutex);
370 /* The reason the state is changed twice is that we do not want to change state with
371 * notification while the association_mutex is locked. If someone listens
372 * on property change and call this object a deadlock might occur.*/
373 gst_sctp_association_change_state (self,
374 GST_SCTP_ASSOCIATION_STATE_CONNECTING, TRUE);
376 thread_name = g_strdup_printf ("connection_thread_%u", self->association_id);
377 self->connection_thread = g_thread_new (thread_name,
378 (GThreadFunc) connection_thread_func, self);
379 g_free (thread_name);
383 g_mutex_unlock (&self->association_mutex);
384 gst_sctp_association_change_state (self, GST_SCTP_ASSOCIATION_STATE_ERROR,
387 g_mutex_unlock (&self->association_mutex);
392 gst_sctp_association_set_on_packet_out (GstSctpAssociation * self,
393 GstSctpAssociationPacketOutCb packet_out_cb, gpointer user_data)
395 g_return_if_fail (GST_SCTP_IS_ASSOCIATION (self));
397 g_mutex_lock (&self->association_mutex);
398 if (self->state == GST_SCTP_ASSOCIATION_STATE_NEW) {
399 self->packet_out_cb = packet_out_cb;
400 self->packet_out_user_data = user_data;
402 /* This is to be thread safe. The Association might try to write to the closure already */
403 g_warning ("It is not possible to change packet callback in this state");
405 g_mutex_unlock (&self->association_mutex);
407 maybe_set_state_to_ready (self);
411 gst_sctp_association_set_on_packet_received (GstSctpAssociation * self,
412 GstSctpAssociationPacketReceivedCb packet_received_cb, gpointer user_data)
414 g_return_if_fail (GST_SCTP_IS_ASSOCIATION (self));
416 g_mutex_lock (&self->association_mutex);
417 if (self->state == GST_SCTP_ASSOCIATION_STATE_NEW) {
418 self->packet_received_cb = packet_received_cb;
419 self->packet_received_user_data = user_data;
421 /* This is to be thread safe. The Association might try to write to the closure already */
422 g_warning ("It is not possible to change receive callback in this state");
424 g_mutex_unlock (&self->association_mutex);
426 maybe_set_state_to_ready (self);
430 gst_sctp_association_incoming_packet (GstSctpAssociation * self, guint8 * buf,
433 usrsctp_conninput ((void *) self, (const void *) buf, (size_t) length, 0);
437 gst_sctp_association_send_data (GstSctpAssociation * self, guint8 * buf,
438 guint32 length, guint16 stream_id, guint32 ppid, gboolean ordered,
439 GstSctpAssociationPartialReliability pr, guint32 reliability_param)
441 struct sctp_sendv_spa spa;
443 gboolean result = FALSE;
444 struct sockaddr_conn remote_addr;
446 g_mutex_lock (&self->association_mutex);
447 if (self->state != GST_SCTP_ASSOCIATION_STATE_CONNECTED)
450 memset (&spa, 0, sizeof (spa));
452 spa.sendv_sndinfo.snd_ppid = g_htonl (ppid);
453 spa.sendv_sndinfo.snd_sid = stream_id;
454 spa.sendv_sndinfo.snd_flags = ordered ? 0 : SCTP_UNORDERED;
455 spa.sendv_sndinfo.snd_context = 0;
456 spa.sendv_sndinfo.snd_assoc_id = 0;
457 spa.sendv_flags = SCTP_SEND_SNDINFO_VALID;
458 if (pr != GST_SCTP_ASSOCIATION_PARTIAL_RELIABILITY_NONE) {
459 spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
460 spa.sendv_prinfo.pr_value = g_htonl (reliability_param);
461 if (pr == GST_SCTP_ASSOCIATION_PARTIAL_RELIABILITY_TTL)
462 spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL;
463 else if (pr == GST_SCTP_ASSOCIATION_PARTIAL_RELIABILITY_RTX)
464 spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX;
465 else if (pr == GST_SCTP_ASSOCIATION_PARTIAL_RELIABILITY_BUF)
466 spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_BUF;
469 remote_addr = get_sctp_socket_address (self, self->remote_port);
471 usrsctp_sendv (self->sctp_ass_sock, buf, length,
472 (struct sockaddr *) &remote_addr, 1, (void *) &spa,
473 (socklen_t) sizeof (struct sctp_sendv_spa), SCTP_SENDV_SPA, 0);
474 if (bytes_sent < 0) {
475 if (errno == EAGAIN || errno == EWOULDBLOCK) {
476 /* Resending this buffer is taken care of by the gstsctpenc */
479 g_warning ("Error sending data on stream %u: (%u) %s", stream_id, errno,
487 g_mutex_unlock (&self->association_mutex);
493 gst_sctp_association_reset_stream (GstSctpAssociation * self, guint16 stream_id)
495 struct sctp_reset_streams *srs;
498 length = (socklen_t) (sizeof (struct sctp_reset_streams) + sizeof (guint16));
499 srs = (struct sctp_reset_streams *) g_malloc0 (length);
500 srs->srs_flags = SCTP_STREAM_RESET_OUTGOING;
501 srs->srs_number_streams = 1;
502 srs->srs_stream_list[0] = stream_id;
504 g_mutex_lock (&self->association_mutex);
505 usrsctp_setsockopt (self->sctp_ass_sock, IPPROTO_SCTP, SCTP_RESET_STREAMS,
507 g_mutex_unlock (&self->association_mutex);
513 gst_sctp_association_force_close (GstSctpAssociation * self)
515 g_mutex_lock (&self->association_mutex);
516 if (self->sctp_ass_sock) {
517 usrsctp_close (self->sctp_ass_sock);
518 self->sctp_ass_sock = NULL;
521 g_mutex_unlock (&self->association_mutex);
524 static struct socket *
525 create_sctp_socket (GstSctpAssociation * self)
529 struct sctp_event event;
530 struct sctp_assoc_value stream_reset;
532 guint16 event_types[] = {
534 SCTP_PEER_ADDR_CHANGE,
538 SCTP_ADAPTATION_INDICATION,
539 /*SCTP_PARTIAL_DELIVERY_EVENT, */
540 /*SCTP_AUTHENTICATION_EVENT, */
541 SCTP_STREAM_RESET_EVENT,
542 /*SCTP_SENDER_DRY_EVENT, */
543 /*SCTP_NOTIFICATIONS_STOPPED_EVENT, */
544 /*SCTP_ASSOC_RESET_EVENT, */
545 SCTP_STREAM_CHANGE_EVENT
548 guint sock_type = self->use_sock_stream ? SOCK_STREAM : SOCK_SEQPACKET;
551 usrsctp_socket (AF_CONN, sock_type, IPPROTO_SCTP, receive_cb, NULL, 0,
552 (void *) self)) == NULL)
555 if (usrsctp_set_non_blocking (sock, 1) < 0) {
556 g_warning ("Could not set non-blocking mode on SCTP socket");
560 memset (&l, 0, sizeof (l));
563 if (usrsctp_setsockopt (sock, SOL_SOCKET, SO_LINGER, (const void *) &l,
564 (socklen_t) sizeof (struct linger)) < 0) {
565 g_warning ("Could not set SO_LINGER on SCTP socket");
569 if (usrsctp_setsockopt (sock, IPPROTO_SCTP, SCTP_NODELAY, &value,
571 g_warning ("Could not set SCTP_NODELAY");
575 memset (&stream_reset, 0, sizeof (stream_reset));
576 stream_reset.assoc_id = SCTP_ALL_ASSOC;
577 stream_reset.assoc_value = 1;
578 if (usrsctp_setsockopt (sock, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET,
579 &stream_reset, sizeof (stream_reset))) {
580 g_warning ("Could not set SCTP_ENABLE_STREAM_RESET");
584 memset (&event, 0, sizeof (event));
585 event.se_assoc_id = SCTP_ALL_ASSOC;
587 for (i = 0; i < sizeof (event_types) / sizeof (event_types[0]); i++) {
588 event.se_type = event_types[i];
589 if (usrsctp_setsockopt (sock, IPPROTO_SCTP, SCTP_EVENT,
590 &event, sizeof (event)) < 0) {
591 g_warning ("Failed to register event %u", event_types[i]);
598 usrsctp_close (sock);
599 g_warning ("Could not create socket. Error: (%u) %s", errno,
607 static struct sockaddr_conn
608 get_sctp_socket_address (GstSctpAssociation * gst_sctp_association,
611 struct sockaddr_conn addr;
613 memset ((void *) &addr, 0, sizeof (struct sockaddr_conn));
615 addr.sconn_len = sizeof (struct sockaddr_conn);
617 addr.sconn_family = AF_CONN;
618 addr.sconn_port = g_htons (port);
619 addr.sconn_addr = (void *) gst_sctp_association;
625 connection_thread_func (GstSctpAssociation * self)
627 /* TODO: Support both server and client role */
628 client_role_connect (self);
633 client_role_connect (GstSctpAssociation * self)
635 struct sockaddr_conn addr;
638 g_mutex_lock (&self->association_mutex);
639 addr = get_sctp_socket_address (self, self->local_port);
641 usrsctp_bind (self->sctp_ass_sock, (struct sockaddr *) &addr,
642 sizeof (struct sockaddr_conn));
644 g_warning ("usrsctp_bind() error: (%u) %s", errno, strerror (errno));
648 addr = get_sctp_socket_address (self, self->remote_port);
650 usrsctp_connect (self->sctp_ass_sock, (struct sockaddr *) &addr,
651 sizeof (struct sockaddr_conn));
652 if (ret < 0 && errno != EINPROGRESS) {
653 g_warning ("usrsctp_connect() error: (%u) %s", errno, strerror (errno));
656 g_mutex_unlock (&self->association_mutex);
659 g_mutex_unlock (&self->association_mutex);
664 sctp_packet_out (void *addr, void *buffer, size_t length, guint8 tos,
667 GstSctpAssociation *self = GST_SCTP_ASSOCIATION (addr);
669 if (self->packet_out_cb) {
670 self->packet_out_cb (self, buffer, length, self->packet_out_user_data);
677 receive_cb (struct socket *sock, union sctp_sockstore addr, void *data,
678 size_t datalen, struct sctp_rcvinfo rcv_info, gint flags, void *ulp_info)
680 GstSctpAssociation *self = GST_SCTP_ASSOCIATION (ulp_info);
683 /* Not sure if this can happend. */
684 g_warning ("Received empty data buffer");
686 if (flags & MSG_NOTIFICATION) {
687 handle_notification (self, (const union sctp_notification *) data,
691 handle_message (self, data, datalen, rcv_info.rcv_sid,
692 ntohl (rcv_info.rcv_ppid));
700 handle_notification (GstSctpAssociation * self,
701 const union sctp_notification *notification, size_t length)
703 g_assert (notification->sn_header.sn_length == length);
705 switch (notification->sn_header.sn_type) {
706 case SCTP_ASSOC_CHANGE:
707 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_ASSOC_CHANGE");
708 handle_association_changed (self, ¬ification->sn_assoc_change);
710 case SCTP_PEER_ADDR_CHANGE:
711 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_PEER_ADDR_CHANGE");
713 case SCTP_REMOTE_ERROR:
714 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_REMOTE_ERROR");
716 case SCTP_SEND_FAILED:
717 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_SEND_FAILED");
719 case SCTP_SHUTDOWN_EVENT:
720 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_SHUTDOWN_EVENT");
722 case SCTP_ADAPTATION_INDICATION:
723 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
724 "Event: SCTP_ADAPTATION_INDICATION");
726 case SCTP_PARTIAL_DELIVERY_EVENT:
727 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
728 "Event: SCTP_PARTIAL_DELIVERY_EVENT");
730 case SCTP_AUTHENTICATION_EVENT:
731 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
732 "Event: SCTP_AUTHENTICATION_EVENT");
734 case SCTP_STREAM_RESET_EVENT:
735 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_STREAM_RESET_EVENT");
736 handle_stream_reset_event (self, ¬ification->sn_strreset_event);
738 case SCTP_SENDER_DRY_EVENT:
739 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_SENDER_DRY_EVENT");
741 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
742 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
743 "Event: SCTP_NOTIFICATIONS_STOPPED_EVENT");
745 case SCTP_ASSOC_RESET_EVENT:
746 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_ASSOC_RESET_EVENT");
748 case SCTP_STREAM_CHANGE_EVENT:
749 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_STREAM_CHANGE_EVENT");
751 case SCTP_SEND_FAILED_EVENT:
752 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Event: SCTP_SEND_FAILED_EVENT");
760 handle_association_changed (GstSctpAssociation * self,
761 const struct sctp_assoc_change *sac)
763 gboolean change_state = FALSE;
764 GstSctpAssociationState new_state;
766 switch (sac->sac_state) {
768 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "SCTP_COMM_UP()");
769 g_mutex_lock (&self->association_mutex);
770 if (self->state == GST_SCTP_ASSOCIATION_STATE_CONNECTING) {
772 new_state = GST_SCTP_ASSOCIATION_STATE_CONNECTED;
773 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "SCTP association connected!");
774 } else if (self->state == GST_SCTP_ASSOCIATION_STATE_CONNECTED) {
775 g_warning ("SCTP association already open");
777 g_warning ("SCTP association in unexpected state");
779 g_mutex_unlock (&self->association_mutex);
782 g_warning ("SCTP event SCTP_COMM_LOST received");
783 /* TODO: Tear down association and signal that this has happend */
786 g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
787 "SCTP event SCTP_RESTART received");
789 case SCTP_SHUTDOWN_COMP:
790 g_warning ("SCTP event SCTP_SHUTDOWN_COMP received");
791 /* TODO: Tear down association and signal that this has happend */
793 case SCTP_CANT_STR_ASSOC:
794 g_warning ("SCTP event SCTP_CANT_STR_ASSOC received");
799 gst_sctp_association_change_state (self, new_state, TRUE);
803 handle_stream_reset_event (GstSctpAssociation * self,
804 const struct sctp_stream_reset_event *sr)
807 if (!(sr->strreset_flags & SCTP_STREAM_RESET_DENIED) &&
808 !(sr->strreset_flags & SCTP_STREAM_RESET_DENIED)) {
809 n = (sr->strreset_length -
810 sizeof (struct sctp_stream_reset_event)) / sizeof (uint16_t);
811 for (i = 0; i < n; i++) {
812 if (sr->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) {
813 g_signal_emit (self, signals[SIGNAL_STREAM_RESET], 0,
814 sr->strreset_stream_list[i]);
821 handle_message (GstSctpAssociation * self, guint8 * data, guint32 datalen,
822 guint16 stream_id, guint32 ppid)
824 if (self->packet_received_cb) {
825 self->packet_received_cb (self, data, datalen, stream_id, ppid,
826 self->packet_received_user_data);
831 gst_sctp_association_change_state (GstSctpAssociation * self,
832 GstSctpAssociationState new_state, gboolean notify)
834 self->state = new_state;
836 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE]);