blob: dc73977cc00518caeb934ae0af747b0e5da6009f [file] [log] [blame]
/*
* Copyright (c) 2016 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mqtt_pack.h"
#include "MQTTPacket.h"
#include "MQTTConnect.h"
#include "MQTTPublish.h"
#include "MQTTSubscribe.h"
#include "MQTTUnsubscribe.h"
#include <errno.h>
#include <string.h>
/* From MQTTConnectClient.c */
extern int MQTTSerialize_zero(unsigned char *buf, int buflen,
unsigned char packettype);
static void str_to_buf(struct app_buf_t *buf, char *str);
int mqtt_msg_topic(struct mqtt_msg_t *msg, char *str)
{
str_to_buf(&msg->topic, str);
return 0;
}
int mqtt_msg_payload_str(struct mqtt_msg_t *msg, char *str)
{
str_to_buf(&msg->payload, str);
return 0;
}
int mqtt_next_pktid(struct mqtt_client_ctx_t *mqtt_ctx, uint16_t *pkt_id)
{
*pkt_id = 1 + mqtt_ctx->pkt_id++;
return 0;
}
int mqtt_pack_msg(struct app_buf_t *buf, enum mqtt_packet type, uint16_t pkt_id,
int dup)
{
int rc;
switch (type) {
case MQTT_PUBACK:
rc = MQTTSerialize_puback(buf->buf, buf->size, pkt_id);
break;
case MQTT_PUBCOMP:
rc = MQTTSerialize_pubcomp(buf->buf, buf->size, pkt_id);
break;
case MQTT_PUBREC:
rc = MQTTSerialize_ack(buf->buf, buf->size, MQTT_PUBREC,
dup, pkt_id);
break;
case MQTT_PUBREL:
rc = MQTTSerialize_pubrel(buf->buf, buf->size, dup, pkt_id);
break;
default:
buf->length = 0;
return -EINVAL;
}
if (rc <= 0) {
return -EINVAL;
}
buf->length = rc;
return 0;
}
int mqtt_pack_subscribe(struct app_buf_t *buf, int dup, uint16_t pkt_id,
char *topic, enum mqtt_qos qos)
{
MQTTString topic_str = MQTTString_initializer;
int rc;
topic_str.cstring = topic;
rc = MQTTSerialize_subscribe(buf->buf, buf->size, dup, pkt_id, 1,
&topic_str, (int *)&qos);
if (rc <= 0) {
return -EINVAL;
}
buf->length = rc;
return 0;
}
int mqtt_pack_unsubscribe(struct app_buf_t *buf, int dup, uint16_t pkt_id,
char *topic)
{
MQTTString topic_str = MQTTString_initializer;
int rc;
topic_str.cstring = topic;
rc = MQTTSerialize_unsubscribe(buf->buf, buf->size, dup, pkt_id, 1,
&topic_str);
if (rc <= 0) {
return -EINVAL;
}
buf->length = rc;
return 0;
}
int mqtt_unpack_suback(struct app_buf_t *buf, uint16_t *pkt_id,
int *granted_qos)
{
int sub_count;
int rc;
rc = MQTTDeserialize_suback(pkt_id, 1, &sub_count, granted_qos,
buf->buf, buf->length);
if (rc != 1) {
return -EINVAL;
}
return 0;
}
int mqtt_unpack_unsuback(struct app_buf_t *buf, uint16_t *pkt_id)
{
int rc;
rc = MQTTDeserialize_unsuback(pkt_id, buf->buf, buf->length);
if (rc != 1) {
return -EINVAL;
}
return 0;
}
static int paho_mqtt_ctx(MQTTPacket_connectData *paho,
struct mqtt_client_ctx_t *mqtt_ctx)
{
paho->MQTTVersion = mqtt_ctx->proto;
paho->clientID.cstring = (char *)mqtt_ctx->client_id;
paho->keepAliveInterval = mqtt_ctx->keep_alive;
paho->cleansession = mqtt_ctx->clean_session;
paho->username.cstring = (char *)mqtt_ctx->username;
paho->password.cstring = (char *)mqtt_ctx->pass;
paho->willFlag = mqtt_ctx->will_enabled;
paho->will.message.cstring = (char *)mqtt_ctx->will_payload;
paho->will.retained = mqtt_ctx->will_retained;
paho->will.topicName.cstring = (char *)mqtt_ctx->will_topic;
paho->will.qos = mqtt_ctx->will_qos;
return 0;
}
int mqtt_pack_connect(struct app_buf_t *buf,
struct mqtt_client_ctx_t *mqtt_ctx)
{
MQTTPacket_connectData paho = MQTTPacket_connectData_initializer;
int rc;
paho_mqtt_ctx(&paho, mqtt_ctx);
rc = MQTTSerialize_connect(buf->buf, buf->size, &paho);
if (rc <= 0) {
return -EINVAL;
}
buf->length = rc;
return 0;
}
int mqtt_unpack_connack(struct app_buf_t *buf, int *session, int *connect_ack)
{
uint8_t _session;
uint8_t _conn_ack;
int rc;
rc = MQTTDeserialize_connack(&_session, &_conn_ack,
buf->buf, buf->length);
if (rc != 1) {
return -EINVAL;
}
*session = _session;
*connect_ack = _conn_ack;
return 0;
}
int mqtt_pack_disconnect(struct app_buf_t *buf)
{
int rc;
rc = MQTTSerialize_disconnect(buf->buf, buf->size);
if (rc <= 0) {
return -EINVAL;
}
buf->length = rc;
return 0;
}
int mqtt_pack_publish(struct app_buf_t *buf, struct mqtt_msg_t *msg)
{
MQTTString topic_str = MQTTString_initializer;
int rc;
topic_str.cstring = msg->topic.buf;
rc = MQTTSerialize_publish(buf->buf, buf->size,
msg->dup, msg->qos, msg->retained,
msg->pkt_id, topic_str,
msg->payload.buf, msg->payload.length);
if (rc <= 0) {
return -EINVAL;
}
buf->length = rc;
return 0;
}
int mqtt_unpack_publish(struct app_buf_t *buf, struct mqtt_msg_t *msg)
{
MQTTString topic_str = MQTTString_initializer;
uint8_t dup;
uint8_t retained;
int payload_len;
int qos;
int rc;
rc = MQTTDeserialize_publish(&dup, &qos, &retained,
&msg->pkt_id, &topic_str,
&msg->payload.buf, &payload_len,
buf->buf, buf->length);
if (rc <= 0) {
return -EINVAL;
}
msg->dup = dup;
msg->qos = qos;
msg->retained = retained;
msg->payload.length = payload_len;
msg->payload.size = msg->payload.length;
msg->topic.buf = topic_str.lenstring.data;
msg->topic.length = topic_str.lenstring.len;
msg->topic.size = msg->topic.length;
return 0;
}
int mqtt_unpack_ack(struct app_buf_t *buf, uint8_t *pkt_type,
uint8_t *dup, uint16_t *rcv_pkt_id)
{
int rc;
rc = MQTTDeserialize_ack(pkt_type, dup, rcv_pkt_id, buf->buf,
buf->length);
if (rc != 1) {
return -EINVAL;
}
return 0;
}
int mqtt_pack_pubrel(struct app_buf_t *buf, int dup, uint16_t pkt_id)
{
int rc;
rc = MQTTSerialize_pubrel(buf->buf, buf->size, dup, pkt_id);
if (rc <= 0) {
return -EINVAL;
}
buf->length = rc;
return 0;
}
int mqtt_pack_pingreq(struct app_buf_t *buf)
{
int rc;
rc = MQTTSerialize_pingreq(buf->buf, buf->size);
if (rc <= 0) {
return -EINVAL;
}
buf->length = rc;
return 0;
}
int mqtt_pack_pingresp(struct app_buf_t *buf)
{
int rc;
rc = MQTTSerialize_zero(buf->buf, buf->size, MQTT_PINGRESP);
if (rc <= 0) {
return -EINVAL;
}
buf->length = rc;
return 0;
}
static void str_to_buf(struct app_buf_t *buf, char *str)
{
buf->buf = str;
buf->length = strlen(str) + 1;
buf->size = buf->length;
}