mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
protocol: make connect async
Make the protocol client connect call async with a callback when it completes. Move the connect methods into separate files, add an empty connect method that will use the screencast portal to get a pipewire fd. Use the remote intention to get the connect method. Add some better error reporting.
This commit is contained in:
parent
ad1e5fdc10
commit
d14c7abe11
7 changed files with 203 additions and 66 deletions
|
|
@ -69,6 +69,8 @@ pipewire_module_link_factory = shared_library('pipewire-module-link-factory',
|
||||||
|
|
||||||
pipewire_module_protocol_native = shared_library('pipewire-module-protocol-native',
|
pipewire_module_protocol_native = shared_library('pipewire-module-protocol-native',
|
||||||
[ 'module-protocol-native.c',
|
[ 'module-protocol-native.c',
|
||||||
|
'module-protocol-native/local-socket.c',
|
||||||
|
'module-protocol-native/portal-screencast.c',
|
||||||
'module-protocol-native/protocol-native.c',
|
'module-protocol-native/protocol-native.c',
|
||||||
'module-protocol-native/connection.c' ],
|
'module-protocol-native/connection.c' ],
|
||||||
c_args : pipewire_module_c_args,
|
c_args : pipewire_module_c_args,
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@
|
||||||
|
|
||||||
#include "extensions/protocol-native.h"
|
#include "extensions/protocol-native.h"
|
||||||
#include "modules/module-protocol-native/connection.h"
|
#include "modules/module-protocol-native/connection.h"
|
||||||
|
#include "modules/module-protocol-native/defs.h"
|
||||||
|
|
||||||
#ifndef UNIX_PATH_MAX
|
#ifndef UNIX_PATH_MAX
|
||||||
#define UNIX_PATH_MAX 108
|
#define UNIX_PATH_MAX 108
|
||||||
|
|
@ -477,60 +478,6 @@ static bool add_socket(struct pw_protocol *protocol, struct server *s)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
|
||||||
get_remote(const struct pw_properties *properties)
|
|
||||||
{
|
|
||||||
const char *name = NULL;
|
|
||||||
|
|
||||||
if (properties)
|
|
||||||
name = pw_properties_get(properties, PW_REMOTE_PROP_REMOTE_NAME);
|
|
||||||
if (name == NULL)
|
|
||||||
name = getenv("PIPEWIRE_REMOTE");
|
|
||||||
if (name == NULL)
|
|
||||||
name = "pipewire-0";
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int impl_connect(struct pw_protocol_client *client)
|
|
||||||
{
|
|
||||||
struct client *impl = SPA_CONTAINER_OF(client, struct client, this);
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
socklen_t size;
|
|
||||||
const char *runtime_dir, *name = NULL;
|
|
||||||
int name_size, fd;
|
|
||||||
|
|
||||||
if ((runtime_dir = getenv("XDG_RUNTIME_DIR")) == NULL) {
|
|
||||||
pw_log_error("connect failed: XDG_RUNTIME_DIR not set in the environment");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
name = get_remote(impl->properties);
|
|
||||||
|
|
||||||
if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
addr.sun_family = AF_LOCAL;
|
|
||||||
name_size = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", runtime_dir, name) + 1;
|
|
||||||
|
|
||||||
if (name_size > (int) sizeof addr.sun_path) {
|
|
||||||
pw_log_error("socket path \"%s/%s\" plus null terminator exceeds 108 bytes",
|
|
||||||
runtime_dir, name);
|
|
||||||
goto error_close;
|
|
||||||
};
|
|
||||||
|
|
||||||
size = offsetof(struct sockaddr_un, sun_path) + name_size;
|
|
||||||
|
|
||||||
if (connect(fd, (struct sockaddr *) &addr, size) < 0)
|
|
||||||
goto error_close;
|
|
||||||
|
|
||||||
return pw_protocol_client_connect_fd(client, fd);
|
|
||||||
|
|
||||||
error_close:
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int impl_steal_fd(struct pw_protocol_client *client)
|
static int impl_steal_fd(struct pw_protocol_client *client)
|
||||||
{
|
{
|
||||||
struct client *impl = SPA_CONTAINER_OF(client, struct client, this);
|
struct client *impl = SPA_CONTAINER_OF(client, struct client, this);
|
||||||
|
|
@ -660,12 +607,14 @@ static int impl_connect_fd(struct pw_protocol_client *client, int fd)
|
||||||
fd,
|
fd,
|
||||||
SPA_IO_IN | SPA_IO_HUP | SPA_IO_ERR,
|
SPA_IO_IN | SPA_IO_HUP | SPA_IO_ERR,
|
||||||
true, on_remote_data, impl);
|
true, on_remote_data, impl);
|
||||||
|
if (impl->source == NULL)
|
||||||
|
goto error_close;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_close:
|
error_close:
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void impl_disconnect(struct pw_protocol_client *client)
|
static void impl_disconnect(struct pw_protocol_client *client)
|
||||||
|
|
@ -707,6 +656,7 @@ impl_new_client(struct pw_protocol *protocol,
|
||||||
{
|
{
|
||||||
struct client *impl;
|
struct client *impl;
|
||||||
struct pw_protocol_client *this;
|
struct pw_protocol_client *this;
|
||||||
|
const char *str = NULL;
|
||||||
|
|
||||||
if ((impl = calloc(1, sizeof(struct client))) == NULL)
|
if ((impl = calloc(1, sizeof(struct client))) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -717,7 +667,16 @@ impl_new_client(struct pw_protocol *protocol,
|
||||||
|
|
||||||
impl->properties = properties ? pw_properties_copy(properties) : NULL;
|
impl->properties = properties ? pw_properties_copy(properties) : NULL;
|
||||||
|
|
||||||
this->connect = impl_connect;
|
if (properties)
|
||||||
|
str = pw_properties_get(properties, "remote.intention");
|
||||||
|
if (str == NULL)
|
||||||
|
str = "generic";
|
||||||
|
|
||||||
|
if (!strcmp(str, "screencast"))
|
||||||
|
this->connect = pw_protocol_native_connect_portal_screencast;
|
||||||
|
else
|
||||||
|
this->connect = pw_protocol_native_connect_local_socket;
|
||||||
|
|
||||||
this->steal_fd = impl_steal_fd;
|
this->steal_fd = impl_steal_fd;
|
||||||
this->connect_fd = impl_connect_fd;
|
this->connect_fd = impl_connect_fd;
|
||||||
this->disconnect = impl_disconnect;
|
this->disconnect = impl_disconnect;
|
||||||
|
|
|
||||||
25
src/modules/module-protocol-native/defs.h
Normal file
25
src/modules/module-protocol-native/defs.h
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* PipeWire
|
||||||
|
* Copyright (C) 2018 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client,
|
||||||
|
void (*done_callback) (void *data, int res),
|
||||||
|
void *data);
|
||||||
|
int pw_protocol_native_connect_portal_screencast(struct pw_protocol_client *client,
|
||||||
|
void (*done_callback) (void *data, int res),
|
||||||
|
void *data);
|
||||||
98
src/modules/module-protocol-native/local-socket.c
Normal file
98
src/modules/module-protocol-native/local-socket.c
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
/* PipeWire
|
||||||
|
* Copyright (C) 2018 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
|
||||||
|
#include <spa/lib/debug.h>
|
||||||
|
|
||||||
|
#include <pipewire/pipewire.h>
|
||||||
|
#include <pipewire/private.h>
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
get_remote(const struct pw_properties *properties)
|
||||||
|
{
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if (properties)
|
||||||
|
name = pw_properties_get(properties, PW_REMOTE_PROP_REMOTE_NAME);
|
||||||
|
if (name == NULL)
|
||||||
|
name = getenv("PIPEWIRE_REMOTE");
|
||||||
|
if (name == NULL)
|
||||||
|
name = "pipewire-0";
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pw_protocol_native_connect_local_socket(struct pw_protocol_client *client,
|
||||||
|
void (*done_callback) (void *data, int res),
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct pw_remote *remote = client->remote;
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
socklen_t size;
|
||||||
|
const char *runtime_dir, *name = NULL;
|
||||||
|
int res, name_size, fd;
|
||||||
|
|
||||||
|
if ((runtime_dir = getenv("XDG_RUNTIME_DIR")) == NULL) {
|
||||||
|
pw_log_error("connect failed: XDG_RUNTIME_DIR not set in the environment");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = get_remote(pw_remote_get_properties(remote));
|
||||||
|
|
||||||
|
if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_LOCAL;
|
||||||
|
name_size = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", runtime_dir, name) + 1;
|
||||||
|
|
||||||
|
if (name_size > (int) sizeof addr.sun_path) {
|
||||||
|
pw_log_error("socket path \"%s/%s\" plus null terminator exceeds 108 bytes",
|
||||||
|
runtime_dir, name);
|
||||||
|
res = -ENOSPC;
|
||||||
|
goto error_close;
|
||||||
|
};
|
||||||
|
|
||||||
|
size = offsetof(struct sockaddr_un, sun_path) + name_size;
|
||||||
|
|
||||||
|
if (connect(fd, (struct sockaddr *) &addr, size) < 0) {
|
||||||
|
res = -errno;
|
||||||
|
goto error_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = pw_protocol_client_connect_fd(client, fd);
|
||||||
|
|
||||||
|
done_callback(data, res);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
|
||||||
|
error_close:
|
||||||
|
close(fd);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
38
src/modules/module-protocol-native/portal-screencast.c
Normal file
38
src/modules/module-protocol-native/portal-screencast.c
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* PipeWire
|
||||||
|
* Copyright (C) 2018 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <spa/lib/debug.h>
|
||||||
|
|
||||||
|
#include <pipewire/pipewire.h>
|
||||||
|
#include <pipewire/private.h>
|
||||||
|
|
||||||
|
int pw_protocol_native_connect_portal_screencast(struct pw_protocol_client *client,
|
||||||
|
void (*done_callback) (void *data, int res),
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
@ -41,16 +41,18 @@ struct pw_protocol_client {
|
||||||
|
|
||||||
struct pw_remote *remote; /**< the associated remote */
|
struct pw_remote *remote; /**< the associated remote */
|
||||||
|
|
||||||
int (*connect) (struct pw_protocol_client *client);
|
int (*connect) (struct pw_protocol_client *client,
|
||||||
int (*steal_fd) (struct pw_protocol_client *client);
|
void (*done_callback) (void *data, int result),
|
||||||
|
void *data);
|
||||||
int (*connect_fd) (struct pw_protocol_client *client, int fd);
|
int (*connect_fd) (struct pw_protocol_client *client, int fd);
|
||||||
|
int (*steal_fd) (struct pw_protocol_client *client);
|
||||||
void (*disconnect) (struct pw_protocol_client *client);
|
void (*disconnect) (struct pw_protocol_client *client);
|
||||||
void (*destroy) (struct pw_protocol_client *client);
|
void (*destroy) (struct pw_protocol_client *client);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define pw_protocol_client_connect(c) ((c)->connect(c))
|
#define pw_protocol_client_connect(c,cb,d) ((c)->connect(c,cb,d))
|
||||||
#define pw_protocol_client_steal_fd(c) ((c)->steal_fd(c))
|
|
||||||
#define pw_protocol_client_connect_fd(c,fd) ((c)->connect_fd(c,fd))
|
#define pw_protocol_client_connect_fd(c,fd) ((c)->connect_fd(c,fd))
|
||||||
|
#define pw_protocol_client_steal_fd(c) ((c)->steal_fd(c))
|
||||||
#define pw_protocol_client_disconnect(c) ((c)->disconnect(c))
|
#define pw_protocol_client_disconnect(c) ((c)->disconnect(c))
|
||||||
#define pw_protocol_client_destroy(c) ((c)->destroy(c))
|
#define pw_protocol_client_destroy(c) ((c)->destroy(c))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -364,7 +364,7 @@ static int do_connect(struct pw_remote *remote)
|
||||||
no_proxy:
|
no_proxy:
|
||||||
pw_protocol_client_disconnect(remote->conn);
|
pw_protocol_client_disconnect(remote->conn);
|
||||||
pw_remote_update_state(remote, PW_REMOTE_STATE_ERROR, "can't connect: no memory");
|
pw_remote_update_state(remote, PW_REMOTE_STATE_ERROR, "can't connect: no memory");
|
||||||
return -1;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pw_core_proxy * pw_remote_get_core_proxy(struct pw_remote *remote)
|
struct pw_core_proxy * pw_remote_get_core_proxy(struct pw_remote *remote)
|
||||||
|
|
@ -382,18 +382,30 @@ struct pw_proxy *pw_remote_find_proxy(struct pw_remote *remote, uint32_t id)
|
||||||
return pw_map_lookup(&remote->objects, id);
|
return pw_map_lookup(&remote->objects, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void done_connect(void *data, int result)
|
||||||
|
{
|
||||||
|
struct pw_remote *remote = data;
|
||||||
|
if (result < 0) {
|
||||||
|
pw_remote_update_state(remote, PW_REMOTE_STATE_ERROR, "can't connect: %s",
|
||||||
|
spa_strerror(result));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_connect(remote);
|
||||||
|
}
|
||||||
|
|
||||||
int pw_remote_connect(struct pw_remote *remote)
|
int pw_remote_connect(struct pw_remote *remote)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
pw_remote_update_state(remote, PW_REMOTE_STATE_CONNECTING, NULL);
|
pw_remote_update_state(remote, PW_REMOTE_STATE_CONNECTING, NULL);
|
||||||
|
|
||||||
if ((res = pw_protocol_client_connect (remote->conn)) < 0) {
|
if ((res = pw_protocol_client_connect (remote->conn, done_connect, remote)) < 0) {
|
||||||
pw_remote_update_state(remote, PW_REMOTE_STATE_ERROR, "connect failed");
|
pw_remote_update_state(remote, PW_REMOTE_STATE_ERROR,
|
||||||
|
"connect failed %s", spa_strerror(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
return remote->state == PW_REMOTE_STATE_ERROR ? -EIO : 0;
|
||||||
return do_connect(remote);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pw_remote_connect_fd(struct pw_remote *remote, int fd)
|
int pw_remote_connect_fd(struct pw_remote *remote, int fd)
|
||||||
|
|
@ -403,7 +415,8 @@ int pw_remote_connect_fd(struct pw_remote *remote, int fd)
|
||||||
pw_remote_update_state(remote, PW_REMOTE_STATE_CONNECTING, NULL);
|
pw_remote_update_state(remote, PW_REMOTE_STATE_CONNECTING, NULL);
|
||||||
|
|
||||||
if ((res = pw_protocol_client_connect_fd (remote->conn, fd)) < 0) {
|
if ((res = pw_protocol_client_connect_fd (remote->conn, fd)) < 0) {
|
||||||
pw_remote_update_state(remote, PW_REMOTE_STATE_ERROR, "connect_fd failed");
|
pw_remote_update_state(remote, PW_REMOTE_STATE_ERROR,
|
||||||
|
"connect_fd failed %s", spa_strerror(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue