mirror of
https://github.com/albfan/miraclecast.git
synced 2025-03-09 23:38:56 +00:00
shared: add wpa_supplicant bus-helpers
The wpas-helpers provide easy _asynchronous_ access to wpa_supplicant control interfaces. Compared to the old wpa_ctrl_* stuff it's no longer synchronous. Thus, it doesn't block our daemon while wpa_supplicant runs some heavy work again.. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
parent
cf53290608
commit
f34face988
4 changed files with 1957 additions and 1 deletions
|
@ -78,7 +78,10 @@ libmiracle_shared_la_SOURCES = \
|
||||||
src/shared/shl_log.c \
|
src/shared/shl_log.c \
|
||||||
src/shared/shl_macro.h \
|
src/shared/shl_macro.h \
|
||||||
src/shared/shl_util.h \
|
src/shared/shl_util.h \
|
||||||
src/shared/shl_util.c
|
src/shared/shl_util.c \
|
||||||
|
src/shared/util.h \
|
||||||
|
src/shared/wpas.h \
|
||||||
|
src/shared/wpas.c
|
||||||
libmiracle_shared_la_CPPFLAGS = $(AM_CPPFLAGS)
|
libmiracle_shared_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
libmiracle_shared_la_LDFLAGS = $(AM_LDFLAGS)
|
libmiracle_shared_la_LDFLAGS = $(AM_LDFLAGS)
|
||||||
libmiracle_shared_la_LIBADD = $(AM_LIBADD)
|
libmiracle_shared_la_LIBADD = $(AM_LIBADD)
|
||||||
|
|
150
src/shared/util.h
Normal file
150
src/shared/util.h
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MIRACLE_UTIL_H
|
||||||
|
#define MIRACLE_UTIL_H
|
||||||
|
|
||||||
|
#include <alloca.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <systemd/sd-bus.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "shl_macro.h"
|
||||||
|
|
||||||
|
static inline void cleanup_sd_bus_message(sd_bus_message **ptr)
|
||||||
|
{
|
||||||
|
sd_bus_message_unref(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cleanup_udev_device(struct udev_device **ptr)
|
||||||
|
{
|
||||||
|
udev_device_unref(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void cleanup_udev_enumerate(struct udev_enumerate **ptr)
|
||||||
|
{
|
||||||
|
udev_enumerate_unref(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _cleanup_sd_bus_error_ _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 _sd_bus_message_unref_ _shl_cleanup_(cleanup_sd_bus_message)
|
||||||
|
#define _cleanup_udev_device_ _shl_cleanup_(cleanup_udev_device)
|
||||||
|
#define _cleanup_udev_enumerate_ _shl_cleanup_(cleanup_udev_enumerate)
|
||||||
|
|
||||||
|
#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 unsigned int ifindex_from_udev_device(struct udev_device *d)
|
||||||
|
{
|
||||||
|
const char *val;
|
||||||
|
|
||||||
|
val = udev_device_get_property_value(d, "IFINDEX");
|
||||||
|
if (!val)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (unsigned int)atoi(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAC_STRLEN 18
|
||||||
|
|
||||||
|
static inline void reformat_mac(char *dst, const char *src)
|
||||||
|
{
|
||||||
|
unsigned char x1 = 0, x2 = 0, x3 = 0, x4 = 0, x5 = 0, x6 = 0;
|
||||||
|
|
||||||
|
sscanf(src, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
|
||||||
|
&x1, &x2, &x3, &x4, &x5, &x6);
|
||||||
|
sprintf(dst, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
|
||||||
|
x1, x2, x3, x4, x5, x6);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MIRACLE_UTIL_H */
|
1640
src/shared/wpas.c
Normal file
1640
src/shared/wpas.c
Normal file
File diff suppressed because it is too large
Load diff
163
src/shared/wpas.h
Normal file
163
src/shared/wpas.h
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* MiracleCast - Wifi-Display/Miracast Implementation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MIRACLE_WPAS_H
|
||||||
|
#define MIRACLE_WPAS_H
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <systemd/sd-event.h>
|
||||||
|
|
||||||
|
/* types */
|
||||||
|
|
||||||
|
struct wpas;
|
||||||
|
struct wpas_message;
|
||||||
|
|
||||||
|
typedef int (*wpas_callback_fn) (struct wpas *w,
|
||||||
|
struct wpas_message *m,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WPAS_MESSAGE_UNKNOWN,
|
||||||
|
WPAS_MESSAGE_EVENT,
|
||||||
|
WPAS_MESSAGE_REQUEST,
|
||||||
|
WPAS_MESSAGE_REPLY,
|
||||||
|
WPAS_TYPE_CNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WPAS_LEVEL_UNKNOWN,
|
||||||
|
WPAS_LEVEL_MSGDUMP,
|
||||||
|
WPAS_LEVEL_DEBUG,
|
||||||
|
WPAS_LEVEL_INFO,
|
||||||
|
WPAS_LEVEL_WARNING,
|
||||||
|
WPAS_LEVEL_ERROR,
|
||||||
|
WPAS_LEVEL_CNT
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WPAS_TYPE_STRING 's'
|
||||||
|
#define WPAS_TYPE_INT32 'i'
|
||||||
|
#define WPAS_TYPE_UINT32 'u'
|
||||||
|
#define WPAS_TYPE_DICT 'e'
|
||||||
|
|
||||||
|
/* bus */
|
||||||
|
|
||||||
|
int wpas_open(const char *ctrl_path, struct wpas **out);
|
||||||
|
int wpas_create(const char *ctrl_path, struct wpas **out);
|
||||||
|
void wpas_ref(struct wpas *w);
|
||||||
|
void wpas_unref(struct wpas *w);
|
||||||
|
|
||||||
|
int wpas_call_async(struct wpas *w,
|
||||||
|
struct wpas_message *m,
|
||||||
|
wpas_callback_fn cb_fn,
|
||||||
|
void *data,
|
||||||
|
uint64_t timeout,
|
||||||
|
uint64_t *cookie);
|
||||||
|
void wpas_call_async_cancel(struct wpas *w, uint64_t cookie);
|
||||||
|
int wpas_send(struct wpas *w,
|
||||||
|
struct wpas_message *m,
|
||||||
|
uint64_t timeout);
|
||||||
|
|
||||||
|
int wpas_attach_event(struct wpas *w, sd_event *event, int priority);
|
||||||
|
void wpas_detach_event(struct wpas *w);
|
||||||
|
|
||||||
|
int wpas_add_match(struct wpas *w, wpas_callback_fn cb_fn, void *data);
|
||||||
|
void wpas_remove_match(struct wpas *w, wpas_callback_fn cb_fn, void *data);
|
||||||
|
|
||||||
|
bool wpas_is_dead(struct wpas *w);
|
||||||
|
bool wpas_is_server(struct wpas *w);
|
||||||
|
|
||||||
|
static inline void wpas_unref_p(struct wpas **w)
|
||||||
|
{
|
||||||
|
wpas_unref(*w);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _wpas_unref_ __attribute__((__cleanup__(wpas_unref_p)))
|
||||||
|
|
||||||
|
/* messages */
|
||||||
|
|
||||||
|
int wpas_message_new_event(struct wpas *w,
|
||||||
|
const char *name,
|
||||||
|
unsigned int level,
|
||||||
|
struct wpas_message **out);
|
||||||
|
int wpas_message_new_request(struct wpas *w,
|
||||||
|
const char *name,
|
||||||
|
struct wpas_message **out);
|
||||||
|
int wpas_message_new_reply(struct wpas *w,
|
||||||
|
struct wpas_message **out);
|
||||||
|
int wpas_message_new_reply_for(struct wpas *w,
|
||||||
|
struct wpas_message *request,
|
||||||
|
struct wpas_message **out);
|
||||||
|
void wpas_message_ref(struct wpas_message *m);
|
||||||
|
void wpas_message_unref(struct wpas_message *m);
|
||||||
|
|
||||||
|
bool wpas_message_is_event(struct wpas_message *msg, const char *name);
|
||||||
|
bool wpas_message_is_request(struct wpas_message *msg, const char *name);
|
||||||
|
bool wpas_message_is_reply(struct wpas_message *msg);
|
||||||
|
bool wpas_message_is_ok(struct wpas_message *msg);
|
||||||
|
bool wpas_message_is_fail(struct wpas_message *msg);
|
||||||
|
|
||||||
|
uint64_t wpas_message_get_cookie(struct wpas_message *msg);
|
||||||
|
struct wpas *wpas_message_get_bus(struct wpas_message *msg);
|
||||||
|
unsigned int wpas_message_get_type(struct wpas_message *msg);
|
||||||
|
unsigned int wpas_message_get_level(struct wpas_message *msg);
|
||||||
|
const char *wpas_message_get_name(struct wpas_message *msg);
|
||||||
|
const char *wpas_message_get_raw(struct wpas_message *msg);
|
||||||
|
const char *wpas_message_get_ifname(struct wpas_message *msg);
|
||||||
|
bool wpas_message_is_sealed(struct wpas_message *msg);
|
||||||
|
|
||||||
|
const char *wpas_message_get_peer(struct wpas_message *msg);
|
||||||
|
char *wpas_message_get_escaped_peer(struct wpas_message *msg);
|
||||||
|
void wpas_message_set_peer(struct wpas_message *msg, const char *peer);
|
||||||
|
|
||||||
|
int wpas_message_append_basic(struct wpas_message *m, char type, ...);
|
||||||
|
int wpas_message_appendv_basic(struct wpas_message *m,
|
||||||
|
char type,
|
||||||
|
va_list args);
|
||||||
|
int wpas_message_append(struct wpas_message *m, const char *types, ...);
|
||||||
|
int wpas_message_appendv(struct wpas_message *m,
|
||||||
|
const char *types,
|
||||||
|
va_list args);
|
||||||
|
int wpas_message_seal(struct wpas_message *m);
|
||||||
|
|
||||||
|
int wpas_message_read_basic(struct wpas_message *m, char type, void *out);
|
||||||
|
int wpas_message_read(struct wpas_message *m, const char *types, ...);
|
||||||
|
int wpas_message_skip_basic(struct wpas_message *m, char type);
|
||||||
|
int wpas_message_skip(struct wpas_message *m, const char *types);
|
||||||
|
void wpas_message_rewind(struct wpas_message *m);
|
||||||
|
|
||||||
|
int wpas_message_argv_read(struct wpas_message *m,
|
||||||
|
unsigned int pos,
|
||||||
|
char type,
|
||||||
|
void *out);
|
||||||
|
int wpas_message_dict_read(struct wpas_message *m,
|
||||||
|
const char *name,
|
||||||
|
char type,
|
||||||
|
void *out);
|
||||||
|
|
||||||
|
static inline void wpas_message_unref_p(struct wpas_message **m)
|
||||||
|
{
|
||||||
|
wpas_message_unref(*m);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _wpas_message_unref_ __attribute__((__cleanup__(wpas_message_unref_p)))
|
||||||
|
|
||||||
|
#endif /* MIRACLE_WPAS_H */
|
Loading…
Add table
Add a link
Reference in a new issue