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

Remove old wifi code in miracled

The wifi code is now moved to miracle-wifid, no need to keep it anymore.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
David Herrmann 2014-03-19 13:31:01 +01:00
parent 89a268109e
commit 87b804c481
9 changed files with 24 additions and 4137 deletions

View file

@ -161,11 +161,7 @@ bin_PROGRAMS += miracled
miracled_SOURCES = \
src/miracled.h \
src/miracled.c \
src/miracled-dbus.c \
src/miracled-link.c \
src/miracled-peer.c \
src/miracled-wifi.c
src/miracled.c
miracled_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(DEPS_CFLAGS)

View file

@ -1,217 +0,0 @@
/*
* MiracleCast - Wifi-Display/Miracast Implementation
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MIRACLE_H
#define MIRACLE_H
#include <alloca.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/time.h>
#include <systemd/sd-bus.h>
#include <time.h>
#include "shl_log.h"
#include "shl_macro.h"
static inline void cleanup_sd_bus_message(sd_bus_message **ptr)
{
sd_bus_message_unref(*ptr);
}
#define _cleanup_free_ _shl_cleanup_free_
#define _cleanup_sd_bus_error_ _shl_cleanup_(sd_bus_error_free)
#define _cleanup_sd_bus_message_ _shl_cleanup_(cleanup_sd_bus_message)
static inline const char *bus_error_message(const sd_bus_error *e, int error)
{
if (e) {
if (sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED))
return "Access denied";
if (e->message)
return e->message;
}
return strerror(error < 0 ? -error : error);
}
static inline int log_bus_parser(int r)
{
log_error("cannot parse dbus message: %s", strerror(r < 0 ? -r : r));
return r;
}
static inline int log_bus_create(int r)
{
log_error("cannot create dbus message: %s", strerror(r < 0 ? -r : r));
return r;
}
static inline int bus_message_read_basic_variant(sd_bus_message *m,
const char *sig, void *ptr)
{
int r;
if (!sig || !*sig || sig[1] || !ptr)
return -EINVAL;
r = sd_bus_message_enter_container(m, 'v', sig);
if (r < 0)
return r;
r = sd_bus_message_read(m, sig, ptr);
if (r < 0)
return r;
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
return 0;
}
#define strv_from_stdarg_alloca(first) ({ \
char **_l; \
if (!first) { \
_l = (char**)&first; \
} else { \
unsigned _n; \
va_list _ap; \
_n = 1; \
va_start(_ap, first); \
while (va_arg(_ap, char*)) \
_n++; \
va_end(_ap); \
_l = alloca(sizeof(char*) * (_n + 1)); \
_l[_n = 0] = (char*)first; \
va_start(_ap, first); \
for (;;) { \
_l[++_n] = va_arg(_ap, char*); \
if (!_l[_n]) \
break; \
} \
va_end(_ap); \
} \
_l; \
})
static inline int64_t now(clockid_t clock_id)
{
struct timespec ts;
clock_gettime(clock_id, &ts);
return (int64_t)ts.tv_sec * 1000000LL +
(int64_t)ts.tv_nsec / 1000LL;
}
static inline char hexchar(int x)
{
static const char table[16] = "0123456789abcdef";
return table[x & 15];
}
static inline int unhexchar(char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
static inline char *bus_label_escape(const char *s)
{
char *r, *t;
const char *f;
if (*s == 0)
return strdup("_");
r = calloc(sizeof(char), strlen(s)*3 + 1);
if (!r)
return NULL;
for (f = s, t = r; *f; f++) {
/* Escape everything that is not a-zA-Z0-9. We also
* escape 0-9 if it's the first character */
if (!(*f >= 'A' && *f <= 'Z') &&
!(*f >= 'a' && *f <= 'z') &&
!(f > s && *f >= '0' && *f <= '9')) {
*(t++) = '_';
*(t++) = hexchar(*f >> 4);
*(t++) = hexchar(*f);
} else
*(t++) = *f;
}
*t = 0;
return r;
}
static inline char *bus_label_unescape(const char *f)
{
char *r, *t;
/* Special case for the empty string */
if (!strcmp(f, "_"))
return strdup("");
r = calloc(sizeof(char), strlen(f) + 1);
if (!r)
return NULL;
for (t = r; *f; f++) {
if (*f == '_') {
int a, b;
if ((a = unhexchar(f[1])) < 0 ||
(b = unhexchar(f[2])) < 0) {
/* Invalid escape code, let's take it literal then */
*(t++) = '_';
} else {
*(t++) = (char) ((a << 4) | b);
f += 2;
}
} else
*(t++) = *f;
}
*t = 0;
return r;
}
#endif /* MIRACLE_H */

View file

@ -1,874 +0,0 @@
/*
* MiracleCast - Wifi-Display/Miracast Implementation
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define LOG_SUBSYSTEM "dbus"
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-event.h>
#include "miracle.h"
#include "miracled.h"
#include "shl_log.h"
#include "shl_util.h"
/*
* Peer DBus
*/
static int peer_dbus_allow(sd_bus *bus, sd_bus_message *msg,
void *data, sd_bus_error *err)
{
struct peer *p = data;
const char *pin;
int r;
r = sd_bus_message_read(msg, "s", &pin);
if (r < 0)
return r;
r = peer_allow(p, pin);
if (r < 0)
return r;
return sd_bus_reply_method_return(msg, NULL);
}
static int peer_dbus_reject(sd_bus *bus, sd_bus_message *msg,
void *data, sd_bus_error *err)
{
struct peer *p = data;
peer_reject(p);
return sd_bus_reply_method_return(msg, NULL);
}
static int peer_dbus_connect(sd_bus *bus, sd_bus_message *msg,
void *data, sd_bus_error *err)
{
struct peer *p = data;
const char *prov, *pin;
int r;
r = sd_bus_message_read(msg, "ss", &prov, &pin);
if (r < 0)
return r;
r = peer_connect(p, prov, pin);
if (r < 0)
return r;
return sd_bus_reply_method_return(msg, NULL);
}
static int peer_dbus_disconnect(sd_bus *bus, sd_bus_message *msg,
void *data, sd_bus_error *err)
{
struct peer *p = data;
peer_disconnect(p);
return sd_bus_reply_method_return(msg, NULL);
}
static int peer_dbus_get_link(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
_shl_free_ char *link = NULL;
struct peer *p = data;
int r;
link = shl_strcat("/org/freedesktop/miracle/link/", p->l->name);
if (!link)
return log_ENOMEM();
r = sd_bus_message_append_basic(reply, 'o', link);
if (r < 0)
return r;
return 1;
}
static int peer_dbus_get_name(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
struct peer *p = data;
const char *name;
int r;
name = peer_get_friendly_name(p);
r = sd_bus_message_append_basic(reply, 's', name ? name : "<unknown>");
if (r < 0)
return r;
return 1;
}
static int peer_dbus_get_connected(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
struct peer *p = data;
int r, val;
val = peer_is_connected(p);
r = sd_bus_message_append_basic(reply, 'b', &val);
if (r < 0)
return r;
return 1;
}
static int peer_dbus_get_interface(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
struct peer *p = data;
const char *val;
int r;
val = peer_get_interface(p);
r = sd_bus_message_append_basic(reply, 's', val ? : "");
if (r < 0)
return r;
return 1;
}
static int peer_dbus_get_local_address(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
struct peer *p = data;
const char *val;
int r;
val = peer_get_local_address(p);
r = sd_bus_message_append_basic(reply, 's', val ? : "");
if (r < 0)
return r;
return 1;
}
static int peer_dbus_get_remote_address(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
struct peer *p = data;
const char *val;
int r;
val = peer_get_remote_address(p);
r = sd_bus_message_append_basic(reply, 's', val ? : "");
if (r < 0)
return r;
return 1;
}
static const sd_bus_vtable peer_dbus_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("Allow",
"s",
NULL,
peer_dbus_allow,
0),
SD_BUS_METHOD("Reject",
NULL,
NULL,
peer_dbus_reject,
0),
SD_BUS_METHOD("Connect",
"ss",
NULL,
peer_dbus_connect,
0),
SD_BUS_METHOD("Disconnect",
NULL,
NULL,
peer_dbus_disconnect,
0),
SD_BUS_PROPERTY("Link",
"o",
peer_dbus_get_link,
0,
SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Name",
"s",
peer_dbus_get_name,
0,
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Connected",
"b",
peer_dbus_get_connected,
0,
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Interface",
"s",
peer_dbus_get_interface,
0,
0),
SD_BUS_PROPERTY("LocalAddress",
"s",
peer_dbus_get_local_address,
0,
0),
SD_BUS_PROPERTY("RemoteAddress",
"s",
peer_dbus_get_remote_address,
0,
0),
SD_BUS_SIGNAL("ProvisionRequest", "ss", 0),
SD_BUS_VTABLE_END
};
static int peer_dbus_find(sd_bus *bus,
const char *path,
const char *interface,
void *data,
void **found,
sd_bus_error *err)
{
struct manager *m = data;
struct peer *p;
const char *name;
if (!(name = shl_startswith(path, "/org/freedesktop/miracle/peer/")))
return 0;
p = manager_find_peer(m, name);
if (!p)
return 0;
*found = p;
return 1;
}
void peer_dbus_provision_request(struct peer *p,
const char *type,
const char *pin)
{
_shl_free_ char *path = NULL;
int r;
if (!type)
return;
if (!pin)
pin = "";
path = shl_strcat("/org/freedesktop/miracle/peer/", p->name);
if (!path)
return log_vENOMEM();
r = sd_bus_emit_signal(p->l->m->bus,
path,
"org.freedesktop.miracle.Peer",
"ProvisionRequest",
"ss", type, pin);
if (r < 0)
log_vERR(r);
}
void peer_dbus_properties_changed(struct peer *p, const char *prop, ...)
{
_shl_free_ char *path = NULL;
char **strv;
int r;
path = shl_strcat("/org/freedesktop/miracle/peer/", p->name);
if (!path)
return log_vENOMEM();
strv = strv_from_stdarg_alloca(prop);
r = sd_bus_emit_properties_changed_strv(p->l->m->bus,
path,
"org.freedesktop.miracle.Peer",
strv);
if (r < 0)
log_vERR(r);
}
void peer_dbus_added(struct peer *p)
{
_shl_free_ char *path = NULL;
int r;
path = shl_strcat("/org/freedesktop/miracle/peer/", p->name);
if (!path)
return log_vENOMEM();
r = sd_bus_emit_interfaces_added(p->l->m->bus,
path,
/*
"org.freedesktop.DBus.Properties",
"org.freedesktop.DBus.Introspectable",
*/
"org.freedesktop.miracle.Peer",
NULL);
if (r < 0)
log_vERR(r);
}
void peer_dbus_removed(struct peer *p)
{
_shl_free_ char *path = NULL;
int r;
path = shl_strcat("/org/freedesktop/miracle/peer/", p->name);
if (!path)
return log_vENOMEM();
r = sd_bus_emit_interfaces_removed(p->l->m->bus,
path,
/*
"org.freedesktop.DBus.Properties",
"org.freedesktop.DBus.Introspectable",
*/
"org.freedesktop.miracle.Peer",
NULL);
if (r < 0)
log_vERR(r);
}
/*
* Link DBus
*/
static int link_dbus_start_scan(sd_bus *bus, sd_bus_message *msg,
void *data, sd_bus_error *err)
{
struct link *l = data;
int r;
r = link_start_scan(l);
if (r < 0)
return r;
return sd_bus_reply_method_return(msg, NULL);
}
static int link_dbus_stop_scan(sd_bus *bus, sd_bus_message *msg,
void *data, sd_bus_error *err)
{
struct link *l = data;
link_stop_scan(l);
return sd_bus_reply_method_return(msg, NULL);
}
static int link_dbus_get_type(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
struct link *l = data;
int r;
r = sd_bus_message_append_basic(reply, 's',
link_type_to_str(l->type));
if (r < 0)
return r;
return 1;
}
static int link_dbus_get_interface(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
struct link *l = data;
int r;
r = sd_bus_message_append_basic(reply, 's', l->interface);
if (r < 0)
return r;
return 1;
}
static int link_dbus_get_running(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
struct link *l = data;
int r, val;
val = l->running;
r = sd_bus_message_append_basic(reply, 'b', &val);
if (r < 0)
return r;
return 1;
}
static int link_dbus_get_name(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *data,
sd_bus_error *err)
{
struct link *l = data;
int r;
r = sd_bus_message_append_basic(reply, 's', l->friendly_name);
if (r < 0)
return r;
return 1;
}
static int link_dbus_set_name(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *value,
void *data,
sd_bus_error *err)
{
struct link *l = data;
int r;
const char *name;
r = sd_bus_message_read(value, "s", &name);
if (r < 0)
return r;
return link_set_friendly_name(l, name);
}
static const sd_bus_vtable link_dbus_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("StartScan",
NULL,
NULL,
link_dbus_start_scan,
0),
SD_BUS_METHOD("StopScan",
NULL,
NULL,
link_dbus_stop_scan,
0),
SD_BUS_PROPERTY("Type",
"s",
link_dbus_get_type,
0,
SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Interface",
"s",
link_dbus_get_interface,
0,
SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Running",
"b",
link_dbus_get_running,
0,
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_WRITABLE_PROPERTY("Name",
"s",
link_dbus_get_name,
link_dbus_set_name,
0,
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_SIGNAL("ScanStopped", NULL, 0),
SD_BUS_VTABLE_END
};
static int link_dbus_find(sd_bus *bus,
const char *path,
const char *interface,
void *data,
void **found,
sd_bus_error *err)
{
struct manager *m = data;
struct link *l;
const char *name;
if (!(name = shl_startswith(path, "/org/freedesktop/miracle/link/")))
return 0;
l = manager_find_link(m, name);
if (!l)
return 0;
*found = l;
return 1;
}
void link_dbus_properties_changed(struct link *l, const char *prop, ...)
{
_shl_free_ char *path = NULL;
char **strv;
int r;
path = shl_strcat("/org/freedesktop/miracle/link/", l->name);
if (!path)
return log_vENOMEM();
strv = strv_from_stdarg_alloca(prop);
r = sd_bus_emit_properties_changed_strv(l->m->bus,
path,
"org.freedesktop.miracle.Link",
strv);
if (r < 0)
log_vERR(r);
}
void link_dbus_scan_stopped(struct link *l)
{
_shl_free_ char *path = NULL;
int r;
path = shl_strcat("/org/freedesktop/miracle/link/", l->name);
if (!path)
return log_vENOMEM();
r = sd_bus_emit_signal(l->m->bus,
path,
"org.freedesktop.miracle.Link",
"ScanStopped",
NULL);
if (r < 0)
log_vERR(r);
}
void link_dbus_added(struct link *l)
{
_shl_free_ char *path = NULL;
int r;
path = shl_strcat("/org/freedesktop/miracle/link/", l->name);
if (!path)
return log_vENOMEM();
r = sd_bus_emit_interfaces_added(l->m->bus,
path,
/*
"org.freedesktop.DBus.Properties",
"org.freedesktop.DBus.Introspectable",
*/
"org.freedesktop.miracle.Link",
NULL);
if (r < 0)
log_vERR(r);
}
void link_dbus_removed(struct link *l)
{
_shl_free_ char *path = NULL;
int r;
path = shl_strcat("/org/freedesktop/miracle/link/", l->name);
if (!path)
return log_vENOMEM();
r = sd_bus_emit_interfaces_removed(l->m->bus,
path,
/*
"org.freedesktop.DBus.Properties",
"org.freedesktop.DBus.Introspectable",
*/
"org.freedesktop.miracle.Link",
NULL);
if (r < 0)
log_vERR(r);
}
/*
* Manager DBus
*/
static int manager_dbus_add_link(sd_bus *bus, sd_bus_message *msg,
void *data, sd_bus_error *err)
{
struct manager *m = data;
const char *stype, *interface;
unsigned int type;
struct link *l;
int r;
r = sd_bus_message_read(msg, "ss", &stype, &interface);
if (r < 0)
return r;
type = link_type_from_str(stype);
if (type >= LINK_CNT)
return sd_bus_error_setf(err,
SD_BUS_ERROR_INVALID_ARGS,
"invalid type");
r = link_new(m, type, interface, &l);
if (r == -EALREADY)
return sd_bus_error_setf(err,
SD_BUS_ERROR_INVALID_ARGS,
"link already available");
else if (r < 0)
return r;
return sd_bus_reply_method_return(msg, "s", l->name);
}
static int manager_dbus_remove_link(sd_bus *bus, sd_bus_message *msg,
void *data, sd_bus_error *err)
{
_shl_free_ char *link = NULL;
struct manager *m = data;
struct link *l;
const char *name;
int r;
r = sd_bus_message_read(msg, "s", &name);
if (r < 0)
return r;
link = bus_label_escape(name);
if (!link)
return log_ENOMEM();
l = manager_find_link(m, link);
if (!l)
return sd_bus_error_setf(err,
SD_BUS_ERROR_INVALID_ARGS,
"link not available");
link_free(l);
return sd_bus_reply_method_return(msg, NULL);
}
static const sd_bus_vtable manager_dbus_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("AddLink",
"ss",
"s",
manager_dbus_add_link,
0),
SD_BUS_METHOD("RemoveLink",
"s",
NULL,
manager_dbus_remove_link,
0),
SD_BUS_VTABLE_END
};
static int manager_dbus_enumerate(sd_bus *bus,
const char *path,
void *data,
char ***out,
sd_bus_error *err)
{
struct manager *m = data;
struct link *l;
struct peer *p;
size_t i;
char **nodes, *node;
int r;
nodes = malloc(sizeof(*nodes) * (m->link_cnt + m->peer_cnt + 2));
if (!nodes)
return log_ENOMEM();
i = 0;
MANAGER_FOREACH_LINK(l, m) {
if (i >= m->link_cnt + m->peer_cnt) {
log_warning("overflow: skipping link %s",
l->name);
continue;
}
node = shl_strcat("/org/freedesktop/miracle/link/",
l->name);
if (!node) {
r = log_ENOMEM();
goto error;
}
nodes[i++] = node;
}
MANAGER_FOREACH_PEER(p, m) {
if (i >= m->link_cnt + m->peer_cnt) {
log_warning("overflow: skipping peer %s",
p->name);
continue;
}
node = shl_strcat("/org/freedesktop/miracle/peer/",
p->name);
if (!node) {
r = log_ENOMEM();
goto error;
}
nodes[i++] = node;
}
node = strdup("/org/freedesktop/miracle");
if (!node) {
r = log_ENOMEM();
goto error;
}
nodes[i++] = node;
nodes[i] = NULL;
*out = nodes;
return 0;
error:
while (i--)
free(nodes[i]);
free(nodes);
return r;
}
int manager_dbus_connect(struct manager *m)
{
int r;
r = sd_bus_add_object_vtable(m->bus,
"/org/freedesktop/miracle",
"org.freedesktop.miracle.Manager",
manager_dbus_vtable,
m);
if (r < 0)
goto error;
r = sd_bus_add_node_enumerator(m->bus,
"/org/freedesktop/miracle",
manager_dbus_enumerate,
m);
if (r < 0)
goto error;
r = sd_bus_add_fallback_vtable(m->bus,
"/org/freedesktop/miracle/link",
"org.freedesktop.miracle.Link",
link_dbus_vtable,
link_dbus_find,
m);
if (r < 0)
goto error;
r = sd_bus_add_fallback_vtable(m->bus,
"/org/freedesktop/miracle/peer",
"org.freedesktop.miracle.Peer",
peer_dbus_vtable,
peer_dbus_find,
m);
if (r < 0)
goto error;
r = sd_bus_add_object_manager(m->bus, "/org/freedesktop/miracle");
if (r < 0)
goto error;
r = sd_bus_request_name(m->bus, "org.freedesktop.miracle", 0);
if (r < 0) {
log_error("cannot claim org.freedesktop.miracle bus-name: %d",
r);
goto error_silent;
}
return 0;
error:
log_ERR(r);
error_silent:
manager_dbus_disconnect(m);
return r;
}
void manager_dbus_disconnect(struct manager *m)
{
if (!m || !m->bus)
return;
sd_bus_release_name(m->bus, "org.freedesktop.miracle");
sd_bus_remove_object_manager(m->bus, "/org/freedesktop/miracle");
sd_bus_remove_fallback_vtable(m->bus,
"/org/freedesktop/miracle/peer",
"org.freedesktop.miracle.Peer",
peer_dbus_vtable,
peer_dbus_find,
m);
sd_bus_remove_fallback_vtable(m->bus,
"/org/freedesktop/miracle/link",
"org.freedesktop.miracle.Link",
link_dbus_vtable,
link_dbus_find,
m);
sd_bus_remove_node_enumerator(m->bus,
"/org/freedesktop/miracle",
manager_dbus_enumerate,
m);
sd_bus_remove_object_vtable(m->bus,
"/org/freedesktop/miracle",
"org.freedesktop.miracle.Manager",
manager_dbus_vtable,
m);
}

