Commit a437e9f0 authored by Wim Taymans's avatar Wim Taymans
Browse files

gst/rtsp/gstrtspsrc.*: Small cleanups, added documentation.

Original commit message from CVS:
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_media_to_caps),
(gst_rtspsrc_send), (gst_rtspsrc_parse_methods),
(gst_rtspsrc_open), (gst_rtspsrc_close), (gst_rtspsrc_play),
(gst_rtspsrc_pause), (gst_rtspsrc_change_state),
(gst_rtspsrc_uri_get_uri), (gst_rtspsrc_uri_set_uri):
* gst/rtsp/gstrtspsrc.h:
Small cleanups, added documentation.
Try to clean up the requests and responses.
Refactor parsing the supported methods.
* gst/rtsp/rtspconnection.c: (rtsp_connection_open),
(rtsp_connection_create), (rtsp_connection_send),
(parse_response_status), (parse_request_line),
(rtsp_connection_receive), (rtsp_connection_close),
(rtsp_connection_free):
* gst/rtsp/rtsptransport.c: (rtsp_transport_new),
(rtsp_transport_init), (rtsp_transport_parse),
(rtsp_transport_free):
* gst/rtsp/rtspurl.c: (rtsp_url_parse):
* gst/rtsp/sdpmessage.c: (sdp_message_new), (sdp_message_init),
(sdp_message_clean), (sdp_message_free), (sdp_media_new),
(sdp_media_init), (sdp_message_parse_buffer), (sdp_message_dump):
Use g_return_val some more.
* gst/rtsp/rtspdefs.h:
Add more enum values to track initial states.
* gst/rtsp/rtspmessage.c: (rtsp_message_new_request),
(rtsp_message_init_request), (rtsp_message_new_response),
(rtsp_message_init_response), (rtsp_message_init_data),
(rtsp_message_unset), (rtsp_message_free),
(rtsp_message_add_header), (rtsp_message_remove_header),
(rtsp_message_get_header), (rtsp_message_set_body),
(rtsp_message_take_body), (rtsp_message_get_body),
(rtsp_message_steal_body), (rtsp_message_dump):
* gst/rtsp/rtspmessage.h:
Reorder arguments, object goes as the first one.
Use g_return_val some more.
parent ee58147b
2006-09-18 Wim Taymans <wim@fluendo.com>
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_media_to_caps),
(gst_rtspsrc_send), (gst_rtspsrc_parse_methods),
(gst_rtspsrc_open), (gst_rtspsrc_close), (gst_rtspsrc_play),
(gst_rtspsrc_pause), (gst_rtspsrc_change_state),
(gst_rtspsrc_uri_get_uri), (gst_rtspsrc_uri_set_uri):
* gst/rtsp/gstrtspsrc.h:
Small cleanups, added documentation.
Try to clean up the requests and responses.
Refactor parsing the supported methods.
* gst/rtsp/rtspconnection.c: (rtsp_connection_open),
(rtsp_connection_create), (rtsp_connection_send),
(parse_response_status), (parse_request_line),
(rtsp_connection_receive), (rtsp_connection_close),
(rtsp_connection_free):
* gst/rtsp/rtsptransport.c: (rtsp_transport_new),
(rtsp_transport_init), (rtsp_transport_parse),
(rtsp_transport_free):
* gst/rtsp/rtspurl.c: (rtsp_url_parse):
* gst/rtsp/sdpmessage.c: (sdp_message_new), (sdp_message_init),
(sdp_message_clean), (sdp_message_free), (sdp_media_new),
(sdp_media_init), (sdp_message_parse_buffer), (sdp_message_dump):
Use g_return_val some more.
* gst/rtsp/rtspdefs.h:
Add more enum values to track initial states.
* gst/rtsp/rtspmessage.c: (rtsp_message_new_request),
(rtsp_message_init_request), (rtsp_message_new_response),
(rtsp_message_init_response), (rtsp_message_init_data),
(rtsp_message_unset), (rtsp_message_free),
(rtsp_message_add_header), (rtsp_message_remove_header),
(rtsp_message_get_header), (rtsp_message_set_body),
(rtsp_message_take_body), (rtsp_message_get_body),
(rtsp_message_steal_body), (rtsp_message_dump):
* gst/rtsp/rtspmessage.h:
Reorder arguments, object goes as the first one.
Use g_return_val some more.
2006-09-18 Wim Taymans <wim@fluendo.com>
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_base_init),
......
This diff is collapsed.
......@@ -103,8 +103,8 @@ struct _GstRTSPSrc {
guint retry;
GstRTSPProto protocols;
/* supported options */
gint options;
/* supported methods */
gint methods;
RTSPConnection *connection;
RTSPMessage *request;
......
......@@ -71,8 +71,8 @@ rtsp_connection_open (RTSPUrl * url, RTSPConnection ** conn)
struct in_addr addr;
gint ret;
if (url == NULL || conn == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (url != NULL, RTSP_EINVAL);
g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
if (url->protocol != RTSP_PROTO_TCP)
return RTSP_ENOTIMPL;
......@@ -128,6 +128,8 @@ rtsp_connection_create (gint fd, RTSPConnection ** conn)
{
RTSPConnection *newconn;
g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
/* FIXME check fd, must be connected SOCK_STREAM */
newconn = g_new (RTSPConnection, 1);
......@@ -157,8 +159,8 @@ rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message)
gint towrite;
gchar *data;
if (conn == NULL || message == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
g_return_val_if_fail (message != NULL, RTSP_EINVAL);
#ifdef G_OS_WIN32
WSADATA w;
......@@ -333,7 +335,7 @@ parse_response_status (gchar * buffer, RTSPMessage * msg)
while (g_ascii_isspace (*bptr))
bptr++;
rtsp_message_init_response (code, bptr, NULL, msg);
rtsp_message_init_response (msg, code, bptr, NULL);
return RTSP_OK;
......@@ -365,7 +367,7 @@ parse_request_line (gchar * buffer, RTSPMessage * msg)
if (strcmp (versionstr, "RTSP/1.0") != 0)
goto wrong_version;
rtsp_message_init_request (method, urlstr, msg);
rtsp_message_init_request (msg, method, urlstr);
return RTSP_OK;
......@@ -456,8 +458,8 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg)
RTSPResult res;
gboolean need_body;
if (conn == NULL || msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
line = 0;
......@@ -490,7 +492,7 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg)
goto error;
/* now we create a data message */
rtsp_message_init_data ((gint) c, msg);
rtsp_message_init_data (msg, (gint) c);
/* next two bytes are the length of the data */
ret = read (conn->fd, &size, 2);
......@@ -590,8 +592,7 @@ rtsp_connection_close (RTSPConnection * conn)
{
gint res;
if (conn == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
res = CLOSE_SOCKET (conn->fd);
#ifdef G_OS_WIN32
......@@ -612,8 +613,7 @@ sys_error:
RTSPResult
rtsp_connection_free (RTSPConnection * conn)
{
if (conn == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (conn != NULL, RTSP_EINVAL);
#ifdef G_OS_WIN32
WSACleanup ();
......
......@@ -50,6 +50,7 @@ typedef enum {
} RTSPFamily;
typedef enum {
RTSP_STATE_INVALID,
RTSP_STATE_INIT,
RTSP_STATE_READY,
RTSP_STATE_PLAYING,
......@@ -57,6 +58,7 @@ typedef enum {
} RTSPState;
typedef enum {
RTSP_INVALID = 0,
RTSP_DESCRIBE = (1 << 0),
RTSP_ANNOUNCE = (1 << 1),
RTSP_GET_PARAMETER = (1 << 2),
......@@ -120,6 +122,7 @@ typedef enum {
} RTSPHeaderField;
typedef enum {
RTSP_STS_INVALID = 0,
RTSP_STS_CONTINUE = 100,
RTSP_STS_OK = 200,
RTSP_STS_CREATED = 201,
......
......@@ -20,84 +20,69 @@
#include "rtspmessage.h"
RTSPResult
rtsp_message_new_request (RTSPMethod method, gchar * uri, RTSPMessage ** msg)
rtsp_message_new_request (RTSPMessage ** msg, RTSPMethod method, gchar * uri)
{
RTSPMessage *newmsg;
if (msg == NULL || uri == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_return_val_if_fail (uri != NULL, RTSP_EINVAL);
newmsg = g_new0 (RTSPMessage, 1);
*msg = newmsg;
return rtsp_message_init_request (method, uri, newmsg);
return rtsp_message_init_request (newmsg, method, uri);
}
RTSPResult
rtsp_message_init_request (RTSPMethod method, gchar * uri, RTSPMessage * msg)
rtsp_message_init_request (RTSPMessage * msg, RTSPMethod method, gchar * uri)
{
if (msg == NULL || uri == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (uri != NULL, RTSP_EINVAL);
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
rtsp_message_unset (msg);
msg->type = RTSP_MESSAGE_REQUEST;
msg->type_data.request.method = method;
g_free (msg->type_data.request.uri);
msg->type_data.request.uri = g_strdup (uri);
if (msg->hdr_fields != NULL)
g_hash_table_destroy (msg->hdr_fields);
msg->hdr_fields =
g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
if (msg->body) {
g_free (msg->body);
msg->body = NULL;
}
msg->body_size = 0;
return RTSP_OK;
}
RTSPResult
rtsp_message_new_response (RTSPStatusCode code, gchar * reason,
RTSPMessage * request, RTSPMessage ** msg)
rtsp_message_new_response (RTSPMessage ** msg, RTSPStatusCode code,
gchar * reason, RTSPMessage * request)
{
RTSPMessage *newmsg;
if (msg == NULL || reason == NULL || request == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (reason != NULL, RTSP_EINVAL);
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_return_val_if_fail (request != NULL, RTSP_EINVAL);
newmsg = g_new0 (RTSPMessage, 1);
*msg = newmsg;
return rtsp_message_init_response (code, reason, request, newmsg);
return rtsp_message_init_response (newmsg, code, reason, request);
}
RTSPResult
rtsp_message_init_response (RTSPStatusCode code, gchar * reason,
RTSPMessage * request, RTSPMessage * msg)
rtsp_message_init_response (RTSPMessage * msg, RTSPStatusCode code,
gchar * reason, RTSPMessage * request)
{
if (reason == NULL || msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_return_val_if_fail (reason != NULL, RTSP_EINVAL);
rtsp_message_unset (msg);
msg->type = RTSP_MESSAGE_RESPONSE;
msg->type_data.response.code = code;
g_free (msg->type_data.response.reason);
msg->type_data.response.reason = g_strdup (reason);
if (msg->hdr_fields != NULL)
g_hash_table_destroy (msg->hdr_fields);
msg->hdr_fields =
g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
if (msg->body) {
g_free (msg->body);
msg->body = NULL;
}
msg->body_size = 0;
if (request) {
/* FIXME copy headers */
}
......@@ -106,10 +91,11 @@ rtsp_message_init_response (RTSPStatusCode code, gchar * reason,
}
RTSPResult
rtsp_message_init_data (gint channel, RTSPMessage * msg)
rtsp_message_init_data (RTSPMessage * msg, gint channel)
{
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
rtsp_message_unset (msg);
msg->type = RTSP_MESSAGE_DATA;
msg->type_data.data.channel = channel;
......@@ -117,13 +103,51 @@ rtsp_message_init_data (gint channel, RTSPMessage * msg)
return RTSP_OK;
}
RTSPResult
rtsp_message_unset (RTSPMessage * msg)
{
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
msg->type = RTSP_MESSAGE_INVALID;
msg->type_data.request.method = RTSP_INVALID;
g_free (msg->type_data.request.uri);
msg->type_data.request.uri = NULL;
msg->type_data.response.code = RTSP_STS_INVALID;
g_free (msg->type_data.response.reason);
msg->type_data.response.reason = NULL;
if (msg->hdr_fields != NULL)
g_hash_table_destroy (msg->hdr_fields);
msg->hdr_fields = NULL;
g_free (msg->body);
msg->body = NULL;
msg->body_size = 0;
return RTSP_OK;
}
RTSPResult
rtsp_message_free (RTSPMessage * msg)
{
RTSPResult res;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
res = rtsp_message_unset (msg);
if (res == RTSP_OK)
g_free (msg);
return res;
}
RTSPResult
rtsp_message_add_header (RTSPMessage * msg, RTSPHeaderField field,
gchar * value)
{
if (msg == NULL || value == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_return_val_if_fail (value != NULL, RTSP_EINVAL);
g_hash_table_insert (msg->hdr_fields, GINT_TO_POINTER (field),
g_strdup (value));
......@@ -134,8 +158,7 @@ rtsp_message_add_header (RTSPMessage * msg, RTSPHeaderField field,
RTSPResult
rtsp_message_remove_header (RTSPMessage * msg, RTSPHeaderField field)
{
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_hash_table_remove (msg->hdr_fields, GINT_TO_POINTER (field));
......@@ -148,8 +171,8 @@ rtsp_message_get_header (RTSPMessage * msg, RTSPHeaderField field,
{
gchar *val;
if (msg == NULL || value == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_return_val_if_fail (value != NULL, RTSP_EINVAL);
val = g_hash_table_lookup (msg->hdr_fields, GINT_TO_POINTER (field));
if (val == NULL)
......@@ -163,8 +186,7 @@ rtsp_message_get_header (RTSPMessage * msg, RTSPHeaderField field,
RTSPResult
rtsp_message_set_body (RTSPMessage * msg, guint8 * data, guint size)
{
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
return rtsp_message_take_body (msg, g_memdup (data, size), size);
}
......@@ -172,8 +194,7 @@ rtsp_message_set_body (RTSPMessage * msg, guint8 * data, guint size)
RTSPResult
rtsp_message_take_body (RTSPMessage * msg, guint8 * data, guint size)
{
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
if (msg->body)
g_free (msg->body);
......@@ -187,8 +208,9 @@ rtsp_message_take_body (RTSPMessage * msg, guint8 * data, guint size)
RTSPResult
rtsp_message_get_body (RTSPMessage * msg, guint8 ** data, guint * size)
{
if (msg == NULL || data == NULL || size == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_return_val_if_fail (data != NULL, RTSP_EINVAL);
g_return_val_if_fail (size != NULL, RTSP_EINVAL);
*data = msg->body;
*size = msg->body_size;
......@@ -199,8 +221,9 @@ rtsp_message_get_body (RTSPMessage * msg, guint8 ** data, guint * size)
RTSPResult
rtsp_message_steal_body (RTSPMessage * msg, guint8 ** data, guint * size)
{
if (msg == NULL || data == NULL || size == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_return_val_if_fail (data != NULL, RTSP_EINVAL);
g_return_val_if_fail (size != NULL, RTSP_EINVAL);
*data = msg->body;
*size = msg->body_size;
......@@ -257,8 +280,7 @@ rtsp_message_dump (RTSPMessage * msg)
guint8 *data;
guint size;
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
if (msg->type == RTSP_MESSAGE_REQUEST) {
g_print ("request message %p\n", msg);
......
......@@ -28,6 +28,7 @@ G_BEGIN_DECLS
typedef enum
{
RTSP_MESSAGE_INVALID,
RTSP_MESSAGE_REQUEST,
RTSP_MESSAGE_RESPONSE,
RTSP_MESSAGE_DATA,
......@@ -58,15 +59,16 @@ typedef struct _RTSPMessage
} RTSPMessage;
RTSPResult rtsp_message_new_request (RTSPMethod method, gchar *uri, RTSPMessage **msg);
RTSPResult rtsp_message_init_request (RTSPMethod method, gchar *uri, RTSPMessage *msg);
RTSPResult rtsp_message_new_request (RTSPMessage **msg, RTSPMethod method, gchar *uri);
RTSPResult rtsp_message_init_request (RTSPMessage *msg, RTSPMethod method, gchar *uri);
RTSPResult rtsp_message_new_response (RTSPStatusCode code, gchar *reason,
RTSPMessage *request, RTSPMessage **msg);
RTSPResult rtsp_message_init_response (RTSPStatusCode code, gchar *reason,
RTSPMessage *request, RTSPMessage *msg);
RTSPResult rtsp_message_init_data (gint channel, RTSPMessage *msg);
RTSPResult rtsp_message_new_response (RTSPMessage **msg, RTSPStatusCode code, gchar *reason,
RTSPMessage *request);
RTSPResult rtsp_message_init_response (RTSPMessage *msg, RTSPStatusCode code, gchar *reason,
RTSPMessage *request);
RTSPResult rtsp_message_init_data (RTSPMessage *msg, gint channel);
RTSPResult rtsp_message_unset (RTSPMessage *msg);
RTSPResult rtsp_message_free (RTSPMessage *msg);
......
......@@ -27,8 +27,7 @@ rtsp_transport_new (RTSPTransport ** transport)
{
RTSPTransport *trans;
if (transport == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (transport != NULL, RTSP_EINVAL);
trans = g_new0 (RTSPTransport, 1);
......@@ -40,6 +39,8 @@ rtsp_transport_new (RTSPTransport ** transport)
RTSPResult
rtsp_transport_init (RTSPTransport * transport)
{
g_return_val_if_fail (transport != NULL, RTSP_EINVAL);
g_free (transport->destination);
g_free (transport->source);
g_free (transport->ssrc);
......@@ -83,8 +84,8 @@ rtsp_transport_parse (gchar * str, RTSPTransport * transport)
gchar **split, *down;
gint i;
if (str == NULL || transport == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (transport != NULL, RTSP_EINVAL);
g_return_val_if_fail (str != NULL, RTSP_EINVAL);
rtsp_transport_init (transport);
......@@ -141,6 +142,8 @@ rtsp_transport_parse (gchar * str, RTSPTransport * transport)
RTSPResult
rtsp_transport_free (RTSPTransport * transport)
{
g_return_val_if_fail (transport != NULL, RTSP_EINVAL);
rtsp_transport_init (transport);
g_free (transport);
return RTSP_OK;
......
......@@ -34,10 +34,10 @@ rtsp_url_parse (const gchar * urlstr, RTSPUrl ** url)
RTSPUrl *res;
gchar *p, *slash, *at, *col;
res = g_new0 (RTSPUrl, 1);
g_return_val_if_fail (urlstr != NULL, RTSP_EINVAL);
g_return_val_if_fail (url != NULL, RTSP_EINVAL);
if (urlstr == NULL)
goto invalid;
res = g_new0 (RTSPUrl, 1);
p = (gchar *) urlstr;
if (g_str_has_prefix (p, RTSP_PROTO)) {
......
......@@ -76,8 +76,7 @@ sdp_message_new (SDPMessage ** msg)
{
SDPMessage *newmsg;
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
newmsg = g_new0 (SDPMessage, 1);
......@@ -89,8 +88,7 @@ sdp_message_new (SDPMessage ** msg)
RTSPResult
sdp_message_init (SDPMessage * msg)
{
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
FREE_STRING (msg->version);
FREE_STRING (msg->origin.username);
......@@ -123,8 +121,7 @@ sdp_message_init (SDPMessage * msg)
RTSPResult
sdp_message_clean (SDPMessage * msg)
{
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
FREE_ARRAY (msg->emails);
FREE_ARRAY (msg->phones);
......@@ -140,8 +137,7 @@ sdp_message_clean (SDPMessage * msg)
RTSPResult
sdp_message_free (SDPMessage * msg)
{
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
sdp_message_clean (msg);
......@@ -156,8 +152,7 @@ sdp_media_new (SDPMedia ** media)
{
SDPMedia *newmedia;
if (media == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (media != NULL, RTSP_EINVAL);
newmedia = g_new0 (SDPMedia, 1);
......@@ -169,8 +164,7 @@ sdp_media_new (SDPMedia ** media)
RTSPResult
sdp_media_init (SDPMedia * media)
{
if (media == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (media != NULL, RTSP_EINVAL);
FREE_STRING (media->media);
media->port = 0;
......@@ -578,8 +572,9 @@ sdp_message_parse_buffer (guint8 * data, guint size, SDPMessage * msg)
gchar buffer[4096];
gint idx = 0;
if (msg == NULL || data == NULL || size == 0)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_return_val_if_fail (data != NULL, RTSP_EINVAL);
g_return_val_if_fail (size != 0, RTSP_EINVAL);
c.state = SDP_SESSION;
c.msg = msg;
......@@ -651,8 +646,7 @@ print_media (SDPMedia * media)
RTSPResult
sdp_message_dump (SDPMessage * msg)
{
if (msg == NULL)
return RTSP_EINVAL;
g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
g_print ("sdp packet %p:\n", msg);
g_print (" version: '%s'\n", msg->version);
......@@ -666,6 +660,7 @@ sdp_message_dump (SDPMessage * msg)
g_print (" session_name: '%s'\n", msg->session_name);
g_print (" information: '%s'\n", msg->information);
g_print (" uri: '%s'\n", msg->uri);
if (msg->emails->len > 0) {
gint i;
......@@ -710,7 +705,5 @@ sdp_message_dump (SDPMessage * msg)
print_media (&g_array_index (msg->medias, SDPMedia, i));
}
}
return RTSP_OK;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment