1
0
Fork 0
mirror of https://github.com/albfan/miraclecast.git synced 2025-02-15 04:42:06 +00:00

miracle-wfdctl: clarify teardown procedure of session

This commit is contained in:
Derek Dai 2017-02-23 14:20:34 +08:00
parent b0419509b8
commit 155060919e
No known key found for this signature in database
GPG key ID: E109CC97553EF009
8 changed files with 183 additions and 141 deletions

View file

@ -103,10 +103,10 @@ get_prop()
cleanup() cleanup()
{ {
kill 0 set +e
set -x while (( 0 != ${#cleanup[@]} )); do
for (( i=${#cleanup[@]}-1; i>=0; --i )); do eval ${cleanup[${#cleanup[@]}-1]}
eval ${cleanup[$i]} || true unset cleanup[${#cleanup[@]}-1]
done done
} }
@ -115,6 +115,14 @@ cleanup_push()
cleanup+=("$*") cleanup+=("$*")
} }
nm_manage()
{
set_prop org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/"$nm_link_index" \
org.freedesktop.NetworkManager.Device \
Managed b true
}
link_unmanage() link_unmanage()
{ {
set_prop org.freedesktop.miracle.wifi \ set_prop org.freedesktop.miracle.wifi \
@ -149,6 +157,7 @@ set_prop org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/"$nm_link_index" \ /org/freedesktop/NetworkManager/Devices/"$nm_link_index" \
org.freedesktop.NetworkManager.Device \ org.freedesktop.NetworkManager.Device \
Managed b false Managed b false
cleanup_push nm_manage
set_prop org.freedesktop.miracle.wifi \ set_prop org.freedesktop.miracle.wifi \
/org/freedesktop/miracle/wifi/link/$link_index \ /org/freedesktop/miracle/wifi/link/$link_index \
org.freedesktop.miracle.wifi.Link \ org.freedesktop.miracle.wifi.Link \
@ -179,6 +188,8 @@ get_prop org.freedesktop.miracle.wifi \
org.freedesktop.miracle.wifi.Peer \ org.freedesktop.miracle.wifi.Peer \
Interface p2p_iface Interface p2p_iface
tcpdump -nnvvXS -s 0 -i $p2p_iface port 7236 or port 67 or port 68 & tcpdump -nnvvXS -s 0 -i $p2p_iface port 7236 or port 67 or port 68 &
cleanup_push "kill $!"
while ! killall -0 miracle-wfdctl && [[ -z "$nocheck" ]] &>/dev/null; do while ! killall -0 miracle-wfdctl && [[ -z "$nocheck" ]] &>/dev/null; do
echo please run miracle-wfdctl manually echo please run miracle-wfdctl manually
sleep 3 sleep 3

View file

@ -198,6 +198,8 @@ struct wfd_sink
union wfd_sube dev_info; union wfd_sube dev_info;
char *label; char *label;
struct wfd_session *session; struct wfd_session *session;
sd_event_source *session_cleanup_source;
}; };
int wfd_sink_new(struct wfd_sink **out, int wfd_sink_new(struct wfd_sink **out,
@ -237,6 +239,8 @@ struct ctl_wfd
struct shl_htable sessions; struct shl_htable sessions;
size_t n_sessions; size_t n_sessions;
uint64_t id_pool; uint64_t id_pool;
sd_event_source *signal_sources[4];
}; };
struct ctl_wfd * ctl_wfd_get(); struct ctl_wfd * ctl_wfd_get();

View file

@ -163,7 +163,7 @@ int _wfd_dbus_object_removed(struct wfd_dbus *wfd_dbus,
size_t n_ifaces) size_t n_ifaces)
{ {
int i, r; int i, r;
_sd_bus_message_unref_ sd_bus_message *m; _sd_bus_message_unref_ sd_bus_message *m = NULL;
if(!wfd_dbus) { if(!wfd_dbus) {
return -ECANCELED; return -ECANCELED;
@ -209,7 +209,7 @@ int _wfd_dbus_object_added(struct wfd_dbus *wfd_dbus,
size_t n_ifaces) size_t n_ifaces)
{ {
int i, r; int i, r;
_sd_bus_message_unref_ sd_bus_message *m; _sd_bus_message_unref_ sd_bus_message *m = NULL;
if(!wfd_dbus) { if(!wfd_dbus) {
return -ECANCELED; return -ECANCELED;
@ -251,7 +251,7 @@ int _wfd_dbus_object_added(struct wfd_dbus *wfd_dbus,
int wfd_fn_sink_new(struct wfd_sink *s) int wfd_fn_sink_new(struct wfd_sink *s)
{ {
_shl_free_ char *path; _shl_free_ char *path = NULL;
int r = sd_bus_path_encode("/org/freedesktop/miracle/wfd/sink", int r = sd_bus_path_encode("/org/freedesktop/miracle/wfd/sink",
wfd_sink_get_label(s), wfd_sink_get_label(s),
&path); &path);
@ -264,7 +264,7 @@ int wfd_fn_sink_new(struct wfd_sink *s)
int wfd_fn_sink_free(struct wfd_sink *s) int wfd_fn_sink_free(struct wfd_sink *s)
{ {
_shl_free_ char *path; _shl_free_ char *path = NULL;
int r = sd_bus_path_encode("/org/freedesktop/miracle/wfd/sink", int r = sd_bus_path_encode("/org/freedesktop/miracle/wfd/sink",
wfd_sink_get_label(s), wfd_sink_get_label(s),
&path); &path);
@ -277,7 +277,7 @@ int wfd_fn_sink_free(struct wfd_sink *s)
int _wfd_fn_sink_properties_changed(struct wfd_sink *s, char **names) int _wfd_fn_sink_properties_changed(struct wfd_sink *s, char **names)
{ {
_shl_free_ char *path; _shl_free_ char *path = NULL;
int r; int r;
struct wfd_dbus *wfd_dbus = wfd_dbus_get(); struct wfd_dbus *wfd_dbus = wfd_dbus_get();
@ -322,7 +322,7 @@ static int wfd_dbus_find_sink(sd_bus *bus,
int wfd_fn_session_new(struct wfd_session *s) int wfd_fn_session_new(struct wfd_session *s)
{ {
_shl_free_ char *path; _shl_free_ char *path = NULL;
int r = wfd_dbus_get_session_path(s, &path); int r = wfd_dbus_get_session_path(s, &path);
if(0 > r) { if(0 > r) {
return r; return r;
@ -333,7 +333,7 @@ int wfd_fn_session_new(struct wfd_session *s)
int wfd_fn_session_free(struct wfd_session *s) int wfd_fn_session_free(struct wfd_session *s)
{ {
_shl_free_ char *path; _shl_free_ char *path = NULL;
int r = wfd_dbus_get_session_path(s, &path); int r = wfd_dbus_get_session_path(s, &path);
if(0 > r) { if(0 > r) {
return r; return r;
@ -424,6 +424,30 @@ static int wfd_dbus_sink_start_session(sd_bus_message *m,
// return 0; // return 0;
//} //}
static int wfd_dbus_sink_get_session(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *ret_error)
{
struct wfd_sink *s = userdata;
_shl_free_ char *session_path = NULL;
int r;
if(!s->session) {
return 0;
}
r = wfd_dbus_get_session_path(s->session, &session_path);
if(0 > r) {
return r;
}
return sd_bus_message_append(reply, "o", session_path);
}
static int wfd_dbus_sink_get_peer(sd_bus *bus, static int wfd_dbus_sink_get_peer(sd_bus *bus,
const char *path, const char *path,
const char *interface, const char *interface,
@ -433,7 +457,7 @@ static int wfd_dbus_sink_get_peer(sd_bus *bus,
sd_bus_error *ret_error) sd_bus_error *ret_error)
{ {
struct wfd_sink *s = userdata; struct wfd_sink *s = userdata;
_shl_free_ char *peer_path; _shl_free_ char *peer_path = NULL;
int r = sd_bus_path_encode("/org/freedesktop/miracle/wifi/peer", int r = sd_bus_path_encode("/org/freedesktop/miracle/wifi/peer",
s->label, s->label,
&peer_path); &peer_path);
@ -560,7 +584,7 @@ static int wfd_dbus_get_session_state(sd_bus *bus,
int _wfd_fn_session_properties_changed(struct wfd_session *s, char **names) int _wfd_fn_session_properties_changed(struct wfd_session *s, char **names)
{ {
_shl_free_ char *path; _shl_free_ char *path = NULL;
int r; int r;
struct wfd_dbus *wfd_dbus = wfd_dbus_get(); struct wfd_dbus *wfd_dbus = wfd_dbus_get();
@ -591,6 +615,7 @@ static const sd_bus_vtable wfd_dbus_sink_vtable[] = {
/*SD_BUS_PROPERTY("VideoFormats", "a{sv}", wfd_dbus_sink_get_video_formats, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/ /*SD_BUS_PROPERTY("VideoFormats", "a{sv}", wfd_dbus_sink_get_video_formats, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/
/*SD_BUS_PROPERTY("HasAudio", "b", wfd_dbus_sink_has_audio, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/ /*SD_BUS_PROPERTY("HasAudio", "b", wfd_dbus_sink_has_audio, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/
/*SD_BUS_PROPERTY("HasVideo", "b", wfd_dbus_sink_has_video, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/ /*SD_BUS_PROPERTY("HasVideo", "b", wfd_dbus_sink_has_video, 0, SD_BUS_VTABLE_PROPERTY_CONST),*/
SD_BUS_PROPERTY("Session", "o", wfd_dbus_sink_get_session, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Peer", "o", wfd_dbus_sink_get_peer, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Peer", "o", wfd_dbus_sink_get_peer, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_VTABLE_END, SD_BUS_VTABLE_END,
}; };

View file

@ -30,10 +30,13 @@ struct wfd_out_session
struct wfd_session parent; struct wfd_session parent;
struct wfd_sink *sink; struct wfd_sink *sink;
int fd; int fd;
sd_event_source *gst_term_source;
}; };
static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[]; static const struct rtsp_dispatch_entry out_session_rtsp_disp_tbl[];
#include <unistd.h>
int wfd_out_session_new(struct wfd_session **out, struct wfd_sink *sink) 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)); struct wfd_out_session *s = calloc(1, sizeof(struct wfd_out_session));
@ -164,9 +167,14 @@ int wfd_out_session_initiate_io(struct wfd_session *s,
static void wfd_out_session_kill_gst(struct wfd_session *s) static void wfd_out_session_kill_gst(struct wfd_session *s)
{ {
if(-1 != s->stream.gst) { pid_t pid;
kill(s->stream.gst, SIGTERM); struct wfd_out_session *os = wfd_out_session(s);
s->stream.gst = -1; if(os->gst_term_source) {
sd_event_source_get_child_pid(os->gst_term_source, &pid);
kill(pid, SIGTERM);
sd_event_source_set_userdata(os->gst_term_source, NULL);
os->gst_term_source = NULL;
} }
} }
@ -191,20 +199,15 @@ int wfd_out_session_teardown(struct wfd_session *s)
&(struct wfd_arg_list) wfd_arg_list(wfd_arg_cstr("TEARDOWN"))); &(struct wfd_arg_list) wfd_arg_list(wfd_arg_cstr("TEARDOWN")));
} }
void wfd_out_session_end(struct wfd_session *s) void wfd_out_session_destroy(struct wfd_session *s)
{ {
struct wfd_out_session *os = wfd_out_session(s); struct wfd_out_session *os = wfd_out_session(s);
wfd_out_session_kill_gst(s);
if(0 <= os->fd) { if(0 <= os->fd) {
close(os->fd); close(os->fd);
os->fd = -1; os->fd = -1;
} }
}
void wfd_out_session_distruct(struct wfd_session *s) wfd_out_session_kill_gst(s);
{
} }
int wfd_out_session_initiate_request(struct wfd_session *s) int wfd_out_session_initiate_request(struct wfd_session *s)
@ -305,7 +308,6 @@ static int wfd_out_session_request_get_parameter(struct wfd_session *s,
return 0; return 0;
error: error:
wfd_session_end(s);
return r; return r;
} }
@ -425,7 +427,6 @@ static int wfd_out_session_launch_gst(struct wfd_session *s, pid_t *out)
char port[10]; char port[10];
char * args[] = { char * args[] = {
"gst-launch-1.0", "gst-launch-1.0",
"-v",
"ximagesrc", "ximagesrc",
"use-damage=false", "use-damage=false",
"show-pointer=false", "show-pointer=false",
@ -473,9 +474,21 @@ static int wfd_out_session_handle_gst_term(sd_event_source *source,
const siginfo_t *si, const siginfo_t *si,
void *userdata) void *userdata)
{ {
struct wfd_out_session *os = userdata;
log_trace("gst-launch(%d) terminated", si->si_pid); log_trace("gst-launch(%d) terminated", si->si_pid);
wfd_session_end(userdata); sd_event_source_unref(source);
if(!os) {
return 0;
}
os->gst_term_source = NULL;
if(WFD_SESSION_STATE_PAUSED != wfd_session(os)->state) {
wfd_session_teardown(wfd_session(os));
}
return 0; return 0;
} }
@ -530,7 +543,7 @@ static int wfd_out_session_handle_play_request(struct wfd_session *s,
struct rtsp_message *req, struct rtsp_message *req,
struct rtsp_message **out_rep) struct rtsp_message **out_rep)
{ {
_shl_free_ char *v; _shl_free_ char *v = NULL;
_rtsp_message_unref_ struct rtsp_message *m = NULL; _rtsp_message_unref_ struct rtsp_message *m = NULL;
pid_t gst; pid_t gst;
int r, status; int r, status;
@ -564,22 +577,21 @@ static int wfd_out_session_handle_play_request(struct wfd_session *s,
} }
r = sd_event_add_child(ctl_wfd_get_loop(), r = sd_event_add_child(ctl_wfd_get_loop(),
NULL, &wfd_out_session(s)->gst_term_source,
gst, WEXITED, gst, WEXITED,
wfd_out_session_handle_gst_term, wfd_out_session_handle_gst_term,
s); s);
if(0 > r) { if(0 > r) {
kill(gst, SIGKILL); kill(gst, SIGKILL);
waitpid(gst, &status, WNOHANG); waitpid(gst, &status, WNOHANG);
return r; wfd_session_teardown(s);
}
else {
*out_rep = m;
m = NULL;
} }
s->stream.gst = gst; return r;
*out_rep = m;
m = NULL;
return 0;
} }
static int wfd_out_session_handle_setup_request(struct wfd_session *s, static int wfd_out_session_handle_setup_request(struct wfd_session *s,
@ -698,7 +710,7 @@ static int wfd_out_session_request_set_parameter(struct wfd_session *s,
const struct wfd_arg_list *args, const struct wfd_arg_list *args,
struct rtsp_message **out) struct rtsp_message **out)
{ {
_rtsp_message_unref_ struct rtsp_message *m; _rtsp_message_unref_ struct rtsp_message *m = NULL;
_shl_free_ char *body = NULL; _shl_free_ char *body = NULL;
int r; int r;

View file

@ -43,7 +43,7 @@ extern int wfd_out_session_resume(struct wfd_session *);
extern int wfd_out_session_pause(struct wfd_session *); extern int wfd_out_session_pause(struct wfd_session *);
extern int wfd_out_session_teardown(struct wfd_session *); extern int wfd_out_session_teardown(struct wfd_session *);
extern void wfd_out_session_end(struct wfd_session *); extern void wfd_out_session_end(struct wfd_session *);
extern void wfd_out_session_distruct(struct wfd_session *); extern void wfd_out_session_destroy(struct wfd_session *);
const struct wfd_session_vtable session_vtbl[] = { const struct wfd_session_vtable session_vtbl[] = {
[WFD_SESSION_DIR_OUT] = { [WFD_SESSION_DIR_OUT] = {
@ -53,8 +53,7 @@ const struct wfd_session_vtable session_vtbl[] = {
.resume = wfd_out_session_resume, .resume = wfd_out_session_resume,
.pause = wfd_out_session_pause, .pause = wfd_out_session_pause,
.teardown = wfd_out_session_teardown, .teardown = wfd_out_session_teardown,
.end = wfd_out_session_end, .destroy = wfd_out_session_destroy,
.distruct = wfd_out_session_distruct,
} }
}; };
@ -178,6 +177,9 @@ int wfd_session_teardown(struct wfd_session *s)
{ {
assert(wfd_is_session(s)); assert(wfd_is_session(s));
/* notify and detach from sink */
wfd_fn_out_session_ended(s);
if(wfd_session_is_established(s)) { if(wfd_session_is_established(s)) {
if(!session_vtbl[s->dir].teardown) { if(!session_vtbl[s->dir].teardown) {
return 0; return 0;
@ -186,41 +188,21 @@ int wfd_session_teardown(struct wfd_session *s)
return session_vtbl[s->dir].teardown(s);; return session_vtbl[s->dir].teardown(s);;
} }
wfd_session_end(s); wfd_session_free(s);
return 0; return 0;
} }
void wfd_session_end(struct wfd_session *s)
{
assert(wfd_is_session(s));
if(WFD_SESSION_STATE_NULL == s->state) {
return;
}
log_info("session %lu ended", s->id);
wfd_session_set_state(s, WFD_SESSION_STATE_NULL);
(*session_vtbl[s->dir].end)(s);
if(s->rtsp) {
rtsp_unref(s->rtsp);
s->rtsp = NULL;
}
if(wfd_is_out_session(s)) {
wfd_fn_out_session_ended(s);
}
}
void wfd_session_free(struct wfd_session *s) void wfd_session_free(struct wfd_session *s)
{ {
if(!s) { if(!s) {
return; return;
} }
if(session_vtbl[s->dir].destroy) {
(*session_vtbl[s->dir].destroy)(s);
}
if(s->vformats) { if(s->vformats) {
wfd_video_formats_free(s->vformats); wfd_video_formats_free(s->vformats);
s->vformats = NULL; s->vformats = NULL;
@ -236,16 +218,15 @@ void wfd_session_free(struct wfd_session *s)
s->stream.url = NULL; s->stream.url = NULL;
} }
if(s->rtsp) {
rtsp_unref(s->rtsp);
s->rtsp = NULL;
}
s->rtp_ports[0] = 0; s->rtp_ports[0] = 0;
s->rtp_ports[1] = 0; s->rtp_ports[1] = 0;
s->last_request = RTSP_M_UNKNOWN; s->last_request = RTSP_M_UNKNOWN;
wfd_session_end(s);
if(session_vtbl[s->dir].distruct) {
(*session_vtbl[s->dir].distruct)(s);
}
free(s); free(s);
} }
@ -401,6 +382,10 @@ static int wfd_session_post_handle_request_n_reply(struct wfd_session *s,
if(RTSP_M_UNKNOWN != next_request) { if(RTSP_M_UNKNOWN != next_request) {
return wfd_session_request(s, next_request, req_args); return wfd_session_request(s, next_request, req_args);
} }
if(WFD_SESSION_STATE_TEARING_DOWN == new_state) {
wfd_fn_out_session_ended(s);
}
return 0; return 0;
} }
@ -454,7 +439,7 @@ static int wfd_session_handle_request(struct rtsp *bus,
return 0; return 0;
error: error:
wfd_session_end(s); wfd_session_teardown(s);
return r; return r;
@ -498,7 +483,8 @@ static int wfd_session_handle_reply(struct rtsp *bus,
return 0; return 0;
error: error:
wfd_session_end(s); wfd_session_teardown(s);
return r; return r;
} }
@ -552,6 +538,7 @@ static int wfd_session_handle_io(sd_event_source *source,
_rtsp_unref_ struct rtsp *rtsp = NULL; _rtsp_unref_ struct rtsp *rtsp = NULL;
sd_event_source_set_enabled(source, SD_EVENT_OFF); sd_event_source_set_enabled(source, SD_EVENT_OFF);
sd_event_source_unref(source);
if (mask & EPOLLERR) { if (mask & EPOLLERR) {
r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len); r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len);
@ -597,7 +584,7 @@ static int wfd_session_handle_io(sd_event_source *source,
end: end:
if (0 > r) { if (0 > r) {
wfd_session_end(s); wfd_session_teardown(s);
} }
return r; return r;

View file

@ -25,7 +25,6 @@
#define wfd_out_session(s) (assert(wfd_is_out_session(s)), (struct wfd_out_session *) (s)) #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_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_session;
struct wfd_sink; struct wfd_sink;
@ -89,8 +88,7 @@ struct wfd_session_vtable
int (*resume)(struct wfd_session *); int (*resume)(struct wfd_session *);
int (*pause)(struct wfd_session *); int (*pause)(struct wfd_session *);
int (*teardown)(struct wfd_session *); int (*teardown)(struct wfd_session *);
void (*end)(struct wfd_session *s); void (*destroy)(struct wfd_session *s);
void (*distruct)(struct wfd_session *s);
}; };
struct wfd_session struct wfd_session
@ -110,7 +108,6 @@ struct wfd_session
enum wfd_stream_id id; enum wfd_stream_id id;
char *url; char *url;
uint16_t rtp_port; uint16_t rtp_port;
pid_t gst;
} stream; } stream;
}; };

View file

@ -24,6 +24,34 @@
#include "ctl.h" #include "ctl.h"
#include "wfd-dbus.h" #include "wfd-dbus.h"
static int wfd_sink_set_session(struct wfd_sink *sink,
struct wfd_session *session)
{
int r;
if(sink->session == session) {
return 0;
}
if(session) {
r = ctl_wfd_add_session(ctl_wfd_get(), session);
if(0 > r) {
return r;
}
}
if(sink->session) {
ctl_wfd_remove_session_by_id(ctl_wfd_get(),
wfd_session_get_id(sink->session),
NULL);
}
sink->session = session;
wfd_fn_sink_properties_changed(sink, "Session");
return 0;
}
int wfd_sink_new(struct wfd_sink **out, int wfd_sink_new(struct wfd_sink **out,
struct ctl_peer *peer, struct ctl_peer *peer,
union wfd_sube *sube) union wfd_sube *sube)
@ -55,12 +83,16 @@ int wfd_sink_new(struct wfd_sink **out,
void wfd_sink_free(struct wfd_sink *sink) void wfd_sink_free(struct wfd_sink *sink)
{ {
struct wfd_session *s;
if(!sink) { if(!sink) {
return; return;
} }
if(sink->session) { if(sink->session) {
wfd_session_free(sink->session); s = sink->session;
wfd_sink_set_session(sink, NULL);
wfd_session_free(s);
} }
if(sink->label) { if(sink->label) {
@ -107,7 +139,7 @@ int wfd_sink_start_session(struct wfd_sink *sink, struct wfd_session **out)
return r; return r;
} }
r = ctl_wfd_add_session(ctl_wfd_get(), s); r = wfd_sink_set_session(sink, s);
if(0 > r) { if(0 > r) {
return r; return r;
} }
@ -121,43 +153,13 @@ int wfd_sink_start_session(struct wfd_sink *sink, struct wfd_session **out)
return 0; return 0;
} }
static int wfd_sink_defered_session_cleanup(sd_event_source *source,
uint64_t used,
void *userdata)
{
struct wfd_session *s = userdata;
sd_event_source_set_enabled(source, false);
ctl_wfd_remove_session_by_id(ctl_wfd_get(),
wfd_session_get_id(s),
NULL);
wfd_session_free(s);
return 0;
}
int wfd_fn_out_session_ended(struct wfd_session *s) int wfd_fn_out_session_ended(struct wfd_session *s)
{ {
struct wfd_sink *sink;
uint64_t now = 0;
assert(wfd_is_out_session(s)); assert(wfd_is_out_session(s));
sink = wfd_out_session_get_sink(s); wfd_sink_set_session(wfd_out_session_get_sink(s), NULL);
sink->session = NULL;
wfd_fn_sink_properties_changed(sink, "Session"); return 0;
sd_event_now(ctl_wfd_get_loop(), CLOCK_MONOTONIC, &now);
return sd_event_add_time(ctl_wfd_get_loop(),
NULL,
CLOCK_MONOTONIC,
200 * 1000 + now,
0,
wfd_sink_defered_session_cleanup,
s);
} }
bool wfd_sink_is_session_started(struct wfd_sink *sink) bool wfd_sink_is_session_started(struct wfd_sink *sink)

View file

@ -22,6 +22,7 @@
#include <signal.h> #include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#include <systemd/sd-event.h> #include <systemd/sd-event.h>
#include "ctl.h" #include "ctl.h"
#include "wfd.h" #include "wfd.h"
@ -71,21 +72,25 @@ error:
return r; return r;
} }
static void ctl_wfd_destroy(struct ctl_wfd *wfd)
{
ctl_wifi_free(wfd->wifi);
wfd->wifi = NULL;
shl_htable_clear_str(&wfd->sinks, NULL, NULL);
shl_htable_clear_u64(&wfd->sessions, NULL, NULL);
}
static void ctl_wfd_free(struct ctl_wfd *wfd) static void ctl_wfd_free(struct ctl_wfd *wfd)
{ {
int i;
if(!wfd) { if(!wfd) {
return; return;
} }
ctl_wfd_destroy(wfd); ctl_wifi_free(wfd->wifi);
wfd->wifi = NULL;
shl_htable_clear_str(&wfd->sinks, NULL, NULL);
shl_htable_clear_u64(&wfd->sessions, NULL, NULL);
for(i = 0; i < SHL_ARRAY_LENGTH(wfd->signal_sources); ++ i) {
if(wfd->signal_sources[i]) {
sd_event_source_set_enabled(wfd->signal_sources[i], SD_EVENT_OFF);
sd_event_source_unref(wfd->signal_sources[i]);
}
}
if(wfd->loop) { if(wfd->loop) {
sd_event_unref(wfd->loop); sd_event_unref(wfd->loop);
@ -99,7 +104,7 @@ int ctl_wfd_add_sink(struct ctl_wfd *wfd,
union wfd_sube *sube, union wfd_sube *sube,
struct wfd_sink **out) struct wfd_sink **out)
{ {
_wfd_sink_free_ struct wfd_sink *s; _wfd_sink_free_ struct wfd_sink *s = NULL;
int r = shl_htable_lookup_str(&wfd->sinks, int r = shl_htable_lookup_str(&wfd->sinks,
p->label, p->label,
NULL, NULL,
@ -223,7 +228,11 @@ int ctl_wfd_remove_session_by_id(struct ctl_wfd *wfd,
static int ctl_wfd_fetch_info(sd_event_source *s, void *userdata) static int ctl_wfd_fetch_info(sd_event_source *s, void *userdata)
{ {
struct ctl_wfd *wfd = userdata; struct ctl_wfd *wfd = userdata;
int r = ctl_wifi_fetch(wfd->wifi); int r;
sd_event_source_unref(s);
r = ctl_wifi_fetch(wfd->wifi);
if(0 > r) { if(0 > r) {
log_warning("failed to fetch information about links and peers: %s", log_warning("failed to fetch information about links and peers: %s",
strerror(errno)); strerror(errno));
@ -238,7 +247,8 @@ static int ctl_wfd_handle_signal(sd_event_source *s,
void *userdata) void *userdata)
{ {
struct ctl_wfd *wfd = userdata; struct ctl_wfd *wfd = userdata;
ctl_wfd_destroy(wfd);
sd_event_source_set_enabled(s, false);
return sd_event_exit(wfd->loop, 0); return sd_event_exit(wfd->loop, 0);
} }
@ -246,10 +256,12 @@ static int ctl_wfd_handle_signal(sd_event_source *s,
static int ctl_wfd_init(struct ctl_wfd *wfd, sd_bus *bus) static int ctl_wfd_init(struct ctl_wfd *wfd, sd_bus *bus)
{ {
int i, r; int i, r;
const int signals[] = { SIGINT, SIGHUP, SIGQUIT, SIGTERM }; const int signals[SHL_ARRAY_LENGTH(wfd->signal_sources)] = {
SIGINT, SIGHUP, SIGQUIT, SIGTERM
};
struct ctl_wifi *wifi; struct ctl_wifi *wifi;
for(i = 0; i < SHL_ARRAY_LENGTH(signals); i ++) { for(i = 0; i < SHL_ARRAY_LENGTH(wfd->signal_sources); i ++) {
sigset_t mask; sigset_t mask;
sigemptyset(&mask); sigemptyset(&mask);
sigaddset(&mask, signals[i]); sigaddset(&mask, signals[i]);
@ -259,7 +271,7 @@ static int ctl_wfd_init(struct ctl_wfd *wfd, sd_bus *bus)
} }
r = sd_event_add_signal(wfd->loop, r = sd_event_add_signal(wfd->loop,
NULL, &wfd->signal_sources[i],
signals[i], signals[i],
ctl_wfd_handle_signal, ctl_wfd_handle_signal,
wfd); wfd);
@ -286,11 +298,6 @@ end:
return r; return r;
} }
int ctl_wfd_run(struct ctl_wfd *wfd)
{
return sd_event_loop(wfd->loop);
}
/* Callbacks from ctl-src */ /* Callbacks from ctl-src */
void wfd_fn_src_connected(struct wfd_src *s) void wfd_fn_src_connected(struct wfd_src *s)
{ {
@ -366,12 +373,7 @@ void ctl_fn_peer_free(struct ctl_peer *p)
label = strdup(s->label); label = strdup(s->label);
r = wfd_fn_sink_free(s); wfd_fn_sink_free(s);
if(0 > r) {
log_warning("failed to unpublish removed sink (%s): %s",
wfd_sink_get_label(s),
strerror(errno));
}
wfd_sink_free(s); wfd_sink_free(s);
@ -417,6 +419,7 @@ void cli_fn_help()
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int r; int r;
sd_event *loop; sd_event *loop;
sd_bus *bus; sd_bus *bus;
@ -457,25 +460,26 @@ int main(int argc, char **argv)
r = wfd_dbus_expose(wfd_dbus); r = wfd_dbus_expose(wfd_dbus);
if(0 > r) { if(0 > r) {
log_warning("unabled to publish WFD service: %s", strerror(errno)); log_warning("unabled to publish WFD service: %s", strerror(errno));
goto free_ctl_wfd; goto free_wfd_dbus;
} }
r = ctl_wfd_run(wfd); r = sd_event_loop(loop);
if(0 > r) { if(0 > r) {
log_warning("unabled to keep WFD service running: %s", strerror(errno)); log_warning("unabled to keep WFD service running: %s", strerror(errno));
} }
free_wfd_dbus:
wfd_dbus_free(wfd_dbus); wfd_dbus_free(wfd_dbus);
wfd_dbus = NULL; wfd_dbus = NULL;
free_ctl_wfd: free_ctl_wfd:
ctl_wfd_free(wfd); ctl_wfd_free(wfd);
wfd = NULL; wfd = NULL;
bus_detach_event: bus_detach_event:
sd_bus_detach_event(bus); sd_bus_detach_event(bus);
unref_bus: unref_bus:
sd_bus_unref(bus); sd_bus_flush_close_unref(bus);
unref_loop: unref_loop:
sd_event_run(loop, 0);
sd_event_unref(loop); sd_event_unref(loop);
end: end:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;