Updated to release 13 from tizendev
[platform/core/multimedia/gst-rtsp-server-wfd.git] / src / rtsp-client.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3
4 * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21
22 * * Modifications by Samsung Electronics Co., Ltd.
23
24 * 1. Applied Miracast WFD Server function
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <sys/time.h>
33 #include <sys/types.h>
34 #include <netinet/in.h>
35 #include <netdb.h>
36 #include <sys/socket.h>
37 #include <sys/wait.h>
38 #include <fcntl.h>
39 #include <arpa/inet.h>
40 #include <sys/ioctl.h>
41
42 #include "rtsp-client.h"
43 #include "rtsp-sdp.h"
44 #include "rtsp-params.h"
45
46 #include <exynos/exynos_drm.h>
47
48 #include <X11/X.h>
49 #include <X11/Xlib.h>
50 #include <X11/Xutil.h>
51 #include <X11/Xmd.h>
52 #include <dri2.h>
53 #include <utilX.h>
54 #include <xf86drm.h>
55
56 #define DEFAULT_RTSP_TIMEOUT    60
57 #define DRM_EXYNOS_VIDI_ON  1
58 #define DRM_EXYNOS_VIDI_OFF  0
59
60 //#define WFD_PAD_PROBE
61
62 #ifdef WFD_PAD_PROBE
63 gulong ahs_appsrc_cb_probe_id = 0;
64 FILE *f;
65 #endif
66
67 /* temporary multicast address until it's configurable somewhere */
68 #define MCAST_ADDRESS "224.2.0.1"
69
70 #define DEFAULT_WFD_MTU_SIZE 1400
71
72 static GMutex *tunnels_lock;
73 static GHashTable *tunnels;
74
75 enum
76 {
77   PROP_0,
78   PROP_SESSION_POOL,
79   PROP_MEDIA_MAPPING,
80   PROP_LAST
81 };
82
83 enum
84 {
85   SIGNAL_CLOSED,
86   SIGNAL_ERROR,
87   SIGNAL_LAST
88 };
89
90 GST_DEBUG_CATEGORY_STATIC (rtsp_client_debug);
91 #define GST_CAT_DEFAULT rtsp_client_debug
92
93 static guint gst_rtsp_client_signals[SIGNAL_LAST] = { 0 };
94
95 static void gst_rtsp_client_get_property (GObject * object, guint propid,
96     GValue * value, GParamSpec * pspec);
97 static void gst_rtsp_client_set_property (GObject * object, guint propid,
98     const GValue * value, GParamSpec * pspec);
99 static void gst_rtsp_client_finalize (GObject * obj);
100
101 static void client_session_finalized (GstRTSPClient * client,
102     GstRTSPSession * session);
103 static void unlink_session_streams (GstRTSPClient * client,
104     GstRTSPSession * session, GstRTSPSessionMedia * media);
105 static void
106 set_edid_info(gchar *edid_info, gboolean plug);
107
108 static gboolean
109 gst_rtsp_client_parse_methods (GstRTSPClient * client, GstRTSPMessage * response);
110 gboolean
111 keep_alive_condition(gpointer userdata);
112 gboolean
113 gst_rtsp_client_sending_m16_message (GstRTSPClient * client);
114
115 #ifdef WFD_PAD_PROBE
116 static gboolean
117 gst_dump_data (GstPad * pad, GstMiniObject * obj, gpointer u_data);
118 #endif
119 static void gst_rtsp_client_create_srcbin (GstRTSPClient * client);
120
121 G_DEFINE_TYPE (GstRTSPClient, gst_rtsp_client, G_TYPE_OBJECT);
122
123 static const char fake_edid_info[] = {
124     0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x2d, 0x05, 0x05,
125     0x00, 0x00, 0x00, 0x00, 0x30, 0x12, 0x01, 0x03, 0x80, 0x10, 0x09, 0x78,
126     0x0a, 0xee, 0x91, 0xa3, 0x54, 0x4c, 0x99, 0x26, 0x0f, 0x50, 0x54, 0xbd,
127     0xee, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
128     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x66, 0x21, 0x50, 0xb0, 0x51, 0x00,
129     0x1b, 0x30, 0x40, 0x70, 0x36, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e,
130     0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
131     0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18,
132     0x4b, 0x1a, 0x44, 0x17, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
133     0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x41, 0x4d, 0x53, 0x55, 0x4e, 0x47,
134     0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x01, 0xbc, 0x02, 0x03, 0x1e, 0xf1,
135     0x46, 0x84, 0x05, 0x03, 0x10, 0x20, 0x22, 0x23, 0x09, 0x07, 0x07, 0x83,
136     0x01, 0x00, 0x00, 0xe2, 0x00, 0x0f, 0x67, 0x03, 0x0c, 0x00, 0x10, 0x00,
137     0xb8, 0x2d, 0x01, 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c,
138     0x25, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x9e, 0x8c, 0x0a, 0xd0, 0x8a,
139     0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xa0, 0x5a, 0x00, 0x00,
140     0x00, 0x18, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
141     0x45, 0x00, 0xa0, 0x5a, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
142     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145     0x00, 0x00, 0x00, 0x06
146 };
147
148 static void
149 gst_rtsp_client_class_init (GstRTSPClientClass * klass)
150 {
151   GObjectClass *gobject_class;
152
153   gobject_class = G_OBJECT_CLASS (klass);
154
155   gobject_class->get_property = gst_rtsp_client_get_property;
156   gobject_class->set_property = gst_rtsp_client_set_property;
157   gobject_class->finalize = gst_rtsp_client_finalize;
158
159   g_object_class_install_property (gobject_class, PROP_SESSION_POOL,
160       g_param_spec_object ("session-pool", "Session Pool",
161           "The session pool to use for client session",
162           GST_TYPE_RTSP_SESSION_POOL,
163           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
164
165   g_object_class_install_property (gobject_class, PROP_MEDIA_MAPPING,
166       g_param_spec_object ("media-mapping", "Media Mapping",
167           "The media mapping to use for client session",
168           GST_TYPE_RTSP_MEDIA_MAPPING,
169           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
170
171   gst_rtsp_client_signals[SIGNAL_CLOSED] =
172       g_signal_new ("closed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
173       G_STRUCT_OFFSET (GstRTSPClientClass, closed), NULL, NULL,
174       g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
175
176   gst_rtsp_client_signals[SIGNAL_ERROR] =
177         g_signal_new ("error_noti", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
178         G_STRUCT_OFFSET (GstRTSPClientClass, on_error), NULL, NULL,
179         g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
180
181   tunnels =
182       g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
183   tunnels_lock = g_mutex_new ();
184
185   GST_DEBUG_CATEGORY_INIT (rtsp_client_debug, "rtspclient", 0, "GstRTSPClient");
186 }
187
188 static void
189 gst_rtsp_client_init (GstRTSPClient * client)
190 {
191   client->state_lock = g_mutex_new ();
192   client->keep_alive_lock = g_mutex_new();
193   client->keep_alive_flag = TRUE;
194   client->state_wait = g_cond_new ();
195   client->client_state = CLIENT_STATE_UNKNOWN;
196   client->videosrc_type = WFD_INI_VSRC_XVIMAGESRC;
197   client->session_mode = 0;
198   client->infile = NULL;
199   client->MTUsize = DEFAULT_WFD_MTU_SIZE;
200 }
201
202 static void
203 client_unlink_session (GstRTSPClient * client, GstRTSPSession * session)
204 {
205   GList *medias;
206
207   /* unlink all media managed in this session */
208   for (medias = session->medias; medias; medias = g_list_next (medias)) {
209     unlink_session_streams (client, session,
210         (GstRTSPSessionMedia *) medias->data);
211   }
212 }
213
214 static void
215 client_cleanup_sessions (GstRTSPClient * client)
216 {
217   GList *sessions;
218
219   /* remove weak-ref from sessions */
220   for (sessions = client->sessions; sessions; sessions = g_list_next (sessions)) {
221     GstRTSPSession *session = (GstRTSPSession *) sessions->data;
222     g_object_weak_unref (G_OBJECT (session),
223         (GWeakNotify) client_session_finalized, client);
224     client_unlink_session (client, session);
225   }
226   g_list_free (client->sessions);
227   client->sessions = NULL;
228 }
229
230 /* A client is finalized when the connection is broken */
231 static void
232 gst_rtsp_client_finalize (GObject * obj)
233 {
234   GstRTSPClient *client = GST_RTSP_CLIENT (obj);
235
236   GST_INFO ("finalize client %p", client);
237
238   client_cleanup_sessions (client);
239
240   if(client->connection)
241   {
242     gst_rtsp_connection_close (client->connection);
243     gst_rtsp_connection_free(client->connection);
244     if (client->watch)
245       g_source_destroy ((GSource *) client->watch);
246     client->watchid = 0;
247     client->watch = NULL;
248   }
249   if (client->session_pool)
250     g_object_unref (client->session_pool);
251   if (client->media_mapping)
252     g_object_unref (client->media_mapping);
253   if (client->auth)
254     g_object_unref (client->auth);
255
256   if (client->uri)
257     gst_rtsp_url_free (client->uri);
258   if (client->media)
259     g_object_unref (client->media);
260   g_free (client->server_ip);
261   set_edid_info(NULL, FALSE);
262   if(client->keep_alive_lock)
263     g_mutex_free (client->keep_alive_lock);
264   client->keep_alive_lock = NULL;
265   g_cond_signal (client->state_wait);
266   if (client->server)
267     g_object_unref (client->server);
268   if(client->tcpsock)
269     close(client->tcpsock);
270   G_OBJECT_CLASS (gst_rtsp_client_parent_class)->finalize (obj);
271 }
272
273 static void
274 set_edid_info(gchar *edid_info, gboolean plug)
275 {
276   Display *dpy = NULL;
277   int drm_fd;
278   int screen;
279   drm_magic_t magic;
280   int eventBase, errorBase;
281   int dri2Major, dri2Minor;
282   char *driverName, *deviceName;
283   struct drm_exynos_vidi_connection vidi;
284   GST_INFO("set_edid_info");
285
286   dpy = XOpenDisplay(NULL);
287   if (!dpy) {
288     GST_ERROR(" Error: fail to open display");
289   }
290   screen = DefaultScreen(dpy);
291
292   /*DRI2*/
293   if (!DRI2QueryExtension (dpy, &eventBase, &errorBase)) {
294     GST_ERROR(" Error : DRI2QueryExtension");
295   }
296
297   if (!DRI2QueryVersion (dpy, &dri2Major, &dri2Minor)) {
298     GST_ERROR("!!Error : DRI2QueryVersion !!");
299     return;
300   }
301
302   if (!DRI2Connect (dpy, RootWindow(dpy, screen), &driverName, &deviceName)) {
303     GST_ERROR( "!!Error : DRI2Connect !!\n");
304     return;
305   }
306
307   GST_INFO("Open drm device : %s\n", deviceName);
308
309   /* get the drm_fd though opening the deviceName */
310   drm_fd = open (deviceName, O_RDWR);
311   if (drm_fd < 0) {
312     GST_ERROR("!!Error : cannot open drm device (%s)", deviceName);
313     return;
314   }
315   /* get the drm magic */
316   drmGetMagic(drm_fd, &magic);
317   GST_INFO(">>> drm magic=%d", magic);
318
319   if (!DRI2Authenticate(dpy, RootWindow(dpy, screen), magic)) {
320     GST_ERROR("!!Error : DRI2Authenticate !!");
321     close(drm_fd);
322     return;
323   }
324   if (plug == TRUE){
325     vidi.connection = DRM_EXYNOS_VIDI_ON;
326     vidi.extensions = DRM_EXYNOS_VIDI_ON;
327     vidi.edid = (uint64_t *)fake_edid_info;
328     GST_ERROR(">>>>>>>>>>>>>>>>>>>>set\n");
329   } else {
330     vidi.connection = DRM_EXYNOS_VIDI_OFF;
331     vidi.extensions = DRM_EXYNOS_VIDI_OFF;
332     vidi.edid = NULL;
333     GST_ERROR(">>>>>>>>>>>>>>>>>>>>unset\n");
334   }
335
336   ioctl (drm_fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &vidi);
337
338   close(drm_fd);
339
340   return;
341 }
342
343 static void
344 gst_rtsp_client_get_property (GObject * object, guint propid,
345     GValue * value, GParamSpec * pspec)
346 {
347   GstRTSPClient *client = GST_RTSP_CLIENT (object);
348
349   switch (propid) {
350     case PROP_SESSION_POOL:
351       g_value_take_object (value, gst_rtsp_client_get_session_pool (client));
352       break;
353     case PROP_MEDIA_MAPPING:
354       g_value_take_object (value, gst_rtsp_client_get_media_mapping (client));
355       break;
356     default:
357       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
358   }
359 }
360
361 static void
362 gst_rtsp_client_set_property (GObject * object, guint propid,
363     const GValue * value, GParamSpec * pspec)
364 {
365   GstRTSPClient *client = GST_RTSP_CLIENT (object);
366
367   switch (propid) {
368     case PROP_SESSION_POOL:
369       gst_rtsp_client_set_session_pool (client, g_value_get_object (value));
370       break;
371     case PROP_MEDIA_MAPPING:
372       gst_rtsp_client_set_media_mapping (client, g_value_get_object (value));
373       break;
374     default:
375       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
376   }
377 }
378
379 /**
380  * gst_rtsp_client_new:
381  *
382  * Create a new #GstRTSPClient instance.
383  *
384  * Returns: a new #GstRTSPClient
385  */
386 GstRTSPClient *
387 gst_rtsp_client_new (void)
388 {
389   GstRTSPClient *result;
390
391   result = g_object_new (GST_TYPE_RTSP_CLIENT, NULL);
392
393   return result;
394 }
395
396 static void
397 send_response (GstRTSPClient * client, GstRTSPSession * session,
398     GstRTSPMessage * response)
399 {
400 #if 0 //Changes for testing with dongle
401   gst_rtsp_message_add_header (response, GST_RTSP_HDR_SERVER,
402       "GStreamer RTSP server");
403 #endif
404   /* remove any previous header */
405   gst_rtsp_message_remove_header (response, GST_RTSP_HDR_SESSION, -1);
406
407   /* add the new session header for new session ids */
408   if (session) {
409     gchar *str;
410
411     GST_DEBUG ("session is not NULL - %p", session);
412
413     if (session->timeout > 30)
414       str = g_strdup_printf ("%s; timeout=%d", session->sessionid, session->timeout);
415     else
416     {
417       str = g_strdup_printf ("%s;timeout=%d", session->sessionid, 30);
418     }
419
420     gst_rtsp_message_take_header (response, GST_RTSP_HDR_SESSION, str);
421   }
422
423   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
424     gst_rtsp_message_dump (response);
425   }
426
427   gst_rtsp_watch_send_message (client->watch, response, NULL);
428   gst_rtsp_message_unset (response);
429 }
430
431
432 static void
433 send_request (GstRTSPClient * client, GstRTSPSession * session, GstRTSPMessage * request)
434 {
435   /* remove any previous header */
436   gst_rtsp_message_remove_header (request, GST_RTSP_HDR_SESSION, -1);
437
438   /* add the new session header for new session ids */
439   if (session) {
440     gchar *str;
441
442     GST_DEBUG ("session is not NULL - %p", session);
443
444     if (session->timeout != DEFAULT_RTSP_TIMEOUT)
445       str =
446           g_strdup_printf ("%s; timeout=%d", session->sessionid,
447           session->timeout);
448     else
449       str = g_strdup (session->sessionid);
450
451     gst_rtsp_message_take_header (request, GST_RTSP_HDR_SESSION, str);
452   }
453
454   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
455     gst_rtsp_message_dump (request);
456   }
457
458   gst_rtsp_watch_send_message (client->watch, request, NULL);
459   gst_rtsp_message_unset (request);
460 }
461
462 static void
463 send_generic_response (GstRTSPClient * client, GstRTSPStatusCode code,
464     GstRTSPClientState * state)
465 {
466   gst_rtsp_message_init_response (state->response, code,
467       gst_rtsp_status_as_text (code), state->request);
468
469   send_response (client, NULL, state->response);
470 }
471
472 static void
473 handle_unauthorized_request (GstRTSPClient * client, GstRTSPAuth * auth,
474     GstRTSPClientState * state)
475 {
476   gst_rtsp_message_init_response (state->response, GST_RTSP_STS_UNAUTHORIZED,
477       gst_rtsp_status_as_text (GST_RTSP_STS_UNAUTHORIZED), state->request);
478
479   if (auth) {
480     /* and let the authentication manager setup the auth tokens */
481     gst_rtsp_auth_setup_auth (auth, client, 0, state);
482   }
483
484   send_response (client, state->session, state->response);
485 }
486
487
488 static gboolean
489 compare_uri (const GstRTSPUrl * uri1, const GstRTSPUrl * uri2)
490 {
491   if (uri1 == NULL || uri2 == NULL)
492     return FALSE;
493
494   if (strcmp (uri1->abspath, uri2->abspath))
495     return FALSE;
496
497   return TRUE;
498 }
499
500 /* this function is called to initially find the media for the DESCRIBE request
501  * but is cached for when the same client (without breaking the connection) is
502  * doing a setup for the exact same url. */
503 static GstRTSPMedia *
504 find_media (GstRTSPClient * client, GstRTSPClientState * state)
505 {
506   GstRTSPMediaFactory *factory;
507   GstRTSPMedia *media;
508   GstRTSPAuth *auth;
509
510   GST_INFO_OBJECT (client, "client->uri = %s & state->uri = %s",
511     client->uri->abspath, state->uri->abspath);
512
513   if (!compare_uri (client->uri, state->uri)) {
514     /* remove any previously cached values before we try to construct a new
515      * media for uri */
516     if (client->uri)
517       gst_rtsp_url_free (client->uri);
518     client->uri = NULL;
519     if (client->media)
520       g_object_unref (client->media);
521     client->media = NULL;
522
523     if (!client->media_mapping)
524       goto no_mapping;
525
526     GST_DEBUG ("Going to find factory for media mapping...");
527
528     /* find the factory for the uri first */
529     if (!(factory =
530             gst_rtsp_media_mapping_find_factory (client->media_mapping,
531                 state->uri)))
532       goto no_factory;
533
534     state->factory = factory;
535
536     GST_DEBUG ("Going to get media factory auth...");
537
538     /* check if we have access to the factory */
539     if ((auth = gst_rtsp_media_factory_get_auth (factory))) {
540       if (!gst_rtsp_auth_check (auth, client, 0, state))
541         goto not_allowed;
542
543       g_object_unref (auth);
544     }
545
546     GST_DEBUG ("Going to do media factory construct...");
547
548     GST_DEBUG ("Setting source bin...");
549     gst_rtsp_media_factory_set_srcbin (factory, GST_ELEMENT(client->srcbin->srcbin));
550
551     /* prepare the media and add it to the pipeline */
552     if (!(media = gst_rtsp_media_factory_construct (factory, state->uri)))
553       goto no_media;
554
555     g_object_unref (factory);
556
557     /* set ipv6 on the media before preparing */
558     media->is_ipv6 = client->is_ipv6;
559     state->media = media;
560
561     GST_DEBUG ("Going to do prepare media...");
562
563     /* prepare the media */
564     if (!(gst_rtsp_media_prepare (media)))
565       goto no_prepare;
566
567     GST_DEBUG ("prepare media done...");
568
569     /* now keep track of the uri and the media */
570     client->uri = gst_rtsp_url_copy (state->uri);
571     client->media = media;
572   } else {
573     /* we have seen this uri before, used cached media */
574     media = client->media;
575     state->media = media;
576     GST_INFO ("reusing cached media %p", media);
577   }
578
579   if (media)
580     g_object_ref (media);
581
582   return media;
583
584   /* ERRORS */
585 no_mapping:
586   {
587     send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
588     return NULL;
589   }
590 no_factory:
591   {
592     send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
593     return NULL;
594   }
595 not_allowed:
596   {
597     handle_unauthorized_request (client, auth, state);
598     g_object_unref (factory);
599     g_object_unref (auth);
600     return NULL;
601   }
602 no_media:
603   {
604     send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
605     g_object_unref (factory);
606     return NULL;
607   }
608 no_prepare:
609   {
610     send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
611     g_object_unref (media);
612     g_object_unref (factory);
613     return NULL;
614   }
615 }
616
617 static gboolean
618 do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
619 {
620   GstRTSPMessage message = { 0 };
621   GstMapInfo mapinfo;
622   guint8 *data;
623   guint size;
624
625   gst_rtsp_message_init_data (&message, channel);
626
627   gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
628   data = mapinfo.data;
629   size = mapinfo.size;
630   gst_rtsp_message_take_body (&message, data, size);
631
632   /* FIXME, client->watch could have been finalized here, we need to keep an
633    * extra refcount to the watch.  */
634   gst_rtsp_watch_send_message (client->watch, &message, NULL);
635
636   gst_rtsp_message_steal_body (&message, &data, &size);
637   gst_rtsp_message_unset (&message);
638
639   gst_buffer_unmap(buffer, &mapinfo);
640
641   return TRUE;
642 }
643
644 static gboolean
645 do_send_data_list (GstBufferList * blist, guint8 channel,
646     GstRTSPClient * client)
647 {
648     GstBuffer *buffer;
649     guint length = gst_buffer_list_length(blist);
650     guint i = 0;
651     for(; i < length; ++i)
652     {
653         buffer = gst_buffer_list_get(blist, i);
654         if(buffer)
655             do_send_data (buffer, channel, client);
656     }
657
658   return TRUE;
659 }
660
661 static void
662 link_stream (GstRTSPClient * client, GstRTSPSession * session,
663     GstRTSPSessionStream * stream)
664 {
665   GST_DEBUG ("client %p: linking stream %p", client, stream);
666   gst_rtsp_session_stream_set_callbacks (stream, (GstRTSPSendFunc) do_send_data,
667       (GstRTSPSendFunc) do_send_data, (GstRTSPSendListFunc) do_send_data_list,
668       (GstRTSPSendListFunc) do_send_data_list, client, NULL);
669   client->streams = g_list_prepend (client->streams, stream);
670   /* make sure our session can't expire */
671   gst_rtsp_session_prevent_expire (session);
672 }
673
674 static void
675 unlink_stream (GstRTSPClient * client, GstRTSPSession * session,
676     GstRTSPSessionStream * stream)
677 {
678   GST_DEBUG ("client %p: unlinking stream %p", client, stream);
679   gst_rtsp_session_stream_set_callbacks (stream, NULL, NULL, NULL, NULL, NULL,
680       NULL);
681   client->streams = g_list_remove (client->streams, stream);
682   /* our session can now expire */
683   gst_rtsp_session_allow_expire (session);
684 }
685
686 static void
687 unlink_session_streams (GstRTSPClient * client, GstRTSPSession * session,
688     GstRTSPSessionMedia * media)
689 {
690   guint n_streams, i;
691
692   n_streams = gst_rtsp_media_n_streams (media->media);
693   for (i = 0; i < n_streams; i++) {
694     GstRTSPSessionStream *sstream;
695     GstRTSPTransport *tr;
696
697     /* get the stream as configured in the session */
698     sstream = gst_rtsp_session_media_get_stream (media, i);
699     /* get the transport, if there is no transport configured, skip this stream */
700     if (!(tr = sstream->trans.transport))
701       continue;
702
703     if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
704       /* for TCP, unlink the stream from the TCP connection of the client */
705       unlink_stream (client, session, sstream);
706     }
707   }
708 }
709
710 static void
711 close_connection (GstRTSPClient * client)
712 {
713   const gchar *tunnelid;
714
715   GST_DEBUG ("client %p: closing connection", client);
716
717   if ((tunnelid = gst_rtsp_connection_get_tunnelid (client->connection))) {
718     g_mutex_lock (tunnels_lock);
719     /* remove from tunnelids */
720     g_hash_table_remove (tunnels, tunnelid);
721     g_mutex_unlock (tunnels_lock);
722   }
723
724   gst_rtsp_connection_close (client->connection);
725   if (client->watchid) {
726     g_source_destroy ((GSource *) client->watch);
727     client->watchid = 0;
728     client->watch = NULL;
729   }
730 }
731
732 static gboolean
733 handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state)
734 {
735   GstRTSPSession *session;
736   GstRTSPSessionMedia *media;
737   GstRTSPStatusCode code;
738
739   if (!state->session)
740     goto no_session;
741
742   session = state->session;
743
744   /* get a handle to the configuration of the media in the session */
745   media = gst_rtsp_session_get_media (session, state->uri);
746   if (!media)
747     goto not_found;
748
749   state->sessmedia = media;
750
751   /* unlink the all TCP callbacks */
752   unlink_session_streams (client, session, media);
753
754   /* remove the session from the watched sessions */
755   g_object_weak_unref (G_OBJECT (session),
756       (GWeakNotify) client_session_finalized, client);
757   client->sessions = g_list_remove (client->sessions, session);
758
759   gst_rtsp_session_media_set_state (media, GST_STATE_PAUSED);
760   gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
761
762   /* unmanage the media in the session, returns false if all media session
763    * are torn down. */
764   if (!gst_rtsp_session_release_media (session, media)) {
765     /* remove the session */
766     gst_rtsp_session_pool_remove (client->session_pool, session);
767   }
768   /* construct the response now */
769   code = GST_RTSP_STS_OK;
770   gst_rtsp_message_init_response (state->response, code,
771       gst_rtsp_status_as_text (code), state->request);
772
773   gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_CONNECTION,
774       "close");
775
776   send_response (client, session, state->response);
777
778   close_connection (client);
779
780   return TRUE;
781
782   /* ERRORS */
783 no_session:
784   {
785     send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
786     return FALSE;
787   }
788 not_found:
789   {
790     send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
791     return FALSE;
792   }
793 }
794 static GstRTSPResult
795 prepare_src_response (GstRTSPClient *client, GstRTSPMessage *response, GstRTSPMessage *request, GstRTSPMethod method, WFDMessageType message_type)
796 {
797   if(method == GST_RTSP_GET_PARAMETER) {
798     //gst_rtsp_message_init_response (response, GST_RTSP_STS_OK, gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
799     return GST_RTSP_EINVAL;
800   } else if(method == GST_RTSP_SET_PARAMETER) {
801     switch(message_type) {
802     case WFD_MESSAGE_10:
803     case WFD_MESSAGE_11:
804     case WFD_MESSAGE_12:
805     case WFD_MESSAGE_13:
806     case WFD_MESSAGE_14:
807     case WFD_MESSAGE_15:
808       gst_rtsp_message_init_response (response, GST_RTSP_STS_OK, gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
809       return GST_RTSP_OK;
810     default: return GST_RTSP_EINVAL;
811     }
812   }
813   return GST_RTSP_EINVAL;
814 }
815
816 WFDMessageType get_rtsp_source_config_message_type(WFDMessage *msg, GstRTSPMethod message_type)
817 {
818   if(message_type == GST_RTSP_GET_PARAMETER) {
819     return WFD_MESSAGE_UNKNOWN;
820   } else if(message_type == GST_RTSP_SET_PARAMETER) {
821     if (msg->route) return WFD_MESSAGE_10;
822     else if (msg->connector_type) return WFD_MESSAGE_11;
823     else if (msg->standby) return WFD_MESSAGE_12;
824     else if (msg->idr_request) return WFD_MESSAGE_13;
825     else if (msg->uibc_capability) return WFD_MESSAGE_14;
826     else if (msg->uibc_setting) return WFD_MESSAGE_15;
827     else return WFD_MESSAGE_UNKNOWN;
828   }
829   return WFD_MESSAGE_UNKNOWN;
830 }
831
832 static gboolean
833 handle_get_param_request (GstRTSPClient * client, GstRTSPClientState * state)
834 {
835   GstRTSPResult res;
836   guint8 *data;
837   guint size;
838   WFDMessageType message_type;
839
840   res = gst_rtsp_message_get_body (state->request, &data, &size);
841   if (res != GST_RTSP_OK)
842     goto bad_request;
843
844   if (size == 0) {
845     /* no body, keep-alive request */
846     send_generic_response (client, GST_RTSP_STS_OK, state);
847   } else {
848     WFDMessage *msg;
849     wfdconfig_message_new(&msg);
850     wfdconfig_message_init(msg);
851     wfdconfig_message_parse_buffer(data,size,msg);
852     //GST_DEBUG("\nM3 response server side message body: %s\n\n\n", wfdconfig_message_as_text(msg));
853     message_type = get_rtsp_source_config_message_type (msg, GST_RTSP_GET_PARAMETER);
854
855     res = prepare_src_response(client, state->response, state->request, GST_RTSP_GET_PARAMETER, message_type);
856     if (res != GST_RTSP_OK) {
857     /* there is a body, handle the params */
858       res = gst_rtsp_params_get (client, state);
859       if (res != GST_RTSP_OK)
860         goto bad_request;
861     }
862     send_response (client, state->session, state->response);
863   }
864   return TRUE;
865
866   /* ERRORS */
867 bad_request:
868   {
869     send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
870     return FALSE;
871   }
872 }
873
874 static guint32 gIDRReqcount = 0;
875 static gboolean
876 handle_set_param_request (GstRTSPClient * client, GstRTSPClientState * state)
877 {
878   GstRTSPResult res;
879   guint8 *data;
880   guint size;
881   WFDMessageType message_type;
882   WFDResult confret;
883
884   res = gst_rtsp_message_get_body (state->request, &data, &size);
885   if (res != GST_RTSP_OK)
886     goto bad_request;
887
888   if (size == 0) {
889     /* no body, keep-alive request */
890     send_generic_response (client, GST_RTSP_STS_OK, state);
891   } else {
892     WFDMessage *msg;
893     wfdconfig_message_new(&msg);
894     wfdconfig_message_init(msg);
895     wfdconfig_message_parse_buffer(data,size,msg);
896     //GST_DEBUG("\nM3 response server side message body: %s\n\n\n", wfdconfig_message_as_text(msg));
897     message_type = get_rtsp_source_config_message_type (msg, GST_RTSP_SET_PARAMETER);
898     switch (message_type) {
899       case WFD_MESSAGE_10:
900       {
901         WFDSinkType sinktype;
902         confret = wfdconfig_get_audio_sink_type(msg, &sinktype);
903         if(confret == WFD_OK)
904           GST_DEBUG("M10 server set param request route to  %s  sink", sinktype?"SECONDARY":"PRIMARY");
905       }
906       break;
907       case WFD_MESSAGE_11:
908       {
909         WFDConnector connector;
910         confret = wfdconfig_get_connector_type(msg, &connector);
911         if(confret == WFD_OK)
912           GST_DEBUG("M11 server set param request connector type to %d", connector);
913       }
914       break;
915       case WFD_MESSAGE_12:
916       {
917         gboolean standby_enable;
918         confret = wfdconfig_get_standby(msg, &standby_enable);
919         if(confret == WFD_OK)
920           GST_DEBUG("M12 server set param request STANDBY %s", standby_enable?"ENABLE":"DISABLE");
921       }
922       break;
923       case WFD_MESSAGE_13:
924       {
925         GST_DEBUG("M13 server set param request for IDR frame");
926         g_object_set (client->srcbin->venc, "force-i-frame", 1, NULL);
927     //gIDRReqcount++;
928       }
929       break;
930       case WFD_MESSAGE_14:
931       {
932         guint32 input_category;
933         guint32 inp_type;
934         WFDHIDCTypePathPair *inp_pair;
935         guint32 inp_type_path_count = 0;
936         guint32 i = 0;
937         guint32 tcp_port;
938         confret = wfdconfig_get_uibc_capability(msg, &input_category, &inp_type, inp_pair, &inp_type_path_count, &tcp_port);
939         if(confret == WFD_OK) {
940           GST_DEBUG("M14 server set param UIBC input category: %s %s", input_category&WFD_UIBC_INPUT_CAT_GENERIC?"GENERIC":"", input_category&WFD_UIBC_INPUT_CAT_HIDC?"HIDC":"");
941           GST_DEBUG("UIBC input type: %s %s %s %s %s %s %s %s", inp_type&WFD_UIBC_INPUT_TYPE_KEYBOARD?"KEYBOARD":"", inp_type&WFD_UIBC_INPUT_TYPE_MOUSE?"MOUSE":"",
942              inp_type&WFD_UIBC_INPUT_TYPE_SINGLETOUCH?"SINGLETOUCH":"", inp_type&WFD_UIBC_INPUT_TYPE_MULTITOUCH?"MULTITOUCH":"",
943              inp_type&WFD_UIBC_INPUT_TYPE_JOYSTICK?"JOYSTICK":"", inp_type&WFD_UIBC_INPUT_TYPE_CAMERA?"CAMERA":"",
944              inp_type&WFD_UIBC_INPUT_TYPE_GESTURE?"GESTURE":"", inp_type&WFD_UIBC_INPUT_TYPE_REMOTECONTROL?"REMOTECONTROL":"");
945           for(;i<inp_type_path_count;i++) {
946             GST_DEBUG("UIBC %d: %s%s%s%s%s%s%s%s %s%s%s%s%s%s", i, inp_pair[i].inp_type&WFD_UIBC_INPUT_TYPE_KEYBOARD?"KEYBOARD":"", inp_pair[i].inp_type&WFD_UIBC_INPUT_TYPE_MOUSE?"MOUSE":"",
947               inp_pair[i].inp_type&WFD_UIBC_INPUT_TYPE_SINGLETOUCH?"SINGLETOUCH":"", inp_pair[i].inp_type&WFD_UIBC_INPUT_TYPE_MULTITOUCH?"MULTITOUCH":"",
948               inp_pair[i].inp_type&WFD_UIBC_INPUT_TYPE_JOYSTICK?"JOYSTICK":"", inp_pair[i].inp_type&WFD_UIBC_INPUT_TYPE_CAMERA?"CAMERA":"",
949               inp_pair[i].inp_type&WFD_UIBC_INPUT_TYPE_GESTURE?"GESTURE":"", inp_pair[i].inp_type&WFD_UIBC_INPUT_TYPE_REMOTECONTROL?"REMOTECONTROL":"",
950               inp_pair[i].inp_path&WFD_UIBC_INPUT_PATH_INFRARED?"INFRARED":"", inp_pair[i].inp_path&WFD_UIBC_INPUT_PATH_USB?"USB":"",
951               inp_pair[i].inp_path&WFD_UIBC_INPUT_PATH_BT?"BT":"", inp_pair[i].inp_path&WFD_UIBC_INPUT_PATH_ZIGBEE?"ZIGBEE":"",
952               inp_pair[i].inp_path&WFD_UIBC_INPUT_PATH_WIFI?"WIFI":"", inp_pair[i].inp_path&WFD_UIBC_INPUT_PATH_NOSP?"NOSP":"");
953           }
954         }
955       }
956       break;
957       case WFD_MESSAGE_15:
958       {
959         gboolean uibc_enable;
960         confret = wfdconfig_get_uibc_status(msg, &uibc_enable);
961         if(confret == WFD_OK)
962           GST_DEBUG("M15 server set param request for UIBC %s", uibc_enable?"ENABLE":"DISABLE");
963       }
964       break;
965       default:
966       {
967         GST_ERROR_OBJECT (client, "Not handling message num - %d", message_type);
968         goto bad_request;
969       }
970       break;
971     }
972     res = prepare_src_response(client, state->response, state->request, GST_RTSP_SET_PARAMETER, message_type);
973     if (res != GST_RTSP_OK) {
974       /* there is a body, handle the params */
975       res = gst_rtsp_params_set (client, state);
976       if (res != GST_RTSP_OK)
977         goto bad_request;
978     }
979     send_response (client, state->session, state->response);
980   }
981
982   return TRUE;
983
984   /* ERRORS */
985 bad_request:
986   {
987     send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
988     return TRUE;
989   }
990 }
991
992 static gboolean
993 handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state)
994 {
995   GstRTSPSession *session;
996   GstRTSPSessionMedia *media;
997   GstRTSPStatusCode code;
998
999   if (!(session = state->session))
1000     goto no_session;
1001
1002   /* get a handle to the configuration of the media in the session */
1003   media = gst_rtsp_session_get_media (session, state->uri);
1004   if (!media)
1005     goto not_found;
1006
1007   state->sessmedia = media;
1008
1009   /* the session state must be playing or recording */
1010   if (media->state != GST_RTSP_STATE_PLAYING &&
1011       media->state != GST_RTSP_STATE_RECORDING)
1012     goto invalid_state;
1013
1014   /* unlink the all TCP callbacks */
1015   unlink_session_streams (client, session, media);
1016
1017   /* then pause sending */
1018   gst_rtsp_session_media_set_state (media, GST_STATE_PAUSED);
1019
1020   /* construct the response now */
1021   code = GST_RTSP_STS_OK;
1022   gst_rtsp_message_init_response (state->response, code,
1023       gst_rtsp_status_as_text (code), state->request);
1024
1025   send_response (client, session, state->response);
1026
1027   /* the state is now READY */
1028   media->state = GST_RTSP_STATE_READY;
1029
1030   return TRUE;
1031
1032   /* ERRORS */
1033 no_session:
1034   {
1035     send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
1036     return FALSE;
1037   }
1038 not_found:
1039   {
1040     send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
1041     return FALSE;
1042   }
1043 invalid_state:
1044   {
1045     send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE,
1046         state);
1047     return FALSE;
1048   }
1049 }
1050
1051 static gboolean
1052 handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
1053 {
1054   GstRTSPSession *session;
1055   GstRTSPSessionMedia *media;
1056   GstRTSPStatusCode code;
1057   GString *rtpinfo;
1058   guint n_streams, i, infocount;
1059   guint timestamp, seqnum;
1060   gchar *str;
1061   GstRTSPTimeRange *range;
1062   GstRTSPResult res;
1063
1064   if (!(session = state->session))
1065     goto no_session;
1066
1067   /* get a handle to the configuration of the media in the session */
1068   media = gst_rtsp_session_get_media (session, state->uri);
1069   if (!media)
1070     goto not_found;
1071
1072   state->sessmedia = media;
1073
1074   /* the session state must be playing or ready */
1075   if (media->state != GST_RTSP_STATE_PLAYING &&
1076       media->state != GST_RTSP_STATE_READY)
1077     goto invalid_state;
1078
1079   /* parse the range header if we have one */
1080   res =
1081       gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_RANGE, &str, 0);
1082   if (res == GST_RTSP_OK) {
1083     if (gst_rtsp_range_parse (str, &range) == GST_RTSP_OK) {
1084       /* we have a range, seek to the position */
1085       gst_rtsp_media_seek (media->media, range);
1086       gst_rtsp_range_free (range);
1087     }
1088   }
1089
1090   /* grab RTPInfo from the payloaders now */
1091   rtpinfo = g_string_new ("");
1092
1093   n_streams = gst_rtsp_media_n_streams (media->media);
1094   for (i = 0, infocount = 0; i < n_streams; i++) {
1095     GstRTSPSessionStream *sstream;
1096     GstRTSPMediaStream *stream;
1097     GstRTSPTransport *tr;
1098     GObjectClass *payobjclass;
1099     gchar *uristr;
1100
1101     /* get the stream as configured in the session */
1102     sstream = gst_rtsp_session_media_get_stream (media, i);
1103     /* get the transport, if there is no transport configured, skip this stream */
1104     if (!(tr = sstream->trans.transport)) {
1105       GST_INFO ("stream %d is not configured", i);
1106       continue;
1107     }
1108
1109     if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
1110       /* for TCP, link the stream to the TCP connection of the client */
1111       link_stream (client, session, sstream);
1112     }
1113
1114     stream = sstream->media_stream;
1115
1116     payobjclass = G_OBJECT_GET_CLASS (stream->payloader);
1117
1118     if (g_object_class_find_property (payobjclass, "seqnum") &&
1119         g_object_class_find_property (payobjclass, "timestamp")) {
1120       GObject *payobj;
1121
1122       payobj = G_OBJECT (stream->payloader);
1123
1124       /* only add RTP-Info for streams with seqnum and timestamp */
1125       g_object_get (payobj, "seqnum", &seqnum, "timestamp", &timestamp, NULL);
1126
1127       if (infocount > 0)
1128         g_string_append (rtpinfo, ", ");
1129
1130       uristr = gst_rtsp_url_get_request_uri (state->uri);
1131       g_string_append_printf (rtpinfo, "url=%s;seq=%u;rtptime=%u",
1132           uristr,seqnum, timestamp);
1133       g_free (uristr);
1134
1135       infocount++;
1136     } else {
1137       GST_WARNING ("RTP-Info cannot be determined for stream %d", i);
1138     }
1139   }
1140
1141   /* construct the response now */
1142   code = GST_RTSP_STS_OK;
1143   gst_rtsp_message_init_response (state->response, code,
1144   gst_rtsp_status_as_text (code), state->request);
1145   send_response (client, NULL, state->response);
1146
1147   /* start playing after sending the request */
1148   GST_INFO("set media to GST_STATE_PLAYING");
1149   gst_rtsp_session_media_set_state (media, GST_STATE_PLAYING);
1150
1151   media->state = GST_RTSP_STATE_PLAYING;
1152
1153   return TRUE;
1154
1155   /* ERRORS */
1156 no_session:
1157   {
1158     send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
1159     return FALSE;
1160   }
1161 not_found:
1162   {
1163     send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
1164     return FALSE;
1165   }
1166 invalid_state:
1167   {
1168     send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE,
1169         state);
1170     return FALSE;
1171   }
1172 }
1173
1174 static void
1175 do_keepalive (GstRTSPSession * session)
1176 {
1177   GST_INFO ("keep session %p alive", session);
1178   gst_rtsp_session_touch (session);
1179 }
1180
1181 static gboolean
1182 handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
1183 {
1184   GstRTSPResult res;
1185   GstRTSPUrl *uri;
1186   gchar *transport;
1187   gchar *user_agent; //Changes for testing with dongle
1188   gchar **transports;
1189   gboolean have_transport;
1190   GstRTSPTransport *ct, *st;
1191   gint i;
1192   GstRTSPLowerTrans supported;
1193   GstRTSPStatusCode code;
1194   GstRTSPSession *session;
1195   GstRTSPSessionStream *stream;
1196   gchar *trans_str, *pos;
1197   guint streamid;
1198   GstRTSPSessionMedia *media;
1199   GstRTSPUrl *url;
1200
1201   uri = state->uri;
1202
1203   /* the uri contains the stream number we added in the SDP config, which is
1204    * always /stream=%d so we need to strip that off
1205    * parse the stream we need to configure, look for the stream in the abspath
1206    * first and then in the query. */
1207   if (uri->abspath == NULL || !(pos = strstr (uri->abspath, "/streamid="))) {
1208     if (uri->query == NULL || !(pos = strstr (uri->query, "/streamid=")))
1209     {
1210       GST_ERROR ("bad request...");
1211       goto bad_request;
1212     }
1213   }
1214
1215   /* we can mofify the parse uri in place */
1216   *pos = '\0';
1217
1218   pos += strlen ("/streamid=");
1219   if (sscanf (pos, "%u", &streamid) != 1)
1220     goto bad_request;
1221
1222   res = gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_USER_AGENT,
1223       &user_agent, 0);  //Changes for testing with dongle
1224
1225   /* parse the transport */
1226   res =
1227       gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_TRANSPORT,
1228       &transport, 0);
1229   if (res != GST_RTSP_OK)
1230     goto no_transport;
1231
1232   transports = g_strsplit (transport, ",", 0);
1233   gst_rtsp_transport_new (&ct);
1234
1235   /* init transports */
1236   have_transport = FALSE;
1237   gst_rtsp_transport_init (ct);
1238
1239   /* our supported transports */
1240   supported = GST_RTSP_LOWER_TRANS_UDP |
1241       GST_RTSP_LOWER_TRANS_UDP_MCAST | GST_RTSP_LOWER_TRANS_TCP;
1242
1243   /* loop through the transports, try to parse */
1244   for (i = 0; transports[i]; i++) {
1245     res = gst_rtsp_transport_parse (transports[i], ct);
1246     if (res != GST_RTSP_OK) {
1247       /* no valid transport, search some more */
1248       GST_WARNING ("could not parse transport %s", transports[i]);
1249       goto next;
1250     }
1251
1252     /* we have a transport, see if it's RTP/AVP */
1253     if (ct->trans != GST_RTSP_TRANS_RTP || ct->profile != GST_RTSP_PROFILE_AVP) {
1254       GST_WARNING ("invalid transport %s", transports[i]);
1255       goto next;
1256     }
1257
1258     if (!(ct->lower_transport & supported)) {
1259       GST_WARNING ("unsupported transport %s", transports[i]);
1260       goto next;
1261     }
1262
1263     /* we have a valid transport */
1264     GST_INFO ("found valid transport %s", transports[i]);
1265     have_transport = TRUE;
1266     break;
1267
1268   next:
1269     gst_rtsp_transport_init (ct);
1270   }
1271   g_strfreev (transports);
1272
1273   /* we have not found anything usable, error out */
1274   if (!have_transport)
1275     goto unsupported_transports;
1276
1277   if (client->session_pool == NULL)
1278     goto no_pool;
1279
1280   /* we have a valid transport now, set the destination of the client. */
1281   g_free (ct->destination);
1282   if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
1283     ct->destination = g_strdup (MCAST_ADDRESS);
1284     ct->port.min = client->crtp_port0; //Changes for testing with dongle
1285     ct->port.max = -1; //Changes for testing with dongle
1286   } else {
1287     url = gst_rtsp_connection_get_url (client->connection);
1288     ct->destination = g_strdup (url->host);
1289     ct->client_port.min = client->crtp_port0; //Changes for testing with dongle
1290     ct->client_port.max = -1; //Changes for testing with dongle
1291   }
1292
1293   session = state->session;
1294
1295   if (session) {
1296     g_object_ref (session);
1297     /* get a handle to the configuration of the media in the session, this can
1298      * return NULL if this is a new url to manage in this session. */
1299     media = gst_rtsp_session_get_media (session, uri);
1300   } else {
1301     /* create a session if this fails we probably reached our session limit or
1302      * something. */
1303     if (!(session = gst_rtsp_session_pool_create (client->session_pool)))
1304       goto service_unavailable;
1305     session->timeout = DEFAULT_RTSP_TIMEOUT;
1306     state->session = session;
1307     client->sessionid = g_strdup(session->sessionid);
1308     /* we need a new media configuration in this session */
1309     media = NULL;
1310   }
1311
1312   /* we have no media, find one and manage it */
1313   if (media == NULL) {
1314     GstRTSPMedia *m;
1315
1316     // TODO: need to decide on arguments...
1317     gst_rtsp_client_create_srcbin (client);
1318     if (NULL == client->srcbin) {
1319       GST_ERROR_OBJECT (client, "Failed to create src bin...");
1320       goto no_stream;
1321     }
1322
1323     /* get a handle to the configuration of the media in the session */
1324     if ((m = find_media (client, state))) {
1325       /* manage the media in our session now */
1326       media = gst_rtsp_session_manage_media (session, uri, m);
1327     }
1328   }
1329
1330   /* if we stil have no media, error */
1331   if (media == NULL)
1332     goto not_found;
1333
1334   state->sessmedia = media;
1335
1336   /* fix the transports */
1337   if (ct->lower_transport & GST_RTSP_LOWER_TRANS_TCP) {
1338     /* check if the client selected channels for TCP */
1339     if (ct->interleaved.min == -1 || ct->interleaved.max == -1) {
1340       gst_rtsp_session_media_alloc_channels (media, &ct->interleaved);
1341     }
1342   }
1343
1344   /* get a handle to the stream in the media */
1345   if (!(stream = gst_rtsp_session_media_get_stream (media, streamid)))
1346     goto no_stream;
1347
1348   st = gst_rtsp_session_stream_set_transport (stream, ct);
1349
1350   /* configure keepalive for this transport */
1351   gst_rtsp_session_stream_set_keepalive (stream,
1352       (GstRTSPKeepAliveFunc) do_keepalive, session, NULL);
1353
1354   /* serialize the server transport */
1355   trans_str = gst_rtsp_transport_as_text (st);
1356   gst_rtsp_transport_free (st);
1357
1358   /* construct the response now */
1359   code = GST_RTSP_STS_OK;
1360   gst_rtsp_message_init_response (state->response, code,
1361       gst_rtsp_status_as_text (code), state->request);
1362
1363   gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_TRANSPORT,
1364       trans_str);
1365   g_free (trans_str);
1366 /*
1367   GST_ERROR ("user agent %s", user_agent);
1368   if(user_agent) {
1369     gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_USER_AGENT, user_agent);
1370     g_free (user_agent);
1371   }*/ //Changes for testing with dongle
1372   //gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_CONTENT_TYPE, "text/parameters");
1373   //textparam = g_strdup ("wfd_presentation_URL: rtsp://192.168.16.1/wfd1.0/streamid=0 none");
1374   //gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_CONTENT_LENGTH, g_strdup_printf ("%d",strlen(textparam)));
1375     /* adding data field */
1376    //gst_rtsp_message_set_body (state->response, textparam, strlen(textparam));
1377
1378   send_response (client, session, state->response);
1379
1380   /* update the state */
1381   switch (media->state) {
1382     case GST_RTSP_STATE_PLAYING:
1383     case GST_RTSP_STATE_RECORDING:
1384     case GST_RTSP_STATE_READY:
1385       /* no state change */
1386       break;
1387     default:
1388       media->state = GST_RTSP_STATE_READY;
1389       break;
1390   }
1391   g_object_unref (session);
1392
1393   return TRUE;
1394
1395   /* ERRORS */
1396 bad_request:
1397   {
1398     send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
1399     return FALSE;
1400   }
1401 not_found:
1402   {
1403     send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
1404     g_object_unref (session);
1405     return FALSE;
1406   }
1407 no_stream:
1408   {
1409     send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
1410     g_object_unref (media);
1411     g_object_unref (session);
1412     return FALSE;
1413   }
1414 no_transport:
1415   {
1416     send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
1417     return FALSE;
1418   }
1419 unsupported_transports:
1420   {
1421     send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
1422     gst_rtsp_transport_free (ct);
1423     return FALSE;
1424   }
1425 no_pool:
1426   {
1427     send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
1428     return FALSE;
1429   }
1430 service_unavailable:
1431   {
1432     send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
1433     return FALSE;
1434   }
1435 }
1436
1437 static GstSDPMessage *
1438 create_sdp (GstRTSPClient * client, GstRTSPMedia * media)
1439 {
1440   GstSDPMessage *sdp;
1441   GstSDPInfo info;
1442   const gchar *proto;
1443
1444   gst_sdp_message_new (&sdp);
1445
1446   /* some standard things first */
1447   gst_sdp_message_set_version (sdp, "0");
1448
1449   if (client->is_ipv6)
1450     proto = "IP6";
1451   else
1452     proto = "IP4";
1453
1454   gst_sdp_message_set_origin (sdp, "-", "1188340656180883", "1", "IN", proto,
1455       client->server_ip);
1456
1457   gst_sdp_message_set_session_name (sdp, "Session streamed with GStreamer");
1458   gst_sdp_message_set_information (sdp, "rtsp-server");
1459   gst_sdp_message_add_time (sdp, "0", "0", NULL);
1460   gst_sdp_message_add_attribute (sdp, "tool", "GStreamer");
1461   gst_sdp_message_add_attribute (sdp, "type", "broadcast");
1462   gst_sdp_message_add_attribute (sdp, "control", "*");
1463
1464   info.server_proto = proto;
1465   if (media->protocols & GST_RTSP_LOWER_TRANS_UDP_MCAST)
1466     info.server_ip = MCAST_ADDRESS;
1467   else
1468     info.server_ip = client->server_ip;
1469
1470   /* create an SDP for the media object */
1471   if (!gst_rtsp_sdp_from_media (sdp, &info, media))
1472     goto no_sdp;
1473
1474   return sdp;
1475
1476   /* ERRORS */
1477 no_sdp:
1478   {
1479     gst_sdp_message_free (sdp);
1480     return NULL;
1481   }
1482 }
1483
1484 /* for the describe we must generate an SDP */
1485 static gboolean
1486 handle_describe_request (GstRTSPClient * client, GstRTSPClientState * state)
1487 {
1488   GstRTSPResult res;
1489   GstSDPMessage *sdp;
1490   guint i, str_len;
1491   gchar *str, *content_base;
1492   GstRTSPMedia *media;
1493
1494   /* check what kind of format is accepted, we don't really do anything with it
1495    * and always return SDP for now. */
1496   for (i = 0; ;i++) {
1497     gchar *accept;
1498     res =
1499         gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_ACCEPT,
1500         &accept, i);
1501     if (res == GST_RTSP_ENOTIMPL)
1502       break;
1503
1504     if (g_ascii_strcasecmp (accept, "application/sdp") == 0)
1505       break;
1506   }
1507
1508   /* find the media object for the uri */
1509   if (!(media = find_media (client, state)))
1510     goto no_media;
1511
1512   /* create an SDP for the media object on this client */
1513   if (!(sdp = create_sdp (client, media)))
1514     goto no_sdp;
1515
1516   g_object_unref (media);
1517
1518   gst_rtsp_message_init_response (state->response, GST_RTSP_STS_OK,
1519       gst_rtsp_status_as_text (GST_RTSP_STS_OK), state->request);
1520
1521   gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_CONTENT_TYPE,
1522       "application/sdp");
1523
1524   /* content base for some clients that might screw up creating the setup uri */
1525   str = gst_rtsp_url_get_request_uri (state->uri);
1526   str_len = strlen (str);
1527
1528   /* check for trailing '/' and append one */
1529   if (str[str_len - 1] != '/') {
1530     content_base = g_malloc (str_len + 2);
1531     memcpy (content_base, str, str_len);
1532     content_base[str_len] = '/';
1533     content_base[str_len + 1] = '\0';
1534     g_free (str);
1535   } else {
1536     content_base = str;
1537   }
1538
1539   GST_INFO ("adding content-base: %s", content_base);
1540
1541   gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_CONTENT_BASE,
1542       content_base);
1543   g_free (content_base);
1544
1545   /* add SDP to the response body */
1546   str = gst_sdp_message_as_text (sdp);
1547   gst_rtsp_message_take_body (state->response, (guint8 *) str, strlen (str));
1548   gst_sdp_message_free (sdp);
1549
1550   send_response (client, state->session, state->response);
1551
1552   return TRUE;
1553
1554   /* ERRORS */
1555 no_media:
1556   {
1557     /* error reply is already sent */
1558     return FALSE;
1559   }
1560 no_sdp:
1561   {
1562     send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
1563     g_object_unref (media);
1564     return FALSE;
1565   }
1566 }
1567
1568 static gboolean
1569 handle_options_request (GstRTSPClient * client, GstRTSPClientState * state)
1570 {
1571   GstRTSPMethod options;
1572   gchar *str;
1573   GstRTSPMessage request = { 0 };
1574   GstRTSPMessage response = { 0 };
1575   GstRTSPResult res = GST_RTSP_OK;
1576   GstRTSPUrl *url = NULL;
1577   gchar *url_str = NULL;
1578   WFDMessage *msg3res;
1579   WFDAudioFormats caCodec = WFD_AUDIO_UNKNOWN;
1580   WFDAudioFreq cFreq = WFD_FREQ_UNKNOWN;
1581   WFDAudioChannels cChanels = WFD_CHANNEL_UNKNOWN;
1582   guint cBitwidth = 0;
1583   guint caLatency = 0;
1584   WFDVideoCodecs cvCodec = WFD_VIDEO_UNKNOWN;
1585   WFDVideoNativeResolution cNative = WFD_VIDEO_CEA_RESOLUTION;
1586   guint64 cNativeResolution = 0;
1587   WFDVideoCEAResolution cCEAResolution = WFD_CEA_UNKNOWN;
1588   WFDVideoVESAResolution cVESAResolution = WFD_VESA_UNKNOWN;
1589   WFDVideoHHResolution cHHResolution = WFD_HH_UNKNOWN;
1590   WFDVideoH264Profile cProfile = WFD_H264_UNKNOWN_PROFILE;
1591   WFDVideoH264Level cLevel = WFD_H264_LEVEL_UNKNOWN;
1592   guint32 cMaxHeight = 0;
1593   guint32 cMaxWidth = 0;
1594   guint32 cmin_slice_size = 0;
1595   guint32 cslice_enc_params = 0;
1596   guint cframe_rate_control = 0;
1597   guint cvLatency = 0;
1598   WFDRTSPTransMode ctrans = WFD_RTSP_TRANS_UNKNOWN;
1599   WFDRTSPProfile cprofile = WFD_RTSP_PROFILE_UNKNOWN;
1600   WFDRTSPLowerTrans clowertrans = WFD_RTSP_LOWER_TRANS_UNKNOWN;
1601   guint32 crtp_port0 = 0;
1602   guint32 crtp_port1 = 0;
1603   gchar *tmp = NULL;
1604
1605   options = GST_RTSP_OPTIONS |
1606       GST_RTSP_PAUSE |
1607       GST_RTSP_PLAY |
1608       GST_RTSP_SETUP |
1609       GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
1610
1611   str = gst_rtsp_options_as_text (options);
1612
1613   /*append WFD specific method */
1614   //g_string_append (str, "org.wfa.wfd1.0, ");
1615   tmp = g_strdup (", org.wfa.wfd1.0");
1616   g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1);
1617
1618   gst_rtsp_message_init_response (state->response, GST_RTSP_STS_OK,
1619       gst_rtsp_status_as_text (GST_RTSP_STS_OK), state->request);
1620
1621   gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_PUBLIC, str);
1622   g_free (str);
1623
1624   send_response (client, state->session, state->response);
1625
1626   GST_DEBUG_OBJECT (client, "Sent OPTIONS Response...");
1627  
1628   ////////////////////////////////////
1629   ////    GET_PARAMETER Msg (M3)    /////
1630   ///////////////////////////////////
1631
1632   url = gst_rtsp_connection_get_url (client->connection);
1633   url_str = gst_rtsp_url_get_request_uri (url);
1634
1635   res = gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER, url_str);
1636   if (res < 0)
1637     goto create_request_failed;
1638
1639   /* add content type */
1640   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_TYPE, "text/parameters");
1641
1642   {
1643    gchar *msg;
1644    guint msglen = 0;
1645    GString *msglength;
1646    WFDMessage *msg3;
1647    wfdconfig_message_new(&msg3);
1648    wfdconfig_message_init(msg3);
1649    wfdconfig_set_supported_audio_format(msg3, WFD_AUDIO_UNKNOWN, WFD_FREQ_UNKNOWN,WFD_CHANNEL_UNKNOWN, 0, 0);
1650    wfdconfig_set_supported_video_format(msg3, WFD_VIDEO_UNKNOWN, WFD_VIDEO_CEA_RESOLUTION, WFD_CEA_UNKNOWN,
1651       WFD_CEA_UNKNOWN, WFD_VESA_UNKNOWN,WFD_HH_UNKNOWN, WFD_H264_UNKNOWN_PROFILE,
1652       WFD_H264_LEVEL_UNKNOWN,0,0, 0, 0, 0, 0);
1653    wfdconfig_set_prefered_RTP_ports(msg3, WFD_RTSP_TRANS_UNKNOWN, WFD_RTSP_PROFILE_UNKNOWN,
1654       WFD_RTSP_LOWER_TRANS_UNKNOWN, 0, 0);
1655
1656    g_print("===================================M3 Message server side============================\n");
1657    wfdconfig_message_dump(msg3);
1658    g_print("=====================================================================================\n");
1659    msg = wfdconfig_message_as_text(msg3);
1660    msglen = strlen(msg);
1661    msglength = g_string_new ("");
1662    g_string_append_printf (msglength,"%d",msglen);
1663    GST_DEBUG("M3 server side message body: %s\n\n\n", msg);
1664       /* add content-length type */
1665    gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (msglength, FALSE));
1666       /* adding data field */
1667    gst_rtsp_message_set_body (&request, (guint8*)msg, msglen);
1668
1669    wfdconfig_message_free(msg3);
1670   }
1671
1672   GST_DEBUG ("send GET_PARAM (M3)...");
1673
1674   // TODO: need to add session i.e. 2nd variable
1675   send_request (client, NULL, &request);
1676
1677   res = gst_rtsp_connection_receive (client->connection, &response, NULL);
1678   if (GST_RTSP_OK != res) {
1679     goto receive_error;
1680   }
1681
1682   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
1683     gst_rtsp_message_dump (&response);
1684   }
1685
1686   {
1687   gchar *data = NULL;
1688   guint size=0;
1689   gst_rtsp_message_get_body (&response, (guint8**)&data, &size);
1690
1691   wfdconfig_message_new(&msg3res);
1692   wfdconfig_message_init(msg3res);
1693   wfdconfig_message_parse_buffer((guint8*)data,size,msg3res);
1694   GST_DEBUG("\nM3 response server side message body: %s\n\n\n", wfdconfig_message_as_text(msg3res));
1695
1696   wfdconfig_get_supported_audio_format(msg3res, &caCodec, &cFreq, &cChanels, &cBitwidth, &caLatency);
1697   wfdconfig_get_supported_video_format(msg3res, &cvCodec, &cNative, &cNativeResolution,
1698                           (guint64 *)&cCEAResolution, (guint64 *)&cVESAResolution, (guint64 *)&cHHResolution,
1699                           &cProfile, &cLevel, &cvLatency, &cMaxHeight,
1700                           &cMaxWidth, &cmin_slice_size, &cslice_enc_params, &cframe_rate_control);
1701   wfdconfig_get_prefered_RTP_ports(msg3res, &ctrans, &cprofile, &clowertrans, &crtp_port0, &crtp_port1);
1702   g_print("==============================M3 response Message server side========================\n");
1703   wfdconfig_message_dump(msg3res);
1704   g_print("=====================================================================================\n");
1705   }
1706
1707   ////////////////////////////////////
1708   ////    SET_PARAMETER Msg (M4)    /////
1709   ///////////////////////////////////
1710
1711   memset (&request, 0x00, sizeof (GstRTSPMessage));
1712   memset (&response, 0x00, sizeof (GstRTSPMessage));
1713
1714   res = gst_rtsp_message_init_request (&request, GST_RTSP_SET_PARAMETER, url_str);
1715   if (res < 0)
1716     goto create_request_failed;
1717   GST_DEBUG("\nM4 message body server side url : %s\n\n\n", url_str);
1718   /* add content type */
1719   gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_TYPE, "text/parameters");
1720
1721   {
1722    gchar *msg;
1723    guint msglen = 0;
1724    GString *msglength;
1725    WFDMessage *msg4;
1726
1727    wfdconfig_message_new(&msg4);
1728    wfdconfig_message_init(msg4);
1729    wfdconfig_set_prefered_audio_format(msg4, WFD_AUDIO_AAC, WFD_FREQ_48000, WFD_CHANNEL_2, cBitwidth, caLatency);
1730    wfdconfig_set_prefered_video_format(msg4, WFD_VIDEO_H264,WFD_VIDEO_CEA_RESOLUTION, WFD_CEA_1280x720P30,
1731         WFD_CEA_1280x720P30, WFD_VESA_1280x768P30,WFD_HH_960x540P30, WFD_H264_BASE_PROFILE,
1732         WFD_H264_LEVEL_4, cvLatency, cMaxHeight,cMaxWidth, cmin_slice_size, cslice_enc_params, cframe_rate_control);
1733    wfdconfig_set_prefered_RTP_ports(msg4, WFD_RTSP_TRANS_RTP, WFD_RTSP_PROFILE_AVP, WFD_RTSP_LOWER_TRANS_UDP, crtp_port0, crtp_port1);
1734    g_print("==================================M4 Message server side=============================\n");
1735    wfdconfig_message_dump(msg4);
1736    g_print("=====================================================================================\n");
1737    msg = wfdconfig_message_as_text(msg4);
1738    msglen = strlen(msg);
1739    msglength = g_string_new ("");
1740    g_string_append_printf (msglength,"%d",msglen);
1741    GST_DEBUG("\nM4 message body server side : %s\n\n\n", msg);
1742       /* add content-length type */
1743    gst_rtsp_message_add_header (&request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (msglength, FALSE));
1744       /* adding data field */
1745    gst_rtsp_message_set_body (&request, (guint8*)msg, msglen);
1746
1747    wfdconfig_message_free(msg4);
1748   }
1749
1750   GST_DEBUG ("send SET_PARAM (M4)...");
1751
1752   // TODO: need to add session i.e. 2nd variable
1753   send_request (client, NULL, &request);
1754
1755   res = gst_rtsp_connection_receive (client->connection, &response, NULL);
1756   if (GST_RTSP_OK != res) {
1757      goto receive_error;
1758   }
1759
1760   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
1761     gst_rtsp_message_dump (&response);
1762   }
1763
1764   return TRUE;
1765
1766 create_request_failed:
1767   GST_ERROR_OBJECT (client, "Failed to create server request...reason : %d", res);
1768   return FALSE;
1769
1770 receive_error:
1771   GST_ERROR_OBJECT (client, "Failed to receive response .....reason: %d", res);
1772   return FALSE;
1773 }
1774
1775 /* remove duplicate and trailing '/' */
1776 static void
1777 sanitize_uri (GstRTSPUrl * uri)
1778 {
1779   gint i, len;
1780   gchar *s, *d;
1781   gboolean have_slash, prev_slash;
1782
1783   s = d = uri->abspath;
1784   len = strlen (uri->abspath);
1785
1786   prev_slash = FALSE;
1787
1788   for (i = 0; i < len; i++) {
1789     have_slash = s[i] == '/';
1790     *d = s[i];
1791     if (!have_slash || !prev_slash)
1792       d++;
1793     prev_slash = have_slash;
1794   }
1795   len = d - uri->abspath;
1796   /* don't remove the first slash if that's the only thing left */
1797   if (len > 1 && *(d - 1) == '/')
1798     d--;
1799   *d = '\0';
1800 }
1801
1802 static void
1803 client_session_finalized (GstRTSPClient * client, GstRTSPSession * session)
1804 {
1805   GST_INFO ("client %p: session %p finished", client, session);
1806
1807   /* unlink all media managed in this session */
1808   client_unlink_session (client, session);
1809
1810   /* remove the session */
1811   if (!(client->sessions = g_list_remove (client->sessions, session))) {
1812     GST_INFO ("client %p: all sessions finalized, close the connection",
1813         client);
1814     close_connection (client);
1815   }
1816 }
1817
1818 static void
1819 client_watch_session (GstRTSPClient * client, GstRTSPSession * session)
1820 {
1821   GList *walk;
1822
1823   for (walk = client->sessions; walk; walk = g_list_next (walk)) {
1824     GstRTSPSession *msession = (GstRTSPSession *) walk->data;
1825
1826     /* we already know about this session */
1827     if (msession == session)
1828       return;
1829   }
1830
1831   GST_INFO ("watching session %p", session);
1832
1833   g_object_weak_ref (G_OBJECT (session), (GWeakNotify) client_session_finalized,
1834       client);
1835   client->sessions = g_list_prepend (client->sessions, session);
1836 }
1837
1838 static void
1839 handle_request (GstRTSPClient * client, GstRTSPMessage * request)
1840 {
1841   GstRTSPMethod method;
1842   const gchar *uristr;
1843   GstRTSPUrl *uri;
1844   GstRTSPVersion version;
1845   GstRTSPResult res;
1846   GstRTSPSession *session;
1847   GstRTSPClientState state = { NULL };
1848   GstRTSPMessage response = { 0 };
1849   gchar *sessid;
1850
1851   state.request = request;
1852   state.response = &response;
1853
1854   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
1855     gst_rtsp_message_dump (request);
1856   }
1857
1858   GST_INFO ("client %p: received a request", client);
1859
1860   gst_rtsp_message_parse_request (request, &method, &uristr, &version);
1861
1862   if (version != GST_RTSP_VERSION_1_0) {
1863     /* we can only handle 1.0 requests */
1864     send_generic_response (client, GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED,
1865         &state);
1866     return;
1867   }
1868   state.method = method;
1869
1870   /* we always try to parse the url first */
1871   if (gst_rtsp_url_parse (uristr, &uri) != GST_RTSP_OK) {
1872     send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, &state);
1873     return;
1874   }
1875
1876   /* sanitize the uri */
1877   sanitize_uri (uri);
1878   state.uri = uri;
1879
1880   GST_DEBUG ("state -> URI = %s", uri->abspath);
1881
1882   /* get the session if there is any */
1883   res = gst_rtsp_message_get_header (request, GST_RTSP_HDR_SESSION, &sessid, 0);
1884   if (res == GST_RTSP_OK) {
1885     if (client->session_pool == NULL)
1886       goto no_pool;
1887
1888     /* we had a session in the request, find it again */
1889     if (!(session = gst_rtsp_session_pool_find (client->session_pool, sessid)))
1890       goto session_not_found;
1891
1892     GST_DEBUG ("sessid = %s", sessid);
1893
1894     /* we add the session to the client list of watched sessions. When a session
1895      * disappears because it times out, we will be notified. If all sessions are
1896      * gone, we will close the connection */
1897     client_watch_session (client, session);
1898     if(client->sessionID) g_free(client->sessionID);
1899     client->sessionID = g_strdup(sessid);
1900     } else if(method == GST_RTSP_SET_PARAMETER){
1901       if (client->session_pool == NULL)
1902         goto no_pool;
1903       if (!(session = gst_rtsp_session_pool_find (client->session_pool, client->sessionID)))
1904         goto session_not_found;
1905       GST_DEBUG ("sessid = %s", client->sessionID);
1906       client_watch_session (client, session);
1907     }
1908     else session = NULL;
1909
1910   GST_DEBUG ("session = %p", session);
1911   state.session = session;
1912
1913
1914   if(session) {
1915     GstRTSPSessionMedia *temp = session->medias->data;
1916     temp->url->abspath = g_strdup(uri->abspath);
1917   }
1918
1919   if (client->auth) {
1920     if (!gst_rtsp_auth_check (client->auth, client, 0, &state))
1921       goto not_authorized;
1922   }
1923
1924   GST_INFO ("Method = %d", method);
1925
1926   /* now see what is asked and dispatch to a dedicated handler */
1927   switch (method) {
1928     case GST_RTSP_OPTIONS:
1929       //handle_options_request (client, &state);
1930       break;
1931     case GST_RTSP_DESCRIBE:
1932       handle_describe_request (client, &state);
1933       break;
1934     case GST_RTSP_SETUP:
1935       handle_setup_request (client, &state);
1936       break;
1937     case GST_RTSP_PLAY:
1938       handle_play_request (client, &state);
1939       g_timeout_add((DEFAULT_RTSP_TIMEOUT - 5)*1000, keep_alive_condition, client);
1940       break;
1941     case GST_RTSP_PAUSE:
1942       handle_pause_request (client, &state);
1943       break;
1944     case GST_RTSP_TEARDOWN:
1945       handle_teardown_request (client, &state);
1946       break;
1947     case GST_RTSP_SET_PARAMETER:
1948       handle_set_param_request (client, &state);
1949       break;
1950     case GST_RTSP_GET_PARAMETER:
1951       handle_get_param_request (client, &state);
1952       break;
1953     case GST_RTSP_ANNOUNCE:
1954     case GST_RTSP_RECORD:
1955     case GST_RTSP_REDIRECT:
1956       send_generic_response (client, GST_RTSP_STS_NOT_IMPLEMENTED, &state);
1957       break;
1958     case GST_RTSP_INVALID:
1959     default:
1960       send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, &state);
1961       break;
1962   }
1963   if (session)
1964     g_object_unref (session);
1965
1966   gst_rtsp_url_free (uri);
1967   return;
1968
1969   /* ERRORS */
1970 no_pool:
1971   {
1972     send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, &state);
1973     return;
1974   }
1975 session_not_found:
1976   {
1977     send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, &state);
1978     return;
1979   }
1980 not_authorized:
1981   {
1982     handle_unauthorized_request (client, client->auth, &state);
1983     return;
1984   }
1985 }
1986
1987 static void
1988 handle_data (GstRTSPClient * client, GstRTSPMessage * message)
1989 {
1990   GstRTSPResult res;
1991   guint8 channel;
1992   GList *walk;
1993   guint8 *data;
1994   guint size;
1995   GstBuffer *buffer;
1996   gboolean handled;
1997
1998   /* find the stream for this message */
1999   res = gst_rtsp_message_parse_data (message, &channel);
2000   if (res != GST_RTSP_OK)
2001     return;
2002
2003   gst_rtsp_message_steal_body (message, &data, &size);
2004
2005   buffer = gst_buffer_new ();
2006   gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped(0, data, size, 0, size, data, g_free));
2007
2008   handled = FALSE;
2009   for (walk = client->streams; walk; walk = g_list_next (walk)) {
2010     GstRTSPSessionStream *stream = (GstRTSPSessionStream *) walk->data;
2011     GstRTSPMediaStream *mstream;
2012     GstRTSPTransport *tr;
2013
2014     /* get the transport, if there is no transport configured, skip this stream */
2015     if (!(tr = stream->trans.transport))
2016       continue;
2017
2018     /* we also need a media stream */
2019     if (!(mstream = stream->media_stream))
2020       continue;
2021
2022     /* check for TCP transport */
2023     if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
2024       GST_INFO ("Transport is GST_RTSP_LOWER_TRANS_TCP");
2025       /* dispatch to the stream based on the port number */
2026       if (client->crtp_port0) {
2027         gst_rtsp_media_stream_rtp (mstream, buffer);
2028         handled = TRUE;
2029         break;
2030       } else if (client->crtp_port1) {
2031         gst_rtsp_media_stream_rtcp (mstream, buffer);
2032         handled = TRUE;
2033         break;
2034       }
2035     }
2036   }
2037   if (!handled)
2038     gst_buffer_unref (buffer);
2039 }
2040
2041 /**
2042  * gst_rtsp_client_set_session_pool:
2043  * @client: a #GstRTSPClient
2044  * @pool: a #GstRTSPSessionPool
2045  *
2046  * Set @pool as the sessionpool for @client which it will use to find
2047  * or allocate sessions. the sessionpool is usually inherited from the server
2048  * that created the client but can be overridden later.
2049  */
2050 void
2051 gst_rtsp_client_set_session_pool (GstRTSPClient * client,
2052     GstRTSPSessionPool * pool)
2053 {
2054   GstRTSPSessionPool *old;
2055
2056   old = client->session_pool;
2057   if (old != pool) {
2058     if (pool)
2059       g_object_ref (pool);
2060     client->session_pool = pool;
2061     if (old)
2062       g_object_unref (old);
2063   }
2064 }
2065
2066 /**
2067  * gst_rtsp_client_get_session_pool:
2068  * @client: a #GstRTSPClient
2069  *
2070  * Get the #GstRTSPSessionPool object that @client uses to manage its sessions.
2071  *
2072  * Returns: a #GstRTSPSessionPool, unref after usage.
2073  */
2074 GstRTSPSessionPool *
2075 gst_rtsp_client_get_session_pool (GstRTSPClient * client)
2076 {
2077   GstRTSPSessionPool *result;
2078
2079   if ((result = client->session_pool))
2080     g_object_ref (result);
2081
2082   return result;
2083 }
2084
2085 /**
2086  * gst_rtsp_client_set_server:
2087  * @client: a #GstRTSPClient
2088  * @server: a #GstRTSPServer
2089  *
2090  * Set @server as the server that created @client.
2091  */
2092 void
2093 gst_rtsp_client_set_server (GstRTSPClient * client, GstRTSPServer * server)
2094 {
2095   GstRTSPServer *old;
2096
2097   old = client->server;
2098   if (old != server) {
2099     if (server)
2100       g_object_ref (server);
2101     client->server = server;
2102     if (old)
2103       g_object_unref (old);
2104   }
2105 }
2106
2107 /**
2108  * gst_rtsp_client_get_server:
2109  * @client: a #GstRTSPClient
2110  *
2111  * Get the #GstRTSPServer object that @client was created from.
2112  *
2113  * Returns: a #GstRTSPServer, unref after usage.
2114  */
2115 GstRTSPServer *
2116 gst_rtsp_client_get_server (GstRTSPClient * client)
2117 {
2118   GstRTSPServer *result;
2119
2120   if ((result = client->server))
2121     g_object_ref (result);
2122
2123   return result;
2124 }
2125
2126 /**
2127  * gst_rtsp_client_set_media_mapping:
2128  * @client: a #GstRTSPClient
2129  * @mapping: a #GstRTSPMediaMapping
2130  *
2131  * Set @mapping as the media mapping for @client which it will use to map urls
2132  * to media streams. These mapping is usually inherited from the server that
2133  * created the client but can be overriden later.
2134  */
2135 void
2136 gst_rtsp_client_set_media_mapping (GstRTSPClient * client,
2137     GstRTSPMediaMapping * mapping)
2138 {
2139   GstRTSPMediaMapping *old;
2140
2141   old = client->media_mapping;
2142
2143   if (old != mapping) {
2144     if (mapping)
2145       g_object_ref (mapping);
2146     client->media_mapping = mapping;
2147     if (old)
2148       g_object_unref (old);
2149   }
2150 }
2151
2152 /**
2153  * gst_rtsp_client_get_media_mapping:
2154  * @client: a #GstRTSPClient
2155  *
2156  * Get the #GstRTSPMediaMapping object that @client uses to manage its sessions.
2157  *
2158  * Returns: a #GstRTSPMediaMapping, unref after usage.
2159  */
2160 GstRTSPMediaMapping *
2161 gst_rtsp_client_get_media_mapping (GstRTSPClient * client)
2162 {
2163   GstRTSPMediaMapping *result;
2164
2165   if ((result = client->media_mapping))
2166     g_object_ref (result);
2167
2168   return result;
2169 }
2170
2171 /**
2172  * gst_rtsp_client_set_auth:
2173  * @client: a #GstRTSPClient
2174  * @auth: a #GstRTSPAuth
2175  *
2176  * configure @auth to be used as the authentication manager of @client.
2177  */
2178 void
2179 gst_rtsp_client_set_auth (GstRTSPClient * client, GstRTSPAuth * auth)
2180 {
2181   GstRTSPAuth *old;
2182
2183   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
2184
2185   old = client->auth;
2186
2187   if (old != auth) {
2188     if (auth)
2189       g_object_ref (auth);
2190     client->auth = auth;
2191     if (old)
2192       g_object_unref (old);
2193   }
2194 }
2195
2196
2197 /**
2198  * gst_rtsp_client_get_auth:
2199  * @client: a #GstRTSPClient
2200  *
2201  * Get the #GstRTSPAuth used as the authentication manager of @client.
2202  *
2203  * Returns: the #GstRTSPAuth of @client. g_object_unref() after
2204  * usage.
2205  */
2206 GstRTSPAuth *
2207 gst_rtsp_client_get_auth (GstRTSPClient * client)
2208 {
2209   GstRTSPAuth *result;
2210
2211   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
2212
2213   if ((result = client->auth))
2214     g_object_ref (result);
2215
2216   return result;
2217 }
2218
2219 static GstRTSPResult
2220 message_received (GstRTSPWatch * watch, GstRTSPMessage * message,
2221     gpointer user_data)
2222 {
2223   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
2224
2225   GST_INFO_OBJECT (client, "revd message method = %s", 
2226     message->type == GST_RTSP_MESSAGE_REQUEST ? "request" :
2227     message->type == GST_RTSP_MESSAGE_RESPONSE ? "reponse" : "data/unknown");
2228   switch (message->type) {
2229     case GST_RTSP_MESSAGE_REQUEST:
2230       handle_request (client, message);
2231       break;
2232     case GST_RTSP_MESSAGE_RESPONSE:
2233       {
2234         GstRTSPStatusCode code;
2235         const gchar *uristr;
2236         GstRTSPVersion version;
2237
2238         gst_rtsp_message_parse_response (message, &code, &uristr, &version);
2239         GST_INFO_OBJECT (client, "revd message method = %d", code);
2240         g_mutex_lock(client->keep_alive_lock);
2241         client->keep_alive_flag = TRUE;
2242         g_mutex_unlock(client->keep_alive_lock);
2243       }
2244       break;
2245     case GST_RTSP_MESSAGE_DATA:
2246       handle_data (client, message);
2247       break;
2248     default:
2249       break;
2250   }
2251   return GST_RTSP_OK;
2252 }
2253
2254 static GstRTSPResult
2255 message_sent (GstRTSPWatch * watch, guint cseq, gpointer user_data)
2256 {
2257   GstRTSPClient *client;
2258
2259   client = GST_RTSP_CLIENT (user_data);
2260
2261   return GST_RTSP_OK;
2262 }
2263
2264 static GstRTSPResult
2265 closed (GstRTSPWatch * watch, gpointer user_data)
2266 {
2267   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
2268   const gchar *tunnelid;
2269
2270   GST_INFO ("client %p: connection closed", client);
2271
2272   if ((tunnelid = gst_rtsp_connection_get_tunnelid (client->connection))) {
2273     g_mutex_lock (tunnels_lock);
2274     /* remove from tunnelids */
2275     g_hash_table_remove (tunnels, tunnelid);
2276     g_mutex_unlock (tunnels_lock);
2277   }
2278
2279   return GST_RTSP_OK;
2280 }
2281
2282 static GstRTSPResult
2283 error (GstRTSPWatch * watch, GstRTSPResult result, gpointer user_data)
2284 {
2285   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
2286   gchar *str;
2287
2288   str = gst_rtsp_strresult (result);
2289   GST_INFO ("client %p: received an error %s", client, str);
2290   g_free (str);
2291
2292   return GST_RTSP_OK;
2293 }
2294
2295 static GstRTSPResult
2296 error_full (GstRTSPWatch * watch, GstRTSPResult result,
2297     GstRTSPMessage * message, guint id, gpointer user_data)
2298 {
2299   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
2300   gchar *str;
2301
2302   str = gst_rtsp_strresult (result);
2303   GST_INFO
2304       ("client %p: received an error %s when handling message %p with id %d",
2305       client, str, message, id);
2306   g_free (str);
2307
2308   return GST_RTSP_OK;
2309 }
2310
2311 static gboolean
2312 remember_tunnel (GstRTSPClient * client)
2313 {
2314   const gchar *tunnelid;
2315
2316   /* store client in the pending tunnels */
2317   tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
2318   if (tunnelid == NULL)
2319     goto no_tunnelid;
2320
2321   GST_INFO ("client %p: inserting tunnel session %s", client, tunnelid);
2322
2323   /* we can't have two clients connecting with the same tunnelid */
2324   g_mutex_lock (tunnels_lock);
2325   if (g_hash_table_lookup (tunnels, tunnelid))
2326     goto tunnel_existed;
2327
2328   g_hash_table_insert (tunnels, g_strdup (tunnelid), g_object_ref (client));
2329   g_mutex_unlock (tunnels_lock);
2330
2331   return TRUE;
2332
2333   /* ERRORS */
2334 no_tunnelid:
2335   {
2336     GST_ERROR ("client %p: no tunnelid provided", client);
2337     return FALSE;
2338   }
2339 tunnel_existed:
2340   {
2341     g_mutex_unlock (tunnels_lock);
2342     GST_ERROR ("client %p: tunnel session %s already existed", client,
2343         tunnelid);
2344     return FALSE;
2345   }
2346 }
2347
2348 static GstRTSPStatusCode
2349 tunnel_start (GstRTSPWatch * watch, gpointer user_data)
2350 {
2351   GstRTSPClient *client;
2352
2353   client = GST_RTSP_CLIENT (user_data);
2354
2355   GST_INFO ("client %p: tunnel start (connection %p)", client,
2356       client->connection);
2357
2358   if (!remember_tunnel (client))
2359     goto tunnel_error;
2360
2361   return GST_RTSP_STS_OK;
2362
2363   /* ERRORS */
2364 tunnel_error:
2365   {
2366     GST_ERROR ("client %p: error starting tunnel", client);
2367     return GST_RTSP_STS_SERVICE_UNAVAILABLE;
2368   }
2369 }
2370
2371 static GstRTSPResult
2372 tunnel_lost (GstRTSPWatch * watch, gpointer user_data)
2373 {
2374   GstRTSPClient *client;
2375
2376   client = GST_RTSP_CLIENT (user_data);
2377
2378   GST_INFO ("client %p: tunnel lost (connection %p)", client,
2379       client->connection);
2380
2381   /* ignore error, it'll only be a problem when the client does a POST again */
2382   remember_tunnel (client);
2383
2384   return GST_RTSP_OK;
2385 }
2386
2387 static GstRTSPResult
2388 tunnel_complete (GstRTSPWatch * watch, gpointer user_data)
2389 {
2390   const gchar *tunnelid;
2391   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
2392   GstRTSPClient *oclient;
2393
2394   GST_INFO ("client %p: tunnel complete", client);
2395
2396   /* find previous tunnel */
2397   tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
2398   if (tunnelid == NULL)
2399     goto no_tunnelid;
2400
2401   g_mutex_lock (tunnels_lock);
2402   if (!(oclient = g_hash_table_lookup (tunnels, tunnelid)))
2403     goto no_tunnel;
2404
2405   /* remove the old client from the table. ref before because removing it will
2406    * remove the ref to it. */
2407   g_object_ref (oclient);
2408   g_hash_table_remove (tunnels, tunnelid);
2409
2410   if (oclient->watch == NULL)
2411     goto tunnel_closed;
2412   g_mutex_unlock (tunnels_lock);
2413
2414   GST_INFO ("client %p: found tunnel %p (old %p, new %p)", client, oclient,
2415       oclient->connection, client->connection);
2416
2417   /* merge the tunnels into the first client */
2418   gst_rtsp_connection_do_tunnel (oclient->connection, client->connection);
2419   gst_rtsp_watch_reset (oclient->watch);
2420   g_object_unref (oclient);
2421
2422   /* we don't need this watch anymore */
2423   g_source_destroy ((GSource *) client->watch);
2424   client->watchid = 0;
2425   client->watch = NULL;
2426
2427   return GST_RTSP_OK;
2428
2429   /* ERRORS */
2430 no_tunnelid:
2431   {
2432     GST_INFO ("client %p: no tunnelid provided", client);
2433     return GST_RTSP_STS_SERVICE_UNAVAILABLE;
2434   }
2435 no_tunnel:
2436   {
2437     g_mutex_unlock (tunnels_lock);
2438     GST_INFO ("client %p: tunnel session %s not found", client, tunnelid);
2439     return GST_RTSP_STS_SERVICE_UNAVAILABLE;
2440   }
2441 tunnel_closed:
2442   {
2443     g_mutex_unlock (tunnels_lock);
2444     GST_INFO ("client %p: tunnel session %s was closed", client, tunnelid);
2445     g_object_unref (oclient);
2446     return GST_RTSP_STS_SERVICE_UNAVAILABLE;
2447   }
2448 }
2449
2450 static GstRTSPWatchFuncs watch_funcs = {
2451   message_received,
2452   message_sent,
2453   closed,
2454   error,
2455   tunnel_start,
2456   tunnel_complete,
2457   error_full,
2458   tunnel_lost
2459 };
2460
2461 static void
2462 client_watch_notify (GstRTSPClient * client)
2463 {
2464   GST_INFO ("client %p: watch destroyed", client);
2465   client->watchid = 0;
2466   client->watch = NULL;
2467   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL);
2468   g_object_unref (client);
2469 }
2470
2471 #if 0
2472 /**
2473  * gst_rtsp_client_attach:
2474  * @client: a #GstRTSPClient
2475  * @channel: a #GIOChannel
2476  *
2477  * Accept a new connection for @client on the socket in @channel.
2478  *
2479  * This function should be called when the client properties and urls are fully
2480  * configured and the client is ready to start.
2481  *
2482  * Returns: %TRUE if the client could be accepted.
2483  */
2484 gboolean
2485 gst_rtsp_client_accept (GstRTSPClient * client, int sock)
2486 {
2487   int fd;
2488   GstRTSPConnection *conn;
2489   GstRTSPResult res;
2490   GSource *source;
2491   GMainContext *context;
2492   GstRTSPUrl *url;
2493   struct sockaddr_storage addr;
2494   socklen_t addrlen;
2495   gchar ip[INET6_ADDRSTRLEN];
2496
2497  // TODO: try about SIGIO or select or poll calls apart from waiting...
2498
2499   GST_ERROR_OBJECT (client, "Enter accept client...");
2500
2501   GST_RTSP_CHECK (gst_rtsp_connection_accept (sock, &conn), accept_failed);
2502
2503   fd = gst_rtsp_connection_get_readfd (conn);
2504
2505   addrlen = sizeof (addr);
2506   if (getsockname (fd, (struct sockaddr *) &addr, &addrlen) < 0)
2507     goto getpeername_failed;
2508
2509   client->is_ipv6 = addr.ss_family == AF_INET6;
2510
2511   if (getnameinfo ((struct sockaddr *) &addr, addrlen, ip, sizeof (ip), NULL, 0,
2512           NI_NUMERICHOST) != 0)
2513     goto getnameinfo_failed;
2514
2515   /* keep the original ip that the client connected to */
2516   g_free (client->server_ip);
2517   client->server_ip = g_strndup (ip, sizeof (ip));
2518
2519   GST_INFO ("client %p connected to server ip %s, ipv6 = %d", client,
2520       client->server_ip, client->is_ipv6);
2521
2522   url = gst_rtsp_connection_get_url (conn);
2523   GST_INFO ("added new client %p ip %s:%d", client, url->host, url->port);
2524
2525   client->connection = conn;
2526
2527   /* create watch for the connection and attach */
2528   client->watch = gst_rtsp_watch_new (client->connection, &watch_funcs,
2529       g_object_ref (client), (GDestroyNotify) client_watch_notify);
2530
2531   source = client->watch;
2532
2533   GST_DEBUG (" source = %p", source);
2534
2535   // naveen: we are not creating source before below call.. so context will be NULL.. which means, we are attaching
2536   // to main context...
2537
2538   /* find the context to add the watch */
2539   if ((source = g_main_current_source ()))
2540     context = g_source_get_context (source);
2541   else
2542     context = NULL;
2543
2544   GST_DEBUG (" source = %p", source);
2545
2546
2547   GST_INFO ("attaching to context %p", context);
2548
2549   client->watchid = gst_rtsp_watch_attach (client->watch, context);
2550
2551   GST_DEBUG_OBJECT (client, "watch_id = %u", client->watchid);
2552   gst_rtsp_watch_unref (client->watch);
2553
2554   return TRUE;
2555
2556   /* ERRORS */
2557 accept_failed:
2558   {
2559     gchar *str = gst_rtsp_strresult (res);
2560
2561     GST_ERROR ("Could not accept client on server socket %d: %s", sock, str);
2562     g_free (str);
2563     return FALSE;
2564   }
2565 getpeername_failed:
2566   {
2567     GST_ERROR ("getpeername failed: %s", g_strerror (errno));
2568     return FALSE;
2569   }
2570 getnameinfo_failed:
2571   {
2572     GST_ERROR ("getnameinfo failed: %s", g_strerror (errno));
2573     return FALSE;
2574   }
2575 }
2576 #else
2577 /**
2578  * gst_rtsp_client_attach:
2579  * @client: a #GstRTSPClient
2580  * @channel: a #GIOChannel
2581  *
2582  * Accept a new connection for @client on the socket in @channel.
2583  *
2584  * This function should be called when the client properties and urls are fully
2585  * configured and the client is ready to start.
2586  *
2587  * Returns: %TRUE if the client could be accepted.
2588  */
2589 gboolean
2590 gst_rtsp_client_accept (GstRTSPClient * client, GIOChannel * channel, GSource *source)
2591 {
2592   int sock, fd;
2593   GstRTSPConnection *conn;
2594   GstRTSPResult res;
2595   GMainContext *context;
2596   GstRTSPUrl *url;
2597   struct sockaddr_storage addr;
2598   socklen_t addrlen;
2599   gchar ip[INET6_ADDRSTRLEN];
2600   GSocket *socket, *readsocket;
2601
2602   GST_ERROR_OBJECT (client, "Enter accept client...");
2603
2604   /* a new client connected. */
2605   sock = g_io_channel_unix_get_fd (channel);
2606   socket = g_socket_new_from_fd(sock, NULL);
2607
2608   GST_INFO_OBJECT (client, "sock fd  = %d", sock);
2609
2610   GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, NULL), accept_failed);
2611   g_object_unref(socket);
2612   readsocket = gst_rtsp_connection_get_read_socket (conn);
2613   fd = g_socket_get_fd(readsocket);
2614   if (fd == -1) {
2615      res = GST_RTSP_EINVAL;
2616      goto  accept_failed;
2617   }
2618
2619   addrlen = sizeof (addr);
2620   if (getsockname (fd, (struct sockaddr *) &addr, &addrlen) < 0)
2621     goto getpeername_failed;
2622
2623   client->is_ipv6 = addr.ss_family == AF_INET6;
2624
2625   if (getnameinfo ((struct sockaddr *) &addr, addrlen, ip, sizeof (ip), NULL, 0,
2626           NI_NUMERICHOST) != 0)
2627     goto getnameinfo_failed;
2628
2629   /* keep the original ip that the client connected to */
2630   g_free (client->server_ip);
2631   client->server_ip = g_strndup (ip, sizeof (ip));
2632
2633   GST_INFO ("client %p connected to server ip %s, ipv6 = %d", client,
2634       client->server_ip, client->is_ipv6);
2635
2636   url = gst_rtsp_connection_get_url (conn);
2637   GST_INFO ("added new client %p ip %s:%d", client, url->host, url->port);
2638
2639   client->wfdsink_ip = url->host;
2640   GST_INFO ("WFD Sink IP : %s", client->wfdsink_ip);
2641
2642   client->connection = conn;
2643   /* create watch for the connection and attach */
2644   client->watch = gst_rtsp_watch_new (client->connection, &watch_funcs, client, (GDestroyNotify) client_watch_notify);
2645
2646 #if 0
2647   /* find the context to add the watch */
2648   if ((source = g_main_current_source ()))
2649     context = g_source_get_context (source);
2650   else
2651     context = NULL;
2652  #else
2653      context = g_source_get_context (source);
2654
2655 #endif
2656
2657   GST_DEBUG (" source = %p", source);
2658
2659
2660   GST_INFO ("attaching to context %p", context);
2661
2662
2663   client->watchid = gst_rtsp_watch_attach (client->watch, context);
2664   gst_rtsp_watch_unref (client->watch);
2665
2666   return TRUE;
2667
2668   /* ERRORS */
2669 accept_failed:
2670   {
2671     gchar *str = gst_rtsp_strresult (res);
2672
2673     GST_ERROR ("Could not accept client on server socket %d: %s", sock, str);
2674     g_free (str);
2675     return FALSE;
2676   }
2677 getpeername_failed:
2678   {
2679     GST_ERROR ("getpeername failed: %s", g_strerror (errno));
2680     return FALSE;
2681   }
2682 getnameinfo_failed:
2683   {
2684     GST_ERROR ("getnameinfo failed: %s", g_strerror (errno));
2685     return FALSE;
2686   }
2687 }
2688 #endif
2689
2690 /**
2691 * prepare_request:
2692 * @client: client object
2693 * @request : requst message to be prepared
2694 * @method : RTSP method of the request
2695 * @url : url need to be in the request
2696 * @message_type : WFD message type
2697 * @trigger_type : trigger method to be used for M5 mainly
2698 *
2699 * Prepares request based on @method & @message_type
2700 *
2701 * Returns: a #GstRTSPResult.
2702 */
2703 static GstRTSPResult
2704 prepare_request (GstRTSPClient *client, GstRTSPMessage *request, 
2705   GstRTSPMethod method, gchar *url, WFDMessageType message_type, WFDTrigger trigger_type)
2706 {
2707   GstRTSPResult res = GST_RTSP_OK;
2708   gchar *str = NULL;
2709   WFDResult wfd_res = WFD_OK;
2710   GString *cseqstr;
2711   /* initialize the request */
2712   res = gst_rtsp_message_init_request (request, method, url);
2713   if (res < 0) {
2714     GST_ERROR ("init request failed");
2715     return res;
2716   }
2717
2718   switch (method) {
2719
2720     /* Prepare OPTIONS request to send */
2721     case GST_RTSP_OPTIONS: {
2722       /* add wfd specific require filed "org.wfa.wfd1.0" */
2723       str = g_strdup ("org.wfa.wfd1.0");
2724       res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_REQUIRE, str);
2725       if (res < 0) {
2726         GST_ERROR ("Failed to add header");
2727         return res;
2728       }
2729       g_free (str);
2730       str = NULL;
2731       break;
2732     }
2733
2734     /* Prepare GET_PARAMETER request */
2735     case GST_RTSP_GET_PARAMETER: {
2736       gchar *msg;
2737       guint msglen = 0;
2738       GString *msglength;
2739       WFDMessage *msg3;
2740
2741       /* add content type */
2742       res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE, "text/parameters");
2743       if (res < 0) {
2744         GST_ERROR ("Failed to add header");
2745         return res;
2746       }
2747
2748       /* create M3 message to be sent in the request */
2749       wfd_res = wfdconfig_message_new(&msg3);
2750       if (wfd_res != WFD_OK) {
2751         GST_ERROR_OBJECT (client, "Failed to create wfd message...");
2752         res = GST_RTSP_ERROR;
2753         goto error;
2754       }
2755
2756       wfd_res = wfdconfig_message_init(msg3);
2757       if (wfd_res != WFD_OK) {
2758         GST_ERROR_OBJECT (client, "Failed to init wfd message...");
2759         res = GST_RTSP_ERROR;
2760         goto error;
2761       }
2762
2763       /* set the supported audio formats by the WFD server*/
2764       wfd_res = wfdconfig_set_supported_audio_format(msg3, WFD_AUDIO_UNKNOWN, WFD_FREQ_UNKNOWN,WFD_CHANNEL_UNKNOWN, 0, 0);
2765       if (wfd_res != WFD_OK) {
2766         GST_ERROR_OBJECT (client, "Failed to set supported audio formats on wfd message...");
2767         res = GST_RTSP_ERROR;
2768         goto error;
2769       }
2770
2771       /* set the supported Video formats by the WFD server*/
2772       wfd_res = wfdconfig_set_supported_video_format(msg3, WFD_VIDEO_UNKNOWN, WFD_VIDEO_CEA_RESOLUTION, WFD_CEA_UNKNOWN,
2773                         WFD_CEA_UNKNOWN, WFD_VESA_UNKNOWN,WFD_HH_UNKNOWN, WFD_H264_UNKNOWN_PROFILE,
2774                         WFD_H264_LEVEL_UNKNOWN,0,0, 0, 0, 0, 0);
2775       if (wfd_res != WFD_OK) {
2776         GST_ERROR_OBJECT (client, "Failed to set supported video formats on wfd message...");
2777         res = GST_RTSP_ERROR;
2778         goto error;
2779       }
2780
2781       GST_DEBUG ("wfdconfig_set_display_EDID...");
2782       wfd_res = wfdconfig_set_display_EDID(msg3, 0, 0, NULL);
2783       if (wfd_res != WFD_OK) {
2784         GST_ERROR_OBJECT (client, "Failed to set display EDID type on wfd message...");
2785         res = GST_RTSP_ERROR;
2786         goto error;
2787       }
2788       GST_DEBUG ("wfdconfig_set_contentprotection_type...");
2789       wfd_res = wfdconfig_set_contentprotection_type(msg3, WFD_HDCP_NONE, 0);
2790       if (wfd_res != WFD_OK) {
2791         GST_ERROR_OBJECT (client, "Failed to set supported content protection type on wfd message...");
2792         res = GST_RTSP_ERROR;
2793         goto error;
2794       }
2795       /*GST_DEBUG ("wfdconfig_set_coupled_sink...");
2796       wfd_res = wfdconfig_set_coupled_sink(msg3, WFD_SINK_UNKNOWN, NULL);
2797       if (wfd_res != WFD_OK) {
2798         GST_ERROR_OBJECT (client, "Failed to set coupled sink type on wfd message...");
2799         res = GST_RTSP_ERROR;
2800         goto error;
2801       }
2802       GST_DEBUG ("wfdconfig_set_I2C_port...");
2803       wfd_res = wfdconfig_set_I2C_port(msg3, FALSE, 0);
2804       if (wfd_res != WFD_OK) {
2805         GST_ERROR_OBJECT (client, "Failed to set coupled sink type on wfd message...");
2806         res = GST_RTSP_ERROR;
2807         goto error;
2808       }
2809       GST_DEBUG ("wfdconfig_set_uibc_capability...");
2810       wfd_res = wfdconfig_set_uibc_capability(msg3, WFD_UIBC_INPUT_CAT_UNKNOWN, WFD_UIBC_INPUT_TYPE_UNKNOWN, NULL, 0, 0);
2811       if (wfd_res != WFD_OK) {
2812         GST_ERROR_OBJECT (client, "Failed to set coupled sink type on wfd message...");
2813         res = GST_RTSP_ERROR;
2814         goto error;
2815       }
2816       GST_DEBUG ("wfdconfig_set_connector_type...");
2817       wfd_res = wfdconfig_set_connector_type(msg3, WFD_CONNECTOR_NO);
2818       if (wfd_res != WFD_OK) {
2819         GST_ERROR_OBJECT (client, "Failed to set coupled sink type on wfd message...");
2820         res = GST_RTSP_ERROR;
2821         goto error;
2822       } */
2823 #ifdef STANDBY_RESUME_CAPABILITY
2824       GST_DEBUG ("wfdconfig_set_standby_resume_capability...");
2825       wfd_res = wfdconfig_set_standby_resume_capability(msg3, FALSE);
2826       if (wfd_res != WFD_OK) {
2827         GST_ERROR_OBJECT (client, "Failed to set coupled sink type on wfd message...");
2828         res = GST_RTSP_ERROR;
2829         goto error;
2830       }
2831 #endif
2832       /* set the preffered RTP ports for the WFD server*/
2833       wfd_res = wfdconfig_set_prefered_RTP_ports(msg3, WFD_RTSP_TRANS_UNKNOWN, WFD_RTSP_PROFILE_UNKNOWN,
2834                         WFD_RTSP_LOWER_TRANS_UNKNOWN, 0, 0);
2835       if (wfd_res != WFD_OK) {
2836         GST_ERROR_OBJECT (client, "Failed to set supported video formats on wfd message...");
2837         res = GST_RTSP_ERROR;
2838         goto error;
2839       }
2840       GST_DEBUG ("wfdconfig_parameter_names_as_text...");
2841
2842 /*
2843       wfd_res = wfdconfig_message_dump(msg3);
2844       if (wfd_res != WFD_OK) {
2845         GST_ERROR_OBJECT (client, "Failed to set supported video formats on wfd message...");
2846         res = GST_RTSP_ERROR;
2847         goto error;
2848       }*/
2849
2850       msg = wfdconfig_parameter_names_as_text(msg3);
2851       if (msg == NULL) {
2852         GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
2853         res = GST_RTSP_ERROR;
2854         goto error;
2855       }
2856       GST_DEBUG ("wfdconfig_message_as_text...");
2857       msglen = strlen(msg);
2858       msglength = g_string_new ("");
2859       g_string_append_printf (msglength,"%d",msglen);
2860       GST_DEBUG("M3 server side message body: %s", msg);
2861
2862       /* add content-length type */
2863       res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (msglength, FALSE));
2864       if (res != GST_RTSP_OK) {
2865         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2866         goto error;
2867       }
2868
2869       /* adding wfdconfig data to request */
2870       res = gst_rtsp_message_set_body (request, (guint8*)msg, msglen);
2871       if (res != GST_RTSP_OK) {
2872         GST_ERROR_OBJECT (client, "Failed to add header to rtsp message...");
2873         goto error;
2874       }
2875
2876       wfdconfig_message_free(msg3);
2877       break;
2878     }
2879
2880     /* Prepare SET_PARAMETER request */
2881     case GST_RTSP_SET_PARAMETER: {
2882       /* add content type */
2883       res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_TYPE, "text/parameters");
2884       if (res != GST_RTSP_OK) {
2885         GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
2886         goto error;
2887       }
2888
2889       switch (message_type) {
2890         case WFD_MESSAGE_4: {
2891           gchar *msg;
2892           guint msglen = 0;
2893           GString *msglength;
2894           WFDMessage *msg4;
2895
2896           GString *lines;
2897
2898           /* create M4 message to be sent in the request */
2899           wfd_res = wfdconfig_message_new(&msg4);
2900           if (wfd_res != WFD_OK) {
2901             GST_ERROR_OBJECT (client, "Failed to create wfd message...");
2902             res = GST_RTSP_ERROR;
2903             goto error;
2904           }
2905
2906           wfd_res = wfdconfig_message_init(msg4);
2907           if (wfd_res != WFD_OK) {
2908             GST_ERROR_OBJECT (client, "Failed to init wfd message...");
2909             res = GST_RTSP_ERROR;
2910             goto error;
2911           }
2912       lines = g_string_new ("");
2913       g_string_append_printf (lines,"rtsp://");
2914       g_string_append_printf (lines, "%s", client->server_ip);
2915       g_string_append_printf (lines,"/wfd1.0/streamid=0");
2916       wfd_res = wfdconfig_set_presentation_url(msg4, g_string_free (lines, FALSE), NULL);
2917       if (wfd_res != WFD_OK) {
2918       GST_ERROR_OBJECT (client, "Failed to set preffered video formats...");
2919       res = GST_RTSP_ERROR;
2920       goto error;
2921       }
2922
2923           /* set the preffered audio formats for the WFD server*/
2924           {
2925             WFDAudioFormats taudiocodec = WFD_AUDIO_UNKNOWN;
2926         WFDAudioFreq taudiofreq = WFD_FREQ_UNKNOWN;
2927         WFDAudioChannels taudiochannels = WFD_CHANNEL_UNKNOWN;
2928         if(client->caCodec & WFD_AUDIO_AC3) taudiocodec = WFD_AUDIO_AAC;  // TODO Currently AC3 encoder is not present
2929         else if(client->caCodec & WFD_AUDIO_AAC) taudiocodec = WFD_AUDIO_AAC;
2930         else if(client->caCodec & WFD_AUDIO_LPCM) taudiocodec = WFD_AUDIO_LPCM;
2931         client->caCodec = taudiocodec;
2932
2933       if(client->cFreq & WFD_FREQ_48000) taudiofreq = WFD_FREQ_48000;
2934         else if(client->cFreq & WFD_FREQ_44100) taudiofreq = WFD_FREQ_44100;
2935         client->cFreq = taudiofreq;
2936
2937         if(client->cChanels & WFD_CHANNEL_8) taudiochannels = WFD_CHANNEL_2; // TODO Currently only 2 channels is present
2938         else if(client->cChanels & WFD_CHANNEL_6) taudiochannels = WFD_CHANNEL_2;
2939         else if(client->cChanels & WFD_CHANNEL_4) taudiochannels = WFD_CHANNEL_2;
2940         else if(client->cChanels & WFD_CHANNEL_2) taudiochannels = WFD_CHANNEL_2;
2941             client->cChanels = taudiochannels;
2942
2943             wfd_res = wfdconfig_set_prefered_audio_format(msg4, taudiocodec, taudiofreq, taudiochannels, client->cBitwidth, client->caLatency);
2944             if (wfd_res != WFD_OK) {
2945               GST_ERROR_OBJECT (client, "Failed to set preffered audio formats...");
2946               res = GST_RTSP_ERROR;
2947               goto error;
2948             }
2949           }
2950       {
2951       WFDVideoCEAResolution tcCEAResolution = WFD_CEA_UNKNOWN;
2952       WFDVideoVESAResolution tcVESAResolution = WFD_VESA_UNKNOWN;
2953       WFDVideoHHResolution tcHHResolution = WFD_HH_UNKNOWN;
2954       WFDVideoH264Profile tcProfile;
2955       WFDVideoH264Level tcLevel;
2956             /* set the preffered video formats for the WFD server*/
2957         tcCEAResolution = WFD_CEA_1280x720P30; // TODO need to fetch from INI file
2958         client->cvCodec = WFD_VIDEO_H264;
2959         client->cProfile = tcProfile = WFD_H264_BASE_PROFILE; // TODO need to fetch from INI file
2960         client->cLevel = tcLevel = WFD_H264_LEVEL_3_1; // TODO need to fetch from INI file
2961         client->cMaxWidth = 1280;
2962       client->cMaxHeight = 720;
2963             wfd_res = wfdconfig_set_prefered_video_format(msg4, client->cvCodec, WFD_VIDEO_CEA_RESOLUTION, WFD_CEA_UNKNOWN,
2964               tcCEAResolution, tcVESAResolution, tcHHResolution, tcProfile,
2965                             tcLevel, client->cvLatency, client->cMaxHeight,client->cMaxWidth, client->cmin_slice_size, client->cslice_enc_params, client->cframe_rate_control);
2966             if (wfd_res != WFD_OK) {
2967               GST_ERROR_OBJECT (client, "Failed to set preffered video formats...");
2968               res = GST_RTSP_ERROR;
2969               goto error;
2970             }
2971           }
2972           GST_DEBUG("wfd config set presentation URL %s",url);
2973
2974           /* set the preffered RTP ports for the WFD server*/
2975           GST_LOG("Port are %d, %d\n", client->crtp_port0, client->crtp_port1);
2976           wfd_res = wfdconfig_set_prefered_RTP_ports(msg4, WFD_RTSP_TRANS_RTP, WFD_RTSP_PROFILE_AVP,
2977               WFD_RTSP_LOWER_TRANS_UDP, client->crtp_port0, client->crtp_port1);
2978           if (wfd_res != WFD_OK) {
2979             GST_ERROR_OBJECT (client, "Failed to set preffered RTP ports...");
2980             res = GST_RTSP_ERROR;
2981             goto error;
2982           }
2983            /*set the preffered hdcp version and port for the WFD server*/
2984            if (client->hdcp_support) {
2985             GST_DEBUG("hdcp version =%d, tcp port = %d", client->hdcp_version, client->hdcp_tcpport);
2986             wfd_res = wfdconfig_set_contentprotection_type(msg4, client->hdcp_version, client->hdcp_tcpport);
2987             if (wfd_res != WFD_OK) {
2988               GST_ERROR_OBJECT (client, "Failed to set supported content protection type on wfd message...");
2989               res = GST_RTSP_ERROR;
2990               goto error;
2991             }
2992            }
2993 #ifdef STANDBY_RESUME_CAPABILITY           
2994        if(client->standby_resume_capability_support){
2995              wfd_res = wfdconfig_set_standby_resume_capability(msg4, TRUE);
2996              if (wfd_res != WFD_OK) {
2997               GST_ERROR_OBJECT (client, "Failed to set supported standby resume capability  type on wfd message...");
2998               res = GST_RTSP_ERROR;
2999               goto error;
3000             }
3001            }
3002 #endif
3003           wfd_res = wfdconfig_message_dump(msg4);
3004           if (wfd_res != WFD_OK) {
3005             GST_ERROR_OBJECT (client, "Failed to dump wfd message...");
3006             res = GST_RTSP_ERROR;
3007             goto error;
3008           }
3009
3010           msg = wfdconfig_message_as_text(msg4);
3011           if (msg == NULL) {
3012             GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
3013             res = GST_RTSP_ERROR;
3014             goto error;
3015           }
3016
3017           msglen = strlen(msg);
3018           msglength = g_string_new ("");
3019           g_string_append_printf (msglength,"%d",msglen);
3020           GST_DEBUG("M4 message body server side : %s", msg);
3021
3022           /* add content-length type */
3023           res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (msglength, FALSE));
3024           if (res != GST_RTSP_OK) {
3025             GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
3026             goto error;
3027           }
3028
3029           /* adding wfdconfig data to request */
3030           res = gst_rtsp_message_set_body (request, (guint8*)msg, msglen);
3031           if (res != GST_RTSP_OK) {
3032             GST_ERROR_OBJECT (client, "Failed to set body to rtsp request...");
3033             goto error;
3034           }
3035
3036           wfdconfig_message_free(msg4);
3037         }
3038         break;
3039         case WFD_MESSAGE_5: {
3040           WFDMessage *msg5;
3041           gchar *msg;
3042           guint msglen = 0;
3043           GString *msglength;
3044
3045           /* create M4 message to be sent in the request */
3046           wfd_res = wfdconfig_message_new(&msg5);
3047           if (wfd_res != WFD_OK) {
3048             GST_ERROR_OBJECT (client, "Failed to create wfd message...");
3049             res = GST_RTSP_ERROR;
3050             goto error;
3051           }
3052
3053           wfd_res = wfdconfig_message_init(msg5);
3054           if (wfd_res != WFD_OK) {
3055             GST_ERROR_OBJECT (client, "Failed to init wfd message...");
3056             res = GST_RTSP_ERROR;
3057             goto error;
3058           }
3059
3060           /* preparing SETUP trigger message. After client receving this request, client has to send SETUP request */
3061           wfd_res = wfdconfig_set_trigger_type(msg5, trigger_type);
3062           if (wfd_res != WFD_OK) {
3063             GST_ERROR_OBJECT (client, "Failed to trigger type...");
3064             res = GST_RTSP_ERROR;
3065             goto error;
3066           }
3067
3068           wfd_res = wfdconfig_message_dump(msg5);
3069           if (wfd_res != WFD_OK) {
3070             GST_ERROR_OBJECT (client, "Failed to dump wfd message...");
3071             res = GST_RTSP_ERROR;
3072             goto error;
3073           }
3074
3075           msg = wfdconfig_message_as_text(msg5);
3076           if (msg == NULL) {
3077             GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
3078             res = GST_RTSP_ERROR;
3079             goto error;
3080           }
3081
3082           msglen = strlen(msg);
3083           msglength = g_string_new ("");
3084           g_string_append_printf (msglength,"%d",msglen);
3085
3086           GST_DEBUG ("M5 trigger message body: %s", msg);
3087
3088           /* add content-length type */
3089           res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (msglength, FALSE));
3090           if (res != GST_RTSP_OK) {
3091             GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
3092             goto error;
3093           }
3094
3095           /* adding wfdconfig data to request */
3096           res = gst_rtsp_message_set_body (request, (guint8*)msg, msglen);
3097           if (res != GST_RTSP_OK) {
3098             GST_ERROR_OBJECT (client, "Failed to set body to rtsp request...");
3099             goto error;
3100           }
3101
3102           wfdconfig_message_free(msg5);
3103           break;
3104         }
3105         case WFD_MESSAGE_12: {
3106           WFDMessage *msg12;
3107           gchar *msg;
3108           guint msglen = 0;
3109           GString *msglength;
3110
3111           /* create M4 message to be sent in the request */
3112           wfd_res = wfdconfig_message_new(&msg12);
3113           if (wfd_res != WFD_OK) {
3114             GST_ERROR_OBJECT (client, "Failed to create wfd message...");
3115             res = GST_RTSP_ERROR;
3116             goto error;
3117           }
3118
3119           wfd_res = wfdconfig_message_init(msg12);
3120           if (wfd_res != WFD_OK) {
3121             GST_ERROR_OBJECT (client, "Failed to init wfd message...");
3122             res = GST_RTSP_ERROR;
3123             goto error;
3124           }
3125
3126           /* preparing SETUP trigger message. After client receving this request, client has to send SETUP request */
3127           wfd_res = wfdconfig_set_standby(msg12, TRUE);
3128           if (wfd_res != WFD_OK) {
3129             GST_ERROR_OBJECT (client, "Failed to trigger type...");
3130             res = GST_RTSP_ERROR;
3131             goto error;
3132           }
3133
3134           wfd_res = wfdconfig_message_dump(msg12);
3135           if (wfd_res != WFD_OK) {
3136             GST_ERROR_OBJECT (client, "Failed to dump wfd message...");
3137             res = GST_RTSP_ERROR;
3138             goto error;
3139           }
3140
3141           msg = wfdconfig_message_as_text(msg12);
3142           if (msg == NULL) {
3143             GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
3144             res = GST_RTSP_ERROR;
3145             goto error;
3146           }
3147
3148           msglen = strlen(msg);
3149           msglength = g_string_new ("");
3150           g_string_append_printf (msglength,"%d",msglen);
3151
3152           GST_DEBUG ("M12 standby message body: %s", msg);
3153
3154           /* add content-length type */
3155           res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (msglength, FALSE));
3156           if (res != GST_RTSP_OK) {
3157             GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
3158             goto error;
3159           }
3160
3161           /* adding wfdconfig data to request */
3162           res = gst_rtsp_message_set_body (request, (guint8*)msg, msglen);
3163           if (res != GST_RTSP_OK) {
3164             GST_ERROR_OBJECT (client, "Failed to set body to rtsp request...");
3165             goto error;
3166           }
3167
3168           wfdconfig_message_free(msg12);
3169           break;
3170         }
3171         case WFD_MESSAGE_14: {
3172           WFDMessage *msg14;
3173           gchar *msg;
3174           guint msglen = 0;
3175           GString *msglength;
3176           WFDHIDCTypePathPair inp_pair[] = {{WFD_UIBC_INPUT_TYPE_KEYBOARD,WFD_UIBC_INPUT_PATH_USB},{WFD_UIBC_INPUT_TYPE_MOUSE,WFD_UIBC_INPUT_PATH_BT},{WFD_UIBC_INPUT_TYPE_MULTITOUCH,WFD_UIBC_INPUT_PATH_WIFI},{WFD_UIBC_INPUT_TYPE_GESTURE,WFD_UIBC_INPUT_PATH_BT}};
3177
3178           /* create M4 message to be sent in the request */
3179           wfd_res = wfdconfig_message_new(&msg14);
3180           if (wfd_res != WFD_OK) {
3181             GST_ERROR_OBJECT (client, "Failed to create wfd message...");
3182             res = GST_RTSP_ERROR;
3183             goto error;
3184           }
3185
3186           wfd_res = wfdconfig_message_init(msg14);
3187           if (wfd_res != WFD_OK) {
3188             GST_ERROR_OBJECT (client, "Failed to init wfd message...");
3189             res = GST_RTSP_ERROR;
3190             goto error;
3191           }
3192
3193           /* preparing SETUP trigger message. After client receving this request, client has to send SETUP request */
3194           wfd_res = wfdconfig_set_uibc_capability(msg14, WFD_UIBC_INPUT_CAT_GENERIC,
3195                WFD_UIBC_INPUT_TYPE_MOUSE|WFD_UIBC_INPUT_TYPE_MULTITOUCH|WFD_UIBC_INPUT_TYPE_GESTURE, inp_pair, 4, 8558);
3196           if (wfd_res != WFD_OK) {
3197             GST_ERROR_OBJECT (client, "Failed to trigger type...");
3198             res = GST_RTSP_ERROR;
3199             goto error;
3200           }
3201
3202           wfd_res = wfdconfig_message_dump(msg14);
3203           if (wfd_res != WFD_OK) {
3204             GST_ERROR_OBJECT (client, "Failed to dump wfd message...");
3205             res = GST_RTSP_ERROR;
3206             goto error;
3207           }
3208
3209           msg = wfdconfig_message_as_text(msg14);
3210           if (msg == NULL) {
3211             GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
3212             res = GST_RTSP_ERROR;
3213             goto error;
3214           }
3215
3216           msglen = strlen(msg);
3217           msglength = g_string_new ("");
3218           g_string_append_printf (msglength,"%d",msglen);
3219
3220           GST_DEBUG ("M14 UIBC message body: %s", msg);
3221
3222           /* add content-length type */
3223           res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (msglength, FALSE));
3224           if (res != GST_RTSP_OK) {
3225             GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
3226             goto error;
3227           }
3228
3229           /* adding wfdconfig data to request */
3230           res = gst_rtsp_message_set_body (request, (guint8*)msg, msglen);
3231           if (res != GST_RTSP_OK) {
3232             GST_ERROR_OBJECT (client, "Failed to set body to rtsp request...");
3233             goto error;
3234           }
3235
3236           wfdconfig_message_free(msg14);
3237           break;
3238         }
3239         case WFD_MESSAGE_15: {
3240           WFDMessage *msg15;
3241           gchar *msg;
3242           guint msglen = 0;
3243           GString *msglength;
3244
3245           /* create M4 message to be sent in the request */
3246           wfd_res = wfdconfig_message_new(&msg15);
3247           if (wfd_res != WFD_OK) {
3248             GST_ERROR_OBJECT (client, "Failed to create wfd message...");
3249             res = GST_RTSP_ERROR;
3250             goto error;
3251           }
3252
3253           wfd_res = wfdconfig_message_init(msg15);
3254           if (wfd_res != WFD_OK) {
3255             GST_ERROR_OBJECT (client, "Failed to init wfd message...");
3256             res = GST_RTSP_ERROR;
3257             goto error;
3258           }
3259
3260           /* preparing SETUP trigger message. After client receving this request, client has to send SETUP request */
3261           wfd_res = wfdconfig_set_uibc_status(msg15, TRUE);
3262           if (wfd_res != WFD_OK) {
3263             GST_ERROR_OBJECT (client, "Failed to trigger type...");
3264             res = GST_RTSP_ERROR;
3265             goto error;
3266           }
3267
3268           wfd_res = wfdconfig_message_dump(msg15);
3269           if (wfd_res != WFD_OK) {
3270             GST_ERROR_OBJECT (client, "Failed to dump wfd message...");
3271             res = GST_RTSP_ERROR;
3272             goto error;
3273           }
3274
3275           msg = wfdconfig_message_as_text(msg15);
3276           if (msg == NULL) {
3277             GST_ERROR_OBJECT (client, "Failed to get wfd message as text...");
3278             res = GST_RTSP_ERROR;
3279             goto error;
3280           }
3281
3282           msglen = strlen(msg);
3283           msglength = g_string_new ("");
3284           g_string_append_printf (msglength,"%d",msglen);
3285
3286           GST_DEBUG ("M15 UIBC enable message body: %s", msg);
3287
3288           /* add content-length type */
3289           res = gst_rtsp_message_add_header (request, GST_RTSP_HDR_CONTENT_LENGTH, g_string_free (msglength, FALSE));
3290           if (res != GST_RTSP_OK) {
3291             GST_ERROR_OBJECT (client, "Failed to add header to rtsp request...");
3292             goto error;
3293           }
3294
3295           /* adding wfdconfig data to request */
3296           res = gst_rtsp_message_set_body (request, (guint8*)msg, msglen);
3297           if (res != GST_RTSP_OK) {
3298             GST_ERROR_OBJECT (client, "Failed to set body to rtsp request...");
3299             goto error;
3300           }
3301
3302           wfdconfig_message_free(msg15);
3303           break;
3304         }
3305         default:
3306           GST_ERROR_OBJECT (client, "Unhandled WFD message type...");
3307           return GST_RTSP_EINVAL;
3308           break;
3309       }
3310     }
3311     break;
3312
3313     default:
3314       GST_ERROR_OBJECT (client, "Unhandled method...");
3315       return GST_RTSP_EINVAL;
3316       break;
3317   }
3318
3319   return res;
3320
3321 error:
3322   return res;
3323 }
3324
3325 /**
3326 * prepare_response:
3327 * @client: client object
3328 * @request : requst message received
3329 * @response : response to be prepare based on request
3330 * @method : RTSP method
3331 *
3332 * prepare response to the request based on @method & @message_type
3333 *
3334 * Returns: a #GstRTSPResult.
3335 */
3336 static GstRTSPResult
3337 prepare_response (GstRTSPClient *client, GstRTSPMessage *request, GstRTSPMessage *response, GstRTSPMethod method)
3338 {
3339   GstRTSPResult res = GST_RTSP_OK;
3340
3341   switch (method) {
3342     /* prepare OPTIONS response */
3343     case GST_RTSP_OPTIONS: {
3344       GstRTSPMethod options;
3345       gchar *tmp = NULL;
3346       gchar *str = NULL;
3347       gchar *user_agent = NULL;
3348
3349       options = GST_RTSP_OPTIONS |
3350           GST_RTSP_PAUSE |
3351           GST_RTSP_PLAY |
3352           GST_RTSP_SETUP |
3353           GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
3354
3355       str = gst_rtsp_options_as_text (options);
3356
3357       /*append WFD specific method */
3358       tmp = g_strdup (", org.wfa.wfd1.0");
3359       g_strlcat (str, tmp, strlen (tmp) + strlen (str) + 1);
3360
3361       gst_rtsp_message_init_response (response, GST_RTSP_STS_OK,
3362           gst_rtsp_status_as_text (GST_RTSP_STS_OK), request);
3363
3364       gst_rtsp_message_add_header (response, GST_RTSP_HDR_PUBLIC, str);
3365       g_free (str);
3366       str = NULL;
3367       res = gst_rtsp_message_get_header (request, GST_RTSP_HDR_USER_AGENT, &user_agent, 0);
3368       if (res == GST_RTSP_OK)
3369       {
3370         gst_rtsp_message_add_header (response, GST_RTSP_HDR_USER_AGENT, user_agent);
3371       }
3372       else res = GST_RTSP_OK;
3373       break;
3374     }
3375     default:
3376       GST_ERROR_OBJECT (client, "Unhandled method...");
3377       return GST_RTSP_EINVAL;
3378       break;
3379   }
3380
3381   return res;
3382 }
3383
3384 /**
3385 * handle_M1_message:
3386 * @client: client object
3387 *
3388 * Handles M1 WFD message.
3389 * This API will send OPTIONS request to WFDSink & waits for the relavent response.
3390 * After getting the response, this will check whether all mandatory messages are supported by the WFDSink or NOT.
3391 *
3392 * Returns: a #GstRTSPResult.
3393 */
3394
3395 static GstRTSPResult
3396 handle_M1_message (GstRTSPClient * client)
3397 {
3398   GstRTSPResult res = GST_RTSP_OK;
3399   GstRTSPMessage request = { 0 };
3400   GstRTSPMessage response = { 0 };
3401   gboolean bret = FALSE;
3402
3403   res = prepare_request (client, &request, GST_RTSP_OPTIONS, "*", WFD_MESSAGE_1, WFD_TRIGGER_UNKNOWN);
3404   if (GST_RTSP_OK != res) {
3405     GST_ERROR_OBJECT (client, "Failed to prepare M1 request....\n");
3406     return res;
3407   }
3408
3409   GST_DEBUG_OBJECT (client, "Sending OPTIONS request message (M1)...");
3410
3411   // TODO: need to add session i.e. 2nd variable
3412   send_request (client, NULL, &request);
3413
3414   /* Wait for OPTIONS response (M1 response) */
3415   res = gst_rtsp_connection_receive (client->connection, &response, NULL);
3416   if (GST_RTSP_OK != res) {
3417     GST_ERROR_OBJECT (client, "Failed to receive M1 response....\n");
3418     return res;
3419   }
3420
3421   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
3422     gst_rtsp_message_dump (&response);
3423   }
3424
3425   bret = gst_rtsp_client_parse_methods (client, &response);
3426   if (FALSE == bret) {
3427     return GST_RTSP_ERROR;
3428   }
3429
3430   return res;
3431
3432 }
3433
3434 /**
3435 * handle_M2_message:
3436 * @client: client object
3437 *
3438 * Handles M2 WFD message.
3439 * This API will waits for OPTIONS request from WFDSink & responds to the same.
3440 *
3441 * Returns: a #GstRTSPResult.
3442 */
3443 static GstRTSPResult
3444 handle_M2_message (GstRTSPClient * client)
3445 {
3446   GstRTSPResult res = GST_RTSP_OK;
3447   GstRTSPMessage request = { 0 };
3448   GstRTSPMessage response = { 0 };
3449   GstRTSPMethod method;
3450   const gchar *uristr;
3451   GstRTSPVersion version;
3452   GstRTSPClientState state = { NULL };
3453
3454   /* Wait for OPTIONS request from client (M2 request) */
3455   res = gst_rtsp_connection_receive (client->connection, &request, NULL);
3456   if (GST_RTSP_OK != res) {
3457     GST_ERROR_OBJECT (client, "Failed to receiv M2 request....\n");
3458     return res;
3459   }
3460   /*dump M2 request message*/
3461   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
3462     gst_rtsp_message_dump (&request);
3463   }
3464
3465   /* Parse the request received */
3466   res = gst_rtsp_message_parse_request (&request, &method, &uristr, &version);
3467   if (GST_RTSP_OK != res) {
3468     GST_ERROR_OBJECT (client, "Failed to parse request....\n");
3469     return res;
3470   }
3471
3472   state.request = &request;
3473   state.response = &response;
3474
3475   if (version != GST_RTSP_VERSION_1_0) {
3476     /* we can only handle 1.0 requests */
3477     send_generic_response (client, GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED,
3478         &state);
3479     return res;
3480   }
3481
3482   if (method != GST_RTSP_OPTIONS) {
3483     GST_ERROR_OBJECT (client, "Received WRONG request, when server is Waiting for OPTIONS request...");
3484     return GST_RTSP_ERROR;
3485   }
3486 #if 0
3487   /* we always try to parse the url first */
3488   if (gst_rtsp_url_parse (uristr, &uri) != GST_RTSP_OK) {
3489     send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, &state);
3490     return GST_RTSP_ERROR;
3491   }
3492
3493   /* not using the uri at this moment */
3494   gst_rtsp_url_free (uri);
3495 #endif
3496
3497   GST_DEBUG_OBJECT (client, "Received OPTIONS Request (M2 request)...");
3498
3499   /* prepare the response for WFDsink request */
3500   res = prepare_response (client, &request, &response, GST_RTSP_OPTIONS);
3501   if (GST_RTSP_OK != res) {
3502     GST_ERROR_OBJECT (client, "Failed to prepare M2 request....\n");
3503     return res;
3504   }
3505
3506   send_response (client, NULL, &response);
3507
3508   GST_DEBUG_OBJECT (client, "Sent OPTIONS Response (M2 response)...");
3509
3510   return res;
3511
3512 }
3513
3514 /**
3515 * handle_M3_message:
3516 * @client: client object
3517 *
3518 * Handles M3 WFD message.
3519 * This API will send M3 message (GET_PARAMETER) to WFDSink to query supported formats by the WFDSink.
3520 * After getting supported formats info, this API will set those values on WFDConfigMessage obj
3521 *
3522 * Returns: a #GstRTSPResult.
3523 */
3524 static GstRTSPResult
3525 handle_M3_message (GstRTSPClient * client)
3526 {
3527   GstRTSPResult res = GST_RTSP_OK;
3528   GstRTSPMessage request = { 0 };
3529   GstRTSPMessage response = { 0 };
3530   GstRTSPUrl *url = NULL;
3531   gchar *url_str = NULL;
3532
3533   client->caCodec = WFD_AUDIO_UNKNOWN;
3534   client->cFreq = WFD_FREQ_UNKNOWN;
3535   client->cChanels = WFD_CHANNEL_UNKNOWN;
3536   client->cBitwidth = 0;
3537   client->caLatency = 0;
3538   client->cvCodec = WFD_VIDEO_H264;
3539   client->cNative = WFD_VIDEO_CEA_RESOLUTION;
3540   client->cNativeResolution = 0;
3541   client->cCEAResolution = WFD_CEA_UNKNOWN;
3542   client->cVESAResolution = WFD_VESA_UNKNOWN;
3543   client->cHHResolution = WFD_HH_UNKNOWN;
3544   client->cProfile = WFD_H264_UNKNOWN_PROFILE;
3545   client->cLevel = WFD_H264_LEVEL_UNKNOWN;
3546   client->cMaxHeight = 0;
3547   client->cMaxWidth = 0;
3548   client->cmin_slice_size = 0;
3549   client->cslice_enc_params = 0;
3550   client->cframe_rate_control = 0;
3551   client->cvLatency = 0;
3552   client->ctrans = WFD_RTSP_TRANS_UNKNOWN;
3553   client->cprofile = WFD_RTSP_PROFILE_UNKNOWN;
3554   client->clowertrans = WFD_RTSP_LOWER_TRANS_UNKNOWN;
3555   client->crtp_port0 = 0;
3556   client->crtp_port1 = 0;
3557   client->hdcp_version = WFD_HDCP_NONE;
3558   client->hdcp_tcpport = 0;
3559   client->hdcp_support = FALSE;
3560 #ifdef STANDBY_RESUME_CAPABILITY
3561   client->standby_resume_capability_support = FALSE;
3562 #endif
3563
3564   url = gst_rtsp_connection_get_url (client->connection);
3565   if (url == NULL) {
3566     GST_ERROR_OBJECT (client, "Failed to get connection URL");
3567     return GST_RTSP_ERROR;
3568   }
3569
3570   url_str = gst_rtsp_url_get_request_uri (url);
3571   if (url_str == NULL) {
3572     GST_ERROR_OBJECT (client, "Failed to get connection URL");
3573     return GST_RTSP_ERROR;
3574   }
3575
3576   res = prepare_request (client, &request, GST_RTSP_GET_PARAMETER, url_str, WFD_MESSAGE_3, WFD_TRIGGER_UNKNOWN);
3577   if (GST_RTSP_OK != res) {
3578     GST_ERROR_OBJECT (client, "Failed to prepare M3 request....\n");
3579     return res;
3580   }
3581
3582   GST_DEBUG_OBJECT (client, "Sending GET_PARAMETER request message (M3)...");
3583
3584   // TODO: need to add session i.e. 2nd variable
3585   send_request (client, NULL, &request);
3586
3587   /* Wait for the response */
3588   res = gst_rtsp_connection_receive (client->connection, &response, NULL);
3589   if (GST_RTSP_OK != res) {
3590     GST_ERROR ("Failed to received response....\n");
3591     return FALSE;
3592   }
3593
3594   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
3595     gst_rtsp_message_dump (&response);
3596   }
3597
3598   /* parsing the GET_PARAMTER response */
3599   {
3600     gchar *data = NULL;
3601     guint size=0;
3602     WFDMessage *msg3res;
3603     WFDResult wfd_res = WFD_OK;
3604
3605     res = gst_rtsp_message_get_body (&response, (guint8**)&data, &size);
3606     if (res != GST_RTSP_OK) {
3607       GST_ERROR_OBJECT (client, "Failed to get body of response...");
3608       goto error;
3609     }
3610
3611     /* create M3 response message */
3612     wfd_res = wfdconfig_message_new(&msg3res);
3613     if (wfd_res != WFD_OK) {
3614       GST_ERROR_OBJECT (client, "Failed to prepare wfd message...");
3615       goto error;
3616     }
3617
3618     wfd_res = wfdconfig_message_init(msg3res);
3619     if (wfd_res != WFD_OK) {
3620       GST_ERROR_OBJECT (client, "Failed to init wfd message...");
3621       goto error;
3622     }
3623
3624     wfd_res = wfdconfig_message_parse_buffer((guint8*)data,size,msg3res);
3625     if (wfd_res != WFD_OK) {
3626       GST_ERROR_OBJECT (client, "Failed to init wfd message...");
3627       goto error;
3628     }
3629
3630     GST_DEBUG_OBJECT(client, "M3 response server side message body: %s", wfdconfig_message_as_text(msg3res));
3631
3632     /* Get the audio formats supported by WFDSink */
3633     if (msg3res->audio_codecs) {
3634       wfd_res = wfdconfig_get_supported_audio_format(msg3res, &client->caCodec, &client->cFreq, &client->cChanels, &client->cBitwidth, &client->caLatency);
3635       if (wfd_res != WFD_OK) {
3636         GST_WARNING_OBJECT (client, "Failed to get wfd support audio formats...");
3637         goto error;
3638       }
3639     }
3640
3641
3642     /* Get the Video formats supported by WFDSink */
3643     wfd_res = wfdconfig_get_supported_video_format(msg3res, &client->cvCodec, &client->cNative, &client->cNativeResolution,
3644                       (guint64*)&client->cCEAResolution, (guint64*)&client->cVESAResolution, (guint64*)&client->cHHResolution,
3645                       &client->cProfile, &client->cLevel, &client->cvLatency, &client->cMaxHeight,
3646                       &client->cMaxWidth, &client->cmin_slice_size, &client->cslice_enc_params, &client->cframe_rate_control);
3647     if (wfd_res != WFD_OK) {
3648       GST_WARNING_OBJECT (client, "Failed to get wfd supported video formats...");
3649       goto error;
3650     }
3651
3652     if (msg3res->client_rtp_ports) {
3653       /* Get the RTP ports preferred by WFDSink */
3654       wfd_res = wfdconfig_get_prefered_RTP_ports(msg3res, &client->ctrans, &client->cprofile, &client->clowertrans, &client->crtp_port0, &client->crtp_port1);
3655       if (wfd_res != WFD_OK) {
3656         GST_WARNING_OBJECT (client, "Failed to get wfd prefered RTP ports...");
3657         goto error;
3658       }
3659     }
3660
3661     if (msg3res->display_edid) {
3662       gboolean edid_supported = FALSE;
3663       guint32 edid_block_count = 0;
3664       gchar *edid_payload = NULL;
3665       /* Get the display edid preferred by WFDSink */
3666       wfd_res = wfdconfig_get_display_EDID(msg3res, &edid_supported, &edid_block_count, &edid_payload);
3667       if (wfd_res != WFD_OK) {
3668         GST_WARNING_OBJECT (client, "Failed to get wfd display edid...");
3669         goto error;
3670       }
3671       GST_DEBUG_OBJECT (client, " edid supported: %d edid_block_count: %d", edid_supported, edid_block_count);
3672       GST_DEBUG_OBJECT (client, "set_edid_info");
3673       set_edid_info(edid_payload, TRUE);
3674     }
3675    if (msg3res->content_protection) {
3676      /*Get the hdcp version and tcp port by WFDSink*/
3677      wfd_res = wfdconfig_get_contentprotection_type(msg3res, &client->hdcp_version, &client->hdcp_tcpport);
3678      GST_DEBUG("hdcp version =%d, tcp port = %d", client->hdcp_version, client->hdcp_tcpport);
3679      if (client->hdcp_version > 0 && client->hdcp_tcpport > 0)
3680        client->hdcp_support = TRUE;
3681
3682       if (wfd_res != WFD_OK) {
3683         GST_WARNING_OBJECT (client, "Failed to get wfd content protection...");
3684         goto error;
3685       }
3686    }
3687 #ifdef STANDBY_RESUME_CAPABILITY
3688    if (msg3res->standby_resume_capability) {
3689      /*Get the standby_resume_capability value by WFDSink*/
3690      wfd_res = wfdconfig_get_standby_resume_capability(msg3res, &client->standby_resume_capability_support );
3691      if (wfd_res != WFD_OK) {
3692        GST_WARNING_OBJECT (client, "Failed to get wfd standby resume capability...");
3693        goto error;
3694      }
3695    }
3696 #endif
3697     wfdconfig_message_dump(msg3res);
3698   }
3699
3700   return res;
3701
3702 error:
3703   return GST_RTSP_ERROR;
3704
3705 }
3706
3707 /**
3708 * handle_M4_message:
3709 * @client: client object
3710 *
3711 * Handles M4 WFD message.
3712 * This API will send M4 message (SET_PARAMETER) to WFDSink to set the format to be used in session
3713 *
3714 * Returns: a #GstRTSPResult.
3715 */
3716 static GstRTSPResult
3717 handle_M4_message (GstRTSPClient * client)
3718 {
3719   GstRTSPResult res = GST_RTSP_OK;
3720   GstRTSPMessage request = { 0 };
3721   GstRTSPMessage response = { 0 };
3722   GstRTSPUrl *url = NULL;
3723   gchar *url_str = NULL;
3724
3725   url = gst_rtsp_connection_get_url (client->connection);
3726   if (url == NULL) {
3727     GST_ERROR_OBJECT (client, "Failed to get connection URL");
3728     return GST_RTSP_ERROR;
3729   }
3730
3731   url_str = gst_rtsp_url_get_request_uri (url);
3732   if (url_str == NULL) {
3733     GST_ERROR_OBJECT (client, "Failed to get connection URL");
3734     return GST_RTSP_ERROR;
3735   }
3736
3737   /* prepare the request for M4 message */
3738   res = prepare_request (client, &request, GST_RTSP_SET_PARAMETER, url_str, WFD_MESSAGE_4, WFD_TRIGGER_UNKNOWN);
3739   if (GST_RTSP_OK != res) {
3740     GST_ERROR_OBJECT (client, "Failed to prepare M4 request....\n");
3741     return res;
3742   }
3743
3744   GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message (M4)...");
3745
3746   // TODO: need to add session i.e. 2nd variable
3747   send_request (client, NULL, &request);
3748
3749   /* Wait for the M4 response from WFDSink */
3750   res = gst_rtsp_connection_receive (client->connection, &response, NULL);
3751   if (GST_RTSP_OK != res) {
3752     GST_ERROR ("Failed to received response....\n");
3753     return FALSE;
3754   }
3755
3756   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
3757     gst_rtsp_message_dump (&response);
3758   }
3759
3760   return res;
3761
3762 }
3763
3764
3765 /**
3766 * handle_M5_message:
3767 * @client: client object
3768 *
3769 * Handles M5 WFD message.
3770 * This API will send M5 SETUP trigger message using SET_PARAMETER to WFDSink to intimate that client request SETUP now.
3771 *
3772 * Returns: a #GstRTSPResult.
3773 */
3774 static GstRTSPResult
3775 handle_M5_message (GstRTSPClient * client, WFDTrigger trigger_type)
3776 {
3777   GstRTSPResult res = GST_RTSP_OK;
3778   GstRTSPMessage request = { 0 };
3779   GstRTSPMessage response = { 0 };
3780   GstRTSPUrl *url = NULL;
3781   gchar *url_str = NULL;
3782   GstRTSPSession *session = NULL;
3783
3784   url = gst_rtsp_connection_get_url (client->connection);
3785   if (url == NULL) {
3786     GST_ERROR_OBJECT (client, "Failed to get connection URL");
3787     return GST_RTSP_ERROR;
3788   }
3789
3790   url_str = gst_rtsp_url_get_request_uri (url);
3791   if (url_str == NULL) {
3792     GST_ERROR_OBJECT (client, "Failed to get connection URL");
3793     return GST_RTSP_ERROR;
3794   }
3795
3796   /* prepare the request for M5 message */
3797   res = prepare_request (client, &request, GST_RTSP_SET_PARAMETER, url_str, WFD_MESSAGE_5, trigger_type);
3798   if (GST_RTSP_OK != res) {
3799     GST_ERROR_OBJECT (client, "Failed to prepare M5 request....\n");
3800     return res;
3801   }
3802
3803   GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message (M5)...");
3804
3805   // TODO: need to add session i.e. 2nd variable
3806   if (client->sessionid) {
3807     session = gst_rtsp_session_pool_find (client->session_pool, client->sessionid);
3808     GST_INFO_OBJECT (client, "session = %p & sessionid = %s", session, session->sessionid);
3809   }
3810   send_request (client, session, &request);
3811
3812   /* Wait for the M5 response from WFDSink */
3813   res = gst_rtsp_connection_receive (client->connection, &response, NULL);
3814   if (GST_RTSP_OK != res) {
3815     GST_ERROR ("Failed to received response....\n");
3816     return FALSE;
3817   }
3818
3819   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
3820     gst_rtsp_message_dump (&response);
3821   }
3822
3823   return res;
3824
3825 }
3826
3827
3828 /**
3829 * handle_M12_message:
3830 * @client: client object
3831 *
3832 * Handles M12 WFD message.
3833 * This API will send M5 SETUP trigger message using SET_PARAMETER to WFDSink to intimate that client request SETUP now.
3834 *
3835 * Returns: a #GstRTSPResult.
3836 */
3837 static GstRTSPResult
3838 handle_M12_message (GstRTSPClient * client)
3839 {
3840   GstRTSPResult res = GST_RTSP_OK;
3841   GstRTSPMessage request = { 0 };
3842   GstRTSPMessage response = { 0 };
3843   GstRTSPUrl *url = NULL;
3844   gchar *url_str = NULL;
3845   GstRTSPSession *session = NULL;
3846   GstRTSPSessionMedia *media;
3847   GstRTSPStatusCode code;
3848
3849   url = gst_rtsp_connection_get_url (client->connection);
3850   if (url == NULL) {
3851     GST_ERROR_OBJECT (client, "Failed to get connection URL");
3852     return GST_RTSP_ERROR;
3853   }
3854
3855   url_str = gst_rtsp_url_get_request_uri (url);
3856   if (url_str == NULL) {
3857     GST_ERROR_OBJECT (client, "Failed to get connection URL");
3858     return GST_RTSP_ERROR;
3859   }
3860
3861   /* prepare the request for M12 message */
3862   res = prepare_request (client, &request, GST_RTSP_SET_PARAMETER, url_str, WFD_MESSAGE_12, WFD_TRIGGER_UNKNOWN);
3863   if (GST_RTSP_OK != res) {
3864     GST_ERROR_OBJECT (client, "Failed to prepare M12 request....\n");
3865     return res;
3866   }
3867
3868   GST_DEBUG_OBJECT (client, "Sending SET_PARAMETER request message (M12)...");
3869
3870   // TODO: need to add session i.e. 2nd variable
3871   if (client->sessionid) {
3872     session = gst_rtsp_session_pool_find (client->session_pool, client->sessionid);
3873     GST_INFO_OBJECT (client, "session = %p & sessionid = %s", session, session->sessionid);
3874   }
3875   send_request (client, session, &request);
3876
3877   /* Wait for the M12 response from WFDSink */
3878   res = gst_rtsp_connection_receive (client->connection, &response, NULL);
3879   if (GST_RTSP_OK != res) {
3880     GST_ERROR ("Failed to received response....\n");
3881     return FALSE;
3882   }
3883
3884   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
3885     gst_rtsp_message_dump (&response);
3886   }
3887   if (!(session = gst_rtsp_session_pool_find (client->session_pool, client->sessionID)))
3888   {
3889     GST_ERROR_OBJECT (client, "Failed to handle B1 message...");
3890     return FALSE;
3891   }
3892   GST_DEBUG ("sessid = %s", client->sessionID);
3893
3894   media = session->medias->data;
3895
3896   /* unlink the all TCP callbacks */
3897   unlink_session_streams (client, session, media);
3898
3899   /* then pause sending */
3900   gst_rtsp_session_media_set_state (media, GST_STATE_PAUSED);
3901
3902   /* the state is now READY */
3903   media->state = GST_RTSP_STATE_READY;
3904
3905   return res;
3906
3907 }
3908 /**
3909 * gst_rtsp_client_negotiate:
3910 * @client: client object
3911 *
3912 * This will handle capability negotiation part of WFD session
3913 *
3914 * Returns: a #gboolean. return TRUE on success / FALSE on failure
3915 */
3916 gboolean
3917 gst_rtsp_client_negotiate (GstRTSPClient * client)
3918 {
3919   GstRTSPResult res = GST_RTSP_OK;
3920
3921   /* handle M1 OPTIONS message */
3922   res = handle_M1_message (client);
3923   if (GST_RTSP_OK != res) {
3924     GST_ERROR_OBJECT (client, "Failed to handle M1 message...");
3925     goto rtsp_method_failed;
3926   }
3927
3928   /* handle M2 OPTIONS message */
3929   res = handle_M2_message (client);
3930   if (GST_RTSP_OK != res) {
3931     GST_ERROR_OBJECT (client, "Failed to handle M2 message...");
3932     goto rtsp_method_failed;
3933   }
3934
3935   /* handle M3 GET_PARAMETER request message */
3936   res = handle_M3_message (client);
3937   if (GST_RTSP_OK != res) {
3938     GST_ERROR_OBJECT (client, "Failed to handle M3 message...");
3939     goto rtsp_method_failed;
3940   }
3941
3942   /* handle M4 SET_PARAMETER request message */
3943   res = handle_M4_message (client);
3944   if (GST_RTSP_OK != res) {
3945     GST_ERROR_OBJECT (client, "Failed to handle M4 message...");
3946     goto rtsp_method_failed;
3947   }
3948
3949   return TRUE;
3950
3951 rtsp_method_failed:
3952   GST_ERROR_OBJECT (client, "Failed to handle rtsp method : %d", res);
3953   return FALSE;
3954
3955 }
3956
3957 /**
3958 * gst_rtsp_client_start:
3959 * @client: client object
3960 *
3961 * This will handle M5 message & asks the client to start session
3962 *
3963 * Returns: a #gboolean. return TRUE on success / FALSE on failure
3964 */
3965 gboolean
3966 gst_rtsp_client_start (GstRTSPClient * client)
3967 {
3968   GstRTSPResult res = GST_RTSP_OK;
3969
3970   res = handle_M5_message (client, WFD_TRIGGER_SETUP);
3971   if (GST_RTSP_OK != res) {
3972     GST_ERROR_OBJECT (client, "Failed to handle M5 message...");
3973     return FALSE;
3974   }
3975
3976   return TRUE;
3977 }
3978
3979 void
3980 gst_rtsp_client_set_params (GstRTSPClient *client, int videosrc_type, gint session_mode, int videobitrate, gint mtu_size, gchar *infile)
3981 {
3982   client->videosrc_type = videosrc_type;
3983   client->session_mode = session_mode;
3984   client->bitrate = videobitrate;
3985   client->MTUsize = mtu_size;
3986   client->infile = g_strdup (infile);
3987
3988   g_print ("\n\n\nvideo src type = %d & session_mode = %d & filename = %s\n",
3989     videosrc_type, session_mode, client->infile);
3990 }
3991
3992 gboolean
3993 gst_rtsp_client_pause (GstRTSPClient * client)
3994 {
3995   GstRTSPResult res = GST_RTSP_OK;
3996
3997   res = handle_M5_message (client, WFD_TRIGGER_PAUSE);
3998   if (GST_RTSP_OK != res) {
3999     GST_ERROR_OBJECT (client, "Failed to handle M5 message...");
4000     return FALSE;
4001   }
4002
4003   return TRUE;
4004 }
4005
4006 gboolean
4007 gst_rtsp_client_resume (GstRTSPClient * client)
4008 {
4009   GstRTSPResult res = GST_RTSP_OK;
4010
4011   res = handle_M5_message (client, WFD_TRIGGER_PLAY);
4012   if (GST_RTSP_OK != res) {
4013     GST_ERROR_OBJECT (client, "Failed to handle M5 message...");
4014     return FALSE;
4015   }
4016
4017   return TRUE;
4018 }
4019
4020 gboolean
4021 gst_rtsp_client_standby(GstRTSPClient * client)
4022 {
4023   GstRTSPResult res = GST_RTSP_OK;
4024   res = handle_M12_message (client);
4025   if (GST_RTSP_OK != res) {
4026     GST_ERROR_OBJECT (client, "Failed to handle M12 message...");
4027     return FALSE;
4028   }
4029
4030   return TRUE;
4031 }
4032
4033 gboolean
4034 gst_rtsp_client_stop (GstRTSPClient * client)
4035 {
4036   GstRTSPResult res = GST_RTSP_OK;
4037
4038   res = handle_M5_message (client, WFD_TRIGGER_TEARDOWN);
4039   if (GST_RTSP_OK != res) {
4040     GST_ERROR_OBJECT (client, "Failed to handle M5 message...");
4041     return FALSE;
4042   }
4043
4044   return TRUE;
4045 }
4046
4047 static gboolean
4048 gst_rtsp_client_parse_methods (GstRTSPClient * client, GstRTSPMessage * response)
4049 {
4050   GstRTSPHeaderField field;
4051   gchar *respoptions;
4052   gchar **options;
4053   gint indx = 0;
4054   gint i;
4055   gboolean found_wfd_method = FALSE;
4056
4057   /* reset supported methods */
4058   client->methods = 0;
4059
4060   /* Try Allow Header first */
4061   field = GST_RTSP_HDR_ALLOW;
4062   while (TRUE) {
4063     respoptions = NULL;
4064     gst_rtsp_message_get_header (response, field, &respoptions, indx);
4065     if (indx == 0 && !respoptions) {
4066       /* if no Allow header was found then try the Public header... */
4067       field = GST_RTSP_HDR_PUBLIC;
4068       gst_rtsp_message_get_header (response, field, &respoptions, indx);
4069     }
4070     if (!respoptions)
4071       break;
4072
4073     /* If we get here, the server gave a list of supported methods, parse
4074      * them here. The string is like:
4075      *
4076      * OPTIONS,  PLAY, SETUP, ...
4077      */
4078     options = g_strsplit (respoptions, ",", 0);
4079
4080     for (i = 0; options[i]; i++) {
4081       gchar *stripped;
4082       gint method;
4083
4084       stripped = g_strstrip (options[i]);
4085       method = gst_rtsp_find_method (stripped);
4086
4087       if (!g_ascii_strcasecmp ("org.wfa.wfd1.0", stripped))
4088         found_wfd_method = TRUE;
4089
4090       /* keep bitfield of supported methods */
4091       if (method != GST_RTSP_INVALID)
4092         client->methods |= method;
4093     }
4094     g_strfreev (options);
4095
4096     indx++;
4097   }
4098
4099   if (!found_wfd_method) {
4100     GST_ERROR_OBJECT (client, "WFD client is not supporting WFD mandatory message : org.wfa.wfd1.0...");
4101     goto no_required_methods;
4102   }
4103
4104   /* Checking mandatory method */
4105   if (!(client->methods & GST_RTSP_SET_PARAMETER)) {
4106     GST_ERROR_OBJECT (client, "WFD client is not supporting WFD mandatory message : SET_PARAMETER...");
4107     goto no_required_methods;
4108   }
4109
4110   /* Checking mandatory method */
4111   if (!(client->methods & GST_RTSP_GET_PARAMETER)) {
4112     GST_ERROR_OBJECT (client, "WFD client is not supporting WFD mandatory message : GET_PARAMETER...");
4113     goto no_required_methods;
4114   }
4115
4116   if (!(client->methods & GST_RTSP_OPTIONS)) {
4117     GST_INFO_OBJECT (client, "assuming OPTIONS is supported by client...");
4118     client->methods |= GST_RTSP_OPTIONS;
4119   }
4120
4121   return TRUE;
4122
4123 /* ERRORS */
4124 no_required_methods:
4125   {
4126     GST_ELEMENT_ERROR (client, RESOURCE, OPEN_READ, (NULL),
4127         ("WFD Client does not support mandatory methods."));
4128   // TODO: temporary hack
4129     return FALSE;
4130   }
4131 }
4132
4133
4134 static void
4135 pad_added (GstElement* ele, GstPad* pad, gpointer data)
4136 {
4137   GstRTSPClient *client = (GstRTSPClient *)data;
4138   gchar* name = gst_pad_get_name (pad);
4139
4140   if (name[0] == 'v') {
4141     GstPad* spad = NULL;
4142
4143     g_print (" =========== >>>>>>>>>> Received VIDEO pad...\n");
4144
4145     spad = gst_element_get_request_pad(GST_ELEMENT(client->srcbin->vparse), "sink");
4146     if (gst_pad_link(pad, spad)  != GST_PAD_LINK_OK) {
4147       GST_ERROR ("Failed to link video demuxer pad & video parser sink pad...\n");
4148       return;
4149     }
4150     gst_object_unref(spad);
4151
4152   } else if (name[0] == 'a') {
4153     GstPad* spad = NULL;
4154     GstElement *aparse = NULL;
4155
4156 #if 0
4157     aparse = gst_element_factory_make ("aacparse", "aparser");
4158     if (!aparse) {
4159       GST_ERROR("failed to create audio parse element");
4160       return;
4161     }
4162     gst_bin_add (srcbin->srcbin, aparse);
4163
4164     if (!gst_element_link (aparse, srcbin->aqueue)) {
4165       GST_ERROR ("failed to link aparse & aqueue...\n");
4166       return;
4167     }
4168 #endif
4169
4170     g_print (" =========== >>>>>>>>>> Received AUDIO pad...\n");
4171     spad = gst_element_get_request_pad(GST_ELEMENT(client->srcbin->aqueue), "sink");
4172     if (gst_pad_link(pad, spad)  != GST_PAD_LINK_OK) {
4173       GST_ERROR ("Failed to link audio demuxer pad & audio parse pad...\n");
4174       return;
4175     }
4176     gst_object_unref(spad);
4177   } else {
4178     GST_ERROR ("not handling.....\n\n\n");
4179   }
4180
4181   g_free (name);
4182 }
4183
4184 static gboolean
4185 gst_rtsp_client_create_audio_capture_bin (GstRTSPClient * client, GstRTSPClientSrcBin *srcbin)
4186 {
4187   GstElement *audiosrc = NULL;
4188   GstElement *acaps = NULL;
4189   GstElement *aenc = NULL;
4190   GstElement *aencsrccaps = NULL;
4191   int channels = 0;
4192   int freq = 0;
4193   gchar *acodec = NULL;
4194
4195   /* create audio src element */
4196   audiosrc = gst_element_factory_make ("pulsesrc", "audiosrc");
4197   if (!audiosrc) {
4198     GST_ERROR_OBJECT (client, "failed to create audiosrc element");
4199     goto create_error;
4200   }
4201   g_object_set (audiosrc, "device", "alsa_output.0.analog-stereo.monitor", NULL);
4202   //g_object_set (audiosrc, "provide-clock", 0, NULL);
4203   //g_object_set (audiosrc, "latency-time", 1000, NULL);
4204   //g_object_set (audiosrc, "actual-latency-time", 1000, NULL);
4205
4206   g_object_set (audiosrc, "is-live", 1, NULL);
4207   g_object_set (audiosrc, "do-timestamp", 1, NULL);
4208   /* create audio caps element */
4209   acaps  = gst_element_factory_make ("capsfilter", "audiocaps");
4210   if (NULL == acaps) {
4211     GST_ERROR_OBJECT (client, "failed to create audio capsilfter element");
4212     goto create_error;
4213   }
4214
4215   if(client->cChanels == WFD_CHANNEL_2)
4216     channels = 2;
4217   else if(client->cChanels == WFD_CHANNEL_4)
4218     channels = 4;
4219   else if(client->cChanels == WFD_CHANNEL_6)
4220     channels = 6;
4221   else if(client->cChanels == WFD_CHANNEL_8)
4222     channels = 8;
4223   else
4224     channels = 2;
4225
4226   if(client->cFreq == WFD_FREQ_44100)
4227     freq = 44100;
4228   else if(client->cFreq == WFD_FREQ_48000)
4229     freq = 48000;
4230   else
4231     freq = 44100;
4232
4233   if(client->caCodec == WFD_AUDIO_LPCM) {
4234     g_object_set (G_OBJECT (acaps), "caps",
4235         gst_caps_new_simple ("audio/x-lpcm",
4236         "width", G_TYPE_INT, client->cBitwidth,
4237         "rate", G_TYPE_INT, freq,
4238         "channels", G_TYPE_INT, channels, NULL), NULL);
4239   } else if((client->caCodec == WFD_AUDIO_AAC) || (client->caCodec == WFD_AUDIO_AC3)) {
4240     g_object_set (G_OBJECT (acaps), "caps",
4241         gst_caps_new_simple ("audio/x-raw-int",
4242             "width", G_TYPE_INT, client->cBitwidth,
4243             "endianess", G_TYPE_INT, 1234,
4244             "signed", G_TYPE_BOOLEAN, TRUE,
4245             "depth", G_TYPE_INT, 16,
4246             "rate", G_TYPE_INT, freq,
4247             "channels", G_TYPE_INT, channels, NULL), NULL);
4248   }
4249
4250   if(client->caCodec == WFD_AUDIO_AAC)
4251     acodec = g_strdup("ffenc_aac");
4252   else if(client->caCodec == WFD_AUDIO_AC3)
4253     acodec = g_strdup("savsenc_ac3");
4254   else{
4255     GST_ERROR_OBJECT (client, "Yet to support other than H264 format");
4256     goto create_error;
4257   }
4258
4259   aenc = gst_element_factory_make (acodec, "audioenc");
4260   if (NULL == aenc) {
4261     GST_ERROR_OBJECT (client, "failed to create audio encoder element");
4262     goto create_error;
4263   }
4264   aencsrccaps = gst_element_factory_make ("capsfilter", "audioencsrccaps");
4265   if (NULL == aencsrccaps) {
4266     GST_ERROR_OBJECT (client, "failed to create audio capsilfter element");
4267     goto create_error;
4268   }
4269   g_object_set (G_OBJECT (aencsrccaps), "caps",
4270         gst_caps_new_simple ("audio/mpeg",
4271         "stream-format", G_TYPE_STRING, "adts", NULL), NULL);
4272
4273   srcbin->aqueue  = gst_element_factory_make ("queue", "audio-queue");
4274   if (!srcbin->aqueue) {
4275     GST_ERROR_OBJECT (client, "failed to create audio queue element");
4276     goto create_error;
4277   }
4278
4279   gst_bin_add_many (srcbin->srcbin, audiosrc, acaps, aenc, aencsrccaps, srcbin->aqueue, NULL);
4280
4281   if (!gst_element_link_many (audiosrc, acaps, aenc, aencsrccaps, srcbin->aqueue, NULL)) {
4282     GST_ERROR_OBJECT (client, "Failed to link audio src elements...");
4283     goto create_error;
4284   }
4285
4286   return TRUE;
4287
4288 create_error:
4289   return FALSE;
4290 }
4291
4292 static gboolean
4293 gst_rtsp_client_create_xvcapture_bin (GstRTSPClient * client, GstRTSPClientSrcBin *srcbin)
4294 {
4295   GstElement *videosrc = NULL;
4296   GstElement *vcaps = NULL;
4297   gchar *vcodec = NULL;
4298
4299   videosrc = gst_element_factory_make ("xvimagesrc", "videosrc");
4300   if (NULL == videosrc) {
4301     GST_ERROR_OBJECT (client, "failed to create xvimagesrc element");
4302     goto create_error;
4303   }
4304
4305   /* create video caps element */
4306   vcaps = gst_element_factory_make ("capsfilter", "videocaps");
4307   if (NULL == vcaps) {
4308     GST_ERROR_OBJECT (client, "failed to create video capsilfter element");
4309     goto create_error;
4310   }
4311
4312   GST_INFO_OBJECT (client, "picked xvimagesrc as video source");
4313   g_object_set (G_OBJECT (vcaps), "caps",
4314       gst_caps_new_simple ("video/x-raw",
4315           "width", G_TYPE_INT, client->cMaxWidth,
4316           "height", G_TYPE_INT, client->cMaxHeight,
4317           "format", G_TYPE_STRING, "SN12",
4318           "framerate", GST_TYPE_FRACTION, 30, 1, NULL), NULL);
4319
4320   if(client->cvCodec == WFD_VIDEO_H264)
4321     vcodec = g_strdup("omx_h264enc");
4322   else {
4323     GST_ERROR_OBJECT (client, "Yet to support other than H264 format");
4324     goto create_error;
4325   }
4326
4327   srcbin->venc  = gst_element_factory_make (vcodec, "videoenc");
4328   if (!srcbin->venc) {
4329     GST_ERROR_OBJECT (client, "failed to create video encoder element");
4330     goto create_error;
4331   }
4332   g_object_set (srcbin->venc, "bitrate", client->bitrate, NULL);
4333   g_object_set (srcbin->venc, "byte-stream", 1, NULL);
4334   g_object_set (srcbin->venc, "append-dci", 1, NULL);
4335
4336
4337   srcbin->vqueue  = gst_element_factory_make ("queue", "video-queue");
4338   if (!srcbin->vqueue) {
4339     GST_ERROR_OBJECT (client, "failed to create video queue element");
4340     goto create_error;
4341   }
4342
4343   // TODO: check whether queue is required to have default values
4344
4345   gst_bin_add_many (srcbin->srcbin, videosrc, vcaps, srcbin->venc, srcbin->vqueue, NULL);
4346   if (!gst_element_link_many (videosrc, vcaps, srcbin->venc, srcbin->vqueue,NULL)) {
4347     GST_ERROR_OBJECT (client, "Failed to link video src elements...");
4348     goto create_error;
4349   }
4350
4351   return TRUE;
4352
4353 create_error:
4354   return FALSE;
4355 }
4356
4357 static gboolean
4358 gst_rtsp_client_create_filesrc_bin (GstRTSPClient * client, GstRTSPClientSrcBin *srcbin)
4359 {
4360   GstElement *vdec = NULL;
4361   GstElement *videosrc = NULL;
4362   GstElement *srcdemux = NULL;
4363
4364   videosrc = gst_element_factory_make ("filesrc", "videosrc");
4365   if (NULL == videosrc) {
4366     GST_ERROR_OBJECT (client, "failed to create filesrc element");
4367     goto create_error;
4368   }
4369   g_object_set (videosrc, "location", client->infile, NULL);
4370
4371   GST_INFO_OBJECT (client, "picked filesrc as video source");
4372
4373   // TODO: need to add support for remaing demuxers
4374   srcdemux = gst_element_factory_make ("qtdemux", "demuxer");
4375   if (!srcdemux) {
4376     GST_ERROR_OBJECT (client, "failed to create demuxer element");
4377     goto create_error;
4378   }
4379   g_signal_connect (srcdemux, "pad-added", G_CALLBACK(pad_added), client);
4380
4381   srcbin->vparse = gst_element_factory_make ("legacyh264parse", "parser");
4382   if (!srcbin->vparse) {
4383     GST_ERROR_OBJECT(client, "failed to create video parse element");
4384     goto create_error;
4385   }
4386   g_object_set (srcbin->vparse, "config-interval", 1, NULL);
4387   g_object_set (srcbin->vparse, "output-format", 1, NULL);
4388
4389   vdec = gst_element_factory_make ("omx_h264dec", "video-dec");
4390   if (!vdec) {
4391     GST_ERROR_OBJECT(client, "failed to create video decoder element");
4392     goto create_error;
4393   }
4394
4395   srcbin->venc = gst_element_factory_make ("omx_h264enc", "video-enc");
4396   if (!srcbin->venc) {
4397     GST_ERROR_OBJECT(client, "failed to create video encoder element");
4398     goto create_error;
4399   }
4400   g_object_set (srcbin->venc, "bitrate", client->bitrate, NULL);
4401   g_object_set (srcbin->venc, "byte-stream", 1, NULL);
4402   g_object_set (srcbin->venc, "append-dci", 1, NULL);
4403
4404   srcbin->vqueue  = gst_element_factory_make ("queue", "video-queue");
4405   if (!srcbin->vqueue) {
4406     GST_ERROR_OBJECT (client, "failed to create video queue element");
4407     goto create_error;
4408   }
4409
4410   srcbin->aqueue  = gst_element_factory_make ("queue", "audio-queue");
4411   if (!srcbin->aqueue) {
4412     GST_ERROR_OBJECT (client, "failed to create audio queue element");
4413     goto create_error;
4414   }
4415
4416   gst_bin_add_many (srcbin->srcbin, videosrc, srcdemux, srcbin->vparse, vdec,
4417     srcbin->venc, srcbin->vqueue, srcbin->aqueue, NULL);
4418
4419   gst_element_link (videosrc, srcdemux);
4420
4421   if (!gst_element_link_many (srcbin->vparse, vdec, srcbin->venc, srcbin->vqueue, NULL)) {
4422     GST_ERROR_OBJECT(client,"failed to link vparse &vqueue...\n");
4423     goto create_error;
4424   }
4425
4426   return TRUE;
4427
4428 create_error:
4429   return FALSE;
4430
4431 }
4432 /**
4433 * gst_rtsp_client_create_srcbin:
4434 * @client: client object
4435 *
4436 * Creates the server source bin
4437 *
4438 * Returns: void
4439 */
4440 static void
4441 gst_rtsp_client_create_srcbin (GstRTSPClient * client)
4442 {
4443   GstRTSPClientSrcBin *srcbin = NULL;
4444   GstElement *mux = NULL;
4445   GstElement *payload = NULL;
4446   GstPad *srcpad = NULL;
4447
4448   srcbin = g_slice_new0 (GstRTSPClientSrcBin);
4449
4450   /* create source bin */
4451   srcbin->srcbin = GST_BIN_CAST(gst_bin_new ("srcbin"));
4452   if (!srcbin->srcbin) {
4453     GST_ERROR_OBJECT (client, "failed to create source bin...");
4454     goto create_error;
4455   }
4456
4457   /* create video src element */
4458   switch (client->videosrc_type) {
4459     /* using xvimagesrc */
4460     case WFD_INI_VSRC_XVIMAGESRC: {
4461       if (!gst_rtsp_client_create_xvcapture_bin (client, srcbin)) {
4462         GST_ERROR_OBJECT (client, "failed to create xvcapture bin...");
4463         goto create_error;
4464       }
4465     }
4466     break;
4467     case WFD_INI_VSRC_FILESRC: {
4468       /* using filesrc */
4469       if (!gst_rtsp_client_create_filesrc_bin (client, srcbin)) {
4470         GST_ERROR_OBJECT (client, "failed to create xvcapture bin...");
4471         goto create_error;
4472       }
4473     }
4474     break;
4475     case WFD_INI_VSRC_CAMERASRC:
4476     case WFD_INI_VSRC_VIDEOTESTSRC:
4477     default:
4478       GST_ERROR_OBJECT (client, "unknow mode selected...");
4479       goto create_error;
4480   }
4481
4482   mux = gst_element_factory_make ("mpegtsmux", "tsmux");
4483   if (!mux) {
4484     GST_ERROR_OBJECT (client, "failed to create muxer element");
4485     goto create_error;
4486   }
4487   if (client->hdcp_support) {
4488     g_object_set(mux, "HDCP-IP", client->wfdsink_ip, NULL);
4489     g_object_set(mux, "HDCP-port", client->hdcp_tcpport, NULL);
4490   }
4491
4492   payload = gst_element_factory_make ("rtpmp2tpay", "pay0");
4493   if (!payload) {
4494     GST_ERROR_OBJECT (client, "failed to create payload element");
4495     goto create_error;
4496   }
4497
4498   g_object_set (payload, "pt", 33, NULL);
4499   g_object_set (payload, "mtu", client->MTUsize, NULL);
4500
4501   gst_bin_add_many (srcbin->srcbin, mux, payload, NULL);
4502
4503   if (!gst_element_link_many (mux, payload, NULL)) {
4504     GST_ERROR_OBJECT (client, "Failed to link muxer & payload...");
4505     goto create_error;
4506   }
4507
4508   /* request sink pad from muxer */
4509   srcbin->mux_vsinkpad = gst_element_get_request_pad (mux, "sink_%d");
4510   if (!srcbin->mux_vsinkpad) {
4511     GST_ERROR_OBJECT (client, "Failed to get sink pad from muxer...");
4512     goto create_error;
4513   }
4514
4515   /* request srcpad from video queue */
4516   srcpad = gst_element_get_static_pad (srcbin->vqueue, "src");
4517   if (!srcpad) {
4518     GST_ERROR_OBJECT (client, "Failed to get srcpad from video queue...");
4519     goto create_error;
4520   }
4521
4522   if (gst_pad_link (srcpad, srcbin->mux_vsinkpad) != GST_PAD_LINK_OK) {
4523     GST_ERROR_OBJECT (client, "Failed to link video queue src pad & muxer video sink pad...");
4524     goto create_error;
4525   }
4526
4527   gst_object_unref (srcpad);
4528   srcpad = NULL;
4529
4530   if (client->session_mode != WFD_INI_VIDEO_ONLY) {
4531
4532     if (client->videosrc_type != WFD_INI_VSRC_FILESRC) {
4533       /* create audio source elements & add to pipeline */
4534       if (!gst_rtsp_client_create_audio_capture_bin (client, srcbin))
4535         goto create_error;
4536     }
4537
4538     /* request sink pad from muxer */
4539     srcbin->mux_asinkpad = gst_element_get_request_pad (mux, "sink_%d");
4540     if (!srcbin->mux_asinkpad) {
4541       GST_ERROR_OBJECT (client, "Failed to get sinkpad from muxer...");
4542       goto create_error;
4543     }
4544
4545     /* request srcpad from audio queue */
4546     srcpad = gst_element_get_static_pad (srcbin->aqueue, "src");
4547     if (!srcpad) {
4548       GST_ERROR_OBJECT (client, "Failed to get srcpad from audio queue...");
4549       goto create_error;
4550     }
4551
4552     /* link audio queue's srcpad & muxer sink pad */
4553     if (gst_pad_link (srcpad, srcbin->mux_asinkpad) != GST_PAD_LINK_OK) {
4554       GST_ERROR_OBJECT (client, "Failed to link audio queue src pad & muxer audio sink pad...");
4555       goto create_error;
4556     }
4557
4558 #ifdef WFD_PAD_PROBE
4559     GstPad *pad_probe = NULL;
4560     pad_probe = gst_element_get_static_pad (mux, "src");
4561     if(NULL == pad_probe)
4562     {
4563       GST_INFO("pad for probe not created");
4564     } else
4565     GST_INFO("pad for probe SUCCESSFUL");
4566     gst_pad_add_data_probe (pad_probe, G_CALLBACK (gst_dump_data), client);
4567 #endif
4568
4569     gst_object_unref (srcpad);
4570     srcpad = NULL;
4571   }
4572
4573   client->srcbin = srcbin;
4574
4575   GST_DEBUG_OBJECT (client, "successfully created source bin...");
4576
4577   return;
4578
4579 create_error:
4580   g_slice_free (GstRTSPClientSrcBin, srcbin);
4581
4582   // TODO: Need to clean everything
4583   return;
4584 }
4585
4586 #ifdef WFD_PAD_PROBE
4587 static gboolean gst_dump_data (GstPad * pad, GstMiniObject * obj, gpointer u_data)
4588 {
4589   gint8 *data;
4590   gint size;
4591   GstElement *bin = (GstElement *) u_data;
4592   if (GST_IS_BUFFER (obj)) {
4593     GstBuffer *buffer = GST_BUFFER_CAST (obj);
4594     GST_LOG ("got buffer %p with size %d", buffer, GST_BUFFER_SIZE (buffer));
4595     data = GST_BUFFER_DATA(buffer);
4596     size = GST_BUFFER_SIZE(buffer);
4597     f = fopen("probe.ts", "a");
4598     fwrite(data, size, 1, f);
4599     fclose(f);
4600   }
4601   return TRUE;
4602 }
4603 #endif
4604
4605 static gboolean
4606 keep_alive_response_check (gpointer userdata)
4607 {
4608   GstRTSPClient *client = (GstRTSPClient *)userdata;
4609   if (!client) {
4610     return TRUE;
4611   }
4612   if (client->keep_alive_flag) {
4613     return FALSE;
4614   }
4615   else {
4616     GST_INFO ("%p: source error notification", client);
4617     g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_ERROR], 0, NULL);
4618   }
4619   return TRUE;
4620 }
4621
4622 /*CHecking whether source has got response of any request.
4623  * If yes, keep alive message is sent otherwise error message
4624  * will be displayed.*/
4625 gboolean
4626 keep_alive_condition(gpointer userdata)
4627 {
4628   GstRTSPClient *client;
4629   gboolean res;
4630   client = (GstRTSPClient *)userdata;
4631   if (!client) {
4632     return FALSE;
4633   }
4634   if(client->keep_alive_lock)
4635     g_mutex_lock(client->keep_alive_lock);
4636   else
4637     return FALSE;
4638   if(!client->keep_alive_flag) {
4639     g_timeout_add(5000, keep_alive_response_check, client);
4640   }
4641   else {
4642     GST_DEBUG_OBJECT (client, "have received last keep alive message response");
4643   }
4644   GST_DEBUG("sending keep alive message");
4645   res = gst_rtsp_client_sending_m16_message(client);
4646   if(res) {
4647     client->keep_alive_flag = FALSE;
4648   }
4649   else {
4650     GST_ERROR_OBJECT (client, "Failed to send Keep Alive Message");
4651     g_mutex_unlock(client->keep_alive_lock);
4652     return FALSE;
4653   }
4654   g_mutex_unlock(client->keep_alive_lock);
4655   return TRUE;
4656 }
4657 /*Sending keep_alive (M16) message.
4658   Without calling prepare_request function.*/
4659
4660 gboolean
4661 gst_rtsp_client_sending_m16_message (GstRTSPClient * client)
4662 {
4663   GstRTSPResult res = GST_RTSP_OK;
4664   GstRTSPUrl *url = NULL;
4665   GstRTSPMessage request = { 0 };
4666   gchar *url_str = NULL;
4667   GstRTSPSession *session = NULL;
4668
4669   url = gst_rtsp_connection_get_url (client->connection);
4670   if (url == NULL) {
4671     GST_ERROR_OBJECT (client, "Failed to get connection URL");
4672     return FALSE;
4673   }
4674
4675   url_str = gst_rtsp_url_get_request_uri (url);
4676   if (url_str == NULL) {
4677     GST_ERROR_OBJECT (client, "Failed to get connection URL");
4678     return FALSE;
4679   }
4680
4681   res = gst_rtsp_message_init_request (&request, GST_RTSP_GET_PARAMETER, url_str);
4682   if (res < 0) {
4683     GST_ERROR ("init request failed");
4684     return FALSE;
4685   }
4686
4687   if (client->sessionid) {
4688     session = gst_rtsp_session_pool_find (client->session_pool, client->sessionid);
4689     GST_INFO_OBJECT (client, "session = %p & sessionid = %s", session, session->sessionid);
4690   }
4691   send_request (client, session, &request);
4692   return TRUE;
4693 }
4694