1
0
Fork 0
mirror of https://github.com/albfan/miraclecast.git synced 2025-02-12 20:51:55 +00:00

miracle-dispd: run encoder with user privilege

now we run encoder with unprivileged user and talk through session bus

Change-Id: I09b3b8b15e5a7c7e9b883b7c9dbac601c13f458c
This commit is contained in:
Derek Dai 2017-04-26 22:49:47 +08:00
parent ba10255f70
commit 6415de46fa
No known key found for this signature in database
GPG key ID: E109CC97553EF009
11 changed files with 507 additions and 123 deletions

View file

@ -476,6 +476,8 @@ private class WfdCtl : GLib.Application
return "playing";
case 7:
return "tearing down";
case 8:
return "destroyed";
}
return "unknown";

View file

@ -319,14 +319,13 @@ internal class GstEncoder : DispdEncoder, GLib.Object
public async void prepare() throws Error
{
conn = yield Bus.get(BusType.SYSTEM);
conn = yield Bus.get(BusType.SESSION);
conn.register_object(DispdEncoder.OBJECT_PATH, this as DispdEncoder);
string bus_info = "%s\n%s".printf(conn.unique_name,
BusType.get_address_sync(BusType.SESSION));
/* we are ready, tell parent how to communicate with us */
unowned string unique_name = conn.unique_name;
ssize_t r = Posix.write(3,
(void *) unique_name.data,
unique_name.length);
ssize_t r = Posix.write(3, (void *) bus_info.data, bus_info.length);
if(0 > r) {
throw new DispdEncoderError.CANT_RETURN_UNIQUE_NAME("%s",
Posix.strerror(Posix.errno));

View file

@ -83,8 +83,16 @@ enum wfd_audio_server_type
int wfd_out_session_new(struct wfd_session **out,
unsigned int id,
struct wfd_sink *sink);
struct wfd_session * wfd_session_ref(struct wfd_session *s);
void wfd_session_unref(struct wfd_session *s);
struct wfd_session * _wfd_session_ref(struct wfd_session *s);
#define wfd_session_ref(s) ( \
log_debug("wfd_session_ref(%p): %d => %d", (s), *(int *) s, 1 + *(int *) s), \
_wfd_session_ref(s) \
)
void _wfd_session_unref(struct wfd_session *s);
#define wfd_session_unref(s) { \
log_debug("wfd_session_unref(%p): %d => %d", (s), *(int *) s, *(int *) s - 1); \
_wfd_session_unref(s); \
}
void wfd_session_unrefp(struct wfd_session **s);
unsigned int * wfd_session_to_htable(struct wfd_session *s);
@ -117,7 +125,10 @@ int wfd_session_set_disp_dimension(struct wfd_session *s, const struct wfd_recta
enum wfd_audio_server_type wfd_session_get_audio_type(struct wfd_session *s);
int wfd_session_set_audio_type(struct wfd_session *s, enum wfd_audio_server_type audio_type);
const char * wfd_session_get_audio_dev_name(struct wfd_session *s);
int wfd_session_set_audio_dev_name(struct wfd_session *s, char *audio_dev_name);
int wfd_session_set_audio_dev_name(struct wfd_session *s, const char *audio_dev_name);
const char * wfd_session_get_runtime_path(struct wfd_session *s);
int wfd_session_set_runtime_path(struct wfd_session *s,
const char *runtime_path);
uid_t wfd_session_get_client_uid(struct wfd_session *s);
int wfd_session_set_client_uid(struct wfd_session *s, uid_t uid);
uid_t wfd_session_get_client_gid(struct wfd_session *s);

View file

@ -22,6 +22,7 @@
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <fcntl.h>
#include "dispd-encoder.h"
#include "shl_macro.h"
#include "shl_log.h"
@ -42,26 +43,30 @@ struct dispd_encoder
sd_bus_slot *name_disappeared_slot;
sd_bus_slot *state_change_notify_slot;
char *name;
uid_t bus_owner;
uid_t bus_group;
char *bus_name;
enum dispd_encoder_state state;
dispd_encoder_state_change_handler handler;
void *userdata;
};
static int dispd_encoder_new(struct dispd_encoder **out);
static int on_unique_readable(sd_event_source *source,
static int dispd_encoder_new(struct dispd_encoder **out,
uid_t bus_owner,
gid_t bus_group);
static int on_bus_info_readable(sd_event_source *source,
int fd,
uint32_t events,
void *userdata);
static void dispd_encoder_set_state(struct dispd_encoder *e,
enum dispd_encoder_state state);
static int dispd_encoder_exec(const char *cmd, int fd, struct wfd_session *s)
static void dispd_encoder_exec(const char *cmd, int fd, struct wfd_session *s)
{
int r;
sigset_t mask;
char disp[16], auth[256];
char disp[16], runtime_path[256];
log_info("child forked with pid %d", getpid());
@ -70,30 +75,50 @@ static int dispd_encoder_exec(const char *cmd, int fd, struct wfd_session *s)
sigprocmask(SIG_SETMASK, &mask, NULL);
snprintf(disp, sizeof(disp), "DISPLAY=%s", wfd_session_get_disp_name(s));
snprintf(auth, sizeof(auth), "XAUTHORITY=%s", wfd_session_get_disp_auth(s));
snprintf(runtime_path, sizeof(runtime_path), "XDG_RUNTIME_DIR=%s", wfd_session_get_runtime_path(s));
/* after encoder connected to DBus, write unique name to fd 3,
* so we can controll it through DBus
*/
r = dup2(fd, 3);
if(0 > r) {
return log_ERRNO();
log_vERRNO();
goto error;
}
if(fd != 3) {
close(fd);
}
// TODO run encoder as normal user instead of root
// TODO drop caps and don't let user raises thier caps
log_debug("uid=%d, euid=%d", getuid(), geteuid());
r = setgid(wfd_session_get_client_gid(s));
if(0 > r) {
log_vERRNO();
goto error;
}
r = setuid(wfd_session_get_client_uid(s));
if(0 > r) {
log_vERRNO();
goto error;
}
log_debug("uid=%d, euid=%d", getuid(), geteuid());
r = execvpe(cmd,
(char *[]){ (char *) cmd, NULL },
(char *[]){ disp,
auth,
runtime_path,
"G_MESSAGES_DEBUG=all",
NULL
});
if(0 > r) {
log_vERRNO();
goto error;
}
error:
_exit(1);
return 0;
}
static void dispd_encoder_close_pipe(struct dispd_encoder *e)
@ -184,7 +209,7 @@ static int on_child_terminated(sd_event_source *source,
{
struct dispd_encoder *e = userdata;
log_info("encoder %d terminated", si->si_pid);
log_info("encoder process %d terminated", si->si_pid);
dispd_encoder_set_state(e, DISPD_ENCODER_STATE_TERMINATED);
dispd_encoder_cleanup(e);
@ -194,37 +219,35 @@ static int on_child_terminated(sd_event_source *source,
int dispd_encoder_spawn(struct dispd_encoder **out, struct wfd_session *s)
{
pid_t pid;
_dispd_encoder_unref_ struct dispd_encoder *e = NULL;
int fds[2] = { -1, -1 };
pid_t pid;
int r;
assert_ret(out);
assert_ret(s);
r = dispd_encoder_new(&e);
r = dispd_encoder_new(&e,
wfd_session_get_client_uid(s),
wfd_session_get_client_gid(s));
if(0 > r) {
goto end;
}
r = pipe(fds);
r = pipe2(fds, O_NONBLOCK);
if(0 > r) {
goto end;
}
pid = fork();
if(0 > pid) {
r = pid;
r = log_ERRNO();
goto kill_encoder;
}
else if(!pid) {
close(fds[0]);
r = dispd_encoder_exec("gstencoder", fds[1], s);
if(0 > r) {
log_warning("failed to exec encoder: %s", strerror(errno));
}
_exit(1);
dispd_encoder_exec("gstencoder", fds[1], s);
}
r = sd_event_add_child(ctl_wfd_get_loop(),
@ -241,7 +264,7 @@ int dispd_encoder_spawn(struct dispd_encoder **out, struct wfd_session *s)
&e->pipe_source,
fds[0],
EPOLLIN,
on_unique_readable,
on_bus_info_readable,
dispd_encoder_ref(e));
if(0 > r) {
goto close_pipe;
@ -262,11 +285,14 @@ end:
return log_ERRNO();
}
static int dispd_encoder_new(struct dispd_encoder **out)
static int dispd_encoder_new(struct dispd_encoder **out,
uid_t bus_owner,
gid_t bus_group)
{
_shl_free_ struct dispd_encoder *e = NULL;
_dispd_encoder_unref_ struct dispd_encoder *e = NULL;
assert_ret(out);
// assert_ret(bus_addr);
e = calloc(1, sizeof(struct dispd_encoder));
if(!e) {
@ -274,16 +300,22 @@ static int dispd_encoder_new(struct dispd_encoder **out)
}
e->ref = 1;
*out = e;
e = NULL;
e->bus_owner = bus_owner;
e->bus_group = bus_group;
// e->bus_addr = strdup(bus_addr);
// if(!e->bus_addr) {
// return log_ENOMEM();
// }
*out = dispd_encoder_ref(e);
return 0;
}
struct dispd_encoder * dispd_encoder_ref(struct dispd_encoder *e)
{
assert_retv(e, NULL);
assert_retv(0 < e->ref, NULL);
assert_retv(e, e);
assert_retv(0 < e->ref, e);
++ e->ref;
@ -310,13 +342,18 @@ void dispd_encoder_unref(struct dispd_encoder *e)
/* since we encrease ref count at creation of every sources and slots,
* once we get here, it means no sources and slots exist anymore */
if(e->bus) {
sd_bus_detach_event(e->bus);
sd_bus_unref(e->bus);
}
if(e->name) {
free(e->name);
if(e->bus_name) {
free(e->bus_name);
}
// if(e->bus_addr) {
// free(e->bus_addr);
// }
free(e);
}
@ -448,7 +485,7 @@ static int on_encoder_disappeared(sd_bus_message *m,
struct dispd_encoder *e = userdata;
int r;
log_info("encoder %s disappered", e->name);
log_info("encoder %s disappered from bus", e->bus_name);
r = dispd_encoder_kill_child(e);
if(0 > r) {
@ -463,43 +500,123 @@ static int on_encoder_disappeared(sd_bus_message *m,
return 0;
}
static int on_unique_readable(sd_event_source *source,
static int read_line(int fd, char *b, size_t len)
{
int r;
char *p = b;
assert_ret(0 <= fd);
assert_ret(b);
assert_ret(len);
while((p - b) < (len - 1)) {
r = read(fd, p, 1);
if(0 > r) {
if(EINTR == errno) {
continue;
}
else if(EAGAIN == errno) {
break;
}
return log_ERRNO();
}
else if(!r || '\n' == *p) {
break;
}
++ p;
}
*p = '\0';
return p - b;
}
static int on_bus_info_readable(sd_event_source *source,
int fd,
uint32_t events,
void *userdata)
{
struct dispd_encoder *e = userdata;
char buf[1024];
ssize_t r;
char buf[512];
int r;
r = read(fd, buf, sizeof(buf) - 1);
r = read_line(fd, buf, sizeof(buf) - 1);
if(0 > r) {
if(EAGAIN == errno) {
return 0;
}
log_vERR(r);
goto error;
}
else if(!r) {
log_warning("no bus name returned from encoder: %s",
strerror(errno));
log_warning("no bus name returned from encoder");
r = -ENOENT;
goto error;
}
// TODO remove heading and trailing speces from buf before strdup()
buf[r] = '\0';
log_info("got bus name from encoder: %s", buf);
e->name = strdup(buf);
if(!e->name) {
e->bus_name = strdup(buf);
if(!e->bus_name) {
log_vERRNO();
goto error;
}
// TODO connect to encoder through user session bus
r = sd_bus_default_system(&e->bus);
r = read_line(fd, buf, sizeof(buf) - 1);
if(0 > r) {
log_vERR(r);
goto error;
}
else if(!r) {
log_warning("no bus address returned from encoder");
r = -ENOENT;
goto error;
}
log_info("got bus address from encoder: %s", buf);
log_debug(">>> uid=%d, euid=%d", getuid(), geteuid());
r = seteuid(e->bus_owner);
if(0 > r) {
log_vERRNO();
goto error;
}
r = sd_bus_new(&e->bus);
if(0 > r) {
log_vERR(r);
goto error;
}
r = sd_bus_set_address(e->bus, buf);
if(0 > r) {
log_vERR(r);
goto error;
}
r = sd_bus_set_bus_client(e->bus, true);
if(0 > r) {
log_vERR(r);
goto error;
}
r = sd_bus_start(e->bus);
if(0 > r) {
log_vERR(r);
goto error;
}
r = sd_bus_attach_event(e->bus, ctl_wfd_get_loop(), 0);
if(0 > r) {
log_vERR(r);
goto error;
}
r = seteuid(0);
if(0 > r) {
log_vERRNO();
goto error;
}
log_debug("<<< uid=%d, euid=%d", getuid(), geteuid());
snprintf(buf, sizeof(buf),
"type='signal',"
@ -508,36 +625,52 @@ static int on_unique_readable(sd_event_source *source,
"interface='org.freedesktop.DBus.Properties',"
"member='PropertiesChanged',"
"arg0='org.freedesktop.miracle.encoder'",
e->name);
e->bus_name);
if(0 > r) {
log_vERRNO();
goto error;
}
r = sd_bus_add_match(e->bus,
&e->state_change_notify_slot,
buf,
on_encoder_properties_changed,
dispd_encoder_ref(e));
if(0 > r) {
log_vERRNO();
goto error;
}
snprintf(buf, sizeof(buf),
r = snprintf(buf, sizeof(buf),
"type='signal',"
"sender='org.freedesktop.DBus',"
"path='/org/freedesktop/DBus',"
"interface='org.freedesktop.DBus',"
"member='NameOwnerChanged',"
"arg0namespace='%s'",
e->name);
e->bus_name);
if(0 > r) {
log_vERRNO();
goto error;
}
r = sd_bus_add_match(e->bus,
&e->name_disappeared_slot,
buf,
on_encoder_disappeared,
dispd_encoder_ref(e));
if(0 > r) {
log_vERRNO();
goto error;
}
dispd_encoder_set_state(e, DISPD_ENCODER_STATE_SPAWNED);
goto end;
error:
log_vERRNO();
seteuid(0);
log_debug("<<< uid=%d, euid=%d", getuid(), geteuid());
dispd_encoder_kill_child(e);
end:
dispd_encoder_close_pipe(e);
@ -617,17 +750,17 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
r = sd_bus_message_new_method_call(e->bus,
&call,
e->name,
e->bus_name,
"/org/freedesktop/miracle/encoder",
"org.freedesktop.miracle.encoder",
"Configure");
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = sd_bus_message_open_container(call, 'a', "{iv}");
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
sink = wfd_out_session_get_sink(s);
@ -636,7 +769,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
"s",
sink->peer->remote_address);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = config_append(call,
@ -644,7 +777,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
"u",
s->stream.rtp_port);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
if(s->stream.rtcp_port) {
@ -653,7 +786,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
"u",
s->stream.rtcp_port);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
}
@ -662,7 +795,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
"s",
sink->peer->local_address);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
if(s->stream.rtcp_port) {
@ -671,7 +804,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
"u",
s->stream.rtcp_port);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
}
@ -682,7 +815,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
"u",
rect->x);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = config_append(call,
@ -690,7 +823,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
"u",
rect->y);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = config_append(call,
@ -698,7 +831,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
"u",
rect->width);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = config_append(call,
@ -706,23 +839,32 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
"u",
rect->height);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
}
r = sd_bus_message_close_container(call);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
// log_debug(">>> uid=%d, euid=%d", getuid(), geteuid());
// r = seteuid(e->bus_owner);
if(0 > r) {
log_vERR(r);
goto end;
}
r = sd_bus_call(e->bus, call, 0, &error, &reply);
if(0 > r) {
log_warning("%s: %s", error.name, error.message);
sd_bus_error_free(&error);
return log_ERRNO();
log_vERR(r);
}
return 0;
end:
// seteuid(0);
// log_debug("<<< uid=%d, euid=%d", getuid(), geteuid());
return r;
}
static int dispd_encoder_call(struct dispd_encoder *e, const char *method)
@ -738,7 +880,7 @@ static int dispd_encoder_call(struct dispd_encoder *e, const char *method)
r = sd_bus_message_new_method_call(e->bus,
&call,
e->name,
e->bus_name,
"/org/freedesktop/miracle/encoder",
"org.freedesktop.miracle.encoder",
method);
@ -747,6 +889,13 @@ static int dispd_encoder_call(struct dispd_encoder *e, const char *method)
goto error;
}
// log_debug(">>> uid=%d, euid=%d", getuid(), geteuid());
// r = seteuid(e->bus_owner);
if(0 > r) {
log_vERR(r);
goto error;
}
r = sd_bus_call(e->bus, call, 0, &error, &reply);
if(0 > r) {
log_warning("%s: %s", error.name, error.message);
@ -756,6 +905,8 @@ static int dispd_encoder_call(struct dispd_encoder *e, const char *method)
return 0;
error:
// seteuid(0);
// log_debug("<<< uid=%d, euid=%d", getuid(), geteuid());
dispd_encoder_kill_child(e);
return r;

View file

@ -73,7 +73,7 @@ int ctl_wfd_new(struct ctl_wfd **out, sd_event *loop, sd_bus *bus)
error:
ctl_wfd_free(wfd);
return log_ERRNO();
return log_ERR(r);
}
static void ctl_wfd_free(struct ctl_wfd *wfd)
@ -144,14 +144,14 @@ int ctl_wfd_add_sink(struct ctl_wfd *wfd,
r = wfd_sink_new(&s, p, sube);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = shl_htable_insert_str(&wfd->sinks,
wfd_sink_to_htable(s),
NULL);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
++wfd->n_sinks;
@ -209,7 +209,7 @@ int ctl_wfd_add_session(struct ctl_wfd *wfd, struct wfd_session *s)
r = shl_htable_insert_uint(&wfd->sessions, wfd_session_to_htable(s));
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
++wfd->n_sessions;
@ -367,7 +367,7 @@ void ctl_fn_peer_new(struct ctl_peer *p)
r = wfd_sube_parse(sube_str, &sube);
if(0 > r) {
log_debug("peer %s has invalid subelement", p->label);
return log_vERRNO();
return log_vERR(r);
}
if(wfd_sube_device_is_sink(&sube)) {

View file

@ -410,17 +410,67 @@ static int wfd_dbus_find_session(sd_bus *bus,
return r;
}
static int get_user_runtime_path(char **out, sd_bus *bus, uid_t uid)
{
_sd_bus_message_unref_ sd_bus_message *rep = NULL;
_sd_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
char p[256];
char *rp;
int r;
assert_ret(out);
assert_ret(bus);
assert_ret(0 < uid);
r = snprintf(p, sizeof(p), "/org/freedesktop/login1/user/_%d", uid);
if(0 > r) {
return log_ERRNO();
}
r = sd_bus_call_method(bus,
"org.freedesktop.login1",
p,
"org.freedesktop.DBus.Properties",
"Get",
&error,
&rep,
"ss",
"org.freedesktop.login1.User",
"RuntimePath");
if(0 > r) {
log_warning("%s: %s", error.name, error.message);
return r;
}
r = sd_bus_message_read(rep, "v", "s", &rp);
if(0 > r) {
return log_ERR(r);
}
*out = strdup(rp);
if(!*out) {
return log_ENOMEM();
}
return 0;
}
static int wfd_dbus_sink_start_session(sd_bus_message *m,
void *userdata,
sd_bus_error *ret_error)
{
struct wfd_sink *sink = userdata;
_wfd_session_unref_ struct wfd_session *sess = NULL;
_shl_free_ char *path = NULL, *disp_type_name = NULL, *disp_name = NULL;
_sd_bus_creds_unref_ sd_bus_creds *creds = NULL;
_shl_free_ char *runtime_path = NULL;
struct wfd_sink *sink = userdata;
char *disp_params;
const char *disp, *disp_auth;
const char *audio_dev;
struct wfd_rectangle rect;
pid_t pid;
uid_t uid;
gid_t gid;
int r;
r = sd_bus_message_read(m,
@ -433,7 +483,7 @@ static int wfd_dbus_sink_start_session(sd_bus_message *m,
&rect.height,
&audio_dev);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = sscanf(disp, "%m[^:]://%ms",
@ -449,12 +499,12 @@ static int wfd_dbus_sink_start_session(sd_bus_message *m,
r = wfd_sink_create_session(sink, &sess);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
wfd_session_set_disp_type(sess, WFD_DISPLAY_SERVER_TYPE_X);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
disp_params = strchr(disp_name, '?');
@ -464,47 +514,92 @@ static int wfd_dbus_sink_start_session(sd_bus_message *m,
r = wfd_session_set_disp_name(sess, disp_name);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = wfd_session_set_disp_params(sess, disp_params);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = wfd_session_set_disp_auth(sess, disp_auth);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = wfd_session_set_disp_dimension(sess, &rect);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = wfd_session_set_audio_type(sess, WFD_AUDIO_SERVER_TYPE_PULSE_AUDIO);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = wfd_session_set_audio_type(sess, WFD_AUDIO_SERVER_TYPE_PULSE_AUDIO);
r = wfd_session_set_audio_dev_name(sess, audio_dev);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_PID, &creds);
if(0 > r) {
return log_ERR(r);
}
r = sd_bus_creds_get_pid(creds, &pid);
if(0 > r) {
return log_ERR(r);
}
sd_bus_creds_unref(creds);
creds = NULL;
r = sd_bus_creds_new_from_pid(&creds,
pid,
SD_BUS_CREDS_UID | SD_BUS_CREDS_GID);
if(0 > r) {
return log_ERR(r);
}
wfd_session_set_client_pid(sess, gid);
r = sd_bus_creds_get_uid(creds, &uid);
if(0 > r) {
return log_ERR(r);
}
wfd_session_set_client_uid(sess, uid);
sd_bus_creds_get_gid(creds, &gid);
if(0 > r) {
return log_ERR(r);
}
wfd_session_set_client_gid(sess, gid);
r = get_user_runtime_path(&runtime_path,
sd_bus_message_get_bus(m),
uid);
if(0 > r) {
return log_ERR(r);
}
r = wfd_session_set_runtime_path(sess, runtime_path);
if(0 > r) {
return log_ERR(r);
}
r = wfd_session_start(sess);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = wfd_dbus_get_session_path(sess, &path);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
r = sd_bus_reply_method_return(m, "o", path);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
return 0;
@ -748,7 +843,7 @@ static int wfd_dbus_shutdown(sd_bus_message *m,
r = sd_bus_reply_method_return(m, NULL);
if(0 > r) {
return log_ERRNO();
return log_ERR(r);
}
return 0;

View file

@ -53,7 +53,6 @@ int wfd_out_session_new(struct wfd_session **out,
struct wfd_sink *sink)
{
_wfd_session_unref_ struct wfd_session *s;
struct wfd_out_session *os;
int r;
assert_ret(out);
@ -73,9 +72,8 @@ int wfd_out_session_new(struct wfd_session **out,
return log_ERR(r);
}
os = wfd_out_session(s);
os->fd = -1;
os->sink = sink;
wfd_out_session(s)->fd = -1;
wfd_out_session(s)->sink = sink;
*out = wfd_session_ref(s);
@ -237,6 +235,8 @@ void wfd_out_session_destroy(struct wfd_session *s)
dispd_encoder_unref(os->encoder);
os->encoder = NULL;
}
os->sink = NULL;
}
int wfd_out_session_initiate_request(struct wfd_session *s)
@ -564,14 +564,18 @@ static void on_encoder_state_changed(struct dispd_encoder *e,
case DISPD_ENCODER_STATE_SPAWNED:
if(wfd_session_is_state(s, WFD_SESSION_STATE_SETTING_UP)) {
r = dispd_encoder_configure(wfd_out_session(s)->encoder, s);
if(0 > r) {
log_vERR(r);
}
}
break;
case DISPD_ENCODER_STATE_CONFIGURED:
if(wfd_session_is_state(s, WFD_SESSION_STATE_SETTING_UP)) {
r = dispd_encoder_start(e);
if(0 > r) {
log_vERR(r);
}
}
break;
case DISPD_ENCODER_STATE_READY:
break;
@ -582,7 +586,6 @@ static void on_encoder_state_changed(struct dispd_encoder *e,
wfd_session_set_state(s, WFD_SESSION_STATE_PAUSED);
break;
case DISPD_ENCODER_STATE_TERMINATED:
wfd_session_set_state(s, WFD_SESSION_STATE_TEARING_DOWN);
wfd_session_teardown(s);
break;
default:

View file

@ -71,10 +71,7 @@ static int wfd_session_do_request(struct wfd_session *s,
assert_ret(s);
assert_ret(rtsp_message_id_is_valid(id));
assert_ret(out);
if(!s->rtsp_disp_tbl[id].request) {
return log_ERR(-ENOTSUP);
}
assert_retv(s->rtsp_disp_tbl[id].request, -ENOTSUP);
r = (*s->rtsp_disp_tbl[id].request)(s, args, out);
if(0 > r) {
@ -95,10 +92,7 @@ static int wfd_session_do_handle_request(struct wfd_session *s,
assert_ret(rtsp_message_id_is_valid(id));
assert_ret(req);
assert_ret(rep);
if(!s->rtsp_disp_tbl[id].handle_request) {
return log_ERR(-ENOTSUP);
}
assert_retv(s->rtsp_disp_tbl[id].handle_request, -ENOTSUP);
r = (*s->rtsp_disp_tbl[id].handle_request)(s,
req,
@ -217,7 +211,6 @@ int wfd_session_teardown(struct wfd_session *s)
assert_ret(wfd_session_is_established(s));
assert_ret(session_vtbl[s->dir].teardown);
r = session_vtbl[s->dir].teardown(s);
if(0 > r) {
return log_ERR(r);
@ -283,6 +276,11 @@ int wfd_session_destroy(struct wfd_session *s)
s->audio_dev_name = NULL;
}
if(s->runtime_path) {
free(s->runtime_path);
s->runtime_path = NULL;
}
s->rtp_ports[0] = 0;
s->rtp_ports[1] = 0;
s->last_request = RTSP_M_UNKNOWN;
@ -292,7 +290,7 @@ int wfd_session_destroy(struct wfd_session *s)
return 0;
}
struct wfd_session * wfd_session_ref(struct wfd_session *s)
struct wfd_session * _wfd_session_ref(struct wfd_session *s)
{
if(s) {
++ s->ref;
@ -301,7 +299,7 @@ struct wfd_session * wfd_session_ref(struct wfd_session *s)
return s;
}
void wfd_session_unref(struct wfd_session *s)
void _wfd_session_unref(struct wfd_session *s)
{
if(!s) {
return;
@ -495,6 +493,30 @@ static int wfd_session_post_handle_request_n_reply(struct wfd_session *s,
return 0;
}
static int defered_destroy(struct sd_event_source *source,
void *userdata)
{
struct wfd_session *s = userdata;
wfd_session_destroy(s);
wfd_session_unref(s);
return 0;
}
static inline int schedule_defered_destroy(struct wfd_session *s)
{
int r = sd_event_add_defer(ctl_wfd_get_loop(),
NULL,
defered_destroy,
wfd_session_ref(s));
if(0 > r) {
return log_ERR(r);
}
return 0;
}
static int wfd_session_handle_request(struct rtsp *bus,
struct rtsp_message *m,
void *userdata)
@ -507,13 +529,19 @@ static int wfd_session_handle_request(struct rtsp *bus,
time_t sec;
int r;
if(!m && rtsp_is_dead(bus)) {
if(WFD_SESSION_STATE_TEARING_DOWN != wfd_session_get_state(s)) {
log_info("rtsp disconnected");
r = log_EPIPE();
}
goto error;
}
id = wfd_session_message_to_id(s, m);
if(RTSP_M_UNKNOWN == id) {
if(m) {
log_debug("unable to map request to id: %s",
(char *) rtsp_message_get_raw(m));
}
r = -EPROTO;
r = log_ERR(-EPROTO);
goto error;
}
@ -526,11 +554,13 @@ static int wfd_session_handle_request(struct rtsp *bus,
m,
&rep);
if(0 > r) {
log_vERR(r);
goto error;
}
r = sd_event_now(ctl_wfd_get_loop(), CLOCK_REALTIME, &usec);
if(0 > r) {
log_vERR(r);
goto error;
}
@ -541,16 +571,19 @@ static int wfd_session_handle_request(struct rtsp *bus,
r = rtsp_message_append(rep, "<&>", "Date", date);
if(0 > r) {
log_vERR(r);
goto error;
}
r = rtsp_message_seal(rep);
if(0 > r) {
log_vERR(r);
goto error;
}
r = rtsp_send(bus, rep);
if(0 > r) {
log_vERR(r);
goto error;
}
@ -560,15 +593,16 @@ static int wfd_session_handle_request(struct rtsp *bus,
r = wfd_session_post_handle_request_n_reply(s, id);
if(0 > r) {
log_vERR(r);
goto error;
}
return 0;
error:
wfd_session_destroy(s);
schedule_defered_destroy(s);
return log_ERR(r);
return r;
}
static int wfd_session_handle_reply(struct rtsp *bus,
@ -613,7 +647,7 @@ static int wfd_session_handle_reply(struct rtsp *bus,
goto end;
error:
wfd_session_destroy(s);
schedule_defered_destroy(s);
end:
wfd_session_unref(s);
@ -628,6 +662,9 @@ int wfd_session_init(struct wfd_session *s,
s->ref = 1;
s->id = id;
s->dir = dir;
s->client_uid = -1;
s->client_gid = -1;
s->client_pid = -1;
s->rtsp_disp_tbl = disp_tbl;
return 0;
@ -904,7 +941,8 @@ const char * wfd_session_get_audio_dev_name(struct wfd_session *s)
return s->audio_dev_name;
}
int wfd_session_set_audio_dev_name(struct wfd_session *s, char *audio_dev_name)
int wfd_session_set_audio_dev_name(struct wfd_session *s,
const char *audio_dev_name)
{
char *name;
@ -924,6 +962,82 @@ int wfd_session_set_audio_dev_name(struct wfd_session *s, char *audio_dev_name)
return 0;
}
const char * wfd_session_get_runtime_path(struct wfd_session *s)
{
assert_retv(s, "");
return s->runtime_path;
}
int wfd_session_set_runtime_path(struct wfd_session *s,
const char *runtime_path)
{
char *path;
assert_ret(s);
path = runtime_path ? strdup(runtime_path) : NULL;
if(!path) {
return -ENOMEM;
}
if(s->runtime_path) {
free(s->runtime_path);
}
s->runtime_path = path;
return 0;
}
uid_t wfd_session_get_client_uid(struct wfd_session *s)
{
assert_retv(s, -1);
return s->client_uid;
}
int wfd_session_set_client_uid(struct wfd_session *s, uid_t uid)
{
assert_ret(s);
s->client_uid = uid;
return 0;
}
gid_t wfd_session_get_client_gid(struct wfd_session *s)
{
assert_retv(s, -1);
return s->client_gid;
}
int wfd_session_set_client_gid(struct wfd_session *s, gid_t gid)
{
assert_ret(s);
s->client_gid = gid;
return 0;
}
pid_t wfd_session_get_client_pid(struct wfd_session *s)
{
assert_retv(s, -1);
return s->client_pid;
}
int wfd_session_set_client_pid(struct wfd_session *s, pid_t pid)
{
assert_ret(s);
s->client_pid = pid;
return 0;
}
void wfd_session_unrefp(struct wfd_session **s)
{
if(s && *s) {

View file

@ -118,9 +118,13 @@ struct wfd_session
char *disp_params;
char *disp_auth;
struct wfd_rectangle disp_dimen;
enum wfd_audio_server_type audio_type;
char *audio_dev_name;
uid_t client_uid;
gid_t client_gid;
gid_t client_pid;
char *runtime_path;
};
int wfd_session_init(struct wfd_session *s,

View file

@ -143,7 +143,6 @@ int wfd_sink_create_session(struct wfd_sink *sink, struct wfd_session **out)
return r;
}
sink->session = wfd_session_ref(sess);
*out = wfd_session_ref(sess);
wfd_fn_sink_properties_changed(sink, "Session");

View file

@ -37,6 +37,11 @@ static inline void cleanup_sd_bus_message(sd_bus_message **ptr)
sd_bus_message_unref(*ptr);
}
static inline void cleanup_sd_bus_creds(sd_bus_creds **ptr)
{
sd_bus_creds_unref(*ptr);
}
static inline void cleanup_udev_device(struct udev_device **ptr)
{
udev_device_unref(*ptr);
@ -51,6 +56,7 @@ static inline void cleanup_udev_enumerate(struct udev_enumerate **ptr)
#define _sd_bus_error_free_ _shl_cleanup_(sd_bus_error_free)
#define _cleanup_sd_bus_message_ _shl_cleanup_(cleanup_sd_bus_message)
#define _sd_bus_message_unref_ _shl_cleanup_(cleanup_sd_bus_message)
#define _sd_bus_creds_unref_ _shl_cleanup_(cleanup_sd_bus_creds)
#define _cleanup_udev_device_ _shl_cleanup_(cleanup_udev_device)
#define _cleanup_udev_enumerate_ _shl_cleanup_(cleanup_udev_enumerate)