Plugin persistence interface.
parent
cfe078cd32
commit
0f8733627a
@ -0,0 +1,327 @@
|
||||
/*
|
||||
Copyright (c) 2021 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License 2.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
https://www.eclipse.org/legal/epl-2.0/
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "mosquitto_broker_internal.h"
|
||||
#include "mosquitto_internal.h"
|
||||
#include "mosquitto_broker.h"
|
||||
#include "memory_mosq.h"
|
||||
#include "mqtt_protocol.h"
|
||||
#include "send_mosq.h"
|
||||
#include "util_mosq.h"
|
||||
#include "utlist.h"
|
||||
#include "lib_load.h"
|
||||
#include "will_mosq.h"
|
||||
|
||||
|
||||
void plugin_persist__handle_restore(void)
|
||||
{
|
||||
struct mosquitto_evt_persist_restore event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_restore, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_RESTORE, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_client_add(struct mosquitto *context)
|
||||
{
|
||||
struct mosquitto_evt_persist_client event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
struct mosquitto_message_v5 will;
|
||||
|
||||
UNUSED(will); /* FIXME */
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
event_data.client_id = context->id;
|
||||
event_data.username = context->username;
|
||||
event_data.will_delay_time = context->will_delay_time;
|
||||
event_data.session_expiry_time = context->session_expiry_time;
|
||||
event_data.will_delay_interval = context->will_delay_interval;
|
||||
event_data.session_expiry_interval = context->session_expiry_interval;
|
||||
if(context->listener){
|
||||
event_data.listener_port = context->listener->port;
|
||||
}else{
|
||||
event_data.listener_port = 0;
|
||||
}
|
||||
event_data.max_qos = context->max_qos;
|
||||
event_data.retain_available = context->retain_available;
|
||||
event_data.max_packet_size = context->maximum_packet_size;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_client_add, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_CLIENT_ADD, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_client_update(struct mosquitto *context)
|
||||
{
|
||||
struct mosquitto_evt_persist_client event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
struct mosquitto_message_v5 will;
|
||||
|
||||
UNUSED(will); /* FIXME */
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
event_data.client_id = context->id;
|
||||
event_data.username = context->username;
|
||||
event_data.will_delay_time = context->will_delay_time;
|
||||
event_data.session_expiry_time = context->session_expiry_time;
|
||||
event_data.will_delay_interval = context->will_delay_interval;
|
||||
event_data.session_expiry_interval = context->session_expiry_interval;
|
||||
if(context->listener){
|
||||
event_data.listener_port = context->listener->port;
|
||||
}else{
|
||||
event_data.listener_port = 0;
|
||||
}
|
||||
event_data.max_qos = context->max_qos;
|
||||
event_data.retain_available = context->retain_available;
|
||||
event_data.max_packet_size = context->maximum_packet_size;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_client_update, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_CLIENT_UPDATE, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_client_remove(struct mosquitto *context)
|
||||
{
|
||||
struct mosquitto_evt_persist_client event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
if(context->session_expiry_interval > 0 || context->id == NULL || context->state == mosq_cs_duplicate){
|
||||
return;
|
||||
}
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
event_data.client_id = context->id;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_client_remove, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_CLIENT_REMOVE, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_subscription_add(struct mosquitto *context, const char *sub, uint8_t subscription_options, uint32_t subscription_identifier)
|
||||
{
|
||||
struct mosquitto_evt_persist_subscription event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
event_data.client_id = context->id;
|
||||
event_data.topic = sub;
|
||||
event_data.subscription_identifier = subscription_identifier;
|
||||
event_data.subscription_options = subscription_options;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_subscription_add, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_SUBSCRIPTION_ADD, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_subscription_remove(struct mosquitto *context, const char *sub)
|
||||
{
|
||||
struct mosquitto_evt_persist_subscription event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
event_data.client_id = context->id;
|
||||
event_data.topic = sub;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_subscription_remove, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_SUBSCRIPTION_REMOVE, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_client_msg_add(struct mosquitto *context, const struct mosquitto_client_msg *cmsg)
|
||||
{
|
||||
struct mosquitto_evt_persist_client_msg event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
if(context->session_expiry_interval == 0
|
||||
|| (cmsg->qos == 0 && db.config->queue_qos0_messages == false)){
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
|
||||
event_data.client_id = context->id;
|
||||
event_data.cmsg_id = cmsg->cmsg_id;
|
||||
event_data.store_id = cmsg->store->db_id;
|
||||
event_data.mid = cmsg->mid;
|
||||
event_data.qos = cmsg->qos;
|
||||
event_data.retain = cmsg->retain;
|
||||
event_data.dup = cmsg->dup;
|
||||
event_data.direction = cmsg->direction;
|
||||
event_data.state = cmsg->state;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_client_msg_add, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_CLIENT_MSG_ADD, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_client_msg_remove(struct mosquitto *context, const struct mosquitto_client_msg *cmsg)
|
||||
{
|
||||
struct mosquitto_evt_persist_client_msg event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
event_data.client_id = context->id;
|
||||
event_data.cmsg_id = cmsg->cmsg_id;
|
||||
event_data.mid = cmsg->mid;
|
||||
event_data.state = cmsg->state;
|
||||
event_data.qos = cmsg->qos;
|
||||
event_data.store_id = cmsg->store->db_id;
|
||||
event_data.direction = cmsg->direction;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_client_msg_remove, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_CLIENT_MSG_REMOVE, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_client_msg_update(struct mosquitto *context, const struct mosquitto_client_msg *cmsg)
|
||||
{
|
||||
struct mosquitto_evt_persist_client_msg event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
|
||||
event_data.client_id = context->id;
|
||||
event_data.cmsg_id = cmsg->cmsg_id;
|
||||
event_data.store_id = cmsg->store->db_id;
|
||||
event_data.state = cmsg->state;
|
||||
event_data.dup = cmsg->dup;
|
||||
event_data.direction = cmsg->direction;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_client_msg_update, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_CLIENT_MSG_UPDATE, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_msg_add(struct mosquitto_msg_store *msg)
|
||||
{
|
||||
struct mosquitto_evt_persist_msg event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
if(msg->stored) return;
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
|
||||
event_data.store_id = msg->db_id;
|
||||
event_data.expiry_time = msg->message_expiry_time;
|
||||
event_data.topic = msg->topic;
|
||||
event_data.payload = msg->payload;
|
||||
event_data.source_id = msg->source_id;
|
||||
event_data.source_username = msg->source_username;
|
||||
event_data.properties = msg->properties;
|
||||
event_data.payloadlen = msg->payloadlen;
|
||||
event_data.source_mid = msg->source_mid;
|
||||
if(msg->source_listener){
|
||||
event_data.source_port = msg->source_listener->port;
|
||||
}else{
|
||||
event_data.source_port = 0;
|
||||
}
|
||||
event_data.qos = msg->qos;
|
||||
event_data.retain = msg->retain;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_msg_add, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_MSG_ADD, &event_data, cb_base->userdata);
|
||||
}
|
||||
msg->stored = true;
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_msg_remove(struct mosquitto_msg_store *msg)
|
||||
{
|
||||
struct mosquitto_evt_persist_msg event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
if(msg->stored == false) return;
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
|
||||
event_data.store_id = msg->db_id;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_msg_remove, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_MSG_REMOVE, &event_data, cb_base->userdata);
|
||||
}
|
||||
msg->stored = false;
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_retain_add(struct mosquitto_msg_store *msg)
|
||||
{
|
||||
struct mosquitto_evt_persist_retain event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
|
||||
event_data.store_id = msg->db_id;
|
||||
event_data.topic = msg->topic;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_retain_add, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_MSG_ADD, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plugin_persist__handle_retain_remove(struct mosquitto_msg_store *msg)
|
||||
{
|
||||
struct mosquitto_evt_persist_retain event_data;
|
||||
struct mosquitto__callback *cb_base;
|
||||
struct mosquitto__security_options *opts;
|
||||
|
||||
opts = &db.config->security_options;
|
||||
memset(&event_data, 0, sizeof(event_data));
|
||||
|
||||
event_data.topic = msg->topic;
|
||||
|
||||
DL_FOREACH(opts->plugin_callbacks.persist_retain_remove, cb_base){
|
||||
cb_base->cb(MOSQ_EVT_PERSIST_MSG_REMOVE, &event_data, cb_base->userdata);
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Connect a client, start a QoS 2 flow, disconnect, restore, carry on with the
|
||||
# QoS 2 flow. Is it received?
|
||||
|
||||
from mosq_test_helper import *
|
||||
import persist_help
|
||||
|
||||
port = mosq_test.get_port()
|
||||
conf_file = os.path.basename(__file__).replace('.py', '.conf')
|
||||
persist_help.write_config(conf_file, port)
|
||||
|
||||
rc = 1
|
||||
|
||||
persist_help.init(port)
|
||||
|
||||
keepalive = 10
|
||||
client_id = "persist-client-msg-in-v3-1-1"
|
||||
proto_ver = 4
|
||||
|
||||
helper_id = "persist-client-msg-in-v3-1-1-helper"
|
||||
topic = "client-msg-in/2"
|
||||
qos = 2
|
||||
|
||||
connect_packet = mosq_test.gen_connect(client_id, keepalive=keepalive, proto_ver=proto_ver, clean_session=False)
|
||||
connack_packet1 = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
|
||||
connack_packet2 = mosq_test.gen_connack(rc=0, flags=1, proto_ver=proto_ver)
|
||||
mid = 1
|
||||
publish_packet = mosq_test.gen_publish(topic=topic, qos=qos, payload="message", mid=mid, proto_ver=proto_ver)
|
||||
pubrec_packet = mosq_test.gen_pubrec(mid=mid, proto_ver=proto_ver)
|
||||
pubrel_packet = mosq_test.gen_pubrel(mid=mid, proto_ver=proto_ver)
|
||||
pubcomp_packet = mosq_test.gen_pubcomp(mid=mid, proto_ver=proto_ver)
|
||||
|
||||
connect_packet_helper = mosq_test.gen_connect(helper_id, keepalive=keepalive, proto_ver=proto_ver, clean_session=True)
|
||||
subscribe_packet = mosq_test.gen_subscribe(mid, topic, qos=qos, proto_ver=proto_ver)
|
||||
suback_packet = mosq_test.gen_suback(mid=mid, qos=qos, proto_ver=proto_ver)
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
con = None
|
||||
try:
|
||||
# Connect client, start flow, disconnect
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet1, timeout=5, port=port)
|
||||
mosq_test.do_send_receive(sock, publish_packet, pubrec_packet, "pubrec send")
|
||||
sock.close()
|
||||
|
||||
# Kill broker
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
|
||||
# Restart broker
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
# Connect helper and subscribe
|
||||
helper = mosq_test.do_client_connect(connect_packet_helper, connack_packet1, timeout=5, port=port)
|
||||
mosq_test.do_send_receive(helper, subscribe_packet, suback_packet, "suback helper")
|
||||
|
||||
# Complete the flow
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet2, timeout=5, port=port)
|
||||
mosq_test.do_send_receive(sock, pubrel_packet, pubcomp_packet, "pubrel send")
|
||||
|
||||
mosq_test.do_receive_send(helper, publish_packet, pubrec_packet, "pubrec receive")
|
||||
mosq_test.do_receive_send(helper, pubrel_packet, pubcomp_packet, "pubcomp receive")
|
||||
|
||||
rc = 0
|
||||
finally:
|
||||
if broker is not None:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
(stdo, stde) = broker.communicate()
|
||||
os.remove(conf_file)
|
||||
rc += persist_help.cleanup(port)
|
||||
|
||||
if rc:
|
||||
print(stde.decode('utf-8'))
|
||||
|
||||
|
||||
exit(rc)
|
@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Connect a client, add a subscription, disconnect, send a message with a
|
||||
# different client, restore, reconnect, check it is received.
|
||||
|
||||
from mosq_test_helper import *
|
||||
import persist_help
|
||||
|
||||
port = mosq_test.get_port()
|
||||
conf_file = os.path.basename(__file__).replace('.py', '.conf')
|
||||
persist_help.write_config(conf_file, port)
|
||||
|
||||
rc = 1
|
||||
|
||||
persist_help.init(port)
|
||||
|
||||
keepalive = 10
|
||||
client_id = "persist-client-msg-v3-1-1"
|
||||
proto_ver = 4
|
||||
|
||||
helper_id = "persist-client-msg-v3-1-1-helper"
|
||||
topic0 = "client-msg/0"
|
||||
topic1 = "client-msg/1"
|
||||
topic2 = "client-msg/2"
|
||||
|
||||
connect_packet = mosq_test.gen_connect(client_id, keepalive=keepalive, proto_ver=proto_ver, clean_session=False)
|
||||
connack_packet1 = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
|
||||
connack_packet2 = mosq_test.gen_connack(rc=0, flags=1, proto_ver=proto_ver)
|
||||
mid = 1
|
||||
subscribe_packet0 = mosq_test.gen_subscribe(mid, topic0, qos=0, proto_ver=proto_ver)
|
||||
suback_packet0 = mosq_test.gen_suback(mid=mid, qos=0, proto_ver=proto_ver)
|
||||
subscribe_packet1 = mosq_test.gen_subscribe(mid, topic1, qos=1, proto_ver=proto_ver)
|
||||
suback_packet1 = mosq_test.gen_suback(mid=mid, qos=1, proto_ver=proto_ver)
|
||||
subscribe_packet2 = mosq_test.gen_subscribe(mid, topic2, qos=2, proto_ver=proto_ver)
|
||||
suback_packet2 = mosq_test.gen_suback(mid=mid, qos=2, proto_ver=proto_ver)
|
||||
|
||||
connect_packet_helper = mosq_test.gen_connect(helper_id, keepalive=keepalive, proto_ver=proto_ver, clean_session=True)
|
||||
publish_packet0 = mosq_test.gen_publish(topic=topic0, qos=0, payload="message", proto_ver=proto_ver)
|
||||
mid = 1
|
||||
publish_packet1 = mosq_test.gen_publish(topic=topic1, qos=1, payload="message", mid=mid, proto_ver=proto_ver)
|
||||
puback_packet = mosq_test.gen_puback(mid=mid, proto_ver=proto_ver)
|
||||
mid = 2
|
||||
publish_packet2 = mosq_test.gen_publish(topic=topic2, qos=2, payload="message", mid=mid, proto_ver=proto_ver)
|
||||
pubrec_packet = mosq_test.gen_pubrec(mid=mid, proto_ver=proto_ver)
|
||||
pubrel_packet = mosq_test.gen_pubrel(mid=mid, proto_ver=proto_ver)
|
||||
pubcomp_packet = mosq_test.gen_pubcomp(mid=mid, proto_ver=proto_ver)
|
||||
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
con = None
|
||||
try:
|
||||
# Connect client, subscribe, disconnect
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet1, timeout=5, port=port)
|
||||
mosq_test.do_send_receive(sock, subscribe_packet0, suback_packet0, "suback 0")
|
||||
mosq_test.do_send_receive(sock, subscribe_packet1, suback_packet1, "suback 1")
|
||||
mosq_test.do_send_receive(sock, subscribe_packet2, suback_packet2, "suback 2")
|
||||
sock.close()
|
||||
|
||||
# Connect helper and publish
|
||||
helper = mosq_test.do_client_connect(connect_packet_helper, connack_packet1, timeout=5, port=port)
|
||||
helper.send(publish_packet0)
|
||||
mosq_test.do_send_receive(helper, publish_packet1, puback_packet, "puback helper")
|
||||
mosq_test.do_send_receive(helper, publish_packet2, pubrec_packet, "pubrec helper")
|
||||
mosq_test.do_send_receive(helper, pubrel_packet, pubcomp_packet, "pubcomp helper")
|
||||
helper.close()
|
||||
|
||||
# Kill broker
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
|
||||
# Restart broker
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
# Connect client again, it should have a session
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet2, timeout=5, port=port)
|
||||
|
||||
# Does the client get the messages
|
||||
mosq_test.do_receive_send(sock, publish_packet1, puback_packet, "publish 1")
|
||||
mosq_test.do_receive_send(sock, publish_packet2, pubrec_packet, "publish 2")
|
||||
mosq_test.do_receive_send(sock, pubrel_packet, pubcomp_packet, "pubrel 2")
|
||||
sock.close()
|
||||
|
||||
# Connect client again, it should have a session
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet2, timeout=5, port=port)
|
||||
# If there are messages, the ping will fail
|
||||
mosq_test.do_ping(sock)
|
||||
|
||||
rc = 0
|
||||
finally:
|
||||
if broker is not None:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
(stdo, stde) = broker.communicate()
|
||||
os.remove(conf_file)
|
||||
rc += persist_help.cleanup(port)
|
||||
|
||||
if rc:
|
||||
print(stde.decode('utf-8'))
|
||||
|
||||
|
||||
exit(rc)
|
@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Connect a client, check it is restored, clear the client, check it is not there.
|
||||
|
||||
from mosq_test_helper import *
|
||||
import persist_help
|
||||
|
||||
port = mosq_test.get_port()
|
||||
conf_file = os.path.basename(__file__).replace('.py', '.conf')
|
||||
persist_help.write_config(conf_file, port)
|
||||
|
||||
rc = 1
|
||||
|
||||
persist_help.init(port)
|
||||
|
||||
keepalive = 10
|
||||
client_id = "persist-client-v3-1-1"
|
||||
proto_ver = 4
|
||||
|
||||
connect_packet = mosq_test.gen_connect(client_id, keepalive=keepalive, proto_ver=proto_ver, clean_session=False)
|
||||
connack_packet1 = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
|
||||
connack_packet2 = mosq_test.gen_connack(rc=0, flags=1, proto_ver=proto_ver)
|
||||
|
||||
connect_packet_clean = mosq_test.gen_connect(client_id, keepalive=keepalive, proto_ver=proto_ver, clean_session=True)
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
con = None
|
||||
try:
|
||||
# Connect client
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet1, timeout=5, port=port, connack_error="connack 1")
|
||||
mosq_test.do_ping(sock)
|
||||
sock.close()
|
||||
|
||||
# Kill broker
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
|
||||
# Restart broker
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
# Connect client again, it should have a session
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet2, timeout=5, port=port, connack_error="connack 2")
|
||||
mosq_test.do_ping(sock)
|
||||
sock.close()
|
||||
|
||||
# Clear the client
|
||||
sock = mosq_test.do_client_connect(connect_packet_clean, connack_packet1, timeout=5, port=port, connack_error="connack 3")
|
||||
mosq_test.do_ping(sock)
|
||||
sock.close()
|
||||
|
||||
# Connect client, it should not have a session
|
||||
sock = mosq_test.do_client_connect(connect_packet_clean, connack_packet1, timeout=5, port=port, connack_error="connack 4")
|
||||
mosq_test.do_ping(sock)
|
||||
sock.close()
|
||||
|
||||
# Kill broker
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
|
||||
# Restart broker
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
# Connect client, it should not have a session
|
||||
sock = mosq_test.do_client_connect(connect_packet_clean, connack_packet1, timeout=5, port=port, connack_error="connack 5")
|
||||
mosq_test.do_ping(sock)
|
||||
sock.close()
|
||||
|
||||
rc = 0
|
||||
finally:
|
||||
if broker is not None:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
(stdo, stde) = broker.communicate()
|
||||
os.remove(conf_file)
|
||||
rc += persist_help.cleanup(port)
|
||||
|
||||
if rc:
|
||||
print(stde.decode('utf-8'))
|
||||
|
||||
|
||||
exit(rc)
|
@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Publish a retained messages, check they are restored
|
||||
|
||||
from mosq_test_helper import *
|
||||
import persist_help
|
||||
|
||||
port = mosq_test.get_port()
|
||||
conf_file = os.path.basename(__file__).replace('.py', '.conf')
|
||||
persist_help.write_config(conf_file, port)
|
||||
|
||||
rc = 1
|
||||
|
||||
persist_help.init(port)
|
||||
|
||||
keepalive = 10
|
||||
topic1 = "test/retain1"
|
||||
topic2 = "test/retain2"
|
||||
topic3 = "test/retain3"
|
||||
source_id = "persist-retain-v3-1-1"
|
||||
qos = 0
|
||||
payload2 = "retained message 2"
|
||||
payload3 = "retained message 3"
|
||||
proto_ver = 4
|
||||
connect_packet = mosq_test.gen_connect(source_id, keepalive=keepalive, proto_ver=proto_ver, clean_session=True)
|
||||
connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
|
||||
|
||||
publish1_packet = mosq_test.gen_publish(topic1, qos=qos, payload="retained message 1", retain=True, proto_ver=proto_ver)
|
||||
publish2_packet = mosq_test.gen_publish(topic2, qos=qos, payload=payload2, retain=False, proto_ver=proto_ver)
|
||||
publish3_packet = mosq_test.gen_publish(topic3, qos=qos, payload=payload3, retain=True, proto_ver=proto_ver)
|
||||
|
||||
mid = 1
|
||||
subscribe_packet = mosq_test.gen_subscribe(mid, "#", 0, proto_ver=4)
|
||||
suback_packet = mosq_test.gen_suback(mid, qos=0, proto_ver=4)
|
||||
|
||||
mid = 2
|
||||
unsubscribe_packet = mosq_test.gen_unsubscribe(mid, "#", proto_ver=4)
|
||||
unsuback_packet = mosq_test.gen_unsuback(mid, proto_ver=4)
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
try:
|
||||
# Connect client
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=5, port=port)
|
||||
# Check no retained messages exist
|
||||
mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback")
|
||||
# Ping will fail if a PUBLISH is received
|
||||
mosq_test.do_ping(sock)
|
||||
# Unsubscribe, so we don't receive the messages
|
||||
mosq_test.do_send_receive(sock, unsubscribe_packet, unsuback_packet, "unsuback")
|
||||
|
||||
# Send some retained messages
|
||||
sock.send(publish1_packet)
|
||||
mosq_test.do_ping(sock)
|
||||
sock.send(publish2_packet) # Not retained
|
||||
mosq_test.do_ping(sock)
|
||||
sock.send(publish3_packet)
|
||||
mosq_test.do_ping(sock)
|
||||
sock.close()
|
||||
|
||||
# Kill broker
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
|
||||
# Restart broker
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
# Connect client
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=5, port=port)
|
||||
# Subscribe
|
||||
mosq_test.do_send_receive(sock, subscribe_packet, suback_packet, "suback")
|
||||
# Check retained messages exist
|
||||
mosq_test.receive_unordered(sock, publish1_packet, publish3_packet, "publish 1 / 3")
|
||||
mosq_test.do_ping(sock)
|
||||
|
||||
rc = 0
|
||||
finally:
|
||||
if broker is not None:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
(stdo, stde) = broker.communicate()
|
||||
os.remove(conf_file)
|
||||
rc += persist_help.cleanup(port)
|
||||
|
||||
if rc:
|
||||
print(stde.decode('utf-8'))
|
||||
|
||||
|
||||
exit(rc)
|
@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Connect a client, add a subscription, disconnect, restore, reconnect, send a
|
||||
# message with a different client, check it is received.
|
||||
|
||||
from mosq_test_helper import *
|
||||
import persist_help
|
||||
|
||||
port = mosq_test.get_port()
|
||||
conf_file = os.path.basename(__file__).replace('.py', '.conf')
|
||||
persist_help.write_config(conf_file, port)
|
||||
|
||||
rc = 1
|
||||
|
||||
persist_help.init(port)
|
||||
|
||||
keepalive = 10
|
||||
client_id = "persist-subscription-v3-1-1"
|
||||
proto_ver = 4
|
||||
|
||||
helper_id = "persist-subscription-v3-1-1-helper"
|
||||
topic0 = "subscription/0"
|
||||
topic1 = "subscription/1"
|
||||
topic2 = "subscription/2"
|
||||
|
||||
connect_packet = mosq_test.gen_connect(client_id, keepalive=keepalive, proto_ver=proto_ver, clean_session=False)
|
||||
connack_packet1 = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
|
||||
connack_packet2 = mosq_test.gen_connack(rc=0, flags=1, proto_ver=proto_ver)
|
||||
mid = 1
|
||||
subscribe_packet0 = mosq_test.gen_subscribe(mid, topic0, qos=0, proto_ver=proto_ver)
|
||||
suback_packet0 = mosq_test.gen_suback(mid=mid, qos=0, proto_ver=proto_ver)
|
||||
subscribe_packet1 = mosq_test.gen_subscribe(mid, topic1, qos=1, proto_ver=proto_ver)
|
||||
suback_packet1 = mosq_test.gen_suback(mid=mid, qos=1, proto_ver=proto_ver)
|
||||
subscribe_packet2 = mosq_test.gen_subscribe(mid, topic2, qos=2, proto_ver=proto_ver)
|
||||
suback_packet2 = mosq_test.gen_suback(mid=mid, qos=2, proto_ver=proto_ver)
|
||||
|
||||
unsubscribe_packet2 = mosq_test.gen_unsubscribe(mid, topic2, proto_ver=proto_ver)
|
||||
unsuback_packet2 = mosq_test.gen_unsuback(mid=mid, proto_ver=proto_ver)
|
||||
|
||||
connect_packet_helper = mosq_test.gen_connect(helper_id, keepalive=keepalive, proto_ver=proto_ver, clean_session=True)
|
||||
publish_packet0 = mosq_test.gen_publish(topic=topic0, qos=0, payload="message", proto_ver=proto_ver)
|
||||
mid = 1
|
||||
publish_packet1 = mosq_test.gen_publish(topic=topic1, qos=1, payload="message", mid=mid, proto_ver=proto_ver)
|
||||
puback_packet = mosq_test.gen_puback(mid=mid, proto_ver=proto_ver)
|
||||
mid = 2
|
||||
publish_packet2 = mosq_test.gen_publish(topic=topic2, qos=2, payload="message", mid=mid, proto_ver=proto_ver)
|
||||
pubrec_packet = mosq_test.gen_pubrec(mid=mid, proto_ver=proto_ver)
|
||||
pubrel_packet = mosq_test.gen_pubrel(mid=mid, proto_ver=proto_ver)
|
||||
pubcomp_packet = mosq_test.gen_pubcomp(mid=mid, proto_ver=proto_ver)
|
||||
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
con = None
|
||||
try:
|
||||
# Connect client
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet1, timeout=5, port=port)
|
||||
mosq_test.do_send_receive(sock, subscribe_packet0, suback_packet0, "suback 0")
|
||||
mosq_test.do_send_receive(sock, subscribe_packet1, suback_packet1, "suback 1")
|
||||
mosq_test.do_send_receive(sock, subscribe_packet2, suback_packet2, "suback 2")
|
||||
sock.close()
|
||||
|
||||
# Kill broker
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
|
||||
# Restart broker
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
# Connect client again, it should have a session
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet2, timeout=5, port=port)
|
||||
mosq_test.do_ping(sock)
|
||||
|
||||
# Connect helper and publish
|
||||
helper = mosq_test.do_client_connect(connect_packet_helper, connack_packet1, timeout=5, port=port)
|
||||
helper.send(publish_packet0)
|
||||
mosq_test.do_send_receive(helper, publish_packet1, puback_packet, "puback helper")
|
||||
mosq_test.do_send_receive(helper, publish_packet2, pubrec_packet, "pubrec helper")
|
||||
mosq_test.do_send_receive(helper, pubrel_packet, pubcomp_packet, "pubcomp helper")
|
||||
helper.close()
|
||||
|
||||
# Does the client get the messages
|
||||
mosq_test.expect_packet(sock, "publish 0", publish_packet0)
|
||||
mosq_test.do_receive_send(sock, publish_packet1, puback_packet, "publish 1")
|
||||
mosq_test.do_receive_send(sock, publish_packet2, pubrec_packet, "publish 2")
|
||||
mosq_test.do_receive_send(sock, pubrel_packet, pubcomp_packet, "pubrel 2")
|
||||
|
||||
# Unsubscribe
|
||||
mosq_test.do_send_receive(sock, unsubscribe_packet2, unsuback_packet2, "unsuback 2")
|
||||
sock.close()
|
||||
|
||||
# Kill broker
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
|
||||
# Restart broker
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
# Connect client again, it should have a session
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet2, timeout=5, port=port)
|
||||
mosq_test.do_ping(sock)
|
||||
|
||||
# Connect helper and publish
|
||||
helper = mosq_test.do_client_connect(connect_packet_helper, connack_packet1, timeout=5, port=port)
|
||||
helper.send(publish_packet0)
|
||||
mosq_test.do_send_receive(helper, publish_packet1, puback_packet, "puback helper")
|
||||
mosq_test.do_send_receive(helper, publish_packet2, pubrec_packet, "pubrec helper")
|
||||
mosq_test.do_send_receive(helper, pubrel_packet, pubcomp_packet, "pubcomp helper")
|
||||
helper.close()
|
||||
|
||||
# Does the client get the messages
|
||||
mosq_test.expect_packet(sock, "publish 0", publish_packet0)
|
||||
mosq_test.do_receive_send(sock, publish_packet1, puback_packet, "publish 1")
|
||||
mosq_test.do_ping(sock)
|
||||
|
||||
rc = 0
|
||||
finally:
|
||||
if broker is not None:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
(stdo, stde) = broker.communicate()
|
||||
os.remove(conf_file)
|
||||
rc += persist_help.cleanup(port)
|
||||
|
||||
if rc:
|
||||
print(stde.decode('utf-8'))
|
||||
|
||||
|
||||
exit(rc)
|
@ -0,0 +1,13 @@
|
||||
# This can be rewritten to easily support persistence plugins with all of
|
||||
# the 15-persist-* tests.
|
||||
|
||||
def init(port):
|
||||
pass
|
||||
|
||||
def cleanup(port):
|
||||
return 0
|
||||
|
||||
def write_config(filename, port):
|
||||
with open(filename, 'w') as f:
|
||||
#f.write("plugin ..\n")
|
||||
pass
|
Loading…
Reference in New Issue