View file

@ -1,429 +0,0 @@
/*
* MiracleCast - Wifi-Display/Miracast Implementation
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define LOG_SUBSYSTEM "link"
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
#include "miracled.h"
#include "miracled-wifi.h"
#include "shl_dlist.h"
#include "shl_log.h"
#include "shl_util.h"
static const char *link_type_to_str_table[LINK_CNT] = {
[LINK_VIRTUAL] = "virtual",
[LINK_WIFI] = "wifi",
};
const char *link_type_to_str(unsigned int type)
{
if (type >= LINK_CNT)
return NULL;
return link_type_to_str_table[type];
}
unsigned int link_type_from_str(const char *str)
{
unsigned int i;
if (!str)
return LINK_CNT;
for (i = 0; i < LINK_CNT; ++i)
if (link_type_to_str_table[i] &&
!strcmp(link_type_to_str_table[i], str))
return i;
return LINK_CNT;
}
int link_make_name(unsigned int type, const char *interface, char **out)
{
const char *tname;
char *name, *res;
size_t tlen, ilen;
tname = link_type_to_str(type);
if (!tname || !interface)
return -EINVAL;
/* hard-coded maximum of 255 just to be safe */
tlen = strlen(tname);
ilen = strlen(interface);
if (!tlen || tlen > 255 || !ilen || ilen > 255)
return -EINVAL;
if (!out)
return 0;
name = shl_strjoin(tname, ":", interface, NULL);
if (!name)
return log_ENOMEM();
res = bus_label_escape(name);
free(name);
if (!res)
return log_ENOMEM();
*out = res;
return 0;
}
/*
* Wifi Handling
*/
static void link_wifi_event_fn(struct wifi *w, void *data,
struct wifi_event *ev)
{
struct link *l = data;
struct peer *p;
switch (ev->type) {
case WIFI_HUP:
/* destroy this link */
link_free(l);
break;
case WIFI_SCAN_STOPPED:
link_dbus_scan_stopped(l);
break;
case WIFI_DEV_FOUND:
peer_new_wifi(l, ev->dev_found.dev, NULL);
break;
case WIFI_DEV_LOST:
p = wifi_dev_get_data(ev->dev_lost.dev);
if (!p)
break;
peer_free(p);
break;
case WIFI_DEV_PROVISION:
case WIFI_DEV_CONNECT:
case WIFI_DEV_DISCONNECT:
p = wifi_dev_get_data(ev->dev_lost.dev);
if (!p)
break;
peer_process_wifi(p, ev);
break;
default:
log_debug("unhandled WIFI event: %u", ev->type);
break;
}
}
static int link_wifi_start(struct link *l)
{
_shl_free_ char *path = NULL;
struct wifi_dev *d;
int r;
path = shl_strjoin(arg_wpa_rundir, "/", l->interface, NULL);
if (!path)
return log_ENOMEM();
r = wifi_open(l->w, path);
if (r < 0)
return r;
r = wifi_set_name(l->w, l->friendly_name);
if (r < 0)
return r;
for (d = wifi_get_devs(l->w); d; d = wifi_dev_next(d))
peer_new_wifi(l, d, NULL);
return 0;
}
static int link_wifi_child_fn(sd_event_source *source,
const siginfo_t *si,
void *data)
{
struct link *l = data;
log_error("wpa_supplicant died unexpectedly on link %s", l->name);
link_free(l);
return 0;
}
static int link_wifi_startup_fn(sd_event_source *source,
uint64_t usec,
void *data)
{
struct link *l = data;
int r;
r = link_wifi_start(l);
if (r < 0) {
if (wifi_is_open(l->w) || ++l->wpa_startup_attempts >= 5) {
log_error("cannot start wifi on link %s", l->name);
link_free(l);
return 0;
}
/* reschedule timer */
sd_event_source_set_time(source,
now(CLOCK_MONOTONIC) + 200 * 1000);
sd_event_source_set_enabled(source, SD_EVENT_ON);
log_debug("wpa_supplicant startup still ongoing, reschedule..");
return 0;
}
log_debug("wpa_supplicant startup finished on link %s", l->name);
sd_event_source_set_enabled(source, SD_EVENT_OFF);
l->running = true;
link_dbus_properties_changed(l, "Running", NULL);
return 0;
}
static int link_wifi_init(struct link *l)
{
_shl_free_ char *path = NULL;
int r;
r = wifi_new(l->m->event, link_wifi_event_fn, l, &l->w);
if (r < 0)
return r;
if (!arg_manage_wifi) {
r = link_wifi_start(l);
if (r < 0)
log_error("cannot open wpa_supplicant socket for link %s",
l->name);
else
l->running = true;
return r;
}
path = shl_strcat(arg_wpa_bindir, "/wpa_supplicant");
if (!path)
return log_ENOMEM();
r = wifi_spawn_supplicant(l->w, arg_wpa_rundir, path, l->interface);
if (r < 0)
return r;
r = sd_event_add_child(l->m->event,
&l->wpa_child_source,
wifi_get_supplicant_pid(l->w),
WEXITED,
link_wifi_child_fn,
l);
if (r < 0)
return r;
r = sd_event_add_monotonic(l->m->event,
&l->wpa_startup_source,
now(CLOCK_MONOTONIC) + 200 * 1000,
0,
link_wifi_startup_fn,
l);
if (r < 0)
return r;
return 0;
}
static void link_wifi_destroy(struct link *l)
{
sd_event_source_unref(l->wpa_startup_source);
sd_event_source_unref(l->wpa_child_source);
wifi_close(l->w);
wifi_free(l->w);
}
/*
* Link Handling
*/
int link_new(struct manager *m,
unsigned int type,
const char *interface,
struct link **out)
{
size_t hash = 0;
char *name;
struct link *l;
int r;
if (!m)
return log_EINVAL();
r = link_make_name(type, interface, &name);
if (r < 0)
return r;
if (shl_htable_lookup_str(&m->links, name, &hash, NULL)) {
free(name);
return -EALREADY;
}
log_debug("new link: %s", name);
l = calloc(1, sizeof(*l));
if (!l) {
free(name);
return log_ENOMEM();
}
l->m = m;
l->type = type;
l->name = name;
shl_dlist_init(&l->peers);
l->interface = strdup(interface);
if (!l->interface) {
r = log_ENOMEM();
goto error;
}
l->friendly_name = strdup(m->friendly_name);
if (!l->friendly_name) {
r = log_ENOMEM();
goto error;
}
switch (l->type) {
case LINK_VIRTUAL:
l->running = true;
break;
case LINK_WIFI:
r = link_wifi_init(l);
if (r < 0)
goto error;
break;
}
r = shl_htable_insert_str(&m->links, &l->name, &hash);
if (r < 0) {
log_vERR(r);
goto error;
}
++m->link_cnt;
link_dbus_added(l);
log_info("new managed link: %s", l->name);
if (out)
*out = l;
return 0;
error:
link_free(l);
return r;
}
void link_free(struct link *l)
{
struct peer *p;
if (!l)
return;
log_debug("free link: %s", l->name);
while ((p = LINK_FIRST_PEER(l)))
peer_free(p);
if (shl_htable_remove_str(&l->m->links, l->name, NULL, NULL)) {
log_info("remove managed link: %s", l->name);
link_dbus_removed(l);
--l->m->link_cnt;
}
link_wifi_destroy(l);
free(l->friendly_name);
free(l->name);
free(l->interface);
free(l);
}
int link_set_friendly_name(struct link *l, const char *name)
{
char *dup;
int r;
if (!l || !name)
return log_EINVAL();
dup = strdup(name);
if (!dup)
return log_ENOMEM();
r = 0;
switch (l->type) {
case LINK_WIFI:
r = wifi_set_name(l->w, name);
break;
}
if (r < 0) {
free(dup);
return r;
}
free(l->friendly_name);
l->friendly_name = dup;
link_dbus_properties_changed(l, "Name", NULL);
return 0;
}
int link_start_scan(struct link *l)
{
if (!l)
return -EINVAL;
switch (l->type) {
case LINK_VIRTUAL:
return -EOPNOTSUPP;
case LINK_WIFI:
return wifi_set_discoverable(l->w, true);
}
return -EINVAL;
}
void link_stop_scan(struct link *l)
{
if (!l)
return;
switch (l->type) {
case LINK_WIFI:
wifi_set_discoverable(l->w, false);
}
}

View file

@ -1,305 +0,0 @@
/*
* MiracleCast - Wifi-Display/Miracast Implementation
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define LOG_SUBSYSTEM "peer"
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
#include "miracled.h"
#include "miracled-wifi.h"
#include "shl_log.h"
int peer_make_name(unsigned int id, char **out)
{
char buf[64] = { };
char *name;
if (!out)
return 0;
snprintf(buf, sizeof(buf) - 1, "%u", id);
name = bus_label_escape(buf);
if (!name)
return log_ENOMEM();
*out = name;
return 0;
}
static int peer_new(struct link *l, struct peer **out)
{
unsigned int id;
char *name;
struct peer *p;
int r;
if (!l)
return log_EINVAL();
id = ++l->m->peer_ids;
r = peer_make_name(id, &name);
if (r < 0)
return r;
if (shl_htable_lookup_str(&l->m->peers, name, NULL, NULL)) {
free(name);
return -EALREADY;
}
log_debug("new peer: %s", name);
p = calloc(1, sizeof(*p));
if (!p) {
free(name);
return log_ENOMEM();
}
p->l = l;
p->id = id;
p->name = name;
if (out)
*out = p;
return 0;
}
static int peer_link(struct peer *p)
{
int r;
r = shl_htable_insert_str(&p->l->m->peers, &p->name, NULL);
if (r < 0)
return log_ERR(r);
++p->l->m->peer_cnt;
shl_dlist_link(&p->l->peers, &p->list);
peer_dbus_added(p);
log_info("new peer: %s@%s", p->name, p->l->name);
return 0;
}
int peer_new_wifi(struct link *l, struct wifi_dev *d, struct peer **out)
{
int r;
struct peer *p;
r = peer_new(l, &p);
if (r < 0)
return r;
p->d = d;
wifi_dev_set_data(p->d, p);
r = peer_link(p);
if (r < 0)
goto error;
if (out)
*out = p;
return 0;
error:
peer_free(p);
return r;
}
void peer_free(struct peer *p)
{
if (!p)
return;
log_debug("free peer: %s", p->name);
if (shl_htable_remove_str(&p->l->m->peers, p->name, NULL, NULL)) {
log_info("remove managed peer: %s@%s", p->name, p->l->name);
peer_dbus_removed(p);
--p->l->m->peer_cnt;
shl_dlist_unlink(&p->list);
}
wifi_dev_set_data(p->d, NULL);
free(p->name);
free(p);
}
const char *peer_get_friendly_name(struct peer *p)
{
if (!p)
return NULL;
if (p->d)
return wifi_dev_get_name(p->d);
else
return NULL;
}
bool peer_is_connected(struct peer *p)
{
if (!p)
return false;
if (p->d)
return wifi_dev_is_ready(p->d);
else
return false;
}
const char *peer_get_interface(struct peer *p)
{
if (!p)
return NULL;
if (p->d)
return wifi_dev_get_interface(p->d);
else
return NULL;
}
const char *peer_get_local_address(struct peer *p)
{
if (!p)
return NULL;
if (p->d)
return wifi_dev_get_local_address(p->d);
else
return NULL;
}
const char *peer_get_remote_address(struct peer *p)
{
if (!p)
return NULL;
if (p->d)
return wifi_dev_get_remote_address(p->d);
else
return NULL;
}
static const char *peer_provision_str[WIFI_PROVISION_CNT] = {
[WIFI_PROVISION_PBC] = "pbc",
[WIFI_PROVISION_DISPLAY] = "display",
[WIFI_PROVISION_PIN] = "pin",
};
static const char *peer_provision_to_str(unsigned int prov)
{
if (prov >= WIFI_PROVISION_CNT)
return NULL;
return peer_provision_str[prov];
}
static unsigned int peer_provision_from_str(const char *prov)
{
unsigned int i;
if (!prov || !*prov)
return WIFI_PROVISION_CNT;
for (i = 0; i < WIFI_PROVISION_CNT; ++i)
if (peer_provision_str[i])
if (!strcmp(prov, peer_provision_str[i]))
return i;
return WIFI_PROVISION_CNT;
}
void peer_process_wifi(struct peer *p, struct wifi_event *ev)
{
const char *prov;
if (!p || !p->d)
return;
switch (ev->type) {
case WIFI_DEV_PROVISION:
prov = peer_provision_to_str(ev->dev_provision.type);
if (!prov)
break;
peer_dbus_provision_request(p, prov, ev->dev_provision.pin);
break;
case WIFI_DEV_CONNECT:
peer_dbus_properties_changed(p, "Connected", NULL);
break;
case WIFI_DEV_DISCONNECT:
peer_dbus_properties_changed(p, "Connected", NULL);
break;
default:
log_debug("unhandled WIFI event: %u", ev->type);
break;
}
}
int peer_allow(struct peer *p, const char *pin)
{
if (!p || !p->d)
return -EOPNOTSUPP;
wifi_dev_allow(p->d, pin);
return 0;
}
void peer_reject(struct peer *p)
{
if (!p || !p->d)
return;
wifi_dev_reject(p->d);
}
int peer_connect(struct peer *p, const char *prov, const char *pin)
{
if (!p || !p->d)
return -EOPNOTSUPP;
if (!prov)
prov = "";
if (!pin)
pin = "";
return wifi_dev_connect(p->d, peer_provision_from_str(prov), pin);
}
void peer_disconnect(struct peer *p)
{
bool change;
if (!p || !p->d)
return;
change = peer_is_connected(p);
wifi_dev_disconnect(p->d);
if (change)
peer_dbus_properties_changed(p, "Connected", NULL);
}

File diff suppressed because it is too large Load diff

View file

@ -1,138 +0,0 @@
/*
* MiracleCast - Wifi-Display/Miracast Implementation
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <systemd/sd-event.h>
#include "miracle.h"
#ifndef MIRACLED_WIFI_H
#define MIRACLED_WIFI_H
struct wifi;
struct wifi_dev;
/* wifi */
struct wifi;
struct wifi_dev;
enum wifi_event_type {
WIFI_HUP,
WIFI_SCAN_STOPPED,
WIFI_DEV_FOUND,
WIFI_DEV_LOST,
WIFI_DEV_PROVISION,
WIFI_DEV_CONNECT,
WIFI_DEV_DISCONNECT,
};
enum wifi_provision_type {
WIFI_PROVISION_PBC,
WIFI_PROVISION_DISPLAY,
WIFI_PROVISION_PIN,
WIFI_PROVISION_CNT,
};
/* WPS pins are fixed to 8 chars (+1 terminating zero) */
#define WIFI_PIN_STRLEN (8 + 1)
struct wifi_event {
unsigned int type;
union {
struct wifi_event_dev_found {
struct wifi_dev *dev;
} dev_found;
struct wifi_event_dev_lost {
struct wifi_dev *dev;
} dev_lost;
struct wifi_event_dev_provision {
struct wifi_dev *dev;
unsigned int type;
char pin[WIFI_PIN_STRLEN];
} dev_provision;
struct wifi_event_dev_connect {
struct wifi_dev *dev;
} dev_connect;
struct wifi_event_dev_disconnect {
struct wifi_dev *dev;
} dev_disconnect;
};
};
typedef void (*wifi_event_t) (struct wifi *w, void *data,
struct wifi_event *ev);
int wifi_new(sd_event *event, wifi_event_t event_fn, void *data,
struct wifi **out);
void wifi_free(struct wifi *w);
void wifi_set_data(struct wifi *w, void *data);
void *wifi_get_data(struct wifi *w);
pid_t wifi_get_supplicant_pid(struct wifi *w);
int wifi_spawn_supplicant(struct wifi *w,
const char *rundir,
const char *binary,
const char *ifname);
bool wifi_is_open(struct wifi *w);
int wifi_open(struct wifi *w, const char *wpa_path);
void wifi_close(struct wifi *w);
int wifi_set_discoverable(struct wifi *w, bool on);
int wifi_set_name(struct wifi *w, const char *name);
struct wifi_dev *wifi_get_devs(struct wifi *w);
struct wifi_dev *wifi_dev_next(struct wifi_dev *d);
/* wifi device */
void wifi_dev_ref(struct wifi_dev *d);
void wifi_dev_unref(struct wifi_dev *d);
void wifi_dev_set_data(struct wifi_dev *d, void *data);
void *wifi_dev_get_data(struct wifi_dev *d);
bool wifi_dev_is_available(struct wifi_dev *d);
bool wifi_dev_is_running(struct wifi_dev *d);
bool wifi_dev_is_ready(struct wifi_dev *d);
void wifi_dev_allow(struct wifi_dev *d, const char *pin);
void wifi_dev_reject(struct wifi_dev *d);
int wifi_dev_connect(struct wifi_dev *d, unsigned int provision,
const char *pin);
void wifi_dev_disconnect(struct wifi_dev *d);
const char *wifi_dev_get_name(struct wifi_dev *d);
const char *wifi_dev_get_interface(struct wifi_dev *d);
const char *wifi_dev_get_local_address(struct wifi_dev *d);
const char *wifi_dev_get_remote_address(struct wifi_dev *d);
#endif /* MIRACLED_WIFI_H */

View file

@ -3,30 +3,22 @@
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
* MiracleCast is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
* MiracleCast 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
* Lesser General Public License for more details.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* You should have received a copy of the GNU Lesser General Public License
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <getopt.h>
#include <libudev.h>
#include <libwfd.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
@ -39,373 +31,26 @@
#include <time.h>
#include <unistd.h>
#include "miracled.h"
#include "shl_htable.h"
#include "shl_macro.h"
#include "shl_log.h"
#include "shl_util.h"
bool arg_manage_wifi = false;
const char *arg_wpa_rundir = "/run/wpa_supplicant";
const char *arg_wpa_bindir = "/usr/bin";
/*
* Peer Handling
*/
struct peer *manager_find_peer(struct manager *m, const char *name)
{
char **elem;
bool res;
res = shl_htable_lookup_str(&m->peers, name, NULL, &elem);
if (!res)
return NULL;
return peer_from_htable(elem);
}
/*
* Link Handling
*/
struct link *manager_find_link(struct manager *m, const char *name)
{
char **elem;
bool res;
res = shl_htable_lookup_str(&m->links, name, NULL, &elem);
if (!res)
return NULL;
return link_from_htable(elem);
}
/*
* Manager Handling
*/
static void manager_add_link_from_udev(struct manager *m,
struct udev_device *d)
{
struct link *l;
if (!udev_device_has_tag(d, "miracle"))
return;
log_debug("link %s tagged via udev",
udev_device_get_sysname(d));
link_new(m,
LINK_WIFI,
udev_device_get_sysname(d),
&l);
}
static void manager_remove_link_from_udev(struct manager *m,
struct udev_device *d)
{
_shl_free_ char *name = NULL;
int r;
struct link *l;
r = link_make_name(LINK_WIFI, udev_device_get_sysname(d), &name);
if (r < 0)
return log_vERR(r);
l = manager_find_link(m, name);
if (!l)
return;
log_debug("link %s removed via udev", name);
link_free(l);
}
static int manager_udev_fn(sd_event_source *source,
int fd,
uint32_t mask,
void *data)
{
struct manager *m = data;
struct udev_device *d = NULL;
const char *action;
d = udev_monitor_receive_device(m->udev_mon);
if (!d)
goto out;
action = udev_device_get_action(d);
if (!action)
goto out;
if (!strcmp(action, "add") && arg_manage_wifi)
manager_add_link_from_udev(m, d);
else if (!strcmp(action, "remove"))
manager_remove_link_from_udev(m, d);
out:
udev_device_unref(d);
return 0;
}
static int manager_signal_fn(sd_event_source *source,
const struct signalfd_siginfo *ssi,
void *data)
{
struct manager *m = data;
if (ssi->ssi_signo == SIGCHLD) {
log_debug("caught SIGCHLD for %d", (int)ssi->ssi_pid);
return 0;
}
log_notice("caught signal %d, exiting..", (int)ssi->ssi_signo);
sd_event_exit(m->event, 0);
return 0;
}
static void manager_free(struct manager *m)
{
unsigned int i;
struct link *l;
if (!m)
return;
while ((l = MANAGER_FIRST_LINK(m)))
link_free(l);
shl_htable_clear_str(&m->links, NULL, NULL);
shl_htable_clear_str(&m->peers, NULL, NULL);
manager_dbus_disconnect(m);
sd_event_source_unref(m->udev_mon_source);
udev_monitor_unref(m->udev_mon);
udev_unref(m->udev);
for (i = 0; m->sigs[i]; ++i)
sd_event_source_unref(m->sigs[i]);
sd_bus_unref(m->bus);
sd_event_unref(m->event);
free(m->friendly_name);
free(m);
}
static int manager_new(struct manager **out)
{
char buf[64] = { };
struct manager *m;
static const int sigs[] = {
SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGPIPE, SIGCHLD, 0
};
unsigned int i;
sigset_t mask;
int r;
m = calloc(1, sizeof(*m));
if (!m)
return log_ENOMEM();
shl_htable_init_str(&m->links);
shl_htable_init_str(&m->peers);
snprintf(buf, sizeof(buf) - 1, "unknown-%u", rand());
m->friendly_name = strdup(buf);
if (!m->friendly_name) {
r = log_ENOMEM();
goto error;
}
r = sd_event_default(&m->event);
if (r < 0) {
log_vERR(r);
goto error;
}
r = sd_event_set_watchdog(m->event, true);
if (r < 0) {
log_vERR(r);
goto error;
}
r = sd_bus_default_system(&m->bus);
if (r < 0) {
log_error("cannot connect to system bus: %d", r);
goto error;
}
r = sd_bus_attach_event(m->bus, m->event, 0);
if (r < 0) {
log_vERR(r);
goto error;
}
for (i = 0; sigs[i]; ++i) {
sigemptyset(&mask);
sigaddset(&mask, sigs[i]);
sigprocmask(SIG_BLOCK, &mask, NULL);
r = sd_event_add_signal(m->event,
&m->sigs[i],
sigs[i],
manager_signal_fn,
m);
if (r < 0) {
log_vERR(r);
goto error;
}
}
m->udev = udev_new();
if (!m->udev) {
r = log_ENOMEM();
goto error;
}
m->udev_mon = udev_monitor_new_from_netlink(m->udev, "udev");
if (!m->udev_mon) {
r = log_ENOMEM();
goto error;
}
r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_mon,
"net",
"wlan");
if (r < 0) {
log_vERR(r);
goto error;
}
r = udev_monitor_enable_receiving(m->udev_mon);
if (r < 0) {
log_vERR(r);
goto error;
}
r = sd_event_add_io(m->event,
&m->udev_mon_source,
udev_monitor_get_fd(m->udev_mon),
EPOLLHUP | EPOLLERR | EPOLLIN,
manager_udev_fn,
m);
if (r < 0) {
log_vERR(r);
goto error;
}
r = manager_dbus_connect(m);
if (r < 0)
goto error;
*out = m;
return 0;
error:
manager_free(m);
return r;
}
static void manager_read_name(struct manager *m)
{
_cleanup_sd_bus_error_ sd_bus_error err = SD_BUS_ERROR_NULL;
_cleanup_sd_bus_message_ sd_bus_message *rep = NULL;
const char *name;
char *str;
int r;
r = sd_bus_call_method(m->bus,
"org.freedesktop.hostname1",
"/org/freedesktop/hostname1",
"org.freedesktop.DBus.Properties",
"Get",
&err,
&rep,
"ss", "org.freedesktop.hostname1", "Hostname");
if (r < 0) {
return;
}
r = sd_bus_message_enter_container(rep, 'v', "s");
if (r < 0)
goto error;
r = sd_bus_message_read(rep, "s", &name);
if (r < 0)
goto error;
if (!name || !*name) {
log_warning("no hostname set on systemd.hostname1, using: %s",
m->friendly_name);
return;
}
str = strdup(name);
if (!str)
return log_vENOMEM();
free(m->friendly_name);
m->friendly_name = str;
log_debug("friendly-name from local hostname: %s", str);
return;
error:
log_warning("cannot read hostname from systemd.hostname1: %s",
bus_error_message(&err, r));
}
static void manager_read_links(struct manager *m)
{
struct udev_enumerate *e = NULL;
struct udev_list_entry *l;
struct udev_device *d;
int r;
e = udev_enumerate_new(m->udev);
if (!e)
goto error;
r = udev_enumerate_add_match_subsystem(e, "net");
if (r < 0)
goto error;
r = udev_enumerate_add_match_property(e, "DEVTYPE", "wlan");
if (r < 0)
goto error;
r = udev_enumerate_add_match_is_initialized(e);
if (r < 0)
goto error;
r = udev_enumerate_scan_devices(e);
if (r < 0)
goto error;
udev_list_entry_foreach(l, udev_enumerate_get_list_entry(e)) {
d = udev_device_new_from_syspath(m->udev,
udev_list_entry_get_name(l));
if (!d)
goto error;
manager_add_link_from_udev(m, d);
udev_device_unref(d);
}
goto out;
error:
log_warning("cannot enumerate links via udev");
out:
udev_enumerate_unref(e);
return -EINVAL;
}
static int manager_run(struct manager *m)
{
manager_read_name(m);
manager_read_links(m);
return sd_event_loop(m->event);
return 0;
}
static int help(void)
@ -415,16 +60,11 @@ static int help(void)
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
*/
printf("%s [OPTIONS...] ...\n\n"
"Wifi-Display Daemon.\n\n"
"Remote-display Management-daemon.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --log-level <lvl> Maximum level for log messages\n"
" --log-time Prefix log-messages with timestamp\n"
"\n"
" --manage-wifi Enable internal wifi-management via wpa_supplicant if\n"
" they're not managed externally (like NetworkManager)\n"
" --wpa-rundir <dir> wpa_supplicant runtime dir [/run/wpa_supplicant]\n"
" --wpa-bindir <dir> wpa_supplicant binary dir [/usr/bin]\n"
, program_invocation_short_name);
/*
* 80-char barrier:
@ -440,20 +80,12 @@ static int parse_argv(int argc, char *argv[])
ARG_VERSION = 0x100,
ARG_LOG_LEVEL,
ARG_LOG_TIME,
ARG_MANAGE_WIFI,
ARG_WPA_RUNDIR,
ARG_WPA_BINDIR,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "log-level", required_argument, NULL, ARG_LOG_LEVEL },
{ "log-time", no_argument, NULL, ARG_LOG_TIME },
{ "manage-wifi", no_argument, NULL, ARG_MANAGE_WIFI },
{ "wpa-rundir", required_argument, NULL, ARG_WPA_RUNDIR },
{ "wpa-bindir", required_argument, NULL, ARG_WPA_BINDIR },
{}
};
int c;
@ -471,16 +103,6 @@ static int parse_argv(int argc, char *argv[])
case ARG_LOG_TIME:
log_init_time();
break;
case ARG_MANAGE_WIFI:
arg_manage_wifi = true;
break;
case ARG_WPA_RUNDIR:
arg_wpa_rundir = optarg;
break;
case ARG_WPA_BINDIR:
arg_wpa_bindir = optarg;
break;
case '?':
return -EINVAL;
}

View file

@ -3,178 +3,33 @@
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
* MiracleCast is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
* MiracleCast 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
* Lesser General Public License for more details.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* You should have received a copy of the GNU Lesser General Public License
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <libudev.h>
#include <stdbool.h>
#include <stdlib.h>
#include <systemd/sd-bus.h>
#include <systemd/sd-event.h>
#include "miracle.h"
#include "shl_dlist.h"
#include "shl_htable.h"
#ifndef MIRACLED_H
#define MIRACLED_H
struct manager;
struct link;
struct peer;
struct wifi;
struct wifi_dev;
struct wifi_event;
/* peer */
struct peer {
struct shl_dlist list;
struct link *l;
unsigned int id;
char *name;
struct wifi_dev *d;
};
#define peer_from_htable(_p) \
shl_htable_offsetof((_p), struct peer, name)
#define peer_from_list(_p) \
shl_dlist_entry((_p), struct peer, list)
int peer_make_name(unsigned int id, char **out);
int peer_new_wifi(struct link *l, struct wifi_dev *d, struct peer **out);
void peer_free(struct peer *p);
const char *peer_get_friendly_name(struct peer *p);
bool peer_is_connected(struct peer *p);
const char *peer_get_interface(struct peer *p);
const char *peer_get_local_address(struct peer *p);
const char *peer_get_remote_address(struct peer *p);
void peer_process_wifi(struct peer *p, struct wifi_event *ev);
int peer_allow(struct peer *p, const char *pin);
void peer_reject(struct peer *p);
int peer_connect(struct peer *p, const char *prov, const char *pin);
void peer_disconnect(struct peer *p);
/* link */
enum link_type {
LINK_VIRTUAL,
LINK_WIFI,
LINK_CNT,
};
struct link {
struct manager *m;
unsigned int type;
char *interface;
char *name;
char *friendly_name;
struct shl_dlist peers;
struct wifi *w;
sd_event_source *wpa_child_source;
sd_event_source *wpa_startup_source;
unsigned int wpa_startup_attempts;
bool running : 1;
};
#define link_from_htable(_l) \
shl_htable_offsetof((_l), struct link, name)
#define LINK_FIRST_PEER(_l) (shl_dlist_empty(&(_l)->peers) ? \
NULL : peer_from_list((_l)->peers.next))
const char *link_type_to_str(unsigned int type);
unsigned int link_type_from_str(const char *str);
int link_make_name(unsigned int type, const char *interface, char **out);
int link_new(struct manager *m,
unsigned int type,
const char *interface,
struct link **out);
void link_free(struct link *l);
int link_set_friendly_name(struct link *l, const char *name);
int link_start_scan(struct link *l);
void link_stop_scan(struct link *l);
/* manager */
struct manager {
sd_event *event;
sd_bus *bus;
sd_event_source *sigs[_NSIG];
struct udev *udev;
struct udev_monitor *udev_mon;
sd_event_source *udev_mon_source;
unsigned int peer_ids;
size_t link_cnt;
size_t peer_cnt;
struct shl_htable links;
struct shl_htable peers;
char *friendly_name;
};
#define MANAGER_FIRST_LINK(_m) \
SHL_HTABLE_FIRST_MACRO(&(_m)->links, link_from_htable)
#define MANAGER_FOREACH_LINK(_i, _m) \
SHL_HTABLE_FOREACH_MACRO(_i, &(_m)->links, link_from_htable)
#define MANAGER_FOREACH_PEER(_i, _m) \
SHL_HTABLE_FOREACH_MACRO(_i, &(_m)->peers, peer_from_htable)
int manager_dbus_connect(struct manager *m);
void manager_dbus_disconnect(struct manager *m);
struct link *manager_find_link(struct manager *m, const char *name);
struct peer *manager_find_peer(struct manager *m, const char *name);
/* dbus */
void peer_dbus_provision_request(struct peer *p,
const char *type,
const char *pin);
_shl_sentinel_
void peer_dbus_properties_changed(struct peer *p, const char *prop, ...);
void peer_dbus_added(struct peer *p);
void peer_dbus_removed(struct peer *p);
_shl_sentinel_
void link_dbus_properties_changed(struct link *l, const char *prop, ...);
void link_dbus_scan_stopped(struct link *l);
void link_dbus_added(struct link *l);
void link_dbus_removed(struct link *l);
/* cli arguments */
extern bool arg_manage_wifi;
extern const char *arg_wpa_rundir;
extern const char *arg_wpa_bindir;
#endif /* MIRACLED_H */