gst_plugins_base/gst-libs/gst/rtsp/gstrtspmessage.c
branchRCL_3
changeset 29 567bb019e3e3
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
6:9b2c3c7a1a9c 29:567bb019e3e3
    55  * Last reviewed on 2007-07-25 (0.10.14)
    55  * Last reviewed on 2007-07-25 (0.10.14)
    56  */
    56  */
    57 
    57 
    58 #include <string.h>
    58 #include <string.h>
    59 
    59 
       
    60 #include <gst/gstutils.h>
    60 #include "gstrtspmessage.h"
    61 #include "gstrtspmessage.h"
    61 
    62 
    62 typedef struct _RTSPKeyValue
    63 typedef struct _RTSPKeyValue
    63 {
    64 {
    64   GstRTSPHeaderField field;
    65   GstRTSPHeaderField field;
    79 
    80 
    80 /**
    81 /**
    81  * gst_rtsp_message_new:
    82  * gst_rtsp_message_new:
    82  * @msg: a location for the new #GstRTSPMessage
    83  * @msg: a location for the new #GstRTSPMessage
    83  *
    84  *
    84  * Create a new initialized #GstRTSPMessage.
    85  * Create a new initialized #GstRTSPMessage. Free with gst_rtsp_message_free().
    85  *
    86  *
    86  * Returns: a #GstRTSPResult. Free with gst_rtsp_message_free().
    87  * Returns: a #GstRTSPResult.
    87  */
    88  */
    88 GstRTSPResult
    89 GstRTSPResult
    89 gst_rtsp_message_new (GstRTSPMessage ** msg)
    90 gst_rtsp_message_new (GstRTSPMessage ** msg)
    90 {
    91 {
    91   GstRTSPMessage *newmsg;
    92   GstRTSPMessage *newmsg;
   142  * @msg: a location for the new #GstRTSPMessage
   143  * @msg: a location for the new #GstRTSPMessage
   143  * @method: the request method to use
   144  * @method: the request method to use
   144  * @uri: the uri of the request
   145  * @uri: the uri of the request
   145  *
   146  *
   146  * Create a new #GstRTSPMessage with @method and @uri and store the result
   147  * Create a new #GstRTSPMessage with @method and @uri and store the result
   147  * request message in @msg. 
   148  * request message in @msg. Free with gst_rtsp_message_free().
   148  *
   149  *
   149  * Returns: a #GstRTSPResult. Free with gst_rtsp_message_free().
   150  * Returns: a #GstRTSPResult.
   150  */
   151  */
   151 GstRTSPResult
   152 GstRTSPResult
   152 gst_rtsp_message_new_request (GstRTSPMessage ** msg, GstRTSPMethod method,
   153 gst_rtsp_message_new_request (GstRTSPMessage ** msg, GstRTSPMethod method,
   153     const gchar * uri)
   154     const gchar * uri)
   154 {
   155 {
   211 GstRTSPResult
   212 GstRTSPResult
   212 gst_rtsp_message_parse_request (GstRTSPMessage * msg,
   213 gst_rtsp_message_parse_request (GstRTSPMessage * msg,
   213     GstRTSPMethod * method, const gchar ** uri, GstRTSPVersion * version)
   214     GstRTSPMethod * method, const gchar ** uri, GstRTSPVersion * version)
   214 {
   215 {
   215   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   216   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   216   g_return_val_if_fail (msg->type != GST_RTSP_MESSAGE_REQUEST, GST_RTSP_EINVAL);
   217   g_return_val_if_fail (msg->type == GST_RTSP_MESSAGE_REQUEST, GST_RTSP_EINVAL);
   217 
   218 
   218   if (method)
   219   if (method)
   219     *method = msg->type_data.request.method;
   220     *method = msg->type_data.request.method;
   220   if (uri)
   221   if (uri)
   221     *uri = msg->type_data.request.uri;
   222     *uri = msg->type_data.request.uri;
   231  * @code: the status code
   232  * @code: the status code
   232  * @reason: the status reason or #NULL
   233  * @reason: the status reason or #NULL
   233  * @request: the request that triggered the response or #NULL
   234  * @request: the request that triggered the response or #NULL
   234  *
   235  *
   235  * Create a new response #GstRTSPMessage with @code and @reason and store the
   236  * Create a new response #GstRTSPMessage with @code and @reason and store the
   236  * result message in @msg. 
   237  * result message in @msg. Free with gst_rtsp_message_free().
   237  *
   238  *
   238  * When @reason is #NULL, the default reason for @code will be used.
   239  * When @reason is #NULL, the default reason for @code will be used.
   239  *
   240  *
   240  * When @request is not #NULL, the relevant headers will be copied to the new
   241  * When @request is not #NULL, the relevant headers will be copied to the new
   241  * response message.
   242  * response message.
   242  *
   243  *
   243  * Returns: a #GstRTSPResult. Free with gst_rtsp_message_free().
   244  * Returns: a #GstRTSPResult.
   244  */
   245  */
   245 GstRTSPResult
   246 GstRTSPResult
   246 gst_rtsp_message_new_response (GstRTSPMessage ** msg, GstRTSPStatusCode code,
   247 gst_rtsp_message_new_response (GstRTSPMessage ** msg, GstRTSPStatusCode code,
   247     const gchar * reason, const GstRTSPMessage * request)
   248     const gchar * reason, const GstRTSPMessage * request)
   248 {
   249 {
   307       header = g_strdup (header);
   308       header = g_strdup (header);
   308       if ((pos = strchr (header, ';'))) {
   309       if ((pos = strchr (header, ';'))) {
   309         *pos = '\0';
   310         *pos = '\0';
   310       }
   311       }
   311       g_strchomp (header);
   312       g_strchomp (header);
   312       gst_rtsp_message_add_header (msg, GST_RTSP_HDR_SESSION, header);
   313       gst_rtsp_message_take_header (msg, GST_RTSP_HDR_SESSION, header);
   313       g_free (header);
       
   314     }
   314     }
   315 
   315 
   316     /* FIXME copy more headers? */
   316     /* FIXME copy more headers? */
   317   }
   317   }
   318 
   318 
   338 GstRTSPResult
   338 GstRTSPResult
   339 gst_rtsp_message_parse_response (GstRTSPMessage * msg,
   339 gst_rtsp_message_parse_response (GstRTSPMessage * msg,
   340     GstRTSPStatusCode * code, const gchar ** reason, GstRTSPVersion * version)
   340     GstRTSPStatusCode * code, const gchar ** reason, GstRTSPVersion * version)
   341 {
   341 {
   342   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   342   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   343   g_return_val_if_fail (msg->type != GST_RTSP_MESSAGE_RESPONSE,
   343   g_return_val_if_fail (msg->type == GST_RTSP_MESSAGE_RESPONSE,
   344       GST_RTSP_EINVAL);
   344       GST_RTSP_EINVAL);
   345 
   345 
   346   if (code)
   346   if (code)
   347     *code = msg->type_data.response.code;
   347     *code = msg->type_data.response.code;
   348   if (reason)
   348   if (reason)
   357  * gst_rtsp_message_new_data:
   357  * gst_rtsp_message_new_data:
   358  * @msg: a location for the new #GstRTSPMessage
   358  * @msg: a location for the new #GstRTSPMessage
   359  * @channel: the channel
   359  * @channel: the channel
   360  *
   360  *
   361  * Create a new data #GstRTSPMessage with @channel and store the
   361  * Create a new data #GstRTSPMessage with @channel and store the
   362  * result message in @msg. 
   362  * result message in @msg. Free with gst_rtsp_message_free().
   363  *
   363  *
   364  * Returns: a #GstRTSPResult. Free with gst_rtsp_message_free().
   364  * Returns: a #GstRTSPResult.
   365  */
   365  */
   366 GstRTSPResult
   366 GstRTSPResult
   367 gst_rtsp_message_new_data (GstRTSPMessage ** msg, guint8 channel)
   367 gst_rtsp_message_new_data (GstRTSPMessage ** msg, guint8 channel)
   368 {
   368 {
   369   GstRTSPMessage *newmsg;
   369   GstRTSPMessage *newmsg;
   410  */
   410  */
   411 GstRTSPResult
   411 GstRTSPResult
   412 gst_rtsp_message_parse_data (GstRTSPMessage * msg, guint8 * channel)
   412 gst_rtsp_message_parse_data (GstRTSPMessage * msg, guint8 * channel)
   413 {
   413 {
   414   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   414   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   415   g_return_val_if_fail (msg->type != GST_RTSP_MESSAGE_DATA, GST_RTSP_EINVAL);
   415   g_return_val_if_fail (msg->type == GST_RTSP_MESSAGE_DATA, GST_RTSP_EINVAL);
   416 
   416 
   417   if (channel)
   417   if (channel)
   418     *channel = msg->type_data.data.channel;
   418     *channel = msg->type_data.data.channel;
   419 
   419 
   420   return GST_RTSP_OK;
   420   return GST_RTSP_OK;
   422 
   422 
   423 /**
   423 /**
   424  * gst_rtsp_message_unset:
   424  * gst_rtsp_message_unset:
   425  * @msg: a #GstRTSPMessage
   425  * @msg: a #GstRTSPMessage
   426  *
   426  *
   427  * Unset the concents of @msg so that it becomes an uninitialized
   427  * Unset the contents of @msg so that it becomes an uninitialized
   428  * #GstRTSPMessage again. This function is mostly used in combination with 
   428  * #GstRTSPMessage again. This function is mostly used in combination with 
   429  * gst_rtsp_message_init_request(), gst_rtsp_message_init_response() and
   429  * gst_rtsp_message_init_request(), gst_rtsp_message_init_response() and
   430  * gst_rtsp_message_init_data() on stack allocated #GstRTSPMessage structures.
   430  * gst_rtsp_message_init_data() on stack allocated #GstRTSPMessage structures.
   431  *
   431  *
   432  * Returns: #GST_RTSP_OK.
   432  * Returns: #GST_RTSP_OK.
   461     }
   461     }
   462     g_array_free (msg->hdr_fields, TRUE);
   462     g_array_free (msg->hdr_fields, TRUE);
   463   }
   463   }
   464   g_free (msg->body);
   464   g_free (msg->body);
   465 
   465 
   466   memset (msg, 0, sizeof *msg);
   466   memset (msg, 0, sizeof (GstRTSPMessage));
   467 
   467 
   468   return GST_RTSP_OK;
   468   return GST_RTSP_OK;
   469 }
   469 }
   470 
   470 
   471 /**
   471 /**
   489 
   489 
   490   return res;
   490   return res;
   491 }
   491 }
   492 
   492 
   493 /**
   493 /**
   494  * gst_rtsp_message_add_header:
   494  * gst_rtsp_message_take_header:
   495  * @msg: a #GstRTSPMessage
   495  * @msg: a #GstRTSPMessage
   496  * @field: a #GstRTSPHeaderField
   496  * @field: a #GstRTSPHeaderField
   497  * @value: the value of the header
   497  * @value: the value of the header
   498  *
   498  *
   499  * Add a header with key @field and @value to @msg.
   499  * Add a header with key @field and @value to @msg. This function takes
       
   500  * ownership of @value.
       
   501  *
       
   502  * Returns: a #GstRTSPResult.
       
   503  *
       
   504  * Since: 0.10.23
       
   505  */
       
   506 GstRTSPResult
       
   507 gst_rtsp_message_take_header (GstRTSPMessage * msg, GstRTSPHeaderField field,
       
   508     gchar * value)
       
   509 {
       
   510   RTSPKeyValue key_value;
       
   511 
       
   512   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
       
   513   g_return_val_if_fail (value != NULL, GST_RTSP_EINVAL);
       
   514 
       
   515   key_value.field = field;
       
   516   key_value.value = value;
       
   517 
       
   518   g_array_append_val (msg->hdr_fields, key_value);
       
   519 
       
   520   return GST_RTSP_OK;
       
   521 }
       
   522 
       
   523 /**
       
   524  * gst_rtsp_message_add_header:
       
   525  * @msg: a #GstRTSPMessage
       
   526  * @field: a #GstRTSPHeaderField
       
   527  * @value: the value of the header
       
   528  *
       
   529  * Add a header with key @field and @value to @msg. This function takes a copy
       
   530  * of @value.
   500  *
   531  *
   501  * Returns: a #GstRTSPResult.
   532  * Returns: a #GstRTSPResult.
   502  */
   533  */
   503 GstRTSPResult
   534 GstRTSPResult
   504 gst_rtsp_message_add_header (GstRTSPMessage * msg, GstRTSPHeaderField field,
   535 gst_rtsp_message_add_header (GstRTSPMessage * msg, GstRTSPHeaderField field,
   505     const gchar * value)
   536     const gchar * value)
   506 {
   537 {
   507   RTSPKeyValue key_value;
   538   return gst_rtsp_message_take_header (msg, field, g_strdup (value));
   508 
       
   509   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
       
   510   g_return_val_if_fail (value != NULL, GST_RTSP_EINVAL);
       
   511 
       
   512   key_value.field = field;
       
   513   key_value.value = g_strdup (value);
       
   514 
       
   515   g_array_append_val (msg->hdr_fields, key_value);
       
   516 
       
   517   return GST_RTSP_OK;
       
   518 }
   539 }
   519 
   540 
   520 /**
   541 /**
   521  * gst_rtsp_message_remove_header:
   542  * gst_rtsp_message_remove_header:
   522  * @msg: a #GstRTSPMessage
   543  * @msg: a #GstRTSPMessage
   537   gint cnt = 0;
   558   gint cnt = 0;
   538 
   559 
   539   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   560   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   540 
   561 
   541   while (i < msg->hdr_fields->len) {
   562   while (i < msg->hdr_fields->len) {
   542     RTSPKeyValue key_value = g_array_index (msg->hdr_fields, RTSPKeyValue, i);
   563     RTSPKeyValue *key_value = &g_array_index (msg->hdr_fields, RTSPKeyValue, i);
   543 
   564 
   544     if (key_value.field == field && (indx == -1 || cnt++ == indx)) {
   565     if (key_value->field == field && (indx == -1 || cnt++ == indx)) {
       
   566       g_free (key_value->value);
   545       g_array_remove_index (msg->hdr_fields, i);
   567       g_array_remove_index (msg->hdr_fields, i);
   546       res = GST_RTSP_OK;
   568       res = GST_RTSP_OK;
   547       if (indx != -1)
   569       if (indx != -1)
   548         break;
   570         break;
   549     } else {
   571     } else {
   558  * @msg: a #GstRTSPMessage
   580  * @msg: a #GstRTSPMessage
   559  * @field: a #GstRTSPHeaderField
   581  * @field: a #GstRTSPHeaderField
   560  * @value: pointer to hold the result
   582  * @value: pointer to hold the result
   561  * @indx: the index of the header
   583  * @indx: the index of the header
   562  *
   584  *
   563  * Get the @indx header value with key @field from @msg.
   585  * Get the @indx header value with key @field from @msg. The result in @value
       
   586  * stays valid as long as it remains present in @msg.
   564  *
   587  *
   565  * Returns: #GST_RTSP_OK when @field was found, #GST_RTSP_ENOTIMPL if the key
   588  * Returns: #GST_RTSP_OK when @field was found, #GST_RTSP_ENOTIMPL if the key
   566  * was not found.
   589  * was not found.
   567  */
   590  */
   568 GstRTSPResult
   591 GstRTSPResult
   572   guint i;
   595   guint i;
   573   gint cnt = 0;
   596   gint cnt = 0;
   574 
   597 
   575   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   598   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   576 
   599 
       
   600   /* no header initialized, there are no headers */
       
   601   if (msg->hdr_fields == NULL)
       
   602     return GST_RTSP_ENOTIMPL;
       
   603 
   577   for (i = 0; i < msg->hdr_fields->len; i++) {
   604   for (i = 0; i < msg->hdr_fields->len; i++) {
   578     RTSPKeyValue key_value = g_array_index (msg->hdr_fields, RTSPKeyValue, i);
   605     RTSPKeyValue *key_value = &g_array_index (msg->hdr_fields, RTSPKeyValue, i);
   579 
   606 
   580     if (key_value.field == field && cnt++ == indx) {
   607     if (key_value->field == field && cnt++ == indx) {
   581       if (value)
   608       if (value)
   582         *value = key_value.value;
   609         *value = key_value->value;
   583       return GST_RTSP_OK;
   610       return GST_RTSP_OK;
   584     }
   611     }
   585   }
   612   }
   586 
   613 
   587   return GST_RTSP_ENOTIMPL;
   614   return GST_RTSP_ENOTIMPL;
   604 
   631 
   605   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   632   g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL);
   606   g_return_val_if_fail (str != NULL, GST_RTSP_EINVAL);
   633   g_return_val_if_fail (str != NULL, GST_RTSP_EINVAL);
   607 
   634 
   608   for (i = 0; i < msg->hdr_fields->len; i++) {
   635   for (i = 0; i < msg->hdr_fields->len; i++) {
   609     RTSPKeyValue key_value = g_array_index (msg->hdr_fields, RTSPKeyValue, i);
   636     RTSPKeyValue *key_value;
   610     const gchar *keystr = gst_rtsp_header_as_text (key_value.field);
   637     const gchar *keystr;
   611 
   638 
   612     g_string_append_printf (str, "%s: %s\r\n", keystr, key_value.value);
   639     key_value = &g_array_index (msg->hdr_fields, RTSPKeyValue, i);
       
   640     keystr = gst_rtsp_header_as_text (key_value->field);
       
   641 
       
   642     g_string_append_printf (str, "%s: %s\r\n", keystr, key_value->value);
   613   }
   643   }
   614   return GST_RTSP_OK;
   644   return GST_RTSP_OK;
   615 }
   645 }
   616 
   646 
   617 /**
   647 /**
   710 
   740 
   711   return GST_RTSP_OK;
   741   return GST_RTSP_OK;
   712 }
   742 }
   713 
   743 
   714 static void
   744 static void
   715 dump_mem (guint8 * mem, guint size)
   745 dump_key_value (gpointer data, gpointer user_data G_GNUC_UNUSED)
   716 {
       
   717   guint i, j;
       
   718   GString *string = g_string_sized_new (50);
       
   719   GString *chars = g_string_sized_new (18);
       
   720 
       
   721   i = j = 0;
       
   722   while (i < size) {
       
   723     if (g_ascii_isprint (mem[i]))
       
   724       g_string_append_printf (chars, "%c", mem[i]);
       
   725     else
       
   726       g_string_append_printf (chars, ".");
       
   727 
       
   728     g_string_append_printf (string, "%02x ", mem[i]);
       
   729 
       
   730     j++;
       
   731     i++;
       
   732 
       
   733     if (j == 16 || i == size) {
       
   734       g_print ("%08x (%p): %-48.48s %-16.16s\n", i - j, mem + i - j,
       
   735           string->str, chars->str);
       
   736       g_string_set_size (string, 0);
       
   737       g_string_set_size (chars, 0);
       
   738       j = 0;
       
   739     }
       
   740   }
       
   741   g_string_free (string, TRUE);
       
   742   g_string_free (chars, TRUE);
       
   743 }
       
   744 
       
   745 static void
       
   746 dump_key_value (gpointer data, gpointer user_data)
       
   747 {
   746 {
   748   RTSPKeyValue *key_value = (RTSPKeyValue *) data;
   747   RTSPKeyValue *key_value = (RTSPKeyValue *) data;
   749 
   748 
   750   g_print ("   key: '%s', value: '%s'\n",
   749   g_print ("   key: '%s', value: '%s'\n",
   751       gst_rtsp_header_as_text (key_value->field), key_value->value);
   750       gst_rtsp_header_as_text (key_value->field), key_value->value);
   778           gst_rtsp_version_as_text (msg->type_data.request.version));
   777           gst_rtsp_version_as_text (msg->type_data.request.version));
   779       g_print (" headers:\n");
   778       g_print (" headers:\n");
   780       key_value_foreach (msg->hdr_fields, dump_key_value, NULL);
   779       key_value_foreach (msg->hdr_fields, dump_key_value, NULL);
   781       g_print (" body:\n");
   780       g_print (" body:\n");
   782       gst_rtsp_message_get_body (msg, &data, &size);
   781       gst_rtsp_message_get_body (msg, &data, &size);
   783       dump_mem (data, size);
   782       gst_util_dump_mem (data, size);
   784       break;
   783       break;
   785     case GST_RTSP_MESSAGE_RESPONSE:
   784     case GST_RTSP_MESSAGE_RESPONSE:
   786       g_print ("RTSP response message %p\n", msg);
   785       g_print ("RTSP response message %p\n", msg);
   787       g_print (" status line:\n");
   786       g_print (" status line:\n");
   788       g_print ("   code:   '%d'\n", msg->type_data.response.code);
   787       g_print ("   code:   '%d'\n", msg->type_data.response.code);
   791           gst_rtsp_version_as_text (msg->type_data.response.version));
   790           gst_rtsp_version_as_text (msg->type_data.response.version));
   792       g_print (" headers:\n");
   791       g_print (" headers:\n");
   793       key_value_foreach (msg->hdr_fields, dump_key_value, NULL);
   792       key_value_foreach (msg->hdr_fields, dump_key_value, NULL);
   794       gst_rtsp_message_get_body (msg, &data, &size);
   793       gst_rtsp_message_get_body (msg, &data, &size);
   795       g_print (" body: length %d\n", size);
   794       g_print (" body: length %d\n", size);
   796       dump_mem (data, size);
   795       gst_util_dump_mem (data, size);
   797       break;
   796       break;
   798     case GST_RTSP_MESSAGE_DATA:
   797     case GST_RTSP_MESSAGE_DATA:
   799       g_print ("RTSP data message %p\n", msg);
   798       g_print ("RTSP data message %p\n", msg);
   800       g_print (" channel: '%d'\n", msg->type_data.data.channel);
   799       g_print (" channel: '%d'\n", msg->type_data.data.channel);
   801       g_print (" size:    '%d'\n", msg->body_size);
   800       g_print (" size:    '%d'\n", msg->body_size);
   802       gst_rtsp_message_get_body (msg, &data, &size);
   801       gst_rtsp_message_get_body (msg, &data, &size);
   803       dump_mem (data, size);
   802       gst_util_dump_mem (data, size);
   804       break;
   803       break;
   805     default:
   804     default:
   806       g_print ("unsupported message type %d\n", msg->type);
   805       g_print ("unsupported message type %d\n", msg->type);
   807       return GST_RTSP_EINVAL;
   806       return GST_RTSP_EINVAL;
   808   }
   807   }