1
0
Fork 0
mirror of https://github.com/albfan/miraclecast.git synced 2025-02-13 10:01:55 +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()
{
kill 0
set -x
for (( i=${#cleanup[@]}-1; i>=0; --i )); do
eval ${cleanup[$i]} || true
set +e
while (( 0 != ${#cleanup[@]} )); do
eval ${cleanup[${#cleanup[@]}-1]}
unset cleanup[${#cleanup[@]}-1]
done
}
@ -115,6 +115,14 @@ cleanup_push()
cleanup+=("$*")
}
nm_manage()
{
set_prop org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager/Devices/"$nm_link_index" \
org.freedesktop.NetworkManager.Device \
Managed b true
}
link_unmanage()
{
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.Device \
Managed b false
cleanup_push nm_manage
set_prop org.freedesktop.miracle.wifi \
/org/freedesktop/miracle/wifi/link/$link_index \
org.freedesktop.miracle.wifi.Link \
@ -179,6 +188,8 @@ get_prop org.freedesktop.miracle.wifi \
org.freedesktop.miracle.wifi.Peer \
Interface p2p_iface
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
echo please run miracle-wfdctl manually
sleep 3

View file

@ -198,6 +198,8 @@ struct wfd_sink
union wfd_sube dev_info;
char *label;
struct wfd_session *session;
sd_event_source *session_cleanup_source;
};
int wfd_sink_new(struct wfd_sink **out,
@ -237,6 +239,8 @@ struct ctl_wfd
struct shl_htable sessions;
size_t n_sessions;
uint64_t id_pool;
sd_event_source *signal_sources[4];
};
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)
{
int i, r;
_sd_bus_message_unref_ sd_bus_message *m;
_sd_bus_message_unref_ sd_bus_message *m = NULL;
if(!wfd_dbus) {
return -ECANCELED;
@ -209,7 +209,7 @@ int _wfd_dbus_object_added(struct wfd_dbus *wfd_dbus,
size_t n_ifaces)
{
int i, r;
_sd_bus_message_unref_ sd_bus_message *m;
_sd_bus_message_unref_ sd_bus_message *m = NULL;
if(!wfd_dbus) {
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)
{
_shl_free_ char *path;
_shl_free_ char *path = NULL;
int r = sd_bus_path_encode("/org/freedesktop/miracle/wfd/sink",
wfd_sink_get_label(s),
&path);
@ -264,7 +264,7 @@ int wfd_fn_sink_new(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",
wfd_sink_get_label(s),
&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)
{
_shl_free_ char *path;
_shl_free_ char *path = NULL;
int r;
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)
{
_shl_free_ char *path;
_shl_free_ char *path = NULL;
int r = wfd_dbus_get_session_path(s, &path);
if(0 > 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)
{
_shl_free_ char *path;
_shl_free_ char *path = NULL;
int r = wfd_dbus_get_session_path(s, &path);
if(0 > r) {
return r;
@ -424,6 +424,30 @@ static int wfd_dbus_sink_start_session(sd_bus_message *m,
// 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,
const char *path,
const char *interface,
@ -433,7 +457,7 @@ static int wfd_dbus_sink_get_peer(sd_bus *bus,
sd_bus_error *ret_error)
{
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",
s->label,
&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)
{
_shl_free_ char *path;
_shl_free_ char *path = NULL;
int r;
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("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("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_VTABLE_END,
};

View file

@ -30,10 +30,13 @@ struct wfd_out_session
struct wfd_session parent;
struct wfd_sink *sink;
int fd;
sd_event_source *gst_term_source;
};
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)
{
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)
{
if(-1 != s->stream.gst) {
kill(s->stream.gst, SIGTERM);
s->stream.gst = -1;
pid_t pid;
struct wfd_out_session *os = wfd_out_session(s);
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")));
}
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);
wfd_out_session_kill_gst(s);
if(0 <= os->fd) {
close(os->fd);
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)
@ -305,7 +308,6 @@ static int wfd_out_session_request_get_parameter(struct wfd_session *s,
return 0;
error:
wfd_session_end(s);
return r;
}
@ -425,7 +427,6 @@ static int wfd_out_session_launch_gst(struct wfd_session *s, pid_t *out)
char port[10];
char * args[] = {
"gst-launch-1.0",
"-v",
"ximagesrc",
"use-damage=false",
"show-pointer=false",
@ -473,9 +474,21 @@ static int wfd_out_session_handle_gst_term(sd_event_source *source,
const siginfo_t *si,
void *userdata)
{
struct wfd_out_session *os = userdata;
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;
}
@ -530,7 +543,7 @@ static int wfd_out_session_handle_play_request(struct wfd_session *s,
struct rtsp_message *req,
struct rtsp_message **out_rep)
{
_shl_free_ char *v;
_shl_free_ char *v = NULL;
_rtsp_message_unref_ struct rtsp_message *m = NULL;
pid_t gst;
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(),
NULL,
&wfd_out_session(s)->gst_term_source,
gst, WEXITED,
wfd_out_session_handle_gst_term,
s);
if(0 > r) {
kill(gst, SIGKILL);
waitpid(gst, &status, WNOHANG);
return r;
wfd_session_teardown(s);
}
s->stream.gst = gst;
else {
*out_rep = m;
m = NULL;
}
return 0;
return r;
}
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,
struct rtsp_message **out)
{
_rtsp_message_unref_ struct rtsp_message *m;
_rtsp_message_unref_ struct rtsp_message *m = NULL;
_shl_free_ char *body = NULL;
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_teardown(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[] = {
[WFD_SESSION_DIR_OUT] = {
@ -53,8 +53,7 @@ const struct wfd_session_vtable session_vtbl[] = {
.resume = wfd_out_session_resume,
.pause = wfd_out_session_pause,
.teardown = wfd_out_session_teardown,
.end = wfd_out_session_end,
.distruct = wfd_out_session_distruct,
.destroy = wfd_out_session_destroy,
}
};
@ -178,6 +177,9 @@ int wfd_session_teardown(struct wfd_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(!session_vtbl[s->dir].teardown) {
return 0;
@ -186,41 +188,21 @@ int wfd_session_teardown(struct wfd_session *s)
return session_vtbl[s->dir].teardown(s);;
}
wfd_session_end(s);
wfd_session_free(s);
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)
{
if(!s) {
return;
}
if(session_vtbl[s->dir].destroy) {
(*session_vtbl[s->dir].destroy)(s);
}
if(s->vformats) {
wfd_video_formats_free(s->vformats);
s->vformats = NULL;
@ -236,16 +218,15 @@ void wfd_session_free(struct wfd_session *s)
s->stream.url = NULL;
}
if(s->rtsp) {
rtsp_unref(s->rtsp);
s->rtsp = NULL;
}
s->rtp_ports[0] = 0;
s->rtp_ports[1] = 0;
s->last_request = RTSP_M_UNKNOWN;
wfd_session_end(s);
if(session_vtbl[s->dir].distruct) {
(*session_vtbl[s->dir].distruct)(s);
}
free(s);
}
@ -402,6 +383,10 @@ static int wfd_session_post_handle_request_n_reply(struct wfd_session *s,
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;
}
@ -454,7 +439,7 @@ static int wfd_session_handle_request(struct rtsp *bus,
return 0;
error:
wfd_session_end(s);
wfd_session_teardown(s);
return r;
@ -498,7 +483,8 @@ static int wfd_session_handle_reply(struct rtsp *bus,
return 0;
error:
wfd_session_end(s);
wfd_session_teardown(s);
return r;
}
@ -552,6 +538,7 @@ static int wfd_session_handle_io(sd_event_source *source,
_rtsp_unref_ struct rtsp *rtsp = NULL;
sd_event_source_set_enabled(source, SD_EVENT_OFF);
sd_event_source_unref(source);
if (mask & EPOLLERR) {
r = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len);
@ -597,7 +584,7 @@ static int wfd_session_handle_io(sd_event_source *source,
end:
if (0 > r) {
wfd_session_end(s);
wfd_session_teardown(s);
}
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_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;
@ -89,8 +88,7 @@ struct wfd_session_vtable
int (*resume)(struct wfd_session *);
int (*pause)(struct wfd_session *);
int (*teardown)(struct wfd_session *);
void (*end)(struct wfd_session *s);
void (*distruct)(struct wfd_session *s);
void (*destroy)(struct wfd_session *s);
};
struct wfd_session
@ -110,7 +108,6 @@ struct wfd_session
enum wfd_stream_id id;
char *url;
uint16_t rtp_port;
pid_t gst;
} stream;
};

View file

@ -24,6 +24,34 @@
#include "ctl.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,
struct ctl_peer *peer,
union wfd_sube *sube)
@ -55,12 +83,16 @@ int wfd_sink_new(struct wfd_sink **out,
void wfd_sink_free(struct wfd_sink *sink)
{
struct wfd_session *s;
if(!sink) {
return;
}
if(sink->session) {
wfd_session_free(sink->session);
s = sink->session;
wfd_sink_set_session(sink, NULL);
wfd_session_free(s);
}
if(sink->label) {
@ -107,7 +139,7 @@ int wfd_sink_start_session(struct wfd_sink *sink, struct wfd_session **out)
return r;
}
r = ctl_wfd_add_session(ctl_wfd_get(), s);
r = wfd_sink_set_session(sink, s);
if(0 > r) {
return r;
}
@ -121,43 +153,13 @@ int wfd_sink_start_session(struct wfd_sink *sink, struct wfd_session **out)
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)
{
struct wfd_sink *sink;
uint64_t now = 0;
assert(wfd_is_out_session(s));
sink = wfd_out_session_get_sink(s);
sink->session = NULL;
wfd_sink_set_session(wfd_out_session_get_sink(s), NULL);
wfd_fn_sink_properties_changed(sink, "Session");
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);
return 0;
}
bool wfd_sink_is_session_started(struct wfd_sink *sink)

View file

@ -22,6 +22,7 @@
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <systemd/sd-event.h>
#include "ctl.h"
#include "wfd.h"
@ -71,21 +72,25 @@ error:
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)
{
int i;
if(!wfd) {
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) {
sd_event_unref(wfd->loop);
@ -99,7 +104,7 @@ int ctl_wfd_add_sink(struct ctl_wfd *wfd,
union wfd_sube *sube,
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,
p->label,
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)
{
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) {
log_warning("failed to fetch information about links and peers: %s",
strerror(errno));
@ -238,7 +247,8 @@ static int ctl_wfd_handle_signal(sd_event_source *s,
void *userdata)
{
struct ctl_wfd *wfd = userdata;
ctl_wfd_destroy(wfd);
sd_event_source_set_enabled(s, false);
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)
{
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;
for(i = 0; i < SHL_ARRAY_LENGTH(signals); i ++) {
for(i = 0; i < SHL_ARRAY_LENGTH(wfd->signal_sources); i ++) {
sigset_t mask;
sigemptyset(&mask);
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,
NULL,
&wfd->signal_sources[i],
signals[i],
ctl_wfd_handle_signal,
wfd);
@ -286,11 +298,6 @@ end:
return r;
}
int ctl_wfd_run(struct ctl_wfd *wfd)
{
return sd_event_loop(wfd->loop);
}
/* Callbacks from ctl-src */
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);
r = 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_fn_sink_free(s);
wfd_sink_free(s);
@ -417,6 +419,7 @@ void cli_fn_help()
int main(int argc, char **argv)
{
int r;
sd_event *loop;
sd_bus *bus;
@ -457,25 +460,26 @@ int main(int argc, char **argv)
r = wfd_dbus_expose(wfd_dbus);
if(0 > r) {
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) {
log_warning("unabled to keep WFD service running: %s", strerror(errno));
}
free_wfd_dbus:
wfd_dbus_free(wfd_dbus);
wfd_dbus = NULL;
free_ctl_wfd:
ctl_wfd_free(wfd);
wfd = NULL;
bus_detach_event:
sd_bus_detach_event(bus);
unref_bus:
sd_bus_unref(bus);
sd_bus_flush_close_unref(bus);
unref_loop:
sd_event_run(loop, 0);
sd_event_unref(loop);
end:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;