diff --git a/proto/ei.proto b/proto/ei.proto index 87a7ba0..6afe99a 100644 --- a/proto/ei.proto +++ b/proto/ei.proto @@ -103,6 +103,17 @@ message ConfigureCapabilities { uint32 allowed_capabilities = 2; } +/** + * ConfigureProperty *must* be sent before the Connect event. Once the client + * is connected or if sent outside a ConfigureStart/ConfigureFinish + * transaction, this message is ignored. + */ +message ConfigureProperty { + string name = 1; + string value = 2; + uint32 permissions = 3; +} + message Connect { uint32 version = 1; /* Must be equal or less to the server's GetVersion response */ string name = 2; @@ -236,6 +247,7 @@ message ClientMessage { ConfigureFinish configure_finish = 101; ConfigureName configure_name = 102; ConfigureCapabilities configure_capabilities = 103; + ConfigureProperty configure_property = 104; } } diff --git a/src/libei-proto.c b/src/libei-proto.c index ac41a3e..4f5c260 100644 --- a/src/libei-proto.c +++ b/src/libei-proto.c @@ -263,6 +263,7 @@ log_wire_message(struct ei *ei, const ClientMessage *msg, int error) MSG_STRING_CASE(CONFIGURE_FINISH); MSG_STRING_CASE(CONFIGURE_NAME); MSG_STRING_CASE(CONFIGURE_CAPABILITIES); + MSG_STRING_CASE(CONFIGURE_PROPERTY); } if (message == NULL) assert(!"Unimplemented message type"); diff --git a/src/libeis-client.c b/src/libeis-client.c index 15431cd..55d0943 100644 --- a/src/libeis-client.c +++ b/src/libeis-client.c @@ -604,6 +604,26 @@ client_msg_configure_capabilities(struct eis_client *client, uint32_t allowed_ca return 0; } +static int +client_msg_configure_property(struct eis_client *client, + const char *name, const char *value, + uint32_t permissions) +{ + tristate t = client_is_in_configure_transaction(client); + + if (tristate_is_finished(t)) + return -EPROTO; + + /* Once the client is connected, we silently ignore all Configure + requests so a broken portal can't accidentally disconnect a client */ + if (tristate_is_connected(t)) + return 0; + + eis_property_update_from_client(client, name, value, permissions); + + return 0; +} + static int client_msg_connect(struct eis_client *client, uint32_t version, const char *name, bool is_sender) @@ -674,6 +694,7 @@ static const struct eis_proto_interface intf_state_new = { .configure_finish = client_msg_configure_finish, .configure_name = client_msg_configure_name, .configure_capabilities = client_msg_configure_capabilities, + .configure_property = client_msg_configure_property, }; /* Client is waiting for us, shouldn't send anything except disconnect */ @@ -685,6 +706,7 @@ static const struct eis_proto_interface intf_state_connecting = { .configure_finish = client_msg_configure_finish, .configure_name = client_msg_configure_name, .configure_capabilities = client_msg_configure_capabilities, + .configure_property = client_msg_configure_property, }; static const struct eis_proto_interface intf_state_connected = { @@ -714,6 +736,7 @@ static const struct eis_proto_interface intf_state_connected = { .configure_finish = client_msg_configure_finish, .configure_name = client_msg_configure_name, .configure_capabilities = client_msg_configure_capabilities, + .configure_property = client_msg_configure_property, }; static const struct eis_proto_interface *interfaces[] = { diff --git a/src/libeis-proto.c b/src/libeis-proto.c index e598265..b7bdb35 100644 --- a/src/libeis-proto.c +++ b/src/libeis-proto.c @@ -639,6 +639,11 @@ eis_proto_handle_message(struct eis_client *client, rc = call(configure_capabilities, client, proto->configure_capabilities->allowed_capabilities); break; + case CLIENT_MESSAGE__MSG_CONFIGURE_PROPERTY: + rc = call(configure_property, client, proto->configure_property->name, + proto->configure_property->value[0] ? proto->configure_property->value : NULL, + proto->configure_property->permissions); + break; default: rc = -EBADMSG; break; diff --git a/src/libeis-proto.h b/src/libeis-proto.h index cfd9e22..949d91d 100644 --- a/src/libeis-proto.h +++ b/src/libeis-proto.h @@ -67,6 +67,8 @@ struct eis_proto_interface { int (*configure_finish)(struct eis_client *client); int (*configure_name)(struct eis_client *client, const char *name); int (*configure_capabilities)(struct eis_client *client, uint32_t allow); + int (*configure_property)(struct eis_client *client, const char *name, + const char *value, uint32_t permissions); }; struct eis_proto_requests { diff --git a/src/libreis.c b/src/libreis.c index 55022d2..853c497 100644 --- a/src/libreis.c +++ b/src/libreis.c @@ -129,13 +129,22 @@ reis_set_property_with_permissions(struct reis *reis, const char *name, const char *value, uint32_t permissions) { - prepare_msg(SET_PROPERTY, SetProperty, set_property); + int rc; - set_property.name = (char*)name; - set_property.value = value ? (char*)value : ""; - set_property.permissions = permissions; + if ((rc = reis_start(reis)) != 0) + return rc; - return send_msg(reis->eisfd, &msg); + prepare_msg(CONFIGURE_PROPERTY, ConfigureProperty, configure_property); + + configure_property.name = (char*)name; + configure_property.value = value ? (char*)value : ""; + configure_property.permissions = permissions; + + rc = send_msg(reis->eisfd, &msg); + if (rc == 0) + return rc; + + return reis_finish(reis); } _public_ int