Add more callbacks to the API so we can subscribe after successful connection for example
This commit is contained in:
parent
5a17278cc9
commit
1d134a23c9
2 changed files with 60 additions and 55 deletions
70
src/mqtt.c
70
src/mqtt.c
|
@ -23,17 +23,6 @@ static inline void disconnect(MQTTHandle *handle) {
|
|||
// FIXME: Do we have to do anything else?
|
||||
}
|
||||
|
||||
static inline bool find_waiting(MQTTHandle *handle, MQTTPacket *packet) {
|
||||
// TODO: Try to find a waiting task and call its callback
|
||||
// TODO: Remove waiting task from queue
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void send_subscription(MQTTHandle *handle, PublishPayload *payload) {
|
||||
// TODO: find subscriber and call the callback
|
||||
}
|
||||
|
||||
static inline void parse_packet(MQTTHandle *handle, MQTTPacket *packet) {
|
||||
switch (packet->packet_type) {
|
||||
case PacketTypeConnAck:
|
||||
|
@ -43,13 +32,20 @@ static inline void parse_packet(MQTTHandle *handle, MQTTPacket *packet) {
|
|||
case PacketTypePubComp:
|
||||
case PacketTypeSubAck:
|
||||
case PacketTypeUnsubAck:
|
||||
case PacketTypePingResp:
|
||||
if (!find_waiting(handle, packet)) {
|
||||
if (!dispatch_packet(handle, packet)) {
|
||||
DEBUG_LOG("Unexpected packet!");
|
||||
disconnect(handle);
|
||||
}
|
||||
break;
|
||||
|
||||
case PacketTypePublish:
|
||||
send_subscription(handle, packet->payload);
|
||||
dispatch_subscription(handle, packet->payload);
|
||||
// TODO: Handle QoS
|
||||
break;
|
||||
|
||||
// just for keepalive, do not handle
|
||||
case PacketTypePingResp:
|
||||
break;
|
||||
|
||||
// client -> server, will not be handled in client
|
||||
case PacketTypeConnect:
|
||||
|
@ -57,13 +53,14 @@ static inline void parse_packet(MQTTHandle *handle, MQTTPacket *packet) {
|
|||
case PacketTypeUnsubscribe:
|
||||
case PacketTypePingReq:
|
||||
case PacketTypeDisconnect:
|
||||
DEBUG_LOG("Server packet on client connection? What's up with the broker?");
|
||||
disconnect(handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _reader(MQTTHandle *handle) {
|
||||
int num_bytes;
|
||||
ssize_t num_bytes;
|
||||
char *read_buffer = malloc(max_receive_buffer_size);
|
||||
uint8_t offset = 0;
|
||||
|
||||
|
@ -78,13 +75,11 @@ static void _reader(MQTTHandle *handle) {
|
|||
return;
|
||||
} else if (num_bytes < 0) {
|
||||
if ((errno == EINTR) || (errno == EAGAIN)) {
|
||||
DEBUG_LOG("Interrupted");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set reader task to dead */
|
||||
handle->reader_alive = false;
|
||||
DEBUG_LOG("Read error: %s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -92,13 +87,11 @@ static void _reader(MQTTHandle *handle) {
|
|||
Buffer *buffer = buffer_from_data_no_copy(read_buffer, num_bytes);
|
||||
MQTTPacket *packet = mqtt_packet_decode(buffer);
|
||||
if (packet == NULL) {
|
||||
DEBUG_LOG("Invalid packet");
|
||||
// invalid packet
|
||||
if (num_bytes < max_receive_buffer_size) {
|
||||
// maybe not long enough, try to fetch the rest
|
||||
offset += num_bytes;
|
||||
free(buffer);
|
||||
DEBUG_LOG("Trying to read more...");
|
||||
break;
|
||||
} else {
|
||||
// no space in buffer, bail and reconnect
|
||||
|
@ -109,12 +102,12 @@ static void _reader(MQTTHandle *handle) {
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
DEBUG_LOG("Packet parsed");
|
||||
// hexdump(buffer->data, num_bytes, 2);
|
||||
|
||||
parse_packet(handle, packet);
|
||||
free_MQTTPacket(packet);
|
||||
|
||||
if (!buffer_eof(buffer)) {
|
||||
DEBUG_LOG("Residual buffer data");
|
||||
// Not complete recv buffer was consumed, so we have more than one packet in there
|
||||
size_t remaining = max_receive_buffer_size - buffer->position;
|
||||
memmove(read_buffer, read_buffer + buffer->position, remaining);
|
||||
|
@ -122,7 +115,6 @@ static void _reader(MQTTHandle *handle) {
|
|||
num_bytes -= remaining;
|
||||
free(buffer);
|
||||
} else {
|
||||
DEBUG_LOG("Buffer consumed");
|
||||
// buffer consumed completely, read another chunk
|
||||
offset = 0;
|
||||
free(buffer);
|
||||
|
@ -133,7 +125,7 @@ static void _reader(MQTTHandle *handle) {
|
|||
}
|
||||
}
|
||||
|
||||
static void _mqtt_connect(MQTTHandle *handle) {
|
||||
static void _mqtt_connect(MQTTHandle *handle, MQTTEventHandler callback, void *context) {
|
||||
int ret;
|
||||
struct sockaddr_in servaddr;
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
|
@ -176,18 +168,20 @@ static void _mqtt_connect(MQTTHandle *handle) {
|
|||
|
||||
run_read_task(handle, _reader);
|
||||
|
||||
expect_packet(handle, PacketTypeConnAck, 0, callback, context);
|
||||
|
||||
bool result = send_connect_packet(handle);
|
||||
if (result == false) {
|
||||
DEBUG_LOG("Sending connect packet failed, running error handler");
|
||||
bool free_handle = handle->error_handler(handle, MQTT_Error_Broker_Disconnected);
|
||||
if (free_handle) {
|
||||
mqtt_free(handle);
|
||||
}
|
||||
DEBUG_LOG("Sending connect packet failed...");
|
||||
close(handle->sock);
|
||||
}
|
||||
}
|
||||
|
||||
MQTTHandle *mqtt_connect(MQTTConfig *config, MQTTErrorHandler callback) {
|
||||
MQTTHandle *mqtt_connect(MQTTConfig *config, MQTTEventHandler callback, void *context, MQTTErrorHandler error_callback) {
|
||||
MQTTHandle *handle = calloc(sizeof(struct _MQTTHandle), 1);
|
||||
initialize_platform(handle);
|
||||
|
||||
|
@ -196,32 +190,37 @@ MQTTHandle *mqtt_connect(MQTTConfig *config, MQTTErrorHandler callback) {
|
|||
}
|
||||
|
||||
handle->config = config;
|
||||
handle->error_handler = callback;
|
||||
handle->error_handler = error_callback;
|
||||
|
||||
_mqtt_connect(handle);
|
||||
_mqtt_connect(handle, callback, context);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
MQTTStatus mqtt_reconnect(MQTTHandle *handle) {
|
||||
MQTTStatus mqtt_reconnect(MQTTHandle *handle, MQTTEventHandler callback, void *context) {
|
||||
if (handle->reader_alive) {
|
||||
DEBUG_LOG("Closing old connection");
|
||||
close(handle->sock);
|
||||
join_read_task(handle);
|
||||
}
|
||||
_mqtt_connect(handle);
|
||||
|
||||
// TODO: re-submit unacknowledged packages with QoS > 0
|
||||
// TODO: clear waiting packets
|
||||
// TODO: re-subscribe all subscriptions
|
||||
|
||||
_mqtt_connect(handle, callback, context);
|
||||
|
||||
return MQTT_STATUS_OK;
|
||||
}
|
||||
|
||||
MQTTStatus mqtt_subscribe(MQTTHandle *handle, char *topic, MQTTEventHandler callback) {
|
||||
MQTTStatus mqtt_subscribe(MQTTHandle *handle, char *topic, MQTTPublishEventHandler callback) {
|
||||
if (!handle->reader_alive) {
|
||||
handle->error_handler(handle, MQTT_Error_Connection_Reset);
|
||||
return MQTT_STATUS_ERROR;
|
||||
}
|
||||
add_subscription(handle, topic, callback);
|
||||
return (send_subscribe_packet(handle, topic) ? MQTT_STATUS_OK : MQTT_STATUS_ERROR);
|
||||
// TODO: add subscription to list
|
||||
}
|
||||
|
||||
MQTTStatus mqtt_unsubscribe(MQTTHandle *handle, char *topic) {
|
||||
|
@ -229,8 +228,8 @@ MQTTStatus mqtt_unsubscribe(MQTTHandle *handle, char *topic) {
|
|||
handle->error_handler(handle, MQTT_Error_Connection_Reset);
|
||||
return MQTT_STATUS_ERROR;
|
||||
}
|
||||
remove_subscription(handle, topic);
|
||||
return (send_unsubscribe_packet(handle, topic) ? MQTT_STATUS_OK : MQTT_STATUS_ERROR);
|
||||
// TODO: remove subscription from list
|
||||
}
|
||||
|
||||
MQTTStatus mqtt_publish(MQTTHandle *handle, char *topic, char *payload, MQTTQosLevel qos_level) {
|
||||
|
@ -241,13 +240,16 @@ MQTTStatus mqtt_publish(MQTTHandle *handle, char *topic, char *payload, MQTTQosL
|
|||
return (send_publish_packet(handle, topic, payload, qos_level) ? MQTT_STATUS_OK : MQTT_STATUS_ERROR);
|
||||
}
|
||||
|
||||
MQTTStatus mqtt_disconnect(MQTTHandle *handle) {
|
||||
DEBUG_LOG("Disconnecting...")
|
||||
MQTTStatus mqtt_disconnect(MQTTHandle *handle, MQTTEventHandler callback, void *callback_context) {
|
||||
send_disconnect_packet(handle);
|
||||
if (close(handle->sock)) {
|
||||
return MQTT_STATUS_ERROR;
|
||||
}
|
||||
join_read_task(handle);
|
||||
mqtt_free(handle);
|
||||
|
||||
if (callback) {
|
||||
callback(NULL, callback_context);
|
||||
}
|
||||
return MQTT_STATUS_OK;
|
||||
}
|
||||
|
|
13
src/mqtt.h
13
src/mqtt.h
|
@ -43,7 +43,10 @@ typedef enum {
|
|||
typedef bool (*MQTTErrorHandler)(MQTTHandle *handle, MQTTErrorCode code);
|
||||
|
||||
/** Event handler callback */
|
||||
typedef void (*MQTTEventHandler)(MQTTHandle *handle, char *topic, char *payload);
|
||||
typedef void (*MQTTEventHandler)(MQTTHandle *handle, void *context);
|
||||
|
||||
/** publish event callback */
|
||||
typedef void (*MQTTPublishEventHandler)(MQTTHandle *handle, char *topic, char *payload);
|
||||
|
||||
/**
|
||||
* Connect to MQTT broker
|
||||
|
@ -56,7 +59,7 @@ typedef void (*MQTTEventHandler)(MQTTHandle *handle, char *topic, char *payload)
|
|||
* the handler is in charge of freeing the handle by returning true
|
||||
* or re-trying by changing settings and calling mqtt_reconnect() and returning false
|
||||
*/
|
||||
MQTTHandle *mqtt_connect(MQTTConfig *config, MQTTErrorHandler callback);
|
||||
MQTTHandle *mqtt_connect(MQTTConfig *config, MQTTEventHandler callback, void *callback_context, MQTTErrorHandler error_callback);
|
||||
|
||||
/**
|
||||
* Re-Connect to MQTT broker
|
||||
|
@ -70,7 +73,7 @@ MQTTHandle *mqtt_connect(MQTTConfig *config, MQTTErrorHandler callback);
|
|||
* @param handle: MQTT Handle from `mqtt_connect`
|
||||
* @returns: Status code
|
||||
*/
|
||||
MQTTStatus mqtt_reconnect(MQTTHandle *handle);
|
||||
MQTTStatus mqtt_reconnect(MQTTHandle *handle, MQTTEventHandler callback, void *callback_context);
|
||||
|
||||
/**
|
||||
* Subscribe to a topic
|
||||
|
@ -80,7 +83,7 @@ MQTTStatus mqtt_reconnect(MQTTHandle *handle);
|
|||
* @param callback: Callback function to call when receiving something for that topic
|
||||
* @returns: Status code
|
||||
*/
|
||||
MQTTStatus mqtt_subscribe(MQTTHandle *handle, char *topic, MQTTEventHandler callback);
|
||||
MQTTStatus mqtt_subscribe(MQTTHandle *handle, char *topic, MQTTPublishEventHandler callback);
|
||||
|
||||
/**
|
||||
* Un-Subscribe from a topic
|
||||
|
@ -110,6 +113,6 @@ MQTTStatus mqtt_publish(MQTTHandle *handle, char *topic, char *payload, MQTTQosL
|
|||
* @attention: do not use the handle after calling this function,
|
||||
* all resources will be freed, this handle is now invalid!
|
||||
*/
|
||||
MQTTStatus mqtt_disconnect(MQTTHandle *handle);
|
||||
MQTTStatus mqtt_disconnect(MQTTHandle *handle, MQTTEventHandler callback, void *callback_context);
|
||||
|
||||
#endif /* mqtt_h__included */
|
||||
|
|
Loading…
Reference in a new issue