From 6c55a332d26308dca660a87b1f2d4d2d8d36080a Mon Sep 17 00:00:00 2001 From: Derek Dai Date: Tue, 14 Feb 2017 10:09:40 +0800 Subject: [PATCH] miracle-wfdctl: refactoring to remove repeated snippets and centralize the dispatching of request and reply --- src/ctl/CMakeLists.txt | 1 + src/ctl/ctl.h | 52 ++- src/ctl/wfd-dbus.c | 8 +- src/ctl/wfd-dbus.h | 1 + src/ctl/wfd-out-session.c | 503 ++++++++++++++++++++++++++ src/ctl/wfd-session.c | 726 +++++++++++++++----------------------- src/ctl/wfd-session.h | 91 +++++ src/ctl/wfd-sink.c | 16 +- src/ctl/wfdctl.c | 14 +- 9 files changed, 915 insertions(+), 497 deletions(-) create mode 100644 src/ctl/wfd-out-session.c create mode 100644 src/ctl/wfd-session.h diff --git a/src/ctl/CMakeLists.txt b/src/ctl/CMakeLists.txt index 8d6bbf2..e9d3af5 100644 --- a/src/ctl/CMakeLists.txt +++ b/src/ctl/CMakeLists.txt @@ -52,6 +52,7 @@ set(miracle-wfdctl_SRCS ctl-cli.c wfd-sink.c wfd-dbus.c wfd-session.c + wfd-out-session.c wfdctl.c wfd.c) diff --git a/src/ctl/ctl.h b/src/ctl/ctl.h index 668c451..94296fc 100644 --- a/src/ctl/ctl.h +++ b/src/ctl/ctl.h @@ -137,31 +137,20 @@ bool ctl_sink_is_connected(struct ctl_sink *s); bool ctl_sink_is_closed(struct ctl_sink *s); /* wfd session */ -#define wfd_session(s) (assert(s), (struct wfd_session *) (s)) +#define wfd_session(s) ((struct wfd_session *) (s)) #define wfd_is_session(s) ( \ (s) && \ (WFD_SESSION_DIR_OUT == wfd_session(s)->dir || \ WFD_SESSION_DIR_IN == wfd_session(s)->dir) \ ) -#define wfd_is_out_session(s) (WFD_SESSION_DIR_OUT == wfd_session(s)->dir) -#define wfd_is_in_session(s) (WFD_SESSION_DIR_IN == wfd_session(s)->dir) -#define wfd_session_to_htable(s) (&(s)->id) -#define wfd_session_from_htable(s) (shl_htable_entry(s, struct wfd_session, id)) +#define wfd_session_has_id(s) (0 < wfd_session_get_id(s)) +#define wfd_is_out_session(s) (WFD_SESSION_DIR_OUT == wfd_session_get_dir(s)) +#define wfd_is_in_session(s) (WFD_SESSION_DIR_IN == wfd_session_get_dir(s)) #define _wfd_session_free_ _shl_cleanup_(wfd_session_freep) struct wfd_sink; -struct wfd_out_session; - -enum wfd_session_state -{ - WFD_SESSION_STATE_NULL, - WFD_SESSION_STATE_CONNECTING, - WFD_SESSION_STATE_CAPS_EXCHAING, - WFD_SESSION_STATE_SETING_UP, - WFD_SESSION_STATE_PLAYING, - WFD_SESSION_STATE_PAUSED, - WFD_SESSION_STATE_TEARING_DOWN, -}; +struct wfd_session; +struct rtsp_dispatch_entry; enum wfd_session_dir { @@ -169,29 +158,32 @@ enum wfd_session_dir WFD_SESSION_DIR_IN, }; -struct wfd_session +enum wfd_session_state { - enum wfd_session_dir dir; - enum wfd_session_state state; - uint64_t id; - char *url; - struct rtsp *rtsp; - - bool hup: 1; + WFD_SESSION_STATE_NULL, + WFD_SESSION_STATE_CONNECTING, + WFD_SESSION_STATE_CAPS_EXCHAING, + WFD_SESSION_STATE_ESTABLISHED, + WFD_SESSION_STATE_SETING_UP, + WFD_SESSION_STATE_PLAYING, + WFD_SESSION_STATE_PAUSED, + WFD_SESSION_STATE_TEARING_DOWN, }; int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink); int wfd_session_start(struct wfd_session *s, uint64_t id); +enum wfd_session_dir wfd_session_get_dir(struct wfd_session *s); +uint64_t wfd_session_get_id(struct wfd_session *s); +const char * wfd_session_get_url(struct wfd_session *s); +enum wfd_session_state wfd_session_get_state(struct wfd_session *s); int wfd_session_is_started(struct wfd_session *s); void wfd_session_end(struct wfd_session *s); void wfd_session_free(struct wfd_session *s); uint64_t wfd_session_get_id(struct wfd_session *s); struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s); -static inline void wfd_session_freep(struct wfd_session **s) -{ - wfd_session_free(*s); - *s = NULL; -} +void wfd_session_freep(struct wfd_session **s); +uint64_t * wfd_session_to_htable(struct wfd_session *s); +struct wfd_session * wfd_session_from_htable(uint64_t *e); /* wfd sink */ #define _wfd_sink_free_ _shl_cleanup_(wfd_sink_freep) diff --git a/src/ctl/wfd-dbus.c b/src/ctl/wfd-dbus.c index e49a876..7734633 100644 --- a/src/ctl/wfd-dbus.c +++ b/src/ctl/wfd-dbus.c @@ -93,7 +93,7 @@ static inline int wfd_dbus_get_sink_path(struct wfd_sink *s, char **out) static inline int wfd_dbus_get_session_path(struct wfd_session *s, char **out) { char buf[64]; - int r = snprintf(buf, sizeof(buf), "%" PRIu64, s->id); + int r = snprintf(buf, sizeof(buf), "%" PRIu64, wfd_session_get_id(s)); if(0 > r) { return r; } @@ -476,7 +476,7 @@ static int wfd_dbus_session_get_sink(sd_bus *bus, _shl_free_ char *sink_path; int r; - if(s->dir != WFD_SESSION_DIR_OUT) { + if(wfd_session_get_id(s) != WFD_SESSION_DIR_OUT) { return 0; } @@ -498,7 +498,7 @@ static int wfd_dbus_session_get_url(sd_bus *bus, sd_bus_error *ret_error) { struct wfd_session *s = userdata; - return sd_bus_message_append(reply, "s", s->url); + return sd_bus_message_append(reply, "s", wfd_session_get_url(s)); } static int wfd_dbus_session_get_state(sd_bus *bus, @@ -510,7 +510,7 @@ static int wfd_dbus_session_get_state(sd_bus *bus, sd_bus_error *ret_error) { struct wfd_session *s = userdata; - return sd_bus_message_append(reply, "i", s->state); + return sd_bus_message_append(reply, "i", wfd_session_get_state(s)); } int _wfd_fn_session_properties_changed(struct wfd_session *s, char **names) diff --git a/src/ctl/wfd-dbus.h b/src/ctl/wfd-dbus.h index c15a6c3..5d77764 100644 --- a/src/ctl/wfd-dbus.h +++ b/src/ctl/wfd-dbus.h @@ -34,6 +34,7 @@ struct wfd_dbus; struct wfd_session; +struct wfd_sink; struct wfd_dbus * wfd_dbus_get(); int wfd_dbus_new(struct wfd_dbus **out, sd_event *loop, sd_bus *bus); diff --git a/src/ctl/wfd-out-session.c b/src/ctl/wfd-out-session.c new file mode 100644 index 0000000..09b3a4b --- /dev/null +++ b/src/ctl/wfd-out-session.c @@ -0,0 +1,503 @@ +/* + * MiracleCast - Wifi-Display/Miracast Implementation + * + * Copyright (c) 2013-2014 David Herrmann + * + * MiracleCast is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * MiracleCast is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MiracleCast; If not, see . + */ +#define LOG_SUBSYSTEM "wfd-session" + +#include +#include "wfd-session.h" +#include "shl_log.h" +#include "rtsp.h" + +struct wfd_out_session +{ + struct wfd_session parent; + struct wfd_sink *sink; + int fd; + + bool sink_has_video: 1; + bool sink_has_audio: 1; + bool sink_has_pref_disp_mode: 1; + bool sink_has_3d: 1; + bool sink_has_uibc: 1; +}; + +static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[]; + +int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink) +{ + struct wfd_out_session *s = calloc(1, sizeof(struct wfd_out_session)); + if(!s) { + return -ENOMEM; + } + + wfd_session(s)->dir = WFD_SESSION_DIR_OUT; + wfd_session(s)->rtsp_disp_tbl = out_session_rtsp_disp_tbl; + s->fd = -1; + s->sink = sink; + + *out = wfd_session(s); + + return 0; +} + +struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s) +{ + assert(wfd_is_out_session(s)); + + return wfd_out_session(s)->sink; +} + +static int wfd_out_session_handle_io(struct wfd_session *s, + int error, + int *out_fd) +{ + socklen_t len; + struct sockaddr_storage addr; + _shl_close_ int fd = -1; + struct wfd_out_session *os = wfd_out_session(s); + + log_debug("accepting incoming RTSP connection\n"); + + len = sizeof(addr); + fd = accept4(os->fd, + (struct sockaddr *) &addr, + &len, + SOCK_NONBLOCK | SOCK_CLOEXEC); + if(0 > fd) { + return -errno; + } + + log_info("RTSP connection established"); + + //wfd_session_set_state(s, WFD_SESSION_STATE_CAPS_EXCHAING); + + close(os->fd); + os->fd = -1; + *out_fd = fd; + fd = -1; + + return 0; +} + +static int wfd_out_session_initiate_io(struct wfd_session *s, + int *out_fd, + uint32_t *out_mask) +{ + struct wfd_out_session *os = wfd_out_session(s); + union wfd_sube sube; + struct sockaddr_in addr = {}; + struct ctl_peer *p = os->sink->peer; + _shl_close_ int fd = -1; + int enable; + int r; + + if(!os->sink->peer->connected) { + log_info("peer not connected yet"); + return -ENOTCONN; + } + + r = wfd_sube_parse_with_id(WFD_SUBE_ID_DEVICE_INFO, + p->l->wfd_subelements, + &sube); + if(0 > r) { + log_warning("WfdSubelements property of link must be set before P2P scan"); + return -EINVAL; + } + else if(WFD_SUBE_ID_DEVICE_INFO != sube.id) { + return -EAFNOSUPPORT; + } + + if(-1 != os->fd) { + return EINPROGRESS; + } + + r = inet_pton(AF_INET, p->local_address, &addr.sin_addr); + if (!r) { + return -EAFNOSUPPORT; + } + addr.sin_family = AF_INET; + addr.sin_port = htons(wfd_sube_device_get_rtsp_port(&sube)); + + fd = socket(addr.sin_family, + SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, + 0); + if (0 > fd) { + return fd; + } + + enable = true; + r = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable)); + if(0 > r) { + return r; + } + + r = bind(fd, (struct sockaddr*) &addr, sizeof(addr)); + if (0 > r) { + return r; + } + + r = listen(fd, 10); + if (0 > r) { + return r; + } + + log_trace("socket listening on %s:%hu", + p->local_address, + wfd_sube_device_get_rtsp_port(&sube)); + + os->fd = fd; + *out_fd = fd; + fd = -1; + *out_mask = EPOLLIN; + + return 0; +} + +static void wfd_out_session_end(struct wfd_session *s) +{ + struct wfd_out_session *os = wfd_out_session(s); + if(0 <= os->fd) { + close(os->fd); + os->fd = -1; + } +} + +static void wfd_out_session_distruct(struct wfd_session *s) +{ +} + +static int wfd_out_session_initiate_request(struct wfd_session *s) +{ + return wfd_session_request(s, RTSP_M1_REQUEST_SINK_OPTIONS); +} + +/*static int wfd_out_session_handle_get_parameter_reply(struct rtsp *bus,*/ + /*struct rtsp_message *m,*/ + /*void *userdata)*/ +/*{*/ + /*struct wfd_session *s = userdata;*/ + + /*log_debug("received GET_PARAMETER reply (M3): %s\n",*/ + /*(char *) rtsp_message_get_raw(m));*/ + /*if(RTSP_CODE_OK != rtsp_message_get_code(m)) {*/ + /*wfd_session_end(wfd_session(userdata));*/ + /*return -EPROTO;*/ + /*}*/ + + /*return 0;*/ +/*}*/ + +/*static int wfd_out_session_send_get_parameter(sd_event_source *source,*/ + /*void *userdata)*/ +/*{*/ + /*struct wfd_session *s = userdata;*/ + /*_rtsp_message_unref_ struct rtsp_message *m = NULL;*/ + /*int r = rtsp_message_new_request(s->rtsp,*/ + /*&m,*/ + /*"GET_PARAMETER",*/ + /*s->url);*/ + /*if (0 > r) {*/ + /*goto error;*/ + /*}*/ + + /*r = rtsp_message_append(m, "{&}",*/ + /*"wfd_video_formats\n"*/ + /*"wfd_audio_codecs\n"*/ + /*"wfd_client_rtp_ports"*/ + /*//"wfd_uibc_capability"*/ + /*);*/ + /*if (0 > r) {*/ + /*goto error;*/ + /*}*/ + + /*rtsp_message_seal(m);*/ + + /*r = rtsp_call_async(s->rtsp,*/ + /*m,*/ + /*wfd_out_session_handle_get_parameter_reply,*/ + /*s,*/ + /*0,*/ + /*NULL);*/ + /*if (r < 0) {*/ + /*goto error;*/ + /*}*/ + + /*log_debug("Sending GET_PARAMETER (M3): %s\n",*/ + /*(char *) rtsp_message_get_raw(m));*/ + + /*return 0;*/ + +/*error:*/ + /*wfd_session_end(s);*/ + + /*return r;*/ +/*}*/ + +static bool find_strv(const char *str, char **strv) +{ + while(strv) { + if(!strcmp(str, *strv)) { + return true; + } + ++strv; + } + + return false; +} + +static int wfd_out_session_handle_options_request(struct wfd_session *s, + struct rtsp_message *req, + struct rtsp_message **out_rep) +{ + const char *require; + _rtsp_message_unref_ struct rtsp_message *rep = NULL; + int r; + + r = rtsp_message_read(req, "", "Require", &require); + if(0 > r) { + return r; + } + + if(strcmp("org.wfa.wfd1.0", require)) { + return rtsp_message_new_reply_for(req, + out_rep, + RTSP_CODE_OPTION_NOT_SUPPORTED, + "Invalid specification"); + } + + r = rtsp_message_new_reply_for(req, + &rep, + RTSP_CODE_OK, + NULL); + if(0 > r) { + return r; + } + + r = rtsp_message_append(rep, + "", + "Public", "org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER"); + if(0 > r) { + return r; + } + + *out_rep = rep; + rep = NULL; + + return 0; +} + +static int wfd_out_session_check_options_reply(struct wfd_session *s, + struct rtsp_message *m) +{ + int r; + const char *public; + char *methods[4]; + + r = rtsp_message_read(m, "<&>", "Public", &public); + if(0 > r) { + return r; + } + + r = sscanf(public, "%m[^,], %m[^,], %ms", &methods[0], &methods[1], &methods[2]); + if(3 != r) { + return -EPROTO; + } + + methods[3] = NULL; + r = find_strv("org.wfa.wfd1.0", methods) && + find_strv("SET_PARAMETER", methods) && + find_strv("GET_PARAMETER", methods); + free(methods[2]); + free(methods[1]); + free(methods[0]); + if(!r) { + return -EPROTO; + } + + return 0; +} + +static int wfd_out_session_request_options(struct wfd_session *s, + struct rtsp_message **out) +{ + _rtsp_message_unref_ struct rtsp_message *m = NULL; + int r = rtsp_message_new_request(s->rtsp, + &m, + "OPTIONS", "*"); + if (0 > r) { + return r; + } + + r = rtsp_message_append(m, + "", + "Require", "org.wfa.wfd1.0"); + if (0 > r) { + return r; + } + + *out = m; + m = NULL; + + return 0; +} + +/*static int wfd_out_session_handle_options_request(struct rtsp *bus,*/ + /*struct rtsp_message *request,*/ + /*struct wfd_session *s)*/ +/*{*/ +/*}*/ + +static int wfd_out_session_handle_play_reply(struct rtsp *bus, + struct rtsp_message *m, + void *userdata) +{ + /*struct wfd_session *s = userdata;*/ + /*log_trace("received SETUP (M5) reply: %s",*/ + /*(char *) rtsp_message_get_raw(m));*/ + + /*wfd_out_session_send_play(s);*/ + + return 0; +} + +static int wfd_out_session_send_play(struct wfd_session *s) +{ + return 0; +} + +static int wfd_out_session_handle_setup_reply(struct rtsp *bus, + struct rtsp_message *m, + void *userdata) +{ + /*struct wfd_session *s = userdata;*/ + /*log_trace("received SETUP (M5) reply: %s",*/ + /*(char *) rtsp_message_get_raw(m));*/ + + /*wfd_out_session_send_play(s);*/ + + return 0; +} + +static int wfd_out_session_handle_set_parameter_reply(struct rtsp *bus, + struct rtsp_message *m, + void *userdata) +{ + /*struct wfd_session *s = userdata;*/ + /*log_trace("received SET_PARAMETER (M4) reply: %s",*/ + /*(char *) rtsp_message_get_raw(m));*/ + + /*wfd_out_session_send_setup(s);*/ + + return 0; +} + +static int wfd_out_session_send_set_parameter_request(struct wfd_session *s) +{ + /*_rtsp_message_unref_ struct rtsp_message *req;*/ + int r; + /*const static char tmp[] =*/ + /*"wfd_video_formats: 38 00 02 10 00000080 00000000 00000000 00 0000 0000 11 none none\n"*/ + /*//"wfd_audio_codecs: AAC 00000001 00\n"*/ + /*//"wfd_uibc_capability: input_category_list=GENERIC\n;generic_cap_list=SingleTouch;hidc_cap_list=none;port=5100\n"*/ + /*//"wfd_uibc_setting: disable\n"*/ + /*"wfd_presentation_URL: %s/streamid=0 none\n"*/ + /*"wfd_client_rtp_ports: %s %d %d mode=play";*/ + + /*r = rtsp_message_new_request(s->rtsp,*/ + /*&req,*/ + /*"SET_PARAMETER",*/ + /*s->url);*/ + /*if (r < 0) {*/ + /*cli_vERR(r);*/ + /*goto error;*/ + /*}*/ + + /*snprintf(buf, sizeof(buf), tmp, s->url, s->sink.rtp_ports.profile,*/ + /*s->sink.rtp_ports.port0, s->sink.rtp_ports.port1);*/ + + /*r = rtsp_message_append(req, "{&}", buf);*/ + /*if (r < 0) {*/ + /*cli_vERR(r);*/ + /*goto error;*/ + /*}*/ + + /*rtsp_message_seal(req);*/ + /*cli_debug("OUTGOING (M4): %s\n", rtsp_message_get_raw(req));*/ + + /*r = rtsp_call_async(s->rtsp, req, src_set_parameter_rep_fn, s, 0, NULL);*/ + /*if (r < 0) {*/ + /*cli_vERR(r);*/ + /*goto error;*/ + /*}*/ + + /*return 0;*/ + +/*error:*/ + /*wfd_src_close(s);*/ + /*wfd_fn_src_disconnected(s);*/ + + return r; +} + +const struct wfd_session_vtable session_vtables[] = { + [WFD_SESSION_DIR_OUT] = { + .initiate_io = wfd_out_session_initiate_io, + .handle_io = wfd_out_session_handle_io, + .initiate_request = wfd_out_session_initiate_request, + .end = wfd_out_session_end, + .distruct = wfd_out_session_distruct, + } +}; + +static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[] = { + [RTSP_M1_REQUEST_SINK_OPTIONS] = { + .request = wfd_out_session_request_options, + .handle_reply = wfd_out_session_check_options_reply + }, + [RTSP_M2_REQUEST_SRC_OPTIONS] = { + .handle_request = wfd_out_session_handle_options_request + }, + [RTSP_M3_GET_PARAMETER] = { + }, + [RTSP_M4_SET_PARAMETER] = { + }, + [RTSP_M5_TRIGGER] = { + }, + [RTSP_M6_SETUP] = { + }, + [RTSP_M7_PLAY] = { + }, + [RTSP_M8_TEARDOWN] = { + }, + [RTSP_M9_PAUSE] = { + }, + [RTSP_M10_SET_ROUTE] = { + }, + [RTSP_M11_SET_CONNECTOR_TYPE] = { + }, + [RTSP_M12_SET_STANDBY] = { + }, + [RTSP_M13_REQUEST_IDR] = { + }, + [RTSP_M14_ESTABLISH_UIBC] = { + }, + [RTSP_M15_ENABLE_UIBC] = { + }, + [RTSP_M16_KEEPALIVE] = { + }, +}; diff --git a/src/ctl/wfd-session.c b/src/ctl/wfd-session.c index 6885397..a1eb99c 100644 --- a/src/ctl/wfd-session.c +++ b/src/ctl/wfd-session.c @@ -18,68 +18,49 @@ */ #define LOG_SUBSYSTEM "wfd-session" -#include -#include "ctl.h" #include "rtsp.h" #include "wfd-dbus.h" +#include "wfd-session.h" +#include "shl_macro.h" -#define wfd_out_session(s) (assert(wfd_is_out_session(s)), (struct wfd_out_session *) (s)) -#define wfd_in_session(s) (assert(wfd_is_in_session(s)), (struct wfd_in_session *) (s)) +#define wfd_message_id_valide(id) ( \ + (id) >= RTSP_M1_REQUEST_SINK_OPTIONS && \ + (id) <= RTSP_M16_KEEPALIVE \ +) -struct wfd_session_vtable +static const char *rtsp_message_names[]; +extern const struct wfd_session_vtable session_vtables[]; +extern const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[]; + +static inline int wfd_session_do_request(struct wfd_session *s, + enum rtsp_message_id id, + struct rtsp_message **out) { - int (*start)(struct wfd_session *s); - void (*end)(struct wfd_session *s); - void (*distruct)(struct wfd_session *s); -}; + assert(wfd_message_id_valide(id)); + assert(s->rtsp_disp_tbl[id].request); -struct wfd_out_session -{ - struct wfd_session parent; - struct wfd_sink *sink; - int fd; - - bool sink_has_video: 1; - bool sink_has_audio: 1; - bool sink_has_pref_disp_mode: 1; - bool sink_has_3d: 1; - bool sink_has_uibc: 1; -}; - -static void wfd_session_set_state(struct wfd_session *s, enum wfd_session_state state); -static int wfd_out_session_start(struct wfd_session *s); -static void wfd_out_session_end(struct wfd_session *s); -static void wfd_out_session_distruct(struct wfd_session *s); - -static const struct wfd_session_vtable session_vtables[] = { - [WFD_SESSION_DIR_OUT] = { - .start = wfd_out_session_start, - .end = wfd_out_session_end, - .distruct = wfd_out_session_distruct, - } -}; - -int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink) -{ - struct wfd_out_session *s = calloc(1, sizeof(struct wfd_out_session)); - if(!s) { - return -ENOMEM; - } - - wfd_session(s)->dir = WFD_SESSION_DIR_OUT; - s->fd = -1; - s->sink = sink; - - *out = wfd_session(s); - - return 0; + return (*s->rtsp_disp_tbl[id].request)(s, out); } -struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s) +static inline int wfd_session_do_handle_request(struct wfd_session *s, + enum rtsp_message_id id, + struct rtsp_message *req, + struct rtsp_message **out_rep) { - assert(wfd_is_out_session(s)); + assert(wfd_message_id_valide(id)); + assert(s->rtsp_disp_tbl[id].handle_request); - return wfd_out_session(s)->sink; + return (*s->rtsp_disp_tbl[id].handle_request)(s, req, out_rep); +} + +static inline int wfd_session_do_handle_reply(struct wfd_session *s, + enum rtsp_message_id id, + struct rtsp_message *m) +{ + assert(wfd_message_id_valide(id)); + assert(s->rtsp_disp_tbl[id].handle_reply); + + return (*s->rtsp_disp_tbl[id].handle_reply)(s, m); } uint64_t wfd_session_get_id(struct wfd_session *s) @@ -87,6 +68,11 @@ uint64_t wfd_session_get_id(struct wfd_session *s) return s->id; } +enum wfd_session_state wfd_session_get_state(struct wfd_session *s) +{ + return s->state; +} + static void wfd_session_set_state(struct wfd_session *s, enum wfd_session_state state) { @@ -99,26 +85,6 @@ static void wfd_session_set_state(struct wfd_session *s, wfd_fn_session_properties_changed(s, "State"); } -int wfd_session_start(struct wfd_session *s, uint64_t id) -{ - int r; - - assert(wfd_is_session(s)); - assert(id); - - if(wfd_session_is_started(s)) { - return -EINPROGRESS; - } - - r = (*session_vtables[s->dir].start)(s); - if(0 <= r) { - s->id = id; - wfd_session_set_state(s, WFD_SESSION_STATE_CONNECTING); - } - - return r; -} - int wfd_session_is_started(struct wfd_session *s) { assert(wfd_is_session(s)); @@ -130,7 +96,7 @@ void wfd_session_end(struct wfd_session *s) { assert(wfd_is_session(s)); - if(!wfd_session_is_started(s)) { + if(WFD_SESSION_STATE_NULL == s->state) { return; } @@ -148,8 +114,6 @@ void wfd_session_end(struct wfd_session *s) s->url = NULL; } - s->hup = false; - wfd_session_set_state(s, WFD_SESSION_STATE_NULL); if(wfd_is_out_session(s)) { @@ -159,20 +123,16 @@ void wfd_session_end(struct wfd_session *s) void wfd_session_free(struct wfd_session *s) { - enum wfd_session_dir dir; - - if(!wfd_is_session(s)) { + if(wfd_session_is_destructed(s)) { return; } - if(wfd_is_out_session(s)) { - wfd_out_session(s)->sink = NULL; - } + s->destructed = true; wfd_session_end(s); - if(session_vtables[dir].distruct) { - (*session_vtables[dir].distruct)(s); + if(session_vtables[s->dir].distruct) { + (*session_vtables[s->dir].distruct)(s); } free(s); @@ -188,7 +148,17 @@ const char * wfd_session_get_url(struct wfd_session *s) return s->url; } -static int wfd_session_gen_url(struct wfd_session *s, const char *addr) +uint64_t * wfd_session_to_htable(struct wfd_session *s) +{ + return &s->id; +} + +struct wfd_session * wfd_session_from_htable(uint64_t *e) +{ + return shl_htable_entry(e, struct wfd_session, id); +} + +static int wfd_session_set_url(struct wfd_session *s, const char *addr) { char *url; int r = asprintf(&url, "rtsp://%s/wfd1.0", addr); @@ -200,117 +170,160 @@ static int wfd_session_gen_url(struct wfd_session *s, const char *addr) return r; } -static int wfd_out_session_handle_get_parameter_reply(struct rtsp *bus, +static enum rtsp_message_id wfd_session_message_to_id(struct wfd_session *s, + struct rtsp_message *m) +{ + + const char *method = m ? rtsp_message_get_method(m) : NULL; + if(!method) { + return RTSP_M_UNKNOWN; + } + + if(!strcmp(method, "SET_PARAMETER")) { + if(0 >= rtsp_message_read(m, "{<>}", "wfd_trigger_method")) { + return RTSP_M5_TRIGGER; + } + + if(0 >= rtsp_message_read(m, "{<>}", "wfd_route")) { + return RTSP_M10_SET_ROUTE; + } + + if(0 >= rtsp_message_read(m, "{<>}", "wfd_connector_type")) { + return RTSP_M11_SET_CONNECTOR_TYPE; + } + + if(0 >= rtsp_message_read(m, "{<>}", "wfd_standby")) { + return RTSP_M12_SET_STANDBY; + } + + if(0 >= rtsp_message_read(m, "{<>}", "wfd_idr_request")) { + return RTSP_M13_REQUEST_IDR; + } + + if(0 >= rtsp_message_read(m, "{<>}", "wfd_uibc_capability") && s->url) { + return RTSP_M14_ESTABLISH_UIBC; + } + + if(0 >= rtsp_message_read(m, "{<>}", "wfd_uibc_capability")) { + return RTSP_M15_ENABLE_UIBC; + } + + if(!s->url) { + return RTSP_M4_SET_PARAMETER; + } + + return RTSP_M_UNKNOWN; + } + + if(!strcmp(method, "OPTIONS")) { + return wfd_is_out_session(s) + ? (RTSP_MESSAGE_REPLY == rtsp_message_get_type(m)) + ? RTSP_M1_REQUEST_SINK_OPTIONS + : RTSP_M2_REQUEST_SRC_OPTIONS + : (RTSP_MESSAGE_REPLY == rtsp_message_get_type(m)) + ? RTSP_M2_REQUEST_SRC_OPTIONS + : RTSP_M1_REQUEST_SINK_OPTIONS; + } + else if(!strcmp(method, "GET_PARAMETER")) { + if(rtsp_message_get_body_size(m)) { + return RTSP_M3_GET_PARAMETER; + } + + return RTSP_M16_KEEPALIVE; + } + else if(!strcmp(method, "SETUP")) { + return RTSP_M6_SETUP; + } + else if(!strcmp(method, "PLAY")) { + return RTSP_M7_PLAY; + } + else if(!strcmp(method, "TEARDOWN")) { + return RTSP_M8_TEARDOWN; + } + else if(!strcmp(method, "PAUSE")) { + return RTSP_M9_PAUSE; + } + + return RTSP_M_UNKNOWN; +} + +static int wfd_session_dispatch_request(struct rtsp *bus, struct rtsp_message *m, void *userdata) { - log_debug("Received GET_PARAMETER reply (M4): %s\n", - (char *) rtsp_message_get_raw(m)); - if(RTSP_CODE_OK == rtsp_message_get_code(m)) { - return 0; - } - - log_warning("Sink reply GET_PARAMETER (M4) with code: %d", - rtsp_message_get_code(m)); - - wfd_session_end(wfd_session(userdata)); - - return -EPROTO; -} - -static int wfd_out_session_send_get_parameter(sd_event_source *source, - void *userdata) -{ + _rtsp_message_unref_ struct rtsp_message *rep = NULL; struct wfd_session *s = userdata; - _rtsp_message_unref_ struct rtsp_message *m = NULL; - int r = rtsp_message_new_request(s->rtsp, - &m, - "GET_PARAMETER", - s->url); - if (0 > r) { - goto error; + enum rtsp_message_id id; + int r; + + id = wfd_session_message_to_id(s, m); + if(RTSP_M_UNKNOWN == id) { + r = -EPROTO; + goto end; } - r = rtsp_message_append(m, "{&}", - "wfd_video_formats\n" - "wfd_audio_codecs\n" - "wfd_client_rtp_ports" - //"wfd_uibc_capability" - ); - if (0 > r) { - goto error; - } - - rtsp_message_seal(m); - - r = rtsp_call_async(s->rtsp, - m, - wfd_out_session_handle_get_parameter_reply, - s, - 0, - NULL); - if (r < 0) { - goto error; - } - - log_debug("Sending GET_PARAMETER (M3): %s\n", + log_trace("received %s (M%d) request: %s", rtsp_message_id_to_string(id), + id, (char *) rtsp_message_get_raw(m)); - return 0; + r = wfd_session_do_handle_request(s, id, m, &rep); + if(0 > r) { + goto end; + } -error: - wfd_session_end(s); + r = rtsp_message_set_cookie(rep, id); + if(0 > r) { + goto end; + } + + r = rtsp_message_seal(rep); + if(0 > r) { + goto end; + } + + r = rtsp_send(bus, rep); + if(0 > r) { + goto end; + } + + log_trace("sending %s (M%d) reply: %s", rtsp_message_id_to_string(id), + id, + (char *) rtsp_message_get_raw(rep)); + +end: + if (0 > r) { + wfd_session_end(s); + } return r; + } -static int wfd_out_session_handle_options_reply(struct rtsp *bus, +static int wfd_session_dispatch_reply(struct rtsp *bus, struct rtsp_message *m, void *userdata) { - int r = 0, i; + int r; + enum rtsp_message_id id; struct wfd_session *s = userdata; - char *public, *methods[3] = { NULL }; - log_trace("received OPTIONS reply (M1): %s", - (char *) rtsp_message_get_raw(m)); + if(!m) { + goto error; + } if(!rtsp_message_is_reply(m, RTSP_CODE_OK, NULL)) { r = -EPROTO; goto error; } - r = rtsp_message_read(m, "<&>", "Public", &public); - if(0 > r) { - goto error; - } + id = (enum rtsp_message_id) rtsp_message_get_cookie(m); - r = sscanf(public, "%m[^,], %m[^,], %ms", &methods[0], &methods[1], &methods[2]); - if(3 != r) { - r = -EINVAL; - goto error; - } + log_trace("received %s (M%d) reply: %s", + rtsp_message_id_to_string(id), + id, + (char *) rtsp_message_get_raw(m)); - for(i = 0; i < SHL_ARRAY_LENGTH(methods); i ++) { - if(strcmp("org.wfa.wfd1.0", methods[i]) && - strcmp("SET_PARAMETER", methods[i]) && - strcmp("GET_PARAMETER", methods[i])) - { - r = -EINVAL; - log_info("Got invalid method from sink: %s", methods[i]); - } - - free(methods[i]); - } - - if(0 > r) { - goto error; - } - - r = sd_event_add_defer(ctl_wfd_get_loop(), - NULL, - wfd_out_session_send_get_parameter, - s); + r = wfd_session_do_handle_reply(s, id, m); if(0 > r) { goto error; } @@ -319,351 +332,172 @@ static int wfd_out_session_handle_options_reply(struct rtsp *bus, error: wfd_session_end(s); - - log_info("error occured while handling reply of OPTIONS"); - return r; } -static int wfd_out_session_send_options(sd_event_source *source, - void *userdata) +int wfd_session_request(struct wfd_session *s, enum rtsp_message_id id) { - struct wfd_session *s = userdata; + int r; _rtsp_message_unref_ struct rtsp_message *m = NULL; - int r = rtsp_message_new_request(s->rtsp, - &m, - "OPTIONS", "*"); - if (0 > r) { - goto error; + uint64_t cookie = id; + + assert(s); + + r = wfd_session_do_request(s, id, &m); + if(0 > r) { + return r; } - r = rtsp_message_append(m, - "", - "Require", "org.wfa.wfd1.0"); - if (0 > r) { - goto error; - } - r = rtsp_message_seal(m); if(0 > r) { - goto error; + return r; } r = rtsp_call_async(s->rtsp, m, - wfd_out_session_handle_options_reply, + wfd_session_dispatch_reply, s, 0, - NULL); - if (0 > r) { - goto error; - } - - log_debug("sending OPTIONS (M1): %s", (char *) rtsp_message_get_raw(m)); - - return 0; - -error: - log_info("failed to send OPTIONS request: %s", strerror(errno)); - wfd_session_end(s); - - return r; -} - -static int wfd_out_session_handle_options_request(struct rtsp *bus, - struct rtsp_message *request, - struct wfd_session *s) -{ - const char *require; - _rtsp_message_unref_ struct rtsp_message *m = NULL; - int r = rtsp_message_read(request, "", "Require", &require); + &cookie); if(0 > r) { - goto error; + return r; } - if(strcmp("org.wfa.wfd1.0", require)) { - r = rtsp_message_new_reply_for(request, - &m, - RTSP_CODE_OPTION_NOT_SUPPORTED, - "Invalid specification"); - } - else { - r = rtsp_message_new_reply_for(request, - &m, - RTSP_CODE_OK, - NULL); - if(0 > r) { - goto error; - } - - r = rtsp_message_append(m, - "", - "Public", "org.wfa.wfd1.0, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER"); - } - - if(0 > r) { - goto error; - } - - r = rtsp_message_seal(m); - if(0 > r) { - goto error; - } - - r = rtsp_send(bus, m); - if(0 > r) { - goto error; - } - - log_debug("sending OPTIONS reply (M2): %s", + log_trace("sending %s (M%d) request: %s", + rtsp_message_id_to_string(id), + id, (char *) rtsp_message_get_raw(m)); return 0; - -error: - s->hup = true; - return r; } -static int wfd_out_session_dispatch_request(struct rtsp *bus, - struct rtsp_message *m, - void *userdata) -{ - const char *method; - struct wfd_session *s = userdata; - int r = 0; - - if (!m) { - s->hup = true; - goto end; - } - - method = rtsp_message_get_method(m); - if(!method) { - log_info("unexpected message: %s", (char *) rtsp_message_get_raw(m)); - r = -EINVAL; - goto end; - } - - if (!strcmp(method, "OPTIONS")) { - r = wfd_out_session_handle_options_request(bus, m, s); - } - /*else if (!strcmp(method, "GET_PARAMETER")) {*/ - /*wfd_out_session_handle_get_parameter_reply(s, m);*/ - /*}*/ - /*[>else if (!strcmp(method, "SETUP")) {<]*/ - /*[>wfd_out_session_handle_setup_reply(s, m);<]*/ - /*[>}<]*/ - /*[>else if (!strcmp(method, "PLAY")) {<]*/ - /*[>wfd_out_session_handle_play_reply(s, m);<]*/ - /*[>}<]*/ - /*[>else if (!strcmp(method, "PAUSE")) {<]*/ - /*[>wfd_out_session_handle_pause_reply(s, m);<]*/ - /*[>}<]*/ - /*[>else if (!strcmp(method, "TEARDOWN")) {<]*/ - /*[>wfd_out_session_handle_teardown_reply(s, m);<]*/ - /*[>}<]*/ - -end: - if (s->hup) { - wfd_session_end(s); - } - - return r; - -} - -static int wfd_out_session_accept_connection(struct wfd_out_session *os) -{ - int r; - socklen_t len; - struct sockaddr_storage addr; - _shl_close_ int fd = -1; - sd_event *loop = ctl_wfd_get_loop(); - struct wfd_session *s = wfd_session(os); - _rtsp_unref_ struct rtsp *rtsp = NULL; - - log_debug("accepting incoming RTSP connection\n"); - - len = sizeof(addr); - fd = accept4(os->fd, - (struct sockaddr *) &addr, - &len, - SOCK_NONBLOCK | SOCK_CLOEXEC); - if(0 > fd) { - return -ENOTCONN; - } - - log_info("RTSP connection established"); - - r = rtsp_open(&rtsp, fd); - if (0 > r) { - goto error; - } - - fd = -1; - - r = rtsp_attach_event(rtsp, loop, 0); - if (0 > r) { - goto error; - } - - r = rtsp_add_match(rtsp, wfd_out_session_dispatch_request, s); - if (0 > r) { - goto error; - } - - r = sd_event_add_defer(loop, NULL, wfd_out_session_send_options, s); - if(0 > r) { - goto error; - } - - wfd_session_set_state(s, WFD_SESSION_STATE_CAPS_EXCHAING); - - s->rtsp = rtsp; - rtsp = NULL; - - close(os->fd); - os->fd = -1; - - return 0; - -error: - s->hup = true; - return r; -} - -static int wfd_out_session_handle_io(sd_event_source *source, +static int wfd_session_handle_io(sd_event_source *source, int fd, uint32_t mask, void *userdata) { - int r, val; + int r, err = 0, conn; socklen_t len; struct wfd_session *s = userdata; + _rtsp_unref_ struct rtsp *rtsp = NULL; sd_event_source_set_enabled(source, SD_EVENT_OFF); if (mask & EPOLLERR) { - r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &len); - s->hup = true; - if(0 <= r) { - r = -val; - errno = val; + r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len); + if(0 > r) { + goto end; } - goto end; } - if (mask & EPOLLIN) { - r = wfd_out_session_accept_connection(userdata); + if (mask & EPOLLIN || mask & EPOLLOUT) { + r = (*session_vtables[s->dir].handle_io)(s, err, &conn); + if(0 > r) { + goto end; + } + + r = rtsp_open(&rtsp, conn); + if (0 > r) { + goto end; + } + + conn = -1; + + r = rtsp_attach_event(rtsp, ctl_wfd_get_loop(), 0); + if (0 > r) { + goto end; + } + + r = rtsp_add_match(rtsp, wfd_session_dispatch_request, s); + if (0 > r) { + goto end; + } + + s->rtsp = rtsp; + rtsp = NULL; + + wfd_session_set_state(s, WFD_SESSION_STATE_CAPS_EXCHAING); + + r = (*session_vtables[s->dir].initiate_request)(s); + } + + if(mask & EPOLLHUP) { + r = -ESHUTDOWN; } end: - if (s->hup) { - log_info("failed to accept remote connection: %s", strerror(errno)); + if (0 > r) { wfd_session_end(s); } return r; } -static int wfd_out_session_start(struct wfd_session *s) +int wfd_session_start(struct wfd_session *s, uint64_t id) { - struct wfd_out_session *os = wfd_out_session(s); - union wfd_sube sube; - struct sockaddr_in addr = {}; - struct ctl_peer *p = os->sink->peer; - _shl_close_ int fd = -1; - int enable; int r; + _shl_close_ int fd = -1; + uint32_t mask; - if(!os->sink->peer->connected) { - log_info("peer not connected yet"); - return -ENOTCONN; + assert(wfd_is_session(s)); + assert(id); + + if(wfd_session_is_started(s)) { + return -EINPROGRESS; } - r = wfd_sube_parse_with_id(WFD_SUBE_ID_DEVICE_INFO, - p->l->wfd_subelements, - &sube); - if(0 > r) { - log_warning("WfdSubelements property of link must be set before P2P scan"); - return -EINVAL; - } - else if(WFD_SUBE_ID_DEVICE_INFO != sube.id) { - return -EAFNOSUPPORT; - } - - if(-1 != os->fd) { - return EINPROGRESS; - } - - r = inet_pton(AF_INET, p->local_address, &addr.sin_addr); - if (!r) { - return -EAFNOSUPPORT; - } - addr.sin_family = AF_INET; - addr.sin_port = htons(wfd_sube_device_get_rtsp_port(&sube)); - - fd = socket(addr.sin_family, - SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, - 0); - if (0 > fd) { - return fd; - } - - enable = true; - r = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable)); + r = (*session_vtables[s->dir].initiate_io)(s, &fd, &mask); if(0 > r) { return r; } - r = bind(fd, (struct sockaddr*) &addr, sizeof(addr)); - if (0 > r) { - return r; - } - - r = listen(fd, 10); - if (0 > r) { - return r; - } - - log_trace("socket listening on %s:%hu", - p->local_address, - wfd_sube_device_get_rtsp_port(&sube)); - r = sd_event_add_io(ctl_wfd_get_loop(), NULL, fd, - EPOLLIN, - wfd_out_session_handle_io, + mask, + wfd_session_handle_io, s); if (r < 0) { return r; } - r = wfd_session_gen_url(s, p->local_address); - if(0 <= r) { - os->fd = fd; - fd = -1; - } + fd = -1; - return r; + s->id = id; + wfd_session_set_state(s, WFD_SESSION_STATE_CONNECTING); + + return 0; } -static void wfd_out_session_end(struct wfd_session *s) +void wfd_session_freep(struct wfd_session **s) { - struct wfd_out_session *os = wfd_out_session(s); - if(os->fd) { - close(os->fd); - os->fd = -1; - } + wfd_session_free(*s); } -static void wfd_out_session_distruct(struct wfd_session *s) +const char * rtsp_message_id_to_string(enum rtsp_message_id id) { - struct wfd_out_session *os = wfd_out_session(s); - if(0 <= os->fd) { - close(os->fd); - } + assert(id >= 0 && 16 >= id); + + return rtsp_message_names[id]; } +static const char *rtsp_message_names[] = { + "UNKNOWN", + "OPTIONS(src->sink)", + "OPTIONS(sink->src)", + "GET_PARAM", + "SET_PARAM", + "SET_PARAM(wfd-trigger-method)", + "SETUP", + "PLAY", + "TEARDOWN", + "PAUSE", + "SET_PARAM(wfd-route)", + "SET_PARAM(wfd-connector-type)", + "SET_PARAM(wfd-standby)", + "SET_PARAM(wfd-idr-request)", + "SET_PARAM(wfd-uibc-cability)", + "SET_PARAM(wfd-uibc-setting)", + "GET_PARAM(keepalive)", +}; + diff --git a/src/ctl/wfd-session.h b/src/ctl/wfd-session.h new file mode 100644 index 0000000..9e97206 --- /dev/null +++ b/src/ctl/wfd-session.h @@ -0,0 +1,91 @@ +/* + * MiracleCast - Wifi-Display/Miracast Implementation + * + * Copyright (c) 2013-2014 David Herrmann + * + * MiracleCast is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * MiracleCast is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MiracleCast; If not, see . + */ +#ifndef MIRACLE_OUT_SESSION_H +#define MIRACLE_OUT_SESSION_H + +#include "ctl.h" + +#define wfd_out_session(s) (assert(wfd_is_out_session(s)), (struct wfd_out_session *) (s)) +#define wfd_in_session(s) (assert(wfd_is_in_session(s)), (struct wfd_in_session *) (s)) +#define wfd_session_is_destructed(s) (!(s) || (s)->destructed) + +struct wfd_session; +struct wfd_sink; +struct rtsp; +struct rtsp_message; + +enum rtsp_message_id +{ + RTSP_M_UNKNOWN, + RTSP_M1_REQUEST_SINK_OPTIONS, + RTSP_M2_REQUEST_SRC_OPTIONS, + RTSP_M3_GET_PARAMETER, + RTSP_M4_SET_PARAMETER, + RTSP_M5_TRIGGER, + RTSP_M6_SETUP, + RTSP_M7_PLAY, + RTSP_M8_TEARDOWN, + RTSP_M9_PAUSE, + RTSP_M10_SET_ROUTE, + RTSP_M11_SET_CONNECTOR_TYPE, + RTSP_M12_SET_STANDBY, + RTSP_M13_REQUEST_IDR, + RTSP_M14_ESTABLISH_UIBC, + RTSP_M15_ENABLE_UIBC, + RTSP_M16_KEEPALIVE, +}; + +struct rtsp_dispatch_entry +{ + union { + int (*request)(struct wfd_session *s, struct rtsp_message **out); + int (*handle_request)(struct wfd_session *s, + struct rtsp_message *req, + struct rtsp_message **out_rep); + }; + int (*handle_reply)(struct wfd_session *s, struct rtsp_message *m); + enum rtsp_message_id next_request; +}; + +struct wfd_session_vtable +{ + int (*initiate_io)(struct wfd_session *s, int *out_fd, uint32_t *out_mask); + int (*handle_io)(struct wfd_session *s, int error, int *out_fd); + int (*initiate_request)(struct wfd_session *s); + void (*end)(struct wfd_session *s); + void (*distruct)(struct wfd_session *s); +}; + +struct wfd_session +{ + enum wfd_session_dir dir; + enum wfd_session_state state; + uint64_t id; + char *url; + struct rtsp *rtsp; + const struct rtsp_dispatch_entry *rtsp_disp_tbl; + + bool destructed: 1; +}; + +const char * rtsp_message_id_to_string(enum rtsp_message_id id); +struct wfd_sink * wfd_out_session_get_sink(struct wfd_session *s); +int wfd_session_request(struct wfd_session *s, enum rtsp_message_id id); + +#endif /* MIRACLE_OUT_SESSION_H */ diff --git a/src/ctl/wfd-sink.c b/src/ctl/wfd-sink.c index 6e4d162..cd1ccdf 100644 --- a/src/ctl/wfd-sink.c +++ b/src/ctl/wfd-sink.c @@ -121,15 +121,17 @@ int wfd_sink_start_session(struct wfd_sink *sink, struct wfd_session **out) int wfd_fn_out_session_ended(struct wfd_session *s) { + struct wfd_sink *sink; + assert(wfd_is_out_session(s)); - struct wfd_sink *sink = wfd_out_session_get_sink(s); - if(sink) { - wfd_fn_sink_properties_changed(sink, "Session"); - ctl_wfd_remove_session_by_id(ctl_wfd_get(), s->id, NULL); - sink->session = NULL; - wfd_session_free(s); - } + sink = wfd_out_session_get_sink(s); + wfd_fn_sink_properties_changed(sink, "Session"); + ctl_wfd_remove_session_by_id(ctl_wfd_get(), + wfd_session_get_id(s), + NULL); + sink->session = NULL; + wfd_session_free(s); return 0; } diff --git a/src/ctl/wfdctl.c b/src/ctl/wfdctl.c index 3ecffb7..347b2ff 100644 --- a/src/ctl/wfdctl.c +++ b/src/ctl/wfdctl.c @@ -191,8 +191,8 @@ int ctl_wfd_add_session(struct ctl_wfd *wfd, struct wfd_session *s) int r; assert(wfd); - assert(s && s->id); - assert(!ctl_wfd_find_session_by_id(wfd, s->id, NULL)); + assert(s && wfd_session_get_id(s)); + assert(!ctl_wfd_find_session_by_id(wfd, wfd_session_get_id(s), NULL)); r = shl_htable_insert_u64(&wfd->sessions, wfd_session_to_htable(s)); if(0 > r) { @@ -258,16 +258,10 @@ static int ctl_wfd_handle_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { - int r; - sd_event_source *exit_source; struct ctl_wfd *wfd = userdata; ctl_wfd_destroy(wfd); - sd_event_exit(wfd->loop, 0); - - sd_event_source_unref(s); - - return 0; + return sd_event_exit(wfd->loop, 0); } static int ctl_wfd_init(struct ctl_wfd *wfd, sd_bus *bus) @@ -372,7 +366,7 @@ void ctl_fn_peer_new(struct ctl_peer *p) void ctl_fn_peer_free(struct ctl_peer *p) { struct wfd_sink *s; - _shl_free_ char *label; + _shl_free_ char *label = NULL; int r = ctl_wfd_remove_sink_by_label(wfd, p->label, &s); if(!r) { return;