mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-05-04 00:18:02 +02:00
Replace the custom message parsing with protobuf
Plain-text was useful for the initial implementation where the counterpart was netcat but now that both parts are in place, protobuf is a much more convenient system to handle a frequently-changing protocol. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
f94a7bae85
commit
9f851bcccb
5 changed files with 250 additions and 130 deletions
|
|
@ -15,6 +15,8 @@ add_project_arguments(cppflags, language: 'cpp')
|
|||
config_h = configuration_data()
|
||||
config_h.set('_GNU_SOURCE', '1')
|
||||
|
||||
subdir('proto')
|
||||
|
||||
lib_util = static_library('util',
|
||||
'src/util-io.h',
|
||||
'src/util-list.h',
|
||||
|
|
@ -37,7 +39,8 @@ lib_libei = shared_library('ei',
|
|||
'src/libei.c',
|
||||
'src/libei-device.c',
|
||||
'src/libei-socket.c',
|
||||
dependencies: [dep_libutil],
|
||||
proto_headers,
|
||||
dependencies: [dep_libutil, dep_protobuf],
|
||||
install: true
|
||||
)
|
||||
install_headers('src/libei.h')
|
||||
|
|
@ -59,7 +62,8 @@ lib_libeis = shared_library('eis',
|
|||
'src/libeis-client.c',
|
||||
'src/libeis-device.c',
|
||||
'src/libeis-socket.c',
|
||||
dependencies: [dep_libutil],
|
||||
proto_headers,
|
||||
dependencies: [dep_libutil, dep_protobuf],
|
||||
install: true
|
||||
)
|
||||
install_headers('src/libeis.h')
|
||||
|
|
|
|||
60
proto/ei.proto
Normal file
60
proto/ei.proto
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
syntax = "proto3";
|
||||
|
||||
message Connect {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message Disconnect {
|
||||
}
|
||||
|
||||
message AddDevice {
|
||||
uint32 deviceid = 1;
|
||||
uint32 capabilities = 2;
|
||||
}
|
||||
|
||||
message RemoveDevice {
|
||||
uint32 deviceid = 1;
|
||||
}
|
||||
|
||||
message PointerRelative {
|
||||
uint32 deviceid = 1;
|
||||
int32 x = 2;
|
||||
int32 y = 3;
|
||||
}
|
||||
|
||||
message ClientMessage {
|
||||
oneof msg {
|
||||
Connect connect = 1;
|
||||
Disconnect disconnect = 2;
|
||||
AddDevice add = 3;
|
||||
RemoveDevice remove = 4;
|
||||
PointerRelative rel = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message Hello {
|
||||
}
|
||||
|
||||
message Connected {
|
||||
}
|
||||
|
||||
message Disconnected {
|
||||
}
|
||||
|
||||
message Accepted {
|
||||
uint32 deviceid = 1;
|
||||
}
|
||||
|
||||
message Removed {
|
||||
uint32 deviceid = 1;
|
||||
}
|
||||
|
||||
message ServerMessage {
|
||||
oneof msg {
|
||||
Hello hello = 1;
|
||||
Connected connected = 2;
|
||||
Disconnected disconnected = 3;
|
||||
Accepted accepted = 4;
|
||||
Removed removed = 5;
|
||||
}
|
||||
}
|
||||
9
proto/meson.build
Normal file
9
proto/meson.build
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
dep_protobuf = dependency('libprotobuf-c')
|
||||
protoc = find_program('protoc')
|
||||
proto_headers = custom_target('proto-headers',
|
||||
input: 'ei.proto',
|
||||
output: ['ei.pb-c.c', 'ei.pb-c.h'],
|
||||
command: [protoc,
|
||||
'--proto_path=@0@'.format(meson.current_source_dir()),
|
||||
'--c_out=@0@'.format(meson.current_build_dir()),
|
||||
'ei.proto'])
|
||||
132
src/libei.c
132
src/libei.c
|
|
@ -38,6 +38,8 @@
|
|||
#include "libei.h"
|
||||
#include "libei-private.h"
|
||||
|
||||
#include "proto/ei.pb-c.h"
|
||||
|
||||
/* The message type for the wire format */
|
||||
enum message_type {
|
||||
MESSAGE_HELLO,
|
||||
|
|
@ -210,19 +212,28 @@ ei_queue_removed_event(struct ei_device *device)
|
|||
ei_queue_event(ei, &e->base);
|
||||
}
|
||||
|
||||
static int
|
||||
connection_send_msg(struct ei *ei, const ClientMessage *msg)
|
||||
{
|
||||
size_t sz = client_message__get_packed_size(msg);
|
||||
uint8_t buf[sz];
|
||||
size_t len = client_message__pack(msg, buf);
|
||||
return min(0, xwrite(source_get_fd(ei->source), buf, len));
|
||||
}
|
||||
|
||||
static int
|
||||
connection_send_connect(struct ei *ei)
|
||||
{
|
||||
if (ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
char buf[128];
|
||||
ClientMessage msg = CLIENT_MESSAGE__INIT;
|
||||
Connect connect = CONNECT__INIT;
|
||||
|
||||
if (!xsnprintf(buf, sizeof(buf), "connect %s\n",
|
||||
ei->name ? ei->name : "unnamed"))
|
||||
return -ENOMEM;
|
||||
msg.connect = &connect;
|
||||
msg.msg_case = CLIENT_MESSAGE__MSG_CONNECT;
|
||||
|
||||
return min(0, xwrite(source_get_fd(ei->source), buf, strlen(buf) + 1));
|
||||
return connection_send_msg(ei, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -231,8 +242,13 @@ connection_send_disconnect(struct ei *ei)
|
|||
if (ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
const char buf[] = "disconnect\n";
|
||||
return min(0, xwrite(source_get_fd(ei->source), buf, sizeof(buf)));
|
||||
ClientMessage msg = CLIENT_MESSAGE__INIT;
|
||||
Disconnect disconnect = DISCONNECT__INIT;
|
||||
|
||||
msg.disconnect = &disconnect;
|
||||
msg.msg_case = CLIENT_MESSAGE__MSG_DISCONNECT;
|
||||
|
||||
return connection_send_msg(ei, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -241,12 +257,16 @@ connection_send_add(struct ei *ei, struct ei_device *device)
|
|||
if (ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
char buf[64];
|
||||
ClientMessage msg = CLIENT_MESSAGE__INIT;
|
||||
AddDevice add = ADD_DEVICE__INIT;
|
||||
|
||||
if (!xsnprintf(buf, sizeof(buf), "add %d %d\n", device->id, device->capabilities))
|
||||
return -ENOMEM;
|
||||
add.deviceid = device->id;
|
||||
add.capabilities = device->capabilities;
|
||||
|
||||
return min(0, xwrite(source_get_fd(ei->source), buf, strlen(buf) + 1));
|
||||
msg.add = &add;
|
||||
msg.msg_case = CLIENT_MESSAGE__MSG_ADD;
|
||||
|
||||
return connection_send_msg(ei, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -255,12 +275,15 @@ connection_send_remove(struct ei *ei, struct ei_device *device)
|
|||
if (ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
char buf[64];
|
||||
ClientMessage msg = CLIENT_MESSAGE__INIT;
|
||||
RemoveDevice remove = REMOVE_DEVICE__INIT;
|
||||
|
||||
if (!xsnprintf(buf, sizeof(buf), "remove %d\n", device->id))
|
||||
return -ENOMEM;
|
||||
remove.deviceid = device->id;
|
||||
|
||||
return min(0, xwrite(source_get_fd(ei->source), buf, strlen(buf) + 1));
|
||||
msg.remove = &remove;
|
||||
msg.msg_case = CLIENT_MESSAGE__MSG_REMOVE;
|
||||
|
||||
return connection_send_msg(ei, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -269,12 +292,17 @@ connection_send_rel(struct ei *ei, struct ei_device *device, int32_t x, int32_t
|
|||
if (ei->state == EI_STATE_DISCONNECTED)
|
||||
return 0;
|
||||
|
||||
char buf[64];
|
||||
ClientMessage msg = CLIENT_MESSAGE__INIT;
|
||||
PointerRelative rel = POINTER_RELATIVE__INIT;
|
||||
|
||||
if (!xsnprintf(buf, sizeof(buf), "rel %d %d %d\n", device->id, x, y))
|
||||
return -ENOMEM;
|
||||
rel.deviceid = device->id;
|
||||
rel.x = x;
|
||||
rel.y = y;
|
||||
|
||||
return min(0, xwrite(source_get_fd(ei->source), buf, strlen(buf) + 1));
|
||||
msg.rel = &rel;
|
||||
msg.msg_case = CLIENT_MESSAGE__MSG_REL;
|
||||
|
||||
return connection_send_msg(ei, &msg);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -379,52 +407,52 @@ static struct message *
|
|||
connection_parse_message(const char *data_in, size_t len)
|
||||
{
|
||||
_cleanup_(message_freep) struct message *msg = xalloc(sizeof(*msg));
|
||||
_cleanup_free_ char *data = strstrip(data_in, "\n");
|
||||
_cleanup_(strv_freep) char **tokens = strv_from_string(data, " ");
|
||||
ServerMessage *proto = server_message__unpack(NULL, len,
|
||||
(const unsigned char*)data_in);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
if (streq(tokens[0], "hello")) {
|
||||
switch (proto->msg_case) {
|
||||
case SERVER_MESSAGE__MSG_HELLO:
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_HELLO,
|
||||
};
|
||||
} else if (streq(tokens[0], "connected")) {
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_CONNECTED:
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_CONNECTED,
|
||||
};
|
||||
} else if (streq(tokens[0], "disconnected")) {
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_DISCONNECTED:
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_DISCONNECTED,
|
||||
};
|
||||
} else if (streq(tokens[0], "accept")) {
|
||||
if (!tokens[1])
|
||||
goto error;
|
||||
|
||||
uint32_t deviceid;
|
||||
if (!xatou(tokens[1], &deviceid))
|
||||
goto error;
|
||||
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_ACCEPT,
|
||||
.accept.deviceid = deviceid,
|
||||
};
|
||||
} else if (streq(tokens[0], "remove")) {
|
||||
if (!tokens[1])
|
||||
goto error;
|
||||
|
||||
uint32_t deviceid;
|
||||
if (!xatou(tokens[1], &deviceid))
|
||||
goto error;
|
||||
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_REMOVE,
|
||||
.remove.deviceid = deviceid,
|
||||
};
|
||||
} else {
|
||||
goto error;
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_ACCEPTED:
|
||||
{
|
||||
Accepted *a = proto->accepted;
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_ACCEPT,
|
||||
.accept.deviceid = a->deviceid,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case SERVER_MESSAGE__MSG_REMOVED:
|
||||
{
|
||||
Removed *r = proto->removed;
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_REMOVE,
|
||||
.remove.deviceid = r->deviceid,
|
||||
};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
server_message__free_unpacked(proto, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
server_message__free_unpacked(proto, NULL);
|
||||
return steal(&msg);
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include "libeis-private.h"
|
||||
|
||||
#include "proto/ei.pb-c.h"
|
||||
|
||||
/* The message type for the wire format */
|
||||
enum message_type {
|
||||
MESSAGE_CONNECT,
|
||||
|
|
@ -112,47 +114,75 @@ eis_client_get_context(struct eis_client *client)
|
|||
return eis_client_parent(client);
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_msg(struct eis_client *client, const ServerMessage *msg)
|
||||
{
|
||||
size_t sz = server_message__get_packed_size(msg);
|
||||
uint8_t buf[sz];
|
||||
size_t len = server_message__pack(msg, buf);
|
||||
return min(0, xwrite(source_get_fd(client->source), buf, len));
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_hello(struct eis_client *client)
|
||||
{
|
||||
const char buf[] = "hello\n";
|
||||
return min(0, xwrite(source_get_fd(client->source), buf, sizeof(buf)));
|
||||
ServerMessage msg = SERVER_MESSAGE__INIT;
|
||||
Hello hello = HELLO__INIT;
|
||||
|
||||
msg.hello = &hello;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_HELLO;
|
||||
|
||||
return client_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_disconnect(struct eis_client *client)
|
||||
{
|
||||
const char buf[] = "disconnected\n";
|
||||
return min(0, xwrite(source_get_fd(client->source), buf, sizeof(buf)));
|
||||
ServerMessage msg = SERVER_MESSAGE__INIT;
|
||||
Disconnected disconnected = DISCONNECTED__INIT;
|
||||
|
||||
msg.disconnected = &disconnected;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_DISCONNECTED;
|
||||
|
||||
return client_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_connect(struct eis_client *client)
|
||||
{
|
||||
const char buf[] = "connected\n";
|
||||
return min(0, xwrite(source_get_fd(client->source), buf, sizeof(buf)));
|
||||
ServerMessage msg = SERVER_MESSAGE__INIT;
|
||||
Connected connected = CONNECTED__INIT;
|
||||
|
||||
msg.connected = &connected;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_CONNECTED;
|
||||
|
||||
return client_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_accepted(struct eis_client *client, struct eis_device *device)
|
||||
{
|
||||
char buf[64];
|
||||
ServerMessage msg = SERVER_MESSAGE__INIT;
|
||||
Accepted accepted = ACCEPTED__INIT;
|
||||
|
||||
if (!xsnprintf(buf, sizeof(buf), "accept %d\n", device->id))
|
||||
return -ENOMEM;
|
||||
accepted.deviceid = device->id;
|
||||
|
||||
return min(0, xwrite(source_get_fd(client->source), buf, strlen(buf) + 1));
|
||||
msg.accepted = &accepted;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_ACCEPTED;
|
||||
|
||||
return client_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
static int
|
||||
client_send_removed(struct eis_client *client, struct eis_device *device)
|
||||
{
|
||||
char buf[64];
|
||||
ServerMessage msg = SERVER_MESSAGE__INIT;
|
||||
Removed removed = REMOVED__INIT;
|
||||
|
||||
if (!xsnprintf(buf, sizeof(buf), "remove %d\n", device->id))
|
||||
return -ENOMEM;
|
||||
msg.removed = &removed;
|
||||
msg.msg_case = SERVER_MESSAGE__MSG_REMOVED;
|
||||
|
||||
return min(0, xwrite(source_get_fd(client->source), buf, strlen(buf) + 1));
|
||||
return client_send_msg(client, &msg);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
|
|
@ -320,76 +350,65 @@ static struct message *
|
|||
client_parse_message(const char *data_in, size_t len)
|
||||
{
|
||||
_cleanup_(message_freep) struct message *msg = xalloc(sizeof(*msg));
|
||||
_cleanup_free_ char *data = strstrip(data_in, "\n");
|
||||
_cleanup_(strv_freep) char **tokens = strv_from_string(data, " ");
|
||||
ClientMessage *proto = client_message__unpack(NULL, len,
|
||||
(const unsigned char*)data_in);
|
||||
|
||||
if (streq(tokens[0], "connect")) {
|
||||
if (!tokens[1])
|
||||
goto error;
|
||||
if (!proto)
|
||||
return NULL;
|
||||
|
||||
char *name = tokens[1];
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_CONNECT,
|
||||
.connect.name = xstrdup(name),
|
||||
};
|
||||
} else if (streq(tokens[0], "disconnect")) {
|
||||
switch (proto->msg_case) {
|
||||
case CLIENT_MESSAGE__MSG_CONNECT:
|
||||
{
|
||||
Connect *c = proto->connect;
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_CONNECT,
|
||||
.connect.name = xstrdup(c->name),
|
||||
};
|
||||
}
|
||||
break;
|
||||
case CLIENT_MESSAGE__MSG_DISCONNECT:
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_DISCONNECT,
|
||||
};
|
||||
} else if (streq(tokens[0], "add")) {
|
||||
if (!tokens[1] || !tokens[2])
|
||||
goto error;
|
||||
|
||||
uint32_t deviceid;
|
||||
if (!xatou(tokens[1], &deviceid))
|
||||
goto error;
|
||||
|
||||
uint32_t capabilities;
|
||||
if (!xatou(tokens[2], &capabilities))
|
||||
goto error;
|
||||
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_ADD_DEVICE,
|
||||
.add_device.deviceid = deviceid,
|
||||
.add_device.capabilities = capabilities,
|
||||
};
|
||||
} else if (streq(tokens[0], "remove")) {
|
||||
if (!tokens[1])
|
||||
goto error;
|
||||
|
||||
uint32_t deviceid;
|
||||
if (!xatou(tokens[1], &deviceid))
|
||||
goto error;
|
||||
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_REMOVE_DEVICE,
|
||||
.remove_device.deviceid = deviceid,
|
||||
};
|
||||
} else if (streq(tokens[0], "rel")) {
|
||||
if (!tokens[1] || !tokens[2] || !tokens[3])
|
||||
return NULL;
|
||||
|
||||
uint32_t deviceid;
|
||||
if (!xatou(tokens[1], &deviceid))
|
||||
goto error;
|
||||
|
||||
int x, y;
|
||||
if (!xatoi(tokens[2], &x) || !xatoi(tokens[3], &y))
|
||||
goto error;
|
||||
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_POINTER_REL,
|
||||
.pointer_rel.deviceid = deviceid,
|
||||
.pointer_rel.x = x,
|
||||
.pointer_rel.y = y,
|
||||
};
|
||||
} else {
|
||||
goto error;
|
||||
break;
|
||||
case CLIENT_MESSAGE__MSG_ADD:
|
||||
{
|
||||
AddDevice *a = proto->add;
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_ADD_DEVICE,
|
||||
.add_device.deviceid = a->deviceid,
|
||||
.add_device.capabilities = a->capabilities,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case CLIENT_MESSAGE__MSG_REMOVE:
|
||||
{
|
||||
RemoveDevice *r = proto->remove;
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_REMOVE_DEVICE,
|
||||
.remove_device.deviceid = r->deviceid,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case CLIENT_MESSAGE__MSG_REL:
|
||||
{
|
||||
PointerRelative *r = proto->rel;
|
||||
*msg = (struct message) {
|
||||
.type = MESSAGE_POINTER_REL,
|
||||
.pointer_rel.deviceid = r->deviceid,
|
||||
.pointer_rel.x = r->x,
|
||||
.pointer_rel.y = r->y,
|
||||
};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
client_message__free_unpacked(proto, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client_message__free_unpacked(proto, NULL);
|
||||
|
||||
return steal(&msg);
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue