mirror of
https://github.com/albfan/miraclecast.git
synced 2025-03-09 23:38:56 +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:
parent
ba10255f70
commit
6415de46fa
11 changed files with 507 additions and 123 deletions
|
@ -476,6 +476,8 @@ private class WfdCtl : GLib.Application
|
||||||
return "playing";
|
return "playing";
|
||||||
case 7:
|
case 7:
|
||||||
return "tearing down";
|
return "tearing down";
|
||||||
|
case 8:
|
||||||
|
return "destroyed";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "unknown";
|
return "unknown";
|
||||||
|
|
|
@ -319,14 +319,13 @@ internal class GstEncoder : DispdEncoder, GLib.Object
|
||||||
|
|
||||||
public async void prepare() throws Error
|
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);
|
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 */
|
/* we are ready, tell parent how to communicate with us */
|
||||||
unowned string unique_name = conn.unique_name;
|
ssize_t r = Posix.write(3, (void *) bus_info.data, bus_info.length);
|
||||||
ssize_t r = Posix.write(3,
|
|
||||||
(void *) unique_name.data,
|
|
||||||
unique_name.length);
|
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
throw new DispdEncoderError.CANT_RETURN_UNIQUE_NAME("%s",
|
throw new DispdEncoderError.CANT_RETURN_UNIQUE_NAME("%s",
|
||||||
Posix.strerror(Posix.errno));
|
Posix.strerror(Posix.errno));
|
||||||
|
|
|
@ -83,8 +83,16 @@ enum wfd_audio_server_type
|
||||||
int wfd_out_session_new(struct wfd_session **out,
|
int wfd_out_session_new(struct wfd_session **out,
|
||||||
unsigned int id,
|
unsigned int id,
|
||||||
struct wfd_sink *sink);
|
struct wfd_sink *sink);
|
||||||
struct wfd_session * wfd_session_ref(struct wfd_session *s);
|
struct wfd_session * _wfd_session_ref(struct wfd_session *s);
|
||||||
void wfd_session_unref(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);
|
void wfd_session_unrefp(struct wfd_session **s);
|
||||||
unsigned int * wfd_session_to_htable(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);
|
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);
|
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);
|
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);
|
uid_t wfd_session_get_client_uid(struct wfd_session *s);
|
||||||
int wfd_session_set_client_uid(struct wfd_session *s, uid_t uid);
|
int wfd_session_set_client_uid(struct wfd_session *s, uid_t uid);
|
||||||
uid_t wfd_session_get_client_gid(struct wfd_session *s);
|
uid_t wfd_session_get_client_gid(struct wfd_session *s);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include "dispd-encoder.h"
|
#include "dispd-encoder.h"
|
||||||
#include "shl_macro.h"
|
#include "shl_macro.h"
|
||||||
#include "shl_log.h"
|
#include "shl_log.h"
|
||||||
|
@ -42,26 +43,30 @@ struct dispd_encoder
|
||||||
sd_bus_slot *name_disappeared_slot;
|
sd_bus_slot *name_disappeared_slot;
|
||||||
sd_bus_slot *state_change_notify_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;
|
enum dispd_encoder_state state;
|
||||||
dispd_encoder_state_change_handler handler;
|
dispd_encoder_state_change_handler handler;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int dispd_encoder_new(struct dispd_encoder **out);
|
static int dispd_encoder_new(struct dispd_encoder **out,
|
||||||
static int on_unique_readable(sd_event_source *source,
|
uid_t bus_owner,
|
||||||
|
gid_t bus_group);
|
||||||
|
static int on_bus_info_readable(sd_event_source *source,
|
||||||
int fd,
|
int fd,
|
||||||
uint32_t events,
|
uint32_t events,
|
||||||
void *userdata);
|
void *userdata);
|
||||||
static void dispd_encoder_set_state(struct dispd_encoder *e,
|
static void dispd_encoder_set_state(struct dispd_encoder *e,
|
||||||
enum dispd_encoder_state state);
|
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;
|
int r;
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
char disp[16], auth[256];
|
char disp[16], runtime_path[256];
|
||||||
|
|
||||||
log_info("child forked with pid %d", getpid());
|
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);
|
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||||
|
|
||||||
snprintf(disp, sizeof(disp), "DISPLAY=%s", wfd_session_get_disp_name(s));
|
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,
|
/* after encoder connected to DBus, write unique name to fd 3,
|
||||||
* so we can controll it through DBus
|
* so we can controll it through DBus
|
||||||
*/
|
*/
|
||||||
r = dup2(fd, 3);
|
r = dup2(fd, 3);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
log_vERRNO();
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fd != 3) {
|
if(fd != 3) {
|
||||||
close(fd);
|
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,
|
r = execvpe(cmd,
|
||||||
(char *[]){ (char *) cmd, NULL },
|
(char *[]){ (char *) cmd, NULL },
|
||||||
(char *[]){ disp,
|
(char *[]){ disp,
|
||||||
auth,
|
runtime_path,
|
||||||
"G_MESSAGES_DEBUG=all",
|
"G_MESSAGES_DEBUG=all",
|
||||||
NULL
|
NULL
|
||||||
});
|
});
|
||||||
|
if(0 > r) {
|
||||||
|
log_vERRNO();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
_exit(1);
|
_exit(1);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dispd_encoder_close_pipe(struct dispd_encoder *e)
|
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;
|
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_set_state(e, DISPD_ENCODER_STATE_TERMINATED);
|
||||||
dispd_encoder_cleanup(e);
|
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)
|
int dispd_encoder_spawn(struct dispd_encoder **out, struct wfd_session *s)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
|
||||||
_dispd_encoder_unref_ struct dispd_encoder *e = NULL;
|
_dispd_encoder_unref_ struct dispd_encoder *e = NULL;
|
||||||
int fds[2] = { -1, -1 };
|
int fds[2] = { -1, -1 };
|
||||||
|
pid_t pid;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_ret(out);
|
assert_ret(out);
|
||||||
assert_ret(s);
|
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) {
|
if(0 > r) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = pipe(fds);
|
r = pipe2(fds, O_NONBLOCK);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if(0 > pid) {
|
if(0 > pid) {
|
||||||
r = pid;
|
r = log_ERRNO();
|
||||||
goto kill_encoder;
|
goto kill_encoder;
|
||||||
}
|
}
|
||||||
else if(!pid) {
|
else if(!pid) {
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
|
|
||||||
r = dispd_encoder_exec("gstencoder", fds[1], s);
|
dispd_encoder_exec("gstencoder", fds[1], s);
|
||||||
if(0 > r) {
|
|
||||||
log_warning("failed to exec encoder: %s", strerror(errno));
|
|
||||||
}
|
|
||||||
_exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_event_add_child(ctl_wfd_get_loop(),
|
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,
|
&e->pipe_source,
|
||||||
fds[0],
|
fds[0],
|
||||||
EPOLLIN,
|
EPOLLIN,
|
||||||
on_unique_readable,
|
on_bus_info_readable,
|
||||||
dispd_encoder_ref(e));
|
dispd_encoder_ref(e));
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
goto close_pipe;
|
goto close_pipe;
|
||||||
|
@ -262,11 +285,14 @@ end:
|
||||||
return log_ERRNO();
|
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(out);
|
||||||
|
// assert_ret(bus_addr);
|
||||||
|
|
||||||
e = calloc(1, sizeof(struct dispd_encoder));
|
e = calloc(1, sizeof(struct dispd_encoder));
|
||||||
if(!e) {
|
if(!e) {
|
||||||
|
@ -274,16 +300,22 @@ static int dispd_encoder_new(struct dispd_encoder **out)
|
||||||
}
|
}
|
||||||
|
|
||||||
e->ref = 1;
|
e->ref = 1;
|
||||||
*out = e;
|
e->bus_owner = bus_owner;
|
||||||
e = NULL;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dispd_encoder * dispd_encoder_ref(struct dispd_encoder *e)
|
struct dispd_encoder * dispd_encoder_ref(struct dispd_encoder *e)
|
||||||
{
|
{
|
||||||
assert_retv(e, NULL);
|
assert_retv(e, e);
|
||||||
assert_retv(0 < e->ref, NULL);
|
assert_retv(0 < e->ref, e);
|
||||||
|
|
||||||
++ e->ref;
|
++ 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,
|
/* since we encrease ref count at creation of every sources and slots,
|
||||||
* once we get here, it means no sources and slots exist anymore */
|
* once we get here, it means no sources and slots exist anymore */
|
||||||
if(e->bus) {
|
if(e->bus) {
|
||||||
|
sd_bus_detach_event(e->bus);
|
||||||
sd_bus_unref(e->bus);
|
sd_bus_unref(e->bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e->name) {
|
if(e->bus_name) {
|
||||||
free(e->name);
|
free(e->bus_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if(e->bus_addr) {
|
||||||
|
// free(e->bus_addr);
|
||||||
|
// }
|
||||||
|
|
||||||
free(e);
|
free(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +485,7 @@ static int on_encoder_disappeared(sd_bus_message *m,
|
||||||
struct dispd_encoder *e = userdata;
|
struct dispd_encoder *e = userdata;
|
||||||
int r;
|
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);
|
r = dispd_encoder_kill_child(e);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
@ -463,43 +500,123 @@ static int on_encoder_disappeared(sd_bus_message *m,
|
||||||
return 0;
|
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,
|
int fd,
|
||||||
uint32_t events,
|
uint32_t events,
|
||||||
void *userdata)
|
void *userdata)
|
||||||
{
|
{
|
||||||
struct dispd_encoder *e = userdata;
|
struct dispd_encoder *e = userdata;
|
||||||
char buf[1024];
|
char buf[512];
|
||||||
ssize_t r;
|
int r;
|
||||||
|
|
||||||
r = read(fd, buf, sizeof(buf) - 1);
|
r = read_line(fd, buf, sizeof(buf) - 1);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
if(EAGAIN == errno) {
|
log_vERR(r);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
else if(!r) {
|
else if(!r) {
|
||||||
log_warning("no bus name returned from encoder: %s",
|
log_warning("no bus name returned from encoder");
|
||||||
strerror(errno));
|
r = -ENOENT;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO remove heading and trailing speces from buf before strdup()
|
// TODO remove heading and trailing speces from buf before strdup()
|
||||||
buf[r] = '\0';
|
|
||||||
log_info("got bus name from encoder: %s", buf);
|
log_info("got bus name from encoder: %s", buf);
|
||||||
|
|
||||||
e->name = strdup(buf);
|
e->bus_name = strdup(buf);
|
||||||
if(!e->name) {
|
if(!e->bus_name) {
|
||||||
|
log_vERRNO();
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO connect to encoder through user session bus
|
r = read_line(fd, buf, sizeof(buf) - 1);
|
||||||
r = sd_bus_default_system(&e->bus);
|
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
log_vERR(r);
|
||||||
goto error;
|
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),
|
snprintf(buf, sizeof(buf),
|
||||||
"type='signal',"
|
"type='signal',"
|
||||||
|
@ -508,36 +625,52 @@ static int on_unique_readable(sd_event_source *source,
|
||||||
"interface='org.freedesktop.DBus.Properties',"
|
"interface='org.freedesktop.DBus.Properties',"
|
||||||
"member='PropertiesChanged',"
|
"member='PropertiesChanged',"
|
||||||
"arg0='org.freedesktop.miracle.encoder'",
|
"arg0='org.freedesktop.miracle.encoder'",
|
||||||
e->name);
|
e->bus_name);
|
||||||
|
if(0 > r) {
|
||||||
|
log_vERRNO();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
r = sd_bus_add_match(e->bus,
|
r = sd_bus_add_match(e->bus,
|
||||||
&e->state_change_notify_slot,
|
&e->state_change_notify_slot,
|
||||||
buf,
|
buf,
|
||||||
on_encoder_properties_changed,
|
on_encoder_properties_changed,
|
||||||
dispd_encoder_ref(e));
|
dispd_encoder_ref(e));
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
log_vERRNO();
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf),
|
r = snprintf(buf, sizeof(buf),
|
||||||
"type='signal',"
|
"type='signal',"
|
||||||
"sender='org.freedesktop.DBus',"
|
"sender='org.freedesktop.DBus',"
|
||||||
"path='/org/freedesktop/DBus',"
|
"path='/org/freedesktop/DBus',"
|
||||||
"interface='org.freedesktop.DBus',"
|
"interface='org.freedesktop.DBus',"
|
||||||
"member='NameOwnerChanged',"
|
"member='NameOwnerChanged',"
|
||||||
"arg0namespace='%s'",
|
"arg0namespace='%s'",
|
||||||
e->name);
|
e->bus_name);
|
||||||
|
if(0 > r) {
|
||||||
|
log_vERRNO();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
r = sd_bus_add_match(e->bus,
|
r = sd_bus_add_match(e->bus,
|
||||||
&e->name_disappeared_slot,
|
&e->name_disappeared_slot,
|
||||||
buf,
|
buf,
|
||||||
on_encoder_disappeared,
|
on_encoder_disappeared,
|
||||||
dispd_encoder_ref(e));
|
dispd_encoder_ref(e));
|
||||||
|
if(0 > r) {
|
||||||
|
log_vERRNO();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
dispd_encoder_set_state(e, DISPD_ENCODER_STATE_SPAWNED);
|
dispd_encoder_set_state(e, DISPD_ENCODER_STATE_SPAWNED);
|
||||||
|
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
log_vERRNO();
|
seteuid(0);
|
||||||
|
log_debug("<<< uid=%d, euid=%d", getuid(), geteuid());
|
||||||
dispd_encoder_kill_child(e);
|
dispd_encoder_kill_child(e);
|
||||||
end:
|
end:
|
||||||
dispd_encoder_close_pipe(e);
|
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,
|
r = sd_bus_message_new_method_call(e->bus,
|
||||||
&call,
|
&call,
|
||||||
e->name,
|
e->bus_name,
|
||||||
"/org/freedesktop/miracle/encoder",
|
"/org/freedesktop/miracle/encoder",
|
||||||
"org.freedesktop.miracle.encoder",
|
"org.freedesktop.miracle.encoder",
|
||||||
"Configure");
|
"Configure");
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_bus_message_open_container(call, 'a', "{iv}");
|
r = sd_bus_message_open_container(call, 'a', "{iv}");
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
sink = wfd_out_session_get_sink(s);
|
sink = wfd_out_session_get_sink(s);
|
||||||
|
@ -636,7 +769,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
|
||||||
"s",
|
"s",
|
||||||
sink->peer->remote_address);
|
sink->peer->remote_address);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = config_append(call,
|
r = config_append(call,
|
||||||
|
@ -644,7 +777,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
|
||||||
"u",
|
"u",
|
||||||
s->stream.rtp_port);
|
s->stream.rtp_port);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s->stream.rtcp_port) {
|
if(s->stream.rtcp_port) {
|
||||||
|
@ -653,7 +786,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
|
||||||
"u",
|
"u",
|
||||||
s->stream.rtcp_port);
|
s->stream.rtcp_port);
|
||||||
if(0 > r) {
|
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",
|
"s",
|
||||||
sink->peer->local_address);
|
sink->peer->local_address);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s->stream.rtcp_port) {
|
if(s->stream.rtcp_port) {
|
||||||
|
@ -671,7 +804,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
|
||||||
"u",
|
"u",
|
||||||
s->stream.rtcp_port);
|
s->stream.rtcp_port);
|
||||||
if(0 > r) {
|
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",
|
"u",
|
||||||
rect->x);
|
rect->x);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = config_append(call,
|
r = config_append(call,
|
||||||
|
@ -690,7 +823,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
|
||||||
"u",
|
"u",
|
||||||
rect->y);
|
rect->y);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = config_append(call,
|
r = config_append(call,
|
||||||
|
@ -698,7 +831,7 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
|
||||||
"u",
|
"u",
|
||||||
rect->width);
|
rect->width);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = config_append(call,
|
r = config_append(call,
|
||||||
|
@ -706,23 +839,32 @@ int dispd_encoder_configure(struct dispd_encoder *e, struct wfd_session *s)
|
||||||
"u",
|
"u",
|
||||||
rect->height);
|
rect->height);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_bus_message_close_container(call);
|
r = sd_bus_message_close_container(call);
|
||||||
if(0 > r) {
|
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);
|
r = sd_bus_call(e->bus, call, 0, &error, &reply);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
log_warning("%s: %s", error.name, error.message);
|
log_warning("%s: %s", error.name, error.message);
|
||||||
sd_bus_error_free(&error);
|
log_vERR(r);
|
||||||
return log_ERRNO();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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,
|
r = sd_bus_message_new_method_call(e->bus,
|
||||||
&call,
|
&call,
|
||||||
e->name,
|
e->bus_name,
|
||||||
"/org/freedesktop/miracle/encoder",
|
"/org/freedesktop/miracle/encoder",
|
||||||
"org.freedesktop.miracle.encoder",
|
"org.freedesktop.miracle.encoder",
|
||||||
method);
|
method);
|
||||||
|
@ -747,6 +889,13 @@ static int dispd_encoder_call(struct dispd_encoder *e, const char *method)
|
||||||
goto error;
|
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);
|
r = sd_bus_call(e->bus, call, 0, &error, &reply);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
log_warning("%s: %s", error.name, error.message);
|
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;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
// seteuid(0);
|
||||||
|
// log_debug("<<< uid=%d, euid=%d", getuid(), geteuid());
|
||||||
dispd_encoder_kill_child(e);
|
dispd_encoder_kill_child(e);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -73,7 +73,7 @@ int ctl_wfd_new(struct ctl_wfd **out, sd_event *loop, sd_bus *bus)
|
||||||
|
|
||||||
error:
|
error:
|
||||||
ctl_wfd_free(wfd);
|
ctl_wfd_free(wfd);
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ctl_wfd_free(struct ctl_wfd *wfd)
|
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);
|
r = wfd_sink_new(&s, p, sube);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = shl_htable_insert_str(&wfd->sinks,
|
r = shl_htable_insert_str(&wfd->sinks,
|
||||||
wfd_sink_to_htable(s),
|
wfd_sink_to_htable(s),
|
||||||
NULL);
|
NULL);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
++wfd->n_sinks;
|
++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));
|
r = shl_htable_insert_uint(&wfd->sessions, wfd_session_to_htable(s));
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
++wfd->n_sessions;
|
++wfd->n_sessions;
|
||||||
|
@ -367,7 +367,7 @@ void ctl_fn_peer_new(struct ctl_peer *p)
|
||||||
r = wfd_sube_parse(sube_str, &sube);
|
r = wfd_sube_parse(sube_str, &sube);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
log_debug("peer %s has invalid subelement", p->label);
|
log_debug("peer %s has invalid subelement", p->label);
|
||||||
return log_vERRNO();
|
return log_vERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(wfd_sube_device_is_sink(&sube)) {
|
if(wfd_sube_device_is_sink(&sube)) {
|
||||||
|
|
|
@ -410,17 +410,67 @@ static int wfd_dbus_find_session(sd_bus *bus,
|
||||||
return r;
|
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,
|
static int wfd_dbus_sink_start_session(sd_bus_message *m,
|
||||||
void *userdata,
|
void *userdata,
|
||||||
sd_bus_error *ret_error)
|
sd_bus_error *ret_error)
|
||||||
{
|
{
|
||||||
struct wfd_sink *sink = userdata;
|
|
||||||
_wfd_session_unref_ struct wfd_session *sess = NULL;
|
_wfd_session_unref_ struct wfd_session *sess = NULL;
|
||||||
_shl_free_ char *path = NULL, *disp_type_name = NULL, *disp_name = 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;
|
char *disp_params;
|
||||||
const char *disp, *disp_auth;
|
const char *disp, *disp_auth;
|
||||||
const char *audio_dev;
|
const char *audio_dev;
|
||||||
struct wfd_rectangle rect;
|
struct wfd_rectangle rect;
|
||||||
|
pid_t pid;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = sd_bus_message_read(m,
|
r = sd_bus_message_read(m,
|
||||||
|
@ -433,7 +483,7 @@ static int wfd_dbus_sink_start_session(sd_bus_message *m,
|
||||||
&rect.height,
|
&rect.height,
|
||||||
&audio_dev);
|
&audio_dev);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sscanf(disp, "%m[^:]://%ms",
|
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);
|
r = wfd_sink_create_session(sink, &sess);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
wfd_session_set_disp_type(sess, WFD_DISPLAY_SERVER_TYPE_X);
|
wfd_session_set_disp_type(sess, WFD_DISPLAY_SERVER_TYPE_X);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
disp_params = strchr(disp_name, '?');
|
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);
|
r = wfd_session_set_disp_name(sess, disp_name);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wfd_session_set_disp_params(sess, disp_params);
|
r = wfd_session_set_disp_params(sess, disp_params);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wfd_session_set_disp_auth(sess, disp_auth);
|
r = wfd_session_set_disp_auth(sess, disp_auth);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wfd_session_set_disp_dimension(sess, &rect);
|
r = wfd_session_set_disp_dimension(sess, &rect);
|
||||||
if(0 > r) {
|
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_type(sess, WFD_AUDIO_SERVER_TYPE_PULSE_AUDIO);
|
||||||
if(0 > r) {
|
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) {
|
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);
|
r = wfd_session_start(sess);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = wfd_dbus_get_session_path(sess, &path);
|
r = wfd_dbus_get_session_path(sess, &path);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_bus_reply_method_return(m, "o", path);
|
r = sd_bus_reply_method_return(m, "o", path);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -748,7 +843,7 @@ static int wfd_dbus_shutdown(sd_bus_message *m,
|
||||||
|
|
||||||
r = sd_bus_reply_method_return(m, NULL);
|
r = sd_bus_reply_method_return(m, NULL);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERRNO();
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -53,7 +53,6 @@ int wfd_out_session_new(struct wfd_session **out,
|
||||||
struct wfd_sink *sink)
|
struct wfd_sink *sink)
|
||||||
{
|
{
|
||||||
_wfd_session_unref_ struct wfd_session *s;
|
_wfd_session_unref_ struct wfd_session *s;
|
||||||
struct wfd_out_session *os;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert_ret(out);
|
assert_ret(out);
|
||||||
|
@ -73,9 +72,8 @@ int wfd_out_session_new(struct wfd_session **out,
|
||||||
return log_ERR(r);
|
return log_ERR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
os = wfd_out_session(s);
|
wfd_out_session(s)->fd = -1;
|
||||||
os->fd = -1;
|
wfd_out_session(s)->sink = sink;
|
||||||
os->sink = sink;
|
|
||||||
|
|
||||||
*out = wfd_session_ref(s);
|
*out = wfd_session_ref(s);
|
||||||
|
|
||||||
|
@ -237,6 +235,8 @@ void wfd_out_session_destroy(struct wfd_session *s)
|
||||||
dispd_encoder_unref(os->encoder);
|
dispd_encoder_unref(os->encoder);
|
||||||
os->encoder = NULL;
|
os->encoder = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os->sink = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wfd_out_session_initiate_request(struct wfd_session *s)
|
int wfd_out_session_initiate_request(struct wfd_session *s)
|
||||||
|
@ -564,13 +564,17 @@ static void on_encoder_state_changed(struct dispd_encoder *e,
|
||||||
case DISPD_ENCODER_STATE_SPAWNED:
|
case DISPD_ENCODER_STATE_SPAWNED:
|
||||||
if(wfd_session_is_state(s, WFD_SESSION_STATE_SETTING_UP)) {
|
if(wfd_session_is_state(s, WFD_SESSION_STATE_SETTING_UP)) {
|
||||||
r = dispd_encoder_configure(wfd_out_session(s)->encoder, s);
|
r = dispd_encoder_configure(wfd_out_session(s)->encoder, s);
|
||||||
log_vERR(r);
|
if(0 > r) {
|
||||||
|
log_vERR(r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DISPD_ENCODER_STATE_CONFIGURED:
|
case DISPD_ENCODER_STATE_CONFIGURED:
|
||||||
if(wfd_session_is_state(s, WFD_SESSION_STATE_SETTING_UP)) {
|
if(wfd_session_is_state(s, WFD_SESSION_STATE_SETTING_UP)) {
|
||||||
r = dispd_encoder_start(e);
|
r = dispd_encoder_start(e);
|
||||||
log_vERR(r);
|
if(0 > r) {
|
||||||
|
log_vERR(r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DISPD_ENCODER_STATE_READY:
|
case DISPD_ENCODER_STATE_READY:
|
||||||
|
@ -582,7 +586,6 @@ static void on_encoder_state_changed(struct dispd_encoder *e,
|
||||||
wfd_session_set_state(s, WFD_SESSION_STATE_PAUSED);
|
wfd_session_set_state(s, WFD_SESSION_STATE_PAUSED);
|
||||||
break;
|
break;
|
||||||
case DISPD_ENCODER_STATE_TERMINATED:
|
case DISPD_ENCODER_STATE_TERMINATED:
|
||||||
wfd_session_set_state(s, WFD_SESSION_STATE_TEARING_DOWN);
|
|
||||||
wfd_session_teardown(s);
|
wfd_session_teardown(s);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -71,10 +71,7 @@ static int wfd_session_do_request(struct wfd_session *s,
|
||||||
assert_ret(s);
|
assert_ret(s);
|
||||||
assert_ret(rtsp_message_id_is_valid(id));
|
assert_ret(rtsp_message_id_is_valid(id));
|
||||||
assert_ret(out);
|
assert_ret(out);
|
||||||
|
assert_retv(s->rtsp_disp_tbl[id].request, -ENOTSUP);
|
||||||
if(!s->rtsp_disp_tbl[id].request) {
|
|
||||||
return log_ERR(-ENOTSUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = (*s->rtsp_disp_tbl[id].request)(s, args, out);
|
r = (*s->rtsp_disp_tbl[id].request)(s, args, out);
|
||||||
if(0 > r) {
|
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(rtsp_message_id_is_valid(id));
|
||||||
assert_ret(req);
|
assert_ret(req);
|
||||||
assert_ret(rep);
|
assert_ret(rep);
|
||||||
|
assert_retv(s->rtsp_disp_tbl[id].handle_request, -ENOTSUP);
|
||||||
if(!s->rtsp_disp_tbl[id].handle_request) {
|
|
||||||
return log_ERR(-ENOTSUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = (*s->rtsp_disp_tbl[id].handle_request)(s,
|
r = (*s->rtsp_disp_tbl[id].handle_request)(s,
|
||||||
req,
|
req,
|
||||||
|
@ -217,7 +211,6 @@ int wfd_session_teardown(struct wfd_session *s)
|
||||||
assert_ret(wfd_session_is_established(s));
|
assert_ret(wfd_session_is_established(s));
|
||||||
assert_ret(session_vtbl[s->dir].teardown);
|
assert_ret(session_vtbl[s->dir].teardown);
|
||||||
|
|
||||||
|
|
||||||
r = session_vtbl[s->dir].teardown(s);
|
r = session_vtbl[s->dir].teardown(s);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
return log_ERR(r);
|
return log_ERR(r);
|
||||||
|
@ -283,6 +276,11 @@ int wfd_session_destroy(struct wfd_session *s)
|
||||||
s->audio_dev_name = NULL;
|
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[0] = 0;
|
||||||
s->rtp_ports[1] = 0;
|
s->rtp_ports[1] = 0;
|
||||||
s->last_request = RTSP_M_UNKNOWN;
|
s->last_request = RTSP_M_UNKNOWN;
|
||||||
|
@ -292,7 +290,7 @@ int wfd_session_destroy(struct wfd_session *s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wfd_session * wfd_session_ref(struct wfd_session *s)
|
struct wfd_session * _wfd_session_ref(struct wfd_session *s)
|
||||||
{
|
{
|
||||||
if(s) {
|
if(s) {
|
||||||
++ s->ref;
|
++ s->ref;
|
||||||
|
@ -301,7 +299,7 @@ struct wfd_session * wfd_session_ref(struct wfd_session *s)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wfd_session_unref(struct wfd_session *s)
|
void _wfd_session_unref(struct wfd_session *s)
|
||||||
{
|
{
|
||||||
if(!s) {
|
if(!s) {
|
||||||
return;
|
return;
|
||||||
|
@ -495,6 +493,30 @@ static int wfd_session_post_handle_request_n_reply(struct wfd_session *s,
|
||||||
return 0;
|
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,
|
static int wfd_session_handle_request(struct rtsp *bus,
|
||||||
struct rtsp_message *m,
|
struct rtsp_message *m,
|
||||||
void *userdata)
|
void *userdata)
|
||||||
|
@ -507,13 +529,19 @@ static int wfd_session_handle_request(struct rtsp *bus,
|
||||||
time_t sec;
|
time_t sec;
|
||||||
int r;
|
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);
|
id = wfd_session_message_to_id(s, m);
|
||||||
if(RTSP_M_UNKNOWN == id) {
|
if(RTSP_M_UNKNOWN == id) {
|
||||||
if(m) {
|
log_debug("unable to map request to id: %s",
|
||||||
log_debug("unable to map request to id: %s",
|
(char *) rtsp_message_get_raw(m));
|
||||||
(char *) rtsp_message_get_raw(m));
|
r = log_ERR(-EPROTO);
|
||||||
}
|
|
||||||
r = -EPROTO;
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,11 +554,13 @@ static int wfd_session_handle_request(struct rtsp *bus,
|
||||||
m,
|
m,
|
||||||
&rep);
|
&rep);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
log_vERR(r);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_event_now(ctl_wfd_get_loop(), CLOCK_REALTIME, &usec);
|
r = sd_event_now(ctl_wfd_get_loop(), CLOCK_REALTIME, &usec);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
log_vERR(r);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,16 +571,19 @@ static int wfd_session_handle_request(struct rtsp *bus,
|
||||||
|
|
||||||
r = rtsp_message_append(rep, "<&>", "Date", date);
|
r = rtsp_message_append(rep, "<&>", "Date", date);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
log_vERR(r);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = rtsp_message_seal(rep);
|
r = rtsp_message_seal(rep);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
log_vERR(r);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = rtsp_send(bus, rep);
|
r = rtsp_send(bus, rep);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
log_vERR(r);
|
||||||
goto error;
|
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);
|
r = wfd_session_post_handle_request_n_reply(s, id);
|
||||||
if(0 > r) {
|
if(0 > r) {
|
||||||
|
log_vERR(r);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
wfd_session_destroy(s);
|
schedule_defered_destroy(s);
|
||||||
|
|
||||||
return log_ERR(r);
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wfd_session_handle_reply(struct rtsp *bus,
|
static int wfd_session_handle_reply(struct rtsp *bus,
|
||||||
|
@ -613,7 +647,7 @@ static int wfd_session_handle_reply(struct rtsp *bus,
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
wfd_session_destroy(s);
|
schedule_defered_destroy(s);
|
||||||
end:
|
end:
|
||||||
wfd_session_unref(s);
|
wfd_session_unref(s);
|
||||||
|
|
||||||
|
@ -628,6 +662,9 @@ int wfd_session_init(struct wfd_session *s,
|
||||||
s->ref = 1;
|
s->ref = 1;
|
||||||
s->id = id;
|
s->id = id;
|
||||||
s->dir = dir;
|
s->dir = dir;
|
||||||
|
s->client_uid = -1;
|
||||||
|
s->client_gid = -1;
|
||||||
|
s->client_pid = -1;
|
||||||
s->rtsp_disp_tbl = disp_tbl;
|
s->rtsp_disp_tbl = disp_tbl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -904,7 +941,8 @@ const char * wfd_session_get_audio_dev_name(struct wfd_session *s)
|
||||||
return s->audio_dev_name;
|
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;
|
char *name;
|
||||||
|
|
||||||
|
@ -924,6 +962,82 @@ int wfd_session_set_audio_dev_name(struct wfd_session *s, char *audio_dev_name)
|
||||||
return 0;
|
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)
|
void wfd_session_unrefp(struct wfd_session **s)
|
||||||
{
|
{
|
||||||
if(s && *s) {
|
if(s && *s) {
|
||||||
|
|
|
@ -118,9 +118,13 @@ struct wfd_session
|
||||||
char *disp_params;
|
char *disp_params;
|
||||||
char *disp_auth;
|
char *disp_auth;
|
||||||
struct wfd_rectangle disp_dimen;
|
struct wfd_rectangle disp_dimen;
|
||||||
|
|
||||||
enum wfd_audio_server_type audio_type;
|
enum wfd_audio_server_type audio_type;
|
||||||
char *audio_dev_name;
|
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,
|
int wfd_session_init(struct wfd_session *s,
|
||||||
|
|
|
@ -143,7 +143,6 @@ int wfd_sink_create_session(struct wfd_sink *sink, struct wfd_session **out)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
sink->session = wfd_session_ref(sess);
|
|
||||||
*out = wfd_session_ref(sess);
|
*out = wfd_session_ref(sess);
|
||||||
|
|
||||||
wfd_fn_sink_properties_changed(sink, "Session");
|
wfd_fn_sink_properties_changed(sink, "Session");
|
||||||
|
|
|
@ -37,6 +37,11 @@ static inline void cleanup_sd_bus_message(sd_bus_message **ptr)
|
||||||
sd_bus_message_unref(*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)
|
static inline void cleanup_udev_device(struct udev_device **ptr)
|
||||||
{
|
{
|
||||||
udev_device_unref(*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 _sd_bus_error_free_ _shl_cleanup_(sd_bus_error_free)
|
||||||
#define _cleanup_sd_bus_message_ _shl_cleanup_(cleanup_sd_bus_message)
|
#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_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_device_ _shl_cleanup_(cleanup_udev_device)
|
||||||
#define _cleanup_udev_enumerate_ _shl_cleanup_(cleanup_udev_enumerate)
|
#define _cleanup_udev_enumerate_ _shl_cleanup_(cleanup_udev_enumerate)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue