1 /* GStreamer unit tests for the souphttpsrc element
2 * Copyright (C) 2006-2007 Tim-Philipp Müller <tim centricular net>
3 * Copyright (C) 2008 Wouter Cloetens <wouter@mind.be>
4 * Copyright (C) 2001-2003, Ximian, Inc.
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., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <stdlib.h>
27
28 #include <glib.h>
29 #include <glib/gprintf.h>
30
31 #define SOUP_VERSION_MIN_REQUIRED (SOUP_VERSION_2_40)
32 #include <libsoup/soup.h>
33 #include <gst/check/gstcheck.h>
34
35 #if !defined(SOUP_MINOR_VERSION) || SOUP_MINOR_VERSION < 44
36 #define SoupStatus SoupKnownStatusCode
37 #endif
38
39
40 gboolean redirect = TRUE;
41
42 static const char **cookies = NULL;
43
44 /* Variables for authentication tests */
45 static const char *user_id = NULL;
46 static const char *user_pw = NULL;
47 static const char *good_user = "good_user";
48 static const char *bad_user = "bad_user";
49 static const char *good_pw = "good_pw";
50 static const char *bad_pw = "bad_pw";
51 static const char *realm = "SOUPHTTPSRC_REALM";
52 static const char *basic_auth_path = "/basic_auth";
53 static const char *digest_auth_path = "/digest_auth";
54
55 static const char *ssl_cert_file = GST_TEST_FILES_PATH "/test-cert.pem";
56 static const char *ssl_key_file = GST_TEST_FILES_PATH "/test-key.pem";
57
58 static guint get_port_from_server (SoupServer * server);
59 static SoupServer *run_server (gboolean use_https);
60
61 static void
handoff_cb(GstElement * fakesink,GstBuffer * buf,GstPad * pad,GstBuffer ** p_outbuf)62 handoff_cb (GstElement * fakesink, GstBuffer * buf, GstPad * pad,
63 GstBuffer ** p_outbuf)
64 {
65 GST_LOG ("handoff, buf = %p", buf);
66 if (*p_outbuf == NULL)
67 *p_outbuf = gst_buffer_ref (buf);
68 }
69
70 static gboolean
basic_auth_cb(SoupAuthDomain * domain,SoupMessage * msg,const char * username,const char * password,gpointer user_data)71 basic_auth_cb (SoupAuthDomain * domain, SoupMessage * msg,
72 const char *username, const char *password, gpointer user_data)
73 {
74 /* There is only one good login for testing */
75 return (strcmp (username, good_user) == 0)
76 && (strcmp (password, good_pw) == 0);
77 }
78
79
80 static char *
digest_auth_cb(SoupAuthDomain * domain,SoupMessage * msg,const char * username,gpointer user_data)81 digest_auth_cb (SoupAuthDomain * domain, SoupMessage * msg,
82 const char *username, gpointer user_data)
83 {
84 /* There is only one good login for testing */
85 if (strcmp (username, good_user) == 0)
86 return soup_auth_domain_digest_encode_password (good_user, realm, good_pw);
87 return NULL;
88 }
89
90 static gboolean
run_test(gboolean use_https,const gchar * path,gint expected)91 run_test (gboolean use_https, const gchar * path, gint expected)
92 {
93 GstStateChangeReturn ret;
94 GstElement *pipe, *src, *sink;
95 GstBuffer *buf = NULL;
96 GstMessage *msg;
97 gchar *url;
98 gboolean res = FALSE;
99 SoupServer *server;
100 guint port;
101
102 server = run_server (use_https);
103 if (server == NULL) {
104 g_print ("Failed to start up %s server", use_https ? "HTTPS" : "HTTP");
105 /* skip this test */
106 return TRUE;
107 }
108
109 pipe = gst_pipeline_new (NULL);
110
111 src = gst_element_factory_make ("souphttpsrc", NULL);
112 fail_unless (src != NULL);
113
114 sink = gst_element_factory_make ("fakesink", NULL);
115 fail_unless (sink != NULL);
116
117 gst_bin_add (GST_BIN (pipe), src);
118 gst_bin_add (GST_BIN (pipe), sink);
119 fail_unless (gst_element_link (src, sink));
120
121 port = get_port_from_server (server);
122 url = g_strdup_printf ("%s://127.0.0.1:%u%s",
123 use_https ? "https" : "http", port, path);
124 fail_unless (url != NULL);
125 g_object_set (src, "location", url, NULL);
126 g_free (url);
127
128 if (use_https) {
129 GTlsDatabase *tlsdb;
130 GError *error = NULL;
131 gchar *path;
132
133 /* GTlsFileDatabase needs an absolute path. Using a relative one
134 * causes a warning from GLib-Net followed by a segfault in GnuTLS */
135 if (g_path_is_absolute (ssl_cert_file)) {
136 path = g_strdup (ssl_cert_file);
137 } else {
138 gchar *cwd = g_get_current_dir ();
139 path = g_build_filename (cwd, ssl_cert_file, NULL);
140 g_free (cwd);
141 }
142
143 tlsdb = g_tls_file_database_new (path, &error);
144 fail_unless (tlsdb, "Failed to load certificate: %s", error->message);
145
146 g_object_set (src, "tls-database", tlsdb, NULL);
147
148 g_object_unref (tlsdb);
149 g_free (path);
150 }
151
152 g_object_set (src, "automatic-redirect", redirect, NULL);
153 if (cookies != NULL)
154 g_object_set (src, "cookies", cookies, NULL);
155 g_object_set (sink, "signal-handoffs", TRUE, NULL);
156 g_signal_connect (sink, "preroll-handoff", G_CALLBACK (handoff_cb), &buf);
157
158 if (user_id != NULL)
159 g_object_set (src, "user-id", user_id, NULL);
160 if (user_pw != NULL)
161 g_object_set (src, "user-pw", user_pw, NULL);
162
163 ret = gst_element_set_state (pipe, GST_STATE_PAUSED);
164 if (ret != GST_STATE_CHANGE_ASYNC) {
165 GST_DEBUG ("failed to start up soup http src, ret = %d", ret);
166 goto done;
167 }
168
169 gst_element_set_state (pipe, GST_STATE_PLAYING);
170 msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
171 GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
172 if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
173 gchar *debug = NULL;
174 GError *err = NULL;
175 gint rc = -1;
176
177 gst_message_parse_error (msg, &err, &debug);
178 GST_INFO ("error: %s", err->message);
179 if (g_str_has_suffix (err->message, "Not Found"))
180 rc = 404;
181 else if (g_str_has_suffix (err->message, "Forbidden"))
182 rc = 403;
183 else if (g_str_has_suffix (err->message, "Unauthorized"))
184 rc = 401;
185 else if (g_str_has_suffix (err->message, "Found"))
186 rc = 302;
187 GST_INFO ("debug: %s", debug);
188 /* should not've gotten any output in case of a 40x error. Wait a bit
189 * to give the streaming thread a chance to push out a buffer and trigger
190 * our callback before shutting down the pipeline */
191 g_usleep (G_USEC_PER_SEC / 2);
192 fail_unless (buf == NULL);
193 g_error_free (err);
194 g_free (debug);
195 gst_message_unref (msg);
196 GST_DEBUG ("Got HTTP error %u, expected %u", rc, expected);
197 res = (rc == expected);
198 goto done;
199 }
200 gst_message_unref (msg);
201
202 /* don't wait for more than 10 seconds */
203 ret = gst_element_get_state (pipe, NULL, NULL, 10 * GST_SECOND);
204 GST_LOG ("ret = %u", ret);
205
206 if (buf == NULL) {
207 /* we want to test the buffer offset, nothing else; if there's a failure
208 * it might be for lots of reasons (no network connection, whatever), we're
209 * not interested in those */
210 GST_DEBUG ("didn't manage to get data within 10 seconds, skipping test");
211 res = TRUE;
212 goto done;
213 }
214
215 GST_DEBUG ("buffer offset = %" G_GUINT64_FORMAT, GST_BUFFER_OFFSET (buf));
216
217 /* first buffer should have a 0 offset */
218 fail_unless (GST_BUFFER_OFFSET (buf) == 0);
219 gst_buffer_unref (buf);
220 res = (expected == 0);
221
222 done:
223
224 gst_element_set_state (pipe, GST_STATE_NULL);
225 gst_object_unref (pipe);
226 gst_object_unref (server);
227 return res;
228 }
229
GST_START_TEST(test_first_buffer_has_offset)230 GST_START_TEST (test_first_buffer_has_offset)
231 {
232 fail_unless (run_test (FALSE, "/", 0));
233 }
234
235 GST_END_TEST;
236
GST_START_TEST(test_not_found)237 GST_START_TEST (test_not_found)
238 {
239 fail_unless (run_test (FALSE, "/404", 404));
240 fail_unless (run_test (FALSE, "/404-with-data", 404));
241 }
242
243 GST_END_TEST;
244
GST_START_TEST(test_forbidden)245 GST_START_TEST (test_forbidden)
246 {
247 fail_unless (run_test (FALSE, "/403", 403));
248 }
249
250 GST_END_TEST;
251
GST_START_TEST(test_redirect_no)252 GST_START_TEST (test_redirect_no)
253 {
254 redirect = FALSE;
255 fail_unless (run_test (FALSE, "/302", 302));
256 }
257
258 GST_END_TEST;
259
GST_START_TEST(test_redirect_yes)260 GST_START_TEST (test_redirect_yes)
261 {
262 redirect = TRUE;
263 fail_unless (run_test (FALSE, "/302", 0));
264 }
265
266 GST_END_TEST;
267
GST_START_TEST(test_https)268 GST_START_TEST (test_https)
269 {
270 fail_unless (run_test (TRUE, "/", 0));
271 }
272
273 GST_END_TEST;
274
GST_START_TEST(test_cookies)275 GST_START_TEST (test_cookies)
276 {
277 static const char *biscotti[] = { "delacre=yummie", "koekje=lu", NULL };
278 gboolean res;
279
280 cookies = biscotti;
281 res = run_test (FALSE, "/", 0);
282 cookies = NULL;
283 fail_unless (res);
284 }
285
286 GST_END_TEST;
287
GST_START_TEST(test_good_user_basic_auth)288 GST_START_TEST (test_good_user_basic_auth)
289 {
290 gboolean res;
291
292 user_id = good_user;
293 user_pw = good_pw;
294 res = run_test (FALSE, basic_auth_path, 0);
295 GST_DEBUG ("Basic Auth user %s password %s res = %d", user_id, user_pw, res);
296 user_id = user_pw = NULL;
297 fail_unless (res);
298 }
299
300 GST_END_TEST;
301
GST_START_TEST(test_bad_user_basic_auth)302 GST_START_TEST (test_bad_user_basic_auth)
303 {
304 gboolean res;
305
306 user_id = bad_user;
307 user_pw = good_pw;
308 res = run_test (FALSE, basic_auth_path, 401);
309 GST_DEBUG ("Basic Auth user %s password %s res = %d", user_id, user_pw, res);
310 user_id = user_pw = NULL;
311 fail_unless (res);
312 }
313
314 GST_END_TEST;
315
GST_START_TEST(test_bad_password_basic_auth)316 GST_START_TEST (test_bad_password_basic_auth)
317 {
318 gboolean res;
319
320 user_id = good_user;
321 user_pw = bad_pw;
322 res = run_test (FALSE, basic_auth_path, 401);
323 GST_DEBUG ("Basic Auth user %s password %s res = %d", user_id, user_pw, res);
324 user_id = user_pw = NULL;
325 fail_unless (res);
326 }
327
328 GST_END_TEST;
329
GST_START_TEST(test_good_user_digest_auth)330 GST_START_TEST (test_good_user_digest_auth)
331 {
332 gboolean res;
333
334 user_id = good_user;
335 user_pw = good_pw;
336 res = run_test (FALSE, digest_auth_path, 0);
337 GST_DEBUG ("Digest Auth user %s password %s res = %d", user_id, user_pw, res);
338 user_id = user_pw = NULL;
339 fail_unless (res);
340 }
341
342 GST_END_TEST;
343
GST_START_TEST(test_bad_user_digest_auth)344 GST_START_TEST (test_bad_user_digest_auth)
345 {
346 gboolean res;
347
348 user_id = bad_user;
349 user_pw = good_pw;
350 res = run_test (FALSE, digest_auth_path, 401);
351 GST_DEBUG ("Digest Auth user %s password %s res = %d", user_id, user_pw, res);
352 user_id = user_pw = NULL;
353 fail_unless (res);
354 }
355
356 GST_END_TEST;
357
GST_START_TEST(test_bad_password_digest_auth)358 GST_START_TEST (test_bad_password_digest_auth)
359 {
360 gboolean res;
361
362 user_id = good_user;
363 user_pw = bad_pw;
364 res = run_test (FALSE, digest_auth_path, 401);
365 GST_DEBUG ("Digest Auth user %s password %s res = %d", user_id, user_pw, res);
366 user_id = user_pw = NULL;
367 fail_unless (res);
368 }
369
370 GST_END_TEST;
371
372 static gboolean icy_caps = FALSE;
373
374 static void
got_buffer(GstElement * fakesink,GstBuffer * buf,GstPad * pad,gpointer user_data)375 got_buffer (GstElement * fakesink, GstBuffer * buf, GstPad * pad,
376 gpointer user_data)
377 {
378 GstStructure *s;
379 GstCaps *caps;
380
381 /* Caps can be anything if we don't except icy caps */
382 if (!icy_caps)
383 return;
384
385 /* Otherwise they _must_ be "application/x-icy" */
386 caps = gst_pad_get_current_caps (pad);
387 fail_unless (caps != NULL);
388 s = gst_caps_get_structure (caps, 0);
389 fail_unless_equals_string (gst_structure_get_name (s), "application/x-icy");
390 gst_caps_unref (caps);
391 }
392
GST_START_TEST(test_icy_stream)393 GST_START_TEST (test_icy_stream)
394 {
395 GstElement *pipe, *src, *sink;
396
397 GstMessage *msg;
398
399 pipe = gst_pipeline_new (NULL);
400
401 src = gst_element_factory_make ("souphttpsrc", NULL);
402 fail_unless (src != NULL);
403
404 sink = gst_element_factory_make ("fakesink", NULL);
405 fail_unless (sink != NULL);
406 g_object_set (sink, "signal-handoffs", TRUE, NULL);
407 g_signal_connect (sink, "handoff", G_CALLBACK (got_buffer), NULL);
408
409 gst_bin_add (GST_BIN (pipe), src);
410 gst_bin_add (GST_BIN (pipe), sink);
411 fail_unless (gst_element_link (src, sink));
412
413 /* Radionomy Hot40Music shoutcast stream */
414 g_object_set (src, "location",
415 "http://streaming.radionomy.com:80/Hot40Music", NULL);
416
417 /* EOS after the first buffer */
418 g_object_set (src, "num-buffers", 1, NULL);
419 icy_caps = TRUE;
420 gst_element_set_state (pipe, GST_STATE_PLAYING);
421 msg = gst_bus_poll (GST_ELEMENT_BUS (pipe),
422 GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
423
424 switch (GST_MESSAGE_TYPE (msg)) {
425 case GST_MESSAGE_EOS:
426 GST_DEBUG ("success, we're done here");
427 gst_message_unref (msg);
428 break;
429 case GST_MESSAGE_ERROR:{
430 GError *err = NULL;
431
432 gst_message_parse_error (msg, &err, NULL);
433 GST_INFO ("Error with ICY mp3 shoutcast stream: %s", err->message);
434 gst_message_unref (msg);
435 g_clear_error (&err);
436 break;
437 }
438 default:
439 break;
440 }
441
442 icy_caps = FALSE;
443
444 gst_element_set_state (pipe, GST_STATE_NULL);
445 gst_object_unref (pipe);
446 }
447
448 GST_END_TEST;
449
450 static Suite *
souphttpsrc_suite(void)451 souphttpsrc_suite (void)
452 {
453 TCase *tc_chain, *tc_internet;
454 Suite *s;
455
456 /* we don't support exceptions from the proxy, so just unset the environment
457 * variable - in case it's set in the test environment it would otherwise
458 * prevent us from connecting to localhost (like jenkins.qa.ubuntu.com) */
459 g_unsetenv ("http_proxy");
460
461 s = suite_create ("souphttpsrc");
462 tc_chain = tcase_create ("general");
463 tc_internet = tcase_create ("internet");
464
465 suite_add_tcase (s, tc_chain);
466 tcase_add_test (tc_chain, test_first_buffer_has_offset);
467 tcase_add_test (tc_chain, test_redirect_yes);
468 tcase_add_test (tc_chain, test_redirect_no);
469 tcase_add_test (tc_chain, test_not_found);
470 tcase_add_test (tc_chain, test_forbidden);
471 tcase_add_test (tc_chain, test_cookies);
472 tcase_add_test (tc_chain, test_good_user_basic_auth);
473 tcase_add_test (tc_chain, test_bad_user_basic_auth);
474 tcase_add_test (tc_chain, test_bad_password_basic_auth);
475 tcase_add_test (tc_chain, test_good_user_digest_auth);
476 tcase_add_test (tc_chain, test_bad_user_digest_auth);
477 tcase_add_test (tc_chain, test_bad_password_digest_auth);
478 tcase_add_test (tc_chain, test_https);
479
480 suite_add_tcase (s, tc_internet);
481 tcase_set_timeout (tc_internet, 250);
482 tcase_add_test (tc_internet, test_icy_stream);
483
484 return s;
485 }
486
487 GST_CHECK_MAIN (souphttpsrc);
488
489 static void
do_get(SoupMessage * msg,const char * path)490 do_get (SoupMessage * msg, const char *path)
491 {
492 gboolean send_error_doc = FALSE;
493 char *uri;
494
495 int buflen = 4096;
496
497 SoupStatus status = SOUP_STATUS_OK;
498
499 uri = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
500 GST_DEBUG ("request: \"%s\"", uri);
501
502 if (!strcmp (path, "/301"))
503 status = SOUP_STATUS_MOVED_PERMANENTLY;
504 else if (!strcmp (path, "/302"))
505 status = SOUP_STATUS_MOVED_TEMPORARILY;
506 else if (!strcmp (path, "/307"))
507 status = SOUP_STATUS_TEMPORARY_REDIRECT;
508 else if (!strcmp (path, "/403"))
509 status = SOUP_STATUS_FORBIDDEN;
510 else if (!strcmp (path, "/404"))
511 status = SOUP_STATUS_NOT_FOUND;
512 else if (!strcmp (path, "/404-with-data")) {
513 status = SOUP_STATUS_NOT_FOUND;
514 send_error_doc = TRUE;
515 }
516
517 if (SOUP_STATUS_IS_REDIRECTION (status)) {
518 char *redir_uri;
519
520 redir_uri = g_strdup_printf ("%s-redirected", uri);
521 soup_message_headers_append (msg->response_headers, "Location", redir_uri);
522 g_free (redir_uri);
523 }
524 if (status != (SoupStatus) SOUP_STATUS_OK && !send_error_doc)
525 goto leave;
526
527 if (msg->method == SOUP_METHOD_GET) {
528 char *buf;
529
530 buf = g_malloc (buflen);
531 memset (buf, 0, buflen);
532 soup_message_body_append (msg->response_body, SOUP_MEMORY_TAKE,
533 buf, buflen);
534 } else { /* msg->method == SOUP_METHOD_HEAD */
535
536 char *length;
537
538 /* We could just use the same code for both GET and
539 * HEAD. But we'll optimize and avoid the extra
540 * malloc.
541 */
542 length = g_strdup_printf ("%lu", (gulong) buflen);
543 soup_message_headers_append (msg->response_headers,
544 "Content-Length", length);
545 g_free (length);
546 }
547
548 leave:
549 soup_message_set_status (msg, status);
550 g_free (uri);
551 }
552
553 static void
print_header(const char * name,const char * value,gpointer data)554 print_header (const char *name, const char *value, gpointer data)
555 {
556 GST_DEBUG ("header: %s: %s", name, value);
557 }
558
559 static void
server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * context,gpointer data)560 server_callback (SoupServer * server, SoupMessage * msg,
561 const char *path, GHashTable * query,
562 SoupClientContext * context, gpointer data)
563 {
564 GST_DEBUG ("%s %s HTTP/1.%d", msg->method, path,
565 soup_message_get_http_version (msg));
566 soup_message_headers_foreach (msg->request_headers, print_header, NULL);
567 if (msg->request_body->length)
568 GST_DEBUG ("%s", msg->request_body->data);
569
570 if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD)
571 do_get (msg, path);
572 else
573 soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
574
575 GST_DEBUG (" -> %d %s", msg->status_code, msg->reason_phrase);
576 }
577
578 static guint
get_port_from_server(SoupServer * server)579 get_port_from_server (SoupServer * server)
580 {
581 GSList *uris;
582 guint port;
583
584 uris = soup_server_get_uris (server);
585 g_assert (g_slist_length (uris) == 1);
586 port = soup_uri_get_port (uris->data);
587 g_slist_free_full (uris, (GDestroyNotify) soup_uri_free);
588
589 return port;
590 }
591
592 static SoupServer *
run_server(gboolean use_https)593 run_server (gboolean use_https)
594 {
595 SoupServer *server = soup_server_new (NULL, NULL);
596 SoupServerListenOptions listen_flags = 0;
597 guint port;
598
599
600 if (use_https) {
601 GTlsBackend *backend = g_tls_backend_get_default ();
602 GError *err = NULL;
603
604 if (backend == NULL || !g_tls_backend_supports_tls (backend)) {
605 GST_INFO ("No TLS support");
606 g_object_unref (server);
607 return NULL;
608 }
609
610 if (!soup_server_set_ssl_cert_file (server, ssl_cert_file, ssl_key_file,
611 &err)) {
612 GST_INFO ("Failed to load certificate: %s", err->message);
613 g_object_unref (server);
614 g_error_free (err);
615 return NULL;
616 }
617
618 listen_flags |= SOUP_SERVER_LISTEN_HTTPS;
619 }
620
621 soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
622
623 {
624 SoupAuthDomain *domain;
625
626 domain = soup_auth_domain_basic_new (SOUP_AUTH_DOMAIN_REALM, realm,
627 SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, basic_auth_cb,
628 SOUP_AUTH_DOMAIN_ADD_PATH, basic_auth_path, NULL);
629 soup_server_add_auth_domain (server, domain);
630 g_object_unref (domain);
631
632 domain = soup_auth_domain_digest_new (SOUP_AUTH_DOMAIN_REALM, realm,
633 SOUP_AUTH_DOMAIN_DIGEST_AUTH_CALLBACK, digest_auth_cb,
634 SOUP_AUTH_DOMAIN_ADD_PATH, digest_auth_path, NULL);
635 soup_server_add_auth_domain (server, domain);
636 g_object_unref (domain);
637 }
638
639 {
640 GSocketAddress *address;
641 GError *err = NULL;
642
643 address =
644 g_inet_socket_address_new_from_string ("0.0.0.0",
645 SOUP_ADDRESS_ANY_PORT);
646 soup_server_listen (server, address, listen_flags, &err);
647 g_object_unref (address);
648
649 if (err) {
650 GST_ERROR ("Failed to start %s server: %s",
651 use_https ? "HTTPS" : "HTTP", err->message);
652 g_object_unref (server);
653 g_error_free (err);
654 return NULL;
655 }
656 }
657
658 port = get_port_from_server (server);
659 GST_DEBUG ("%s server listening on port %u", use_https ? "HTTPS" : "HTTP",
660 port);
661
662 /* check if we can connect to our local http server */
663 {
664 GSocketConnection *conn;
665 GSocketClient *client;
666
667 client = g_socket_client_new ();
668 g_socket_client_set_timeout (client, 2);
669 conn =
670 g_socket_client_connect_to_host (client, "127.0.0.1", port, NULL, NULL);
671 if (conn == NULL) {
672 GST_INFO ("Couldn't connect to 127.0.0.1:%u", port);
673 g_object_unref (client);
674 g_object_unref (server);
675 return NULL;
676 }
677
678 g_object_unref (conn);
679 g_object_unref (client);
680 }
681
682 return server;
683 }
684