move dirs
This commit is contained in:
		
							
								
								
									
										538
									
								
								Internet/MQTT/MQTTClient.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										538
									
								
								Internet/MQTT/MQTTClient.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,538 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
#include "MQTTClient.h"
 | 
			
		||||
//#include <terminal_io.h>
 | 
			
		||||
 | 
			
		||||
   
 | 
			
		||||
void NewMessageData(MessageData* md, MQTTString* aTopicName, MQTTMessage* aMessgage)
 | 
			
		||||
{
 | 
			
		||||
  md->topicName = aTopicName;
 | 
			
		||||
  md->message = aMessgage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t getNextPacketId(Client *c) 
 | 
			
		||||
{
 | 
			
		||||
  return c->next_packetid = (c->next_packetid == MAX_PACKET_ID) ? 1 : c->next_packetid + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t sendPacket(Client* c, int32_t length, Timer* timer)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = FAILURE, sent = 0;
 | 
			
		||||
    
 | 
			
		||||
  while (sent < length && !expired(timer))
 | 
			
		||||
  {
 | 
			
		||||
    rc = c->ipstack->mqttwrite(c->ipstack, &c->buf[sent], length, left_ms(timer));
 | 
			
		||||
 | 
			
		||||
    if (rc < 0)  // there was an error writing the data
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    sent += rc;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  if (sent == length)
 | 
			
		||||
  {
 | 
			
		||||
    countdown(&c->ping_timer, c->keepAliveInterval); // record the fact that we have SUCCESSSfully sent the packet
 | 
			
		||||
    rc = SUCCESSS;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
    rc = FAILURE;
 | 
			
		||||
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void MQTTClient(Client* c, Network* network, uint32_t command_timeout_ms, uint8_t* buf, size_t buf_size, uint8_t* readbuf, size_t readbuf_size)
 | 
			
		||||
{
 | 
			
		||||
  c->ipstack = network;
 | 
			
		||||
    
 | 
			
		||||
  for (int32_t i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
 | 
			
		||||
    c->messageHandlers[i].topicFilter = 0;
 | 
			
		||||
  
 | 
			
		||||
  c->command_timeout_ms = command_timeout_ms;
 | 
			
		||||
  c->buf = buf;
 | 
			
		||||
  c->buf_size = buf_size;
 | 
			
		||||
  c->readbuf = readbuf;
 | 
			
		||||
  c->readbuf_size = readbuf_size;
 | 
			
		||||
  c->isconnected = 0;
 | 
			
		||||
  c->ping_outstanding = 0;
 | 
			
		||||
  c->defaultMessageHandler = NULL;
 | 
			
		||||
 | 
			
		||||
  InitTimer(&c->ping_timer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t decodePacket(Client* c, int32_t* value, int32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t i;
 | 
			
		||||
  int32_t multiplier = 1;
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
  const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
 | 
			
		||||
 | 
			
		||||
  *value = 0;
 | 
			
		||||
  do
 | 
			
		||||
  {
 | 
			
		||||
    int32_t rc = MQTTPACKET_READ_ERROR;
 | 
			
		||||
 | 
			
		||||
    if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
 | 
			
		||||
    {
 | 
			
		||||
      rc = MQTTPACKET_READ_ERROR; /* bad data */
 | 
			
		||||
        goto exit;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rc = c->ipstack->mqttread(c->ipstack, &i, 1, timeout);
 | 
			
		||||
     
 | 
			
		||||
    if (rc != 1)
 | 
			
		||||
      goto exit;
 | 
			
		||||
 
 | 
			
		||||
    *value += (i & 127) * multiplier;
 | 
			
		||||
    multiplier *= 128;
 | 
			
		||||
  } while ((i & 128) != 0);
 | 
			
		||||
exit:
 | 
			
		||||
    return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t readPacket(Client* c, Timer* timer) 
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = FAILURE;
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
  int32_t rem_len = 0;
 | 
			
		||||
 | 
			
		||||
  /* 1. read the header byte.  This has the packet type in it */
 | 
			
		||||
  if (c->ipstack->mqttread(c->ipstack, c->readbuf, 1, left_ms(timer)) != 1)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  len = 1;
 | 
			
		||||
  /* 2. read the remaining length.  This is variable in itself */
 | 
			
		||||
  decodePacket(c, &rem_len, left_ms(timer));
 | 
			
		||||
  len += MQTTPacket_encode(c->readbuf + 1, rem_len); /* put the original remaining length back into the buffer */
 | 
			
		||||
 | 
			
		||||
  /* 3. read the rest of the buffer using a callback to supply the rest of the data */
 | 
			
		||||
  if (rem_len > 0 && (c->ipstack->mqttread(c->ipstack, c->readbuf + len, rem_len, left_ms(timer)) != rem_len))
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  header.byte = c->readbuf[0];
 | 
			
		||||
  rc = header.bits.type;
 | 
			
		||||
exit:
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// assume topic filter and name is in correct format
 | 
			
		||||
// # can only be at end
 | 
			
		||||
// + and # can only be next to separator
 | 
			
		||||
char isTopicMatched(char* topicFilter, MQTTString* topicName)
 | 
			
		||||
{
 | 
			
		||||
  char* curf = topicFilter;
 | 
			
		||||
  char* curn = topicName->lenstring.data;
 | 
			
		||||
  char* curn_end = curn + topicName->lenstring.len;
 | 
			
		||||
    
 | 
			
		||||
  while (*curf && curn < curn_end)
 | 
			
		||||
  {
 | 
			
		||||
    if (*curn == '/' && *curf != '/')
 | 
			
		||||
      break;
 | 
			
		||||
  
 | 
			
		||||
    if (*curf != '+' && *curf != '#' && *curf != *curn)
 | 
			
		||||
      break;
 | 
			
		||||
  
 | 
			
		||||
    if (*curf == '+')
 | 
			
		||||
    {   // skip until we meet the next separator, or end of string
 | 
			
		||||
      char* nextpos = curn + 1;
 | 
			
		||||
  
 | 
			
		||||
      while (nextpos < curn_end && *nextpos != '/')
 | 
			
		||||
        nextpos = ++curn + 1;
 | 
			
		||||
    }
 | 
			
		||||
    else if (*curf == '#')
 | 
			
		||||
      curn = curn_end - 1;    // skip until end of string
 | 
			
		||||
  
 | 
			
		||||
    curf++;
 | 
			
		||||
    curn++;
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  return (curn == curn_end) && (*curf == '\0');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t deliverMessage(Client* c, MQTTString* topicName, MQTTMessage* message)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = FAILURE;
 | 
			
		||||
 | 
			
		||||
  // we have to find the right message handler - indexed by topic
 | 
			
		||||
  for (int32_t i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
 | 
			
		||||
  {
 | 
			
		||||
    if (c->messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(topicName, (char*)c->messageHandlers[i].topicFilter) ||
 | 
			
		||||
        isTopicMatched((char*)c->messageHandlers[i].topicFilter, topicName)))
 | 
			
		||||
    {
 | 
			
		||||
      if (c->messageHandlers[i].fp != NULL)
 | 
			
		||||
      {
 | 
			
		||||
        MessageData md;
 | 
			
		||||
        NewMessageData(&md, topicName, message);
 | 
			
		||||
        c->messageHandlers[i].fp(&md);
 | 
			
		||||
        rc = SUCCESSS;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
  if (rc == FAILURE && c->defaultMessageHandler != NULL) 
 | 
			
		||||
  {
 | 
			
		||||
    MessageData md;
 | 
			
		||||
    NewMessageData(&md, topicName, message);
 | 
			
		||||
    c->defaultMessageHandler(&md);
 | 
			
		||||
    rc = SUCCESSS;
 | 
			
		||||
  }   
 | 
			
		||||
    
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t keepalive(Client* c)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = FAILURE;
 | 
			
		||||
  
 | 
			
		||||
  if (c->keepAliveInterval == 0)
 | 
			
		||||
  {
 | 
			
		||||
    rc = SUCCESSS;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (expired(&c->ping_timer))
 | 
			
		||||
  {
 | 
			
		||||
    if (!c->ping_outstanding)
 | 
			
		||||
    {
 | 
			
		||||
      Timer timer;
 | 
			
		||||
      InitTimer(&timer);
 | 
			
		||||
      countdown_ms(&timer, 1000);
 | 
			
		||||
      int32_t len = MQTTSerialize_pingreq(c->buf, c->buf_size);
 | 
			
		||||
      
 | 
			
		||||
      if (len > 0 && (rc = sendPacket(c, len, &timer)) == SUCCESSS) // send the ping packet
 | 
			
		||||
        c->ping_outstanding = 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t cycle(Client* c, Timer* timer)
 | 
			
		||||
{
 | 
			
		||||
  // read the socket, see what work is due
 | 
			
		||||
  uint16_t packet_type = readPacket(c, timer);
 | 
			
		||||
    
 | 
			
		||||
  int32_t len = 0, rc = SUCCESSS;
 | 
			
		||||
 | 
			
		||||
  switch (packet_type)
 | 
			
		||||
  {
 | 
			
		||||
    case CONNACK:
 | 
			
		||||
    case PUBACK:
 | 
			
		||||
    case SUBACK:
 | 
			
		||||
      break;
 | 
			
		||||
    case PUBLISH:
 | 
			
		||||
      {
 | 
			
		||||
        MQTTString topicName;
 | 
			
		||||
        MQTTMessage msg;
 | 
			
		||||
      
 | 
			
		||||
        if (MQTTDeserialize_publish((uint8_t*)&msg.dup, (uint8_t*)&msg.qos, (uint8_t*)&msg.retained, (uint16_t*)&msg.id, &topicName,
 | 
			
		||||
               (uint8_t**)&msg.payload, (int32_t*)&msg.payloadlen, c->readbuf, c->readbuf_size) != 1)
 | 
			
		||||
          goto exit;
 | 
			
		||||
          
 | 
			
		||||
        deliverMessage(c, &topicName, &msg);
 | 
			
		||||
      
 | 
			
		||||
        if (msg.qos != QOS0)
 | 
			
		||||
        {
 | 
			
		||||
          if (msg.qos == QOS1)
 | 
			
		||||
            len = MQTTSerialize_ack(c->buf, c->buf_size, PUBACK, 0, msg.id);
 | 
			
		||||
          else if (msg.qos == QOS2)
 | 
			
		||||
            len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREC, 0, msg.id);
 | 
			
		||||
  
 | 
			
		||||
          if (len <= 0)
 | 
			
		||||
            rc = FAILURE;
 | 
			
		||||
          else
 | 
			
		||||
            rc = sendPacket(c, len, timer);
 | 
			
		||||
  
 | 
			
		||||
          if (rc == FAILURE)
 | 
			
		||||
            goto exit; // there was a problem
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    case PUBREC:
 | 
			
		||||
      {
 | 
			
		||||
        uint16_t mypacketid;
 | 
			
		||||
        uint8_t dup, type;
 | 
			
		||||
 | 
			
		||||
        if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
 | 
			
		||||
          rc = FAILURE;
 | 
			
		||||
        else if ((len = MQTTSerialize_ack(c->buf, c->buf_size, PUBREL, 0, mypacketid)) <= 0)
 | 
			
		||||
          rc = FAILURE;
 | 
			
		||||
        else if ((rc = sendPacket(c, len, timer)) != SUCCESSS) // send the PUBREL packet
 | 
			
		||||
          rc = FAILURE; // there was a problem
 | 
			
		||||
        
 | 
			
		||||
        if (rc == FAILURE)
 | 
			
		||||
          goto exit; // there was a problem
 | 
			
		||||
    
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    case PUBCOMP:
 | 
			
		||||
      break;
 | 
			
		||||
    case PINGRESP:
 | 
			
		||||
      c->ping_outstanding = 0;
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
  keepalive(c);
 | 
			
		||||
exit:
 | 
			
		||||
  if (rc == SUCCESSS)
 | 
			
		||||
    rc = packet_type;
 | 
			
		||||
  
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t MQTTYield(Client* c, int32_t timeout_ms)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = SUCCESSS;
 | 
			
		||||
  Timer timer;
 | 
			
		||||
 | 
			
		||||
  InitTimer(&timer);    
 | 
			
		||||
  countdown_ms(&timer, timeout_ms);
 | 
			
		||||
    
 | 
			
		||||
  while (!expired(&timer))
 | 
			
		||||
  {
 | 
			
		||||
    if (cycle(c, &timer) == FAILURE)
 | 
			
		||||
    {
 | 
			
		||||
      rc = FAILURE;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// only used in single-threaded mode where one command at a time is in process
 | 
			
		||||
int32_t waitfor(Client* c, int32_t packet_type, Timer* timer)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = FAILURE;
 | 
			
		||||
    
 | 
			
		||||
  do
 | 
			
		||||
  {
 | 
			
		||||
    if (expired(timer)) 
 | 
			
		||||
      break; // we timed out
 | 
			
		||||
  }
 | 
			
		||||
  while ((rc = cycle(c, timer)) != packet_type);  
 | 
			
		||||
    
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t MQTTConnect(Client* c, MQTTPacket_connectData* options)
 | 
			
		||||
{
 | 
			
		||||
  Timer connect_timer;
 | 
			
		||||
  int32_t rc = FAILURE;
 | 
			
		||||
  MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
    
 | 
			
		||||
  InitTimer(&connect_timer);
 | 
			
		||||
  countdown_ms(&connect_timer, c->command_timeout_ms);
 | 
			
		||||
 | 
			
		||||
  if (c->isconnected) // don't send connect packet again if we are already connected
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  if (options == 0)
 | 
			
		||||
    options = &default_options; // set default options if none were supplied
 | 
			
		||||
    
 | 
			
		||||
  c->keepAliveInterval = options->keepAliveInterval;
 | 
			
		||||
  countdown(&c->ping_timer, c->keepAliveInterval);
 | 
			
		||||
  
 | 
			
		||||
  if ((len = MQTTSerialize_connect(c->buf, c->buf_size, options)) <= 0)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  if ((rc = sendPacket(c, len, &connect_timer)) != SUCCESSS)  // send the connect packet
 | 
			
		||||
    goto exit; // there was a problem
 | 
			
		||||
    
 | 
			
		||||
  // this will be a blocking call, wait for the connack
 | 
			
		||||
  if (waitfor(c, CONNACK, &connect_timer) == CONNACK)
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t connack_rc = 255;
 | 
			
		||||
    int8_t sessionPresent = 0;
 | 
			
		||||
 | 
			
		||||
    if (MQTTDeserialize_connack((uint8_t*)&sessionPresent, &connack_rc, c->readbuf, c->readbuf_size) == 1)
 | 
			
		||||
      rc = connack_rc;
 | 
			
		||||
    else
 | 
			
		||||
      rc = FAILURE;
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
    rc = FAILURE;
 | 
			
		||||
    
 | 
			
		||||
exit:
 | 
			
		||||
  if (rc == SUCCESSS)
 | 
			
		||||
    c->isconnected = 1;
 | 
			
		||||
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTSubscribe(Client* c, const char* topicFilter, enum QoS qos, messageHandler messageHandler)
 | 
			
		||||
{ 
 | 
			
		||||
  int32_t rc = FAILURE;  
 | 
			
		||||
  Timer timer;
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
  MQTTString topic = MQTTString_initializer;
 | 
			
		||||
  topic.cstring = (char *)topicFilter;
 | 
			
		||||
    
 | 
			
		||||
  InitTimer(&timer);
 | 
			
		||||
  countdown_ms(&timer, c->command_timeout_ms);
 | 
			
		||||
 | 
			
		||||
  if (!c->isconnected)
 | 
			
		||||
    goto exit;
 | 
			
		||||
    
 | 
			
		||||
  len = MQTTSerialize_subscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic, (int32_t*)&qos);
 | 
			
		||||
  
 | 
			
		||||
  if (len <= 0)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  if ((rc = sendPacket(c, len, &timer)) != SUCCESSS) // send the subscribe packet
 | 
			
		||||
    goto exit;             // there was a problem
 | 
			
		||||
    
 | 
			
		||||
  if (waitfor(c, SUBACK, &timer) == SUBACK)      // wait for suback 
 | 
			
		||||
  {
 | 
			
		||||
    int32_t count = 0, grantedQoS = -1;
 | 
			
		||||
    uint16_t mypacketid;
 | 
			
		||||
    
 | 
			
		||||
    if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, c->readbuf, c->readbuf_size) == 1)
 | 
			
		||||
      rc = grantedQoS; // 0, 1, 2 or 0x80 
 | 
			
		||||
 | 
			
		||||
    if (rc != 0x80)
 | 
			
		||||
    {
 | 
			
		||||
      for (int32_t i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
 | 
			
		||||
      {
 | 
			
		||||
        if (c->messageHandlers[i].topicFilter == 0)
 | 
			
		||||
        {
 | 
			
		||||
          c->messageHandlers[i].topicFilter = topicFilter;
 | 
			
		||||
          c->messageHandlers[i].fp = messageHandler;
 | 
			
		||||
          rc = 0;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else 
 | 
			
		||||
    rc = FAILURE;
 | 
			
		||||
        
 | 
			
		||||
exit:
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t MQTTUnsubscribe(Client* c, const char* topicFilter)
 | 
			
		||||
{   
 | 
			
		||||
  int32_t rc = FAILURE;
 | 
			
		||||
  Timer timer;    
 | 
			
		||||
  MQTTString topic = MQTTString_initializer;
 | 
			
		||||
  topic.cstring = (char *)topicFilter;
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
 | 
			
		||||
  InitTimer(&timer);
 | 
			
		||||
  countdown_ms(&timer, c->command_timeout_ms);
 | 
			
		||||
    
 | 
			
		||||
  if (!c->isconnected)
 | 
			
		||||
    goto exit;
 | 
			
		||||
    
 | 
			
		||||
  if ((len = MQTTSerialize_unsubscribe(c->buf, c->buf_size, 0, getNextPacketId(c), 1, &topic)) <= 0)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  if ((rc = sendPacket(c, len, &timer)) != SUCCESSS) // send the subscribe packet
 | 
			
		||||
    goto exit; // there was a problem
 | 
			
		||||
    
 | 
			
		||||
  if (waitfor(c, UNSUBACK, &timer) == UNSUBACK)
 | 
			
		||||
  {
 | 
			
		||||
    uint16_t mypacketid;  // should be the same as the packetid above
 | 
			
		||||
    
 | 
			
		||||
    if (MQTTDeserialize_unsuback(&mypacketid, c->readbuf, c->readbuf_size) == 1)
 | 
			
		||||
      rc = 0; 
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
    rc = FAILURE;
 | 
			
		||||
    
 | 
			
		||||
exit:
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t MQTTPublish(Client* c, const char* topicName, MQTTMessage* message)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = FAILURE;
 | 
			
		||||
  Timer timer;   
 | 
			
		||||
  MQTTString topic = MQTTString_initializer;
 | 
			
		||||
  topic.cstring = (char *)topicName;
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
 | 
			
		||||
  InitTimer(&timer);
 | 
			
		||||
  countdown_ms(&timer, c->command_timeout_ms);
 | 
			
		||||
    
 | 
			
		||||
  if (!c->isconnected)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  if (message->qos == QOS1 || message->qos == QOS2)
 | 
			
		||||
    message->id = getNextPacketId(c);
 | 
			
		||||
    
 | 
			
		||||
  len = MQTTSerialize_publish(c->buf, c->buf_size, 0, message->qos, message->retained, message->id, 
 | 
			
		||||
        topic, (uint8_t*)message->payload, message->payloadlen);
 | 
			
		||||
    
 | 
			
		||||
  if (len <= 0)
 | 
			
		||||
    goto exit;
 | 
			
		||||
  
 | 
			
		||||
  if ((rc = sendPacket(c, len, &timer)) != SUCCESSS) // send the subscribe packet
 | 
			
		||||
    goto exit; // there was a problem
 | 
			
		||||
    
 | 
			
		||||
  if (message->qos == QOS1)
 | 
			
		||||
  {
 | 
			
		||||
    if (waitfor(c, PUBACK, &timer) == PUBACK)
 | 
			
		||||
    {
 | 
			
		||||
      uint16_t mypacketid;
 | 
			
		||||
      uint8_t dup, type;
 | 
			
		||||
 | 
			
		||||
      if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
 | 
			
		||||
        rc = FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
      rc = FAILURE;
 | 
			
		||||
  }
 | 
			
		||||
  else if (message->qos == QOS2)
 | 
			
		||||
  {
 | 
			
		||||
    if (waitfor(c, PUBCOMP, &timer) == PUBCOMP)
 | 
			
		||||
    {
 | 
			
		||||
      uint16_t mypacketid;
 | 
			
		||||
      uint8_t dup, type;
 | 
			
		||||
    
 | 
			
		||||
      if (MQTTDeserialize_ack(&type, &dup, &mypacketid, c->readbuf, c->readbuf_size) != 1)
 | 
			
		||||
        rc = FAILURE;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
      rc = FAILURE;
 | 
			
		||||
  }
 | 
			
		||||
    
 | 
			
		||||
exit:
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTDisconnect(Client* c)
 | 
			
		||||
{  
 | 
			
		||||
  int32_t rc = FAILURE;
 | 
			
		||||
  Timer timer;     // we might wait for incomplete incoming publishes to complete
 | 
			
		||||
  int32_t len = MQTTSerialize_disconnect(c->buf, c->buf_size);
 | 
			
		||||
 | 
			
		||||
  InitTimer(&timer);
 | 
			
		||||
  countdown_ms(&timer, c->command_timeout_ms);
 | 
			
		||||
 | 
			
		||||
  if (len > 0)
 | 
			
		||||
    rc = sendPacket(c, len, &timer);            // send the disconnect packet
 | 
			
		||||
        
 | 
			
		||||
  c->isconnected = 0;
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										104
									
								
								Internet/MQTT/MQTTClient.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								Internet/MQTT/MQTTClient.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef __MQTT_CLIENT_C_
 | 
			
		||||
#define __MQTT_CLIENT_C_
 | 
			
		||||
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include "mqtt_interface.h" //Platform specific implementation header file
 | 
			
		||||
#include "stdio.h"
 | 
			
		||||
   
 | 
			
		||||
#define MAX_PACKET_ID 65535
 | 
			
		||||
#define MAX_MESSAGE_HANDLERS 5
 | 
			
		||||
 | 
			
		||||
enum QoS 
 | 
			
		||||
{ 
 | 
			
		||||
  QOS0,
 | 
			
		||||
  QOS1, 
 | 
			
		||||
  QOS2 
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// all failure return codes must be negative
 | 
			
		||||
enum returnCode
 | 
			
		||||
{ 
 | 
			
		||||
  BUFFER_OVERFLOW = -2, 
 | 
			
		||||
  FAILURE = -1, 
 | 
			
		||||
  SUCCESSS = 0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void NewTimer(Timer*);
 | 
			
		||||
 | 
			
		||||
typedef struct MQTTMessage MQTTMessage;
 | 
			
		||||
 | 
			
		||||
typedef struct MessageData MessageData;
 | 
			
		||||
 | 
			
		||||
struct MQTTMessage
 | 
			
		||||
{
 | 
			
		||||
  enum QoS qos;
 | 
			
		||||
  char retained;
 | 
			
		||||
  char dup;
 | 
			
		||||
  uint16_t id;
 | 
			
		||||
  void *payload;
 | 
			
		||||
  size_t payloadlen;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct MessageData
 | 
			
		||||
{
 | 
			
		||||
  MQTTMessage* message;
 | 
			
		||||
  MQTTString* topicName;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef void (*messageHandler)(MessageData*);
 | 
			
		||||
 | 
			
		||||
typedef struct Client Client;
 | 
			
		||||
 | 
			
		||||
int32_t MQTTConnect (Client*, MQTTPacket_connectData*);
 | 
			
		||||
int32_t MQTTPublish (Client*, const char*, MQTTMessage*);
 | 
			
		||||
int32_t MQTTSubscribe (Client*, const char*, enum QoS, messageHandler);
 | 
			
		||||
int32_t MQTTUnsubscribe (Client*, const char*);
 | 
			
		||||
int32_t MQTTDisconnect (Client*);
 | 
			
		||||
int32_t MQTTYield (Client*, int32_t);
 | 
			
		||||
 | 
			
		||||
void setDefaultMessageHandler(Client*, messageHandler);
 | 
			
		||||
 | 
			
		||||
void MQTTClient(Client*, Network*, uint32_t, unsigned char*, size_t, unsigned char*, size_t);
 | 
			
		||||
 | 
			
		||||
struct Client 
 | 
			
		||||
{
 | 
			
		||||
  uint32_t next_packetid;
 | 
			
		||||
  uint32_t command_timeout_ms;
 | 
			
		||||
  size_t buf_size, readbuf_size;
 | 
			
		||||
  uint8_t *buf;  
 | 
			
		||||
  uint8_t *readbuf; 
 | 
			
		||||
  uint32_t keepAliveInterval;
 | 
			
		||||
  int8_t ping_outstanding;
 | 
			
		||||
  int32_t isconnected;
 | 
			
		||||
 | 
			
		||||
  struct MessageHandlers
 | 
			
		||||
  {
 | 
			
		||||
    const char* topicFilter;
 | 
			
		||||
    void (*fp) (MessageData*);
 | 
			
		||||
  } messageHandlers[MAX_MESSAGE_HANDLERS];      // Message handlers are indexed by subscription topic
 | 
			
		||||
    
 | 
			
		||||
  void (*defaultMessageHandler) (MessageData*);
 | 
			
		||||
    
 | 
			
		||||
  Network* ipstack;
 | 
			
		||||
  Timer ping_timer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DefaultClient {0, 0, 0, 0, NULL, NULL, 0, 0, 0}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										129
									
								
								Internet/MQTT/MQTTPacket/src/MQTTConnect.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								Internet/MQTT/MQTTPacket/src/MQTTConnect.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *    Xiang Rong - 442039 Add makefile to Embedded C client
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef MQTTCONNECT_H_
 | 
			
		||||
#define MQTTCONNECT_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
   
 | 
			
		||||
#if !defined(DLLImport)
 | 
			
		||||
  #define DLLImport 
 | 
			
		||||
#endif
 | 
			
		||||
#if !defined(DLLExport)
 | 
			
		||||
  #define DLLExport
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef union
 | 
			
		||||
{
 | 
			
		||||
  uint8_t all;	/**< all connect flags */
 | 
			
		||||
#if defined(REVERSED)
 | 
			
		||||
  struct
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t username    : 1;	/**< 3.1 user name */
 | 
			
		||||
    uint8_t password    : 1; 	/**< 3.1 password */
 | 
			
		||||
    uint8_t willRetain  : 1;	/**< will retain setting */
 | 
			
		||||
    uint8_t willQoS     : 2;	/**< will QoS value */
 | 
			
		||||
    uint8_t will        : 1;    /**< will flag */
 | 
			
		||||
    uint8_t cleansession: 1;	/**< clean session flag */
 | 
			
		||||
    uint8_t             : 1;	/**< unused */
 | 
			
		||||
  } bits;
 | 
			
		||||
#else
 | 
			
		||||
  struct
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t             : 1;	/**< unused */
 | 
			
		||||
    uint8_t cleansession: 1;	/**< cleansession flag */
 | 
			
		||||
    uint8_t will        : 1;	/**< will flag */
 | 
			
		||||
    uint8_t willQoS     : 2;	/**< will QoS value */
 | 
			
		||||
    uint8_t willRetain  : 1;	/**< will retain setting */
 | 
			
		||||
    uint8_t password    : 1; 	/**< 3.1 password */
 | 
			
		||||
    uint8_t username    : 1;	/**< 3.1 user name */
 | 
			
		||||
  } bits;
 | 
			
		||||
#endif
 | 
			
		||||
} MQTTConnectFlags;	/**< connect flags byte */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** Defines the MQTT "Last Will and Testament" (LWT) settings for the connect packet. */
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  /** The eyecatcher for this structure.  must be MQTW. */
 | 
			
		||||
  int8_t struct_id[4];
 | 
			
		||||
  /** The version number of this structure.  Must be 0 */
 | 
			
		||||
  int16_t struct_version;
 | 
			
		||||
  /** The LWT topic to which the LWT message will be published. */
 | 
			
		||||
  MQTTString topicName;
 | 
			
		||||
  /** The LWT payload. */
 | 
			
		||||
  MQTTString message;
 | 
			
		||||
  /** The retained flag for the LWT message (see MQTTAsync_message.retained). */
 | 
			
		||||
  uint8_t retained;
 | 
			
		||||
  /** The quality of service setting for the LWT message (see MQTTAsync_message.qos and @ref qos). */
 | 
			
		||||
  int8_t qos;
 | 
			
		||||
} MQTTPacket_willOptions;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  /** The eyecatcher for this structure.  must be MQTC. */
 | 
			
		||||
  int8_t struct_id[4];
 | 
			
		||||
  /** The version number of this structure.  Must be 0 */
 | 
			
		||||
  uint16_t struct_version;
 | 
			
		||||
  /** Version of MQTT to be used.  3 = 3.1 4 = 3.1.1 */
 | 
			
		||||
  uint8_t MQTTVersion;
 | 
			
		||||
  MQTTString clientID;
 | 
			
		||||
  uint16_t keepAliveInterval;
 | 
			
		||||
  uint8_t cleansession;
 | 
			
		||||
  uint8_t willFlag;
 | 
			
		||||
  MQTTPacket_willOptions will;
 | 
			
		||||
  MQTTString username;
 | 
			
		||||
  MQTTString password;
 | 
			
		||||
} MQTTPacket_connectData;
 | 
			
		||||
 | 
			
		||||
typedef union
 | 
			
		||||
{
 | 
			
		||||
  unsigned char all;	/**< all connack flags */
 | 
			
		||||
#if defined(REVERSED)
 | 
			
		||||
  struct
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t sessionpresent      : 1;    /**< session present flag */
 | 
			
		||||
    uint8_t                     : 7;	/**< unused */
 | 
			
		||||
  } bits;
 | 
			
		||||
#else
 | 
			
		||||
  struct
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t                     : 7;	/**< unused */
 | 
			
		||||
    uint8_t sessionpresent      : 1;    /**< session present flag */
 | 
			
		||||
  } bits;
 | 
			
		||||
#endif
 | 
			
		||||
} MQTTConnackFlags;	/**< connack flags byte */
 | 
			
		||||
 | 
			
		||||
#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \
 | 
			
		||||
		MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} }
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTSerialize_connect(uint8_t* buf, int32_t buflen, MQTTPacket_connectData* options);
 | 
			
		||||
DLLExport int32_t MQTTDeserialize_connect(MQTTPacket_connectData* data, uint8_t* buf, int32_t len);
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTSerialize_connack(uint8_t* buf, int32_t buflen, uint8_t connack_rc, uint8_t sessionPresent);
 | 
			
		||||
DLLExport int32_t MQTTDeserialize_connack(uint8_t* sessionPresent, uint8_t* connack_rc, uint8_t* buf, int32_t buflen);
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTSerialize_disconnect(uint8_t* buf, int32_t buflen);
 | 
			
		||||
DLLExport int32_t MQTTSerialize_pingreq(uint8_t* buf, int32_t buflen);
 | 
			
		||||
 | 
			
		||||
#endif /* MQTTCONNECT_H_ */
 | 
			
		||||
							
								
								
									
										217
									
								
								Internet/MQTT/MQTTPacket/src/MQTTConnectClient.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								Internet/MQTT/MQTTPacket/src/MQTTConnectClient.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,217 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
 | 
			
		||||
  * @param options the options to be used to build the connect packet
 | 
			
		||||
  * @return the length of buffer needed to contain the serialized version of the packet
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_connectLength(MQTTPacket_connectData* options)
 | 
			
		||||
{
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  if (options->MQTTVersion == 3)
 | 
			
		||||
    len = 12; /* variable depending on MQTT or MQIsdp */
 | 
			
		||||
  else if (options->MQTTVersion == 4)
 | 
			
		||||
    len = 10;
 | 
			
		||||
 | 
			
		||||
  len += MQTTstrlen(options->clientID) + 2;
 | 
			
		||||
  if (options->willFlag)
 | 
			
		||||
    len += MQTTstrlen(options->will.topicName) + 2 + MQTTstrlen(options->will.message) + 2;
 | 
			
		||||
  if (options->username.cstring || options->username.lenstring.data)
 | 
			
		||||
    len += MQTTstrlen(options->username)+2;
 | 
			
		||||
  if (options->password.cstring || options->password.lenstring.data)
 | 
			
		||||
    len += MQTTstrlen(options->password)+2;
 | 
			
		||||
 | 
			
		||||
  FUNC_EXIT_RC(len);
 | 
			
		||||
  return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes the connect options into the buffer.
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param len the length in bytes of the supplied buffer
 | 
			
		||||
  * @param options the options to be used to build the connect packet
 | 
			
		||||
  * @return serialized length, or error if 0
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_connect(uint8_t* buf, int32_t buflen, MQTTPacket_connectData* options)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t *ptr = buf;
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  MQTTConnectFlags flags = {0};
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
  int32_t rc = -1;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  if (MQTTPacket_len(len = MQTTSerialize_connectLength(options)) > buflen)
 | 
			
		||||
  {
 | 
			
		||||
    rc = MQTTPACKET_BUFFER_TOO_SHORT;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  header.byte = 0;
 | 
			
		||||
  header.bits.type = CONNECT;
 | 
			
		||||
  writeChar(&ptr, header.byte); /* write header */
 | 
			
		||||
 | 
			
		||||
  ptr += MQTTPacket_encode(ptr, len); /* write remaining length */
 | 
			
		||||
 | 
			
		||||
  if (options->MQTTVersion == 4)
 | 
			
		||||
  {
 | 
			
		||||
    writeCString(&ptr, "MQTT");
 | 
			
		||||
    writeChar(&ptr, (char) 4);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    writeCString(&ptr, "MQIsdp");
 | 
			
		||||
    writeChar(&ptr, (char) 3);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  flags.all = 0;
 | 
			
		||||
  flags.bits.cleansession = options->cleansession;
 | 
			
		||||
  flags.bits.will = (options->willFlag) ? 1 : 0;
 | 
			
		||||
 | 
			
		||||
  if (flags.bits.will)
 | 
			
		||||
  {
 | 
			
		||||
    flags.bits.willQoS = options->will.qos;
 | 
			
		||||
    flags.bits.willRetain = options->will.retained;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (options->username.cstring || options->username.lenstring.data)
 | 
			
		||||
    flags.bits.username = 1;
 | 
			
		||||
  if (options->password.cstring || options->password.lenstring.data)
 | 
			
		||||
    flags.bits.password = 1;
 | 
			
		||||
 | 
			
		||||
  writeChar(&ptr, flags.all);
 | 
			
		||||
  writeInt(&ptr, options->keepAliveInterval);
 | 
			
		||||
  writeMQTTString(&ptr, options->clientID);
 | 
			
		||||
 | 
			
		||||
  if (options->willFlag)
 | 
			
		||||
  {
 | 
			
		||||
    writeMQTTString(&ptr, options->will.topicName);
 | 
			
		||||
    writeMQTTString(&ptr, options->will.message);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (flags.bits.username)
 | 
			
		||||
    writeMQTTString(&ptr, options->username);
 | 
			
		||||
  if (flags.bits.password)
 | 
			
		||||
    writeMQTTString(&ptr, options->password);
 | 
			
		||||
 | 
			
		||||
  rc = ptr - buf;
 | 
			
		||||
 | 
			
		||||
  exit: FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Deserializes the supplied (wire) buffer into connack data - return code
 | 
			
		||||
  * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
 | 
			
		||||
  * @param connack_rc returned integer value of the connack return code
 | 
			
		||||
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
 | 
			
		||||
  * @param len the length in bytes of the data in the supplied buffer
 | 
			
		||||
  * @return error code.  1 is success, 0 is failure
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTDeserialize_connack(uint8_t* sessionPresent, uint8_t* connack_rc, uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  uint8_t* curdata = buf;
 | 
			
		||||
  uint8_t* enddata = NULL;
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
  int32_t mylen;
 | 
			
		||||
  MQTTConnackFlags flags = {0};
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  header.byte = readChar(&curdata);
 | 
			
		||||
  if (header.bits.type != CONNACK)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
 | 
			
		||||
  enddata = curdata + mylen;
 | 
			
		||||
  if (enddata - curdata < 2)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  flags.all = readChar(&curdata);
 | 
			
		||||
  *sessionPresent = flags.bits.sessionpresent;
 | 
			
		||||
  *connack_rc = readChar(&curdata);
 | 
			
		||||
 | 
			
		||||
  rc = 1;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes a 0-length packet into the supplied buffer, ready for writing to a socket
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
 | 
			
		||||
  * @param packettype the message type
 | 
			
		||||
  * @return serialized length, or error if 0
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_zero(uint8_t* buf, int32_t buflen, uint8_t packettype)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t rc = -1;
 | 
			
		||||
  uint8_t *ptr = buf;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  if (buflen < 2)
 | 
			
		||||
  {
 | 
			
		||||
    rc = MQTTPACKET_BUFFER_TOO_SHORT;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
  header.byte = 0;
 | 
			
		||||
  header.bits.type = packettype;
 | 
			
		||||
  writeChar(&ptr, header.byte); /* write header */
 | 
			
		||||
 | 
			
		||||
  ptr += MQTTPacket_encode(ptr, 0); /* write remaining length */
 | 
			
		||||
  rc = ptr - buf;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
 | 
			
		||||
  * @return serialized length, or error if 0
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_disconnect(uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  return MQTTSerialize_zero(buf, buflen, DISCONNECT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes a disconnect packet into the supplied buffer, ready for writing to a socket
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer, to avoid overruns
 | 
			
		||||
  * @return serialized length, or error if 0
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_pingreq(uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  return MQTTSerialize_zero(buf, buflen, PINGREQ);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										153
									
								
								Internet/MQTT/MQTTPacket/src/MQTTConnectServer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								Internet/MQTT/MQTTPacket/src/MQTTConnectServer.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#define min(a, b) ((a < b) ? a : b)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Validates MQTT protocol name and version combinations
 | 
			
		||||
  * @param protocol the MQTT protocol name as an MQTTString
 | 
			
		||||
  * @param version the MQTT protocol version number, as in the connect packet
 | 
			
		||||
  * @return correct MQTT combination?  1 is true, 0 is false
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTPacket_checkVersion(MQTTString* protocol, int32_t version)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
 | 
			
		||||
  if (version == 3 && memcmp(protocol->lenstring.data, "MQIsdp", min(6, protocol->lenstring.len)) == 0)
 | 
			
		||||
    rc = 1;
 | 
			
		||||
  else if (version == 4 && memcmp(protocol->lenstring.data, "MQTT", min(4, protocol->lenstring.len)) == 0)
 | 
			
		||||
    rc = 1;
 | 
			
		||||
	
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Deserializes the supplied (wire) buffer into connect data structure
 | 
			
		||||
  * @param data the connect data structure to be filled out
 | 
			
		||||
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
 | 
			
		||||
  * @param len the length in bytes of the data in the supplied buffer
 | 
			
		||||
  * @return error code.  1 is success, 0 is failure
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTDeserialize_connect(MQTTPacket_connectData* data, uint8_t* buf, int32_t len)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  MQTTConnectFlags flags = {0};
 | 
			
		||||
  uint8_t* curdata = buf;
 | 
			
		||||
  uint8_t* enddata = &buf[len];
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
  MQTTString Protocol;
 | 
			
		||||
  int32_t version;
 | 
			
		||||
  int32_t mylen = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  header.byte = readChar(&curdata);
 | 
			
		||||
  if (header.bits.type != CONNECT)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  curdata += MQTTPacket_decodeBuf(curdata, &mylen); /* read remaining length */
 | 
			
		||||
 | 
			
		||||
  /* do we have enough data to read the protocol version byte? */
 | 
			
		||||
  if (!readMQTTLenString(&Protocol, &curdata, enddata) || enddata - curdata < 0)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  version = (int)readChar(&curdata); /* Protocol version */
 | 
			
		||||
 | 
			
		||||
  /* If we don't recognize the protocol version, we don't parse the connect packet on the
 | 
			
		||||
  * basis that we don't know what the format will be. */
 | 
			
		||||
  if (MQTTPacket_checkVersion(&Protocol, version))
 | 
			
		||||
  {
 | 
			
		||||
    flags.all = readChar(&curdata);
 | 
			
		||||
    data->cleansession = flags.bits.cleansession;
 | 
			
		||||
    data->keepAliveInterval = readInt(&curdata);
 | 
			
		||||
	
 | 
			
		||||
    if (!readMQTTLenString(&data->clientID, &curdata, enddata))
 | 
			
		||||
      goto exit;
 | 
			
		||||
  
 | 
			
		||||
    data->willFlag = flags.bits.will;
 | 
			
		||||
    if (flags.bits.will)
 | 
			
		||||
    {
 | 
			
		||||
      data->will.qos = flags.bits.willQoS;
 | 
			
		||||
      data->will.retained = flags.bits.willRetain;
 | 
			
		||||
 | 
			
		||||
      if (!readMQTTLenString(&data->will.topicName, &curdata, enddata) ||
 | 
			
		||||
	  !readMQTTLenString(&data->will.message, &curdata, enddata))
 | 
			
		||||
	goto exit;
 | 
			
		||||
    }
 | 
			
		||||
	
 | 
			
		||||
    if (flags.bits.username)
 | 
			
		||||
    {
 | 
			
		||||
      if (enddata - curdata < 3 || !readMQTTLenString(&data->username, &curdata, enddata))
 | 
			
		||||
	goto exit; /* username flag set, but no username supplied - invalid */
 | 
			
		||||
      if (flags.bits.password &&
 | 
			
		||||
	  (enddata - curdata < 3 || !readMQTTLenString(&data->password, &curdata, enddata)))
 | 
			
		||||
	goto exit; /* password flag set, but no password supplied - invalid */
 | 
			
		||||
    }
 | 
			
		||||
    else if (flags.bits.password)
 | 
			
		||||
      goto exit; /* password flag set without username - invalid */
 | 
			
		||||
	
 | 
			
		||||
    rc = 1;
 | 
			
		||||
  }
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes the connack packet into the supplied buffer.
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
  * @param connack_rc the integer connack return code to be used 
 | 
			
		||||
  * @param sessionPresent the MQTT 3.1.1 sessionPresent flag
 | 
			
		||||
  * @return serialized length, or error if 0
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_connack(uint8_t* buf, int32_t buflen, uint8_t connack_rc, uint8_t sessionPresent)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
  uint8_t *ptr = buf;
 | 
			
		||||
  MQTTConnackFlags flags = {0};
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  if (buflen < 2)
 | 
			
		||||
  {
 | 
			
		||||
    rc = MQTTPACKET_BUFFER_TOO_SHORT;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  header.byte = 0;
 | 
			
		||||
  header.bits.type = CONNACK;
 | 
			
		||||
  writeChar(&ptr, header.byte); /* write header */
 | 
			
		||||
 | 
			
		||||
  ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
 | 
			
		||||
 | 
			
		||||
  flags.all = 0;
 | 
			
		||||
  flags.bits.sessionpresent = sessionPresent;
 | 
			
		||||
  writeChar(&ptr, flags.all); 
 | 
			
		||||
  writeChar(&ptr, connack_rc);
 | 
			
		||||
 | 
			
		||||
  rc = ptr - buf;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										109
									
								
								Internet/MQTT/MQTTPacket/src/MQTTDeserializePublish.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								Internet/MQTT/MQTTPacket/src/MQTTDeserializePublish.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#define min(a, b) ((a < b) ? 1 : 0)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Deserializes the supplied (wire) buffer into publish data
 | 
			
		||||
  * @param dup returned integer - the MQTT dup flag
 | 
			
		||||
  * @param qos returned integer - the MQTT QoS value
 | 
			
		||||
  * @param retained returned integer - the MQTT retained flag
 | 
			
		||||
  * @param packetid returned integer - the MQTT packet identifier
 | 
			
		||||
  * @param topicName returned MQTTString - the MQTT topic in the publish
 | 
			
		||||
  * @param payload returned byte buffer - the MQTT publish payload
 | 
			
		||||
  * @param payloadlen returned integer - the length of the MQTT payload
 | 
			
		||||
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
 | 
			
		||||
  * @param buflen the length in bytes of the data in the supplied buffer
 | 
			
		||||
  * @return error code.  1 is success
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTDeserialize_publish(uint8_t* dup, uint8_t* qos, uint8_t* retained, uint16_t* packetid, MQTTString* topicName,
 | 
			
		||||
		uint8_t** payload, int32_t* payloadlen, uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  uint8_t* curdata = buf;
 | 
			
		||||
  uint8_t* enddata = NULL;
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
  int32_t mylen = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  header.byte = readChar(&curdata);
 | 
			
		||||
 | 
			
		||||
  if (header.bits.type != PUBLISH)
 | 
			
		||||
    goto exit;
 | 
			
		||||
	
 | 
			
		||||
  *dup = header.bits.dup;
 | 
			
		||||
  *qos = header.bits.qos;
 | 
			
		||||
  *retained = header.bits.retain;
 | 
			
		||||
 | 
			
		||||
  curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
 | 
			
		||||
  enddata = curdata + mylen;
 | 
			
		||||
 | 
			
		||||
  /* do we have enough data to read the protocol version byte? */
 | 
			
		||||
  if (!readMQTTLenString(topicName, &curdata, enddata) || enddata - curdata < 0)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  if (*qos > 0)
 | 
			
		||||
    *packetid = readInt(&curdata);
 | 
			
		||||
 | 
			
		||||
  *payloadlen = enddata - curdata;
 | 
			
		||||
  *payload = curdata;
 | 
			
		||||
  rc = 1;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Deserializes the supplied (wire) buffer into an ack
 | 
			
		||||
  * @param packettype returned integer - the MQTT packet type
 | 
			
		||||
  * @param dup returned integer - the MQTT dup flag
 | 
			
		||||
  * @param packetid returned integer - the MQTT packet identifier
 | 
			
		||||
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
 | 
			
		||||
  * @param buflen the length in bytes of the data in the supplied buffer
 | 
			
		||||
  * @return error code.  1 is success, 0 is failure
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTDeserialize_ack(uint8_t* packettype, uint8_t* dup, uint16_t* packetid, uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  uint8_t* curdata = buf;
 | 
			
		||||
  uint8_t* enddata = NULL;
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
  int32_t mylen;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  header.byte = readChar(&curdata);
 | 
			
		||||
  *dup = header.bits.dup;
 | 
			
		||||
  *packettype = header.bits.type;
 | 
			
		||||
 | 
			
		||||
  curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
 | 
			
		||||
  enddata = curdata + mylen;
 | 
			
		||||
 | 
			
		||||
  if (enddata - curdata < 2)
 | 
			
		||||
    goto exit;
 | 
			
		||||
	
 | 
			
		||||
  *packetid = readInt(&curdata);
 | 
			
		||||
 | 
			
		||||
  rc = 1;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										265
									
								
								Internet/MQTT/MQTTPacket/src/MQTTFormat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										265
									
								
								Internet/MQTT/MQTTPacket/src/MQTTFormat.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,265 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const char* MQTTPacket_names[] =
 | 
			
		||||
{
 | 
			
		||||
  "RESERVED", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL",
 | 
			
		||||
  "PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ",
 | 
			
		||||
  "PINGRESP", "DISCONNECT"
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const char* MQTTPacket_getName(uint16_t packetid)
 | 
			
		||||
{
 | 
			
		||||
  return MQTTPacket_names[packetid];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTStringFormat_connect(char* strbuf, int32_t strbuflen, MQTTPacket_connectData* data)
 | 
			
		||||
{
 | 
			
		||||
  int32_t strindex = 0;
 | 
			
		||||
 | 
			
		||||
  strindex = snprintf(strbuf, strbuflen,
 | 
			
		||||
                      "CONNECT MQTT version %ld, client id %.*s, clean session %ld, keep alive %d",
 | 
			
		||||
                      (int32_t)data->MQTTVersion, (int)data->clientID.lenstring.len, data->clientID.lenstring.data,
 | 
			
		||||
                      (int32_t)data->cleansession, data->keepAliveInterval);
 | 
			
		||||
  if (data->willFlag)
 | 
			
		||||
    strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
 | 
			
		||||
                         ", will QoS %d, will retain %d, will topic %.*s, will message %.*s",
 | 
			
		||||
                         data->will.qos, data->will.retained,
 | 
			
		||||
                         (int)data->will.topicName.lenstring.len, data->will.topicName.lenstring.data,
 | 
			
		||||
			 (int)data->will.message.lenstring.len, data->will.message.lenstring.data);
 | 
			
		||||
  if (data->username.lenstring.data && data->username.lenstring.len > 0)
 | 
			
		||||
    strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
 | 
			
		||||
			 ", user name %.*s", (int)data->username.lenstring.len, data->username.lenstring.data);
 | 
			
		||||
  if (data->password.lenstring.data && data->password.lenstring.len > 0)
 | 
			
		||||
    strindex += snprintf(&strbuf[strindex], strbuflen - strindex,
 | 
			
		||||
			 ", password %.*s", (int)data->password.lenstring.len, data->password.lenstring.data);
 | 
			
		||||
    return strindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTStringFormat_connack(char* strbuf, int32_t strbuflen, uint8_t connack_rc, uint8_t sessionPresent)
 | 
			
		||||
{
 | 
			
		||||
  int32_t strindex = snprintf(strbuf, strbuflen, "CONNACK session present %d, rc %d", sessionPresent, connack_rc);
 | 
			
		||||
  return strindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTStringFormat_publish(char* strbuf, int32_t strbuflen, uint8_t dup, uint8_t qos, uint8_t retained,
 | 
			
		||||
		uint16_t packetid, MQTTString topicName, uint8_t* payload, int32_t payloadlen)
 | 
			
		||||
{
 | 
			
		||||
  int32_t strindex = snprintf(strbuf, strbuflen,
 | 
			
		||||
                              "PUBLISH dup %d, QoS %d, retained %d, packet id %d, topic %.*s, payload length %ld, payload %.*s",
 | 
			
		||||
                              dup, qos, retained, packetid,
 | 
			
		||||
                              (topicName.lenstring.len < 20) ? (int)topicName.lenstring.len : 20, topicName.lenstring.data,
 | 
			
		||||
                              payloadlen, (payloadlen < 20) ? (int)payloadlen : 20, payload);
 | 
			
		||||
    return strindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTStringFormat_ack(char* strbuf, int32_t strbuflen, uint8_t packettype, uint8_t dup, uint16_t packetid)
 | 
			
		||||
{
 | 
			
		||||
  int32_t strindex = snprintf(strbuf, strbuflen, "%s, packet id %d", MQTTPacket_names[packettype], packetid);
 | 
			
		||||
  
 | 
			
		||||
  if (dup)
 | 
			
		||||
    strindex += snprintf(strbuf + strindex, strbuflen - strindex, ", dup %d", dup);
 | 
			
		||||
	
 | 
			
		||||
  return strindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTStringFormat_subscribe(char* strbuf, int32_t strbuflen, uint8_t dup, uint16_t packetid, int32_t count,
 | 
			
		||||
		MQTTString topicFilters[], int32_t requestedQoSs[])
 | 
			
		||||
{
 | 
			
		||||
  return snprintf(strbuf, strbuflen, "SUBSCRIBE dup %d, packet id %d count %ld topic %.*s qos %ld",
 | 
			
		||||
                  dup, packetid, count, (int)topicFilters[0].lenstring.len, topicFilters[0].lenstring.data,
 | 
			
		||||
                  requestedQoSs[0]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTStringFormat_suback(char* strbuf, int32_t strbuflen, uint16_t packetid, int32_t count, int32_t* grantedQoSs)
 | 
			
		||||
{
 | 
			
		||||
	return snprintf(strbuf, strbuflen,
 | 
			
		||||
		"SUBACK packet id %d count %ld granted qos %ld", packetid, count, grantedQoSs[0]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTStringFormat_unsubscribe(char* strbuf, int32_t strbuflen, uint8_t dup, uint16_t packetid,
 | 
			
		||||
		int32_t count, MQTTString topicFilters[])
 | 
			
		||||
{
 | 
			
		||||
  return snprintf(strbuf, strbuflen, "UNSUBSCRIBE dup %d, packet id %d count %ld topic %.*s",
 | 
			
		||||
                  dup, packetid, count, (int)topicFilters[0].lenstring.len, topicFilters[0].lenstring.data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
char* MQTTFormat_toClientString(char* strbuf, int32_t strbuflen, uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  int32_t index = 0;
 | 
			
		||||
  int32_t rem_length = 0;
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t strindex = 0;
 | 
			
		||||
 | 
			
		||||
  header.byte = buf[index++];
 | 
			
		||||
  index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
 | 
			
		||||
 | 
			
		||||
  switch (header.bits.type)
 | 
			
		||||
  {
 | 
			
		||||
    case CONNACK:
 | 
			
		||||
      {
 | 
			
		||||
        uint8_t sessionPresent, connack_rc;
 | 
			
		||||
        if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, buf, buflen) == 1)
 | 
			
		||||
          strindex = MQTTStringFormat_connack(strbuf, strbuflen, connack_rc, sessionPresent);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case PUBLISH:
 | 
			
		||||
      {
 | 
			
		||||
	uint8_t dup, retained, *payload;
 | 
			
		||||
	uint16_t packetid;
 | 
			
		||||
	uint8_t qos; 
 | 
			
		||||
        int32_t payloadlen;
 | 
			
		||||
	MQTTString topicName = MQTTString_initializer;
 | 
			
		||||
	
 | 
			
		||||
        if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName, 
 | 
			
		||||
                                    &payload, &payloadlen, buf, buflen) == 1)
 | 
			
		||||
          strindex = MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, 
 | 
			
		||||
                                              packetid, topicName, payload, payloadlen);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case PUBACK:
 | 
			
		||||
    case PUBREC:
 | 
			
		||||
    case PUBREL:
 | 
			
		||||
    case PUBCOMP:
 | 
			
		||||
      {
 | 
			
		||||
	uint8_t packettype, dup;
 | 
			
		||||
	uint16_t packetid;
 | 
			
		||||
        if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
 | 
			
		||||
          strindex = MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case SUBACK:
 | 
			
		||||
      {
 | 
			
		||||
	uint16_t packetid;
 | 
			
		||||
	int32_t maxcount = 1, count = 0;
 | 
			
		||||
	int32_t grantedQoSs[1];
 | 
			
		||||
        if (MQTTDeserialize_suback(&packetid, maxcount, &count, grantedQoSs, buf, buflen) == 1)
 | 
			
		||||
          strindex = MQTTStringFormat_suback(strbuf, strbuflen, packetid, count, grantedQoSs);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case UNSUBACK:
 | 
			
		||||
      {
 | 
			
		||||
	uint16_t packetid;
 | 
			
		||||
	if (MQTTDeserialize_unsuback(&packetid, buf, buflen) == 1)
 | 
			
		||||
          strindex = MQTTStringFormat_ack(strbuf, strbuflen, UNSUBACK, 0, packetid);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case PINGREQ:
 | 
			
		||||
    case PINGRESP:
 | 
			
		||||
    case DISCONNECT:
 | 
			
		||||
      strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
	
 | 
			
		||||
  return strbuf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
char* MQTTFormat_toServerString(char* strbuf, int32_t strbuflen, uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  int32_t index = 0;
 | 
			
		||||
  int32_t rem_length = 0;
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t strindex = 0;
 | 
			
		||||
 | 
			
		||||
  header.byte = buf[index++];
 | 
			
		||||
  index += MQTTPacket_decodeBuf(&buf[index], &rem_length);
 | 
			
		||||
 | 
			
		||||
  switch (header.bits.type)
 | 
			
		||||
  {
 | 
			
		||||
    case CONNECT:
 | 
			
		||||
      {
 | 
			
		||||
        MQTTPacket_connectData data;
 | 
			
		||||
        int32_t rc;
 | 
			
		||||
		
 | 
			
		||||
        if ((rc = MQTTDeserialize_connect(&data, buf, buflen)) == 1)
 | 
			
		||||
          strindex = MQTTStringFormat_connect(strbuf, strbuflen, &data);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case PUBLISH:
 | 
			
		||||
      {
 | 
			
		||||
	uint8_t dup, retained, *payload;
 | 
			
		||||
	uint16_t packetid;
 | 
			
		||||
	uint8_t qos; 
 | 
			
		||||
        int32_t payloadlen;
 | 
			
		||||
	MQTTString topicName = MQTTString_initializer;
 | 
			
		||||
	
 | 
			
		||||
        if (MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicName,
 | 
			
		||||
                                    &payload, &payloadlen, buf, buflen) == 1)
 | 
			
		||||
          strindex = MQTTStringFormat_publish(strbuf, strbuflen, dup, qos, retained, 
 | 
			
		||||
                                              packetid,	topicName, payload, payloadlen);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case PUBACK:
 | 
			
		||||
    case PUBREC:
 | 
			
		||||
    case PUBREL:
 | 
			
		||||
    case PUBCOMP:
 | 
			
		||||
      {
 | 
			
		||||
	uint8_t packettype, dup;
 | 
			
		||||
	uint16_t packetid;
 | 
			
		||||
        
 | 
			
		||||
        if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf, buflen) == 1)
 | 
			
		||||
          strindex = MQTTStringFormat_ack(strbuf, strbuflen, packettype, dup, packetid);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case SUBSCRIBE:
 | 
			
		||||
      {
 | 
			
		||||
	uint8_t dup;
 | 
			
		||||
	uint16_t packetid;
 | 
			
		||||
	int32_t maxcount = 1, count = 0;
 | 
			
		||||
	MQTTString topicFilters[1];
 | 
			
		||||
	int32_t requestedQoSs[1];
 | 
			
		||||
	
 | 
			
		||||
        if (MQTTDeserialize_subscribe(&dup, &packetid, maxcount, &count,
 | 
			
		||||
                                      topicFilters, requestedQoSs, buf, buflen) == 1)
 | 
			
		||||
          strindex = MQTTStringFormat_subscribe(strbuf, strbuflen, dup, packetid, count, topicFilters, requestedQoSs);;
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case UNSUBSCRIBE:
 | 
			
		||||
      {
 | 
			
		||||
	uint8_t dup;
 | 
			
		||||
	uint16_t packetid;
 | 
			
		||||
	int32_t maxcount = 1, count = 0;
 | 
			
		||||
	MQTTString topicFilters[1];
 | 
			
		||||
	if (MQTTDeserialize_unsubscribe(&dup, &packetid, maxcount, &count, topicFilters, buf, buflen) == 1)
 | 
			
		||||
          strindex =  MQTTStringFormat_unsubscribe(strbuf, strbuflen, dup, packetid, count, topicFilters);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case PINGREQ:
 | 
			
		||||
    case PINGRESP:
 | 
			
		||||
    case DISCONNECT:
 | 
			
		||||
      strindex = snprintf(strbuf, strbuflen, "%s", MQTTPacket_names[header.bits.type]);
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  strbuf[strbuflen] = '\0';
 | 
			
		||||
  return strbuf;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								Internet/MQTT/MQTTPacket/src/MQTTFormat.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Internet/MQTT/MQTTPacket/src/MQTTFormat.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#if !defined(MQTTFORMAT_H)
 | 
			
		||||
#define MQTTFORMAT_H
 | 
			
		||||
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
 | 
			
		||||
const char* MQTTPacket_getName(uint16_t packetid);
 | 
			
		||||
int32_t MQTTStringFormat_connect(char* strbuf, int32_t strbuflen, MQTTPacket_connectData* data);
 | 
			
		||||
int32_t MQTTStringFormat_connack(char* strbuf, int32_t strbuflen, uint8_t connack_rc, uint8_t sessionPresent);
 | 
			
		||||
int32_t MQTTStringFormat_publish(char* strbuf, int32_t strbuflen, uint8_t dup, uint8_t qos, uint8_t retained,
 | 
			
		||||
		uint16_t packetid, MQTTString topicName, uint8_t* payload, int32_t payloadlen);
 | 
			
		||||
int32_t MQTTStringFormat_ack(char* strbuf, int32_t strbuflen, uint8_t packettype, uint8_t dup, uint16_t packetid);
 | 
			
		||||
int32_t MQTTStringFormat_subscribe(char* strbuf, int32_t strbuflen, uint8_t dup, uint16_t packetid, int32_t count,
 | 
			
		||||
		MQTTString topicFilters[], int32_t requestedQoSs[]);
 | 
			
		||||
int32_t MQTTStringFormat_suback(char* strbuf, int32_t strbuflen, uint16_t packetid, int32_t count, int32_t* grantedQoSs);
 | 
			
		||||
int32_t MQTTStringFormat_unsubscribe(char* strbuf, int32_t strbuflen, uint8_t dup, uint16_t packetid,
 | 
			
		||||
		int32_t count, MQTTString topicFilters[]);
 | 
			
		||||
char* MQTTFormat_toClientString(char* strbuf, int32_t strbuflen, uint8_t* buf, int32_t buflen);
 | 
			
		||||
char* MQTTFormat_toServerString(char* strbuf, int32_t strbuflen, uint8_t* buf, int32_t buflen);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										443
									
								
								Internet/MQTT/MQTTPacket/src/MQTTPacket.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								Internet/MQTT/MQTTPacket/src/MQTTPacket.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,443 @@
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *    Sergio R. Caprile - non-blocking packet read functions for stream transport
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Encodes the message length according to the MQTT algorithm
 | 
			
		||||
 * @param buf the buffer into which the encoded data is written
 | 
			
		||||
 * @param length the length to be encoded
 | 
			
		||||
 * @return the number of bytes written to buffer
 | 
			
		||||
 */
 | 
			
		||||
int32_t MQTTPacket_encode(uint8_t* buf, int32_t length)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  do
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t d = length % 128;
 | 
			
		||||
    length /= 128;
 | 
			
		||||
	
 | 
			
		||||
    /* if there are more digits to encode, set the top bit of this digit */
 | 
			
		||||
    if (length > 0)
 | 
			
		||||
      d |= 0x80;
 | 
			
		||||
 | 
			
		||||
    buf[rc++] = d;
 | 
			
		||||
  } while (length > 0);
 | 
			
		||||
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decodes the message length according to the MQTT algorithm
 | 
			
		||||
 * @param getcharfn pointer to function to read the next character from the data source
 | 
			
		||||
 * @param value the decoded length returned
 | 
			
		||||
 * @return the number of bytes read from the socket
 | 
			
		||||
 */
 | 
			
		||||
int32_t MQTTPacket_decode(int32_t (*getcharfn)(uint8_t*, int32_t), int32_t* value)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t c;
 | 
			
		||||
  int32_t multiplier = 1;
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
 | 
			
		||||
#define MAX_NO_OF_REMAINING_LENGTH_BYTES 4
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  *value = 0;
 | 
			
		||||
 | 
			
		||||
  do
 | 
			
		||||
  {
 | 
			
		||||
    int32_t rc = MQTTPACKET_READ_ERROR;
 | 
			
		||||
 | 
			
		||||
    if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
 | 
			
		||||
    {
 | 
			
		||||
      rc = MQTTPACKET_READ_ERROR;	/* bad data */
 | 
			
		||||
      goto exit;
 | 
			
		||||
    }
 | 
			
		||||
	
 | 
			
		||||
    rc = (*getcharfn)(&c, 1);
 | 
			
		||||
 | 
			
		||||
    if (rc != 1)
 | 
			
		||||
      goto exit;
 | 
			
		||||
	
 | 
			
		||||
    *value += (c & 127) * multiplier;
 | 
			
		||||
    multiplier *= 128;
 | 
			
		||||
  } while ((c & 128) != 0);
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(len);
 | 
			
		||||
  return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTPacket_len(int32_t rem_len)
 | 
			
		||||
{
 | 
			
		||||
  rem_len += 1; /* header byte */
 | 
			
		||||
 | 
			
		||||
  /* now remaining_length field */
 | 
			
		||||
  if (rem_len < 128)
 | 
			
		||||
    rem_len += 1;
 | 
			
		||||
  else if (rem_len < 16384)
 | 
			
		||||
    rem_len += 2;
 | 
			
		||||
  else if (rem_len < 2097151)
 | 
			
		||||
    rem_len += 3;
 | 
			
		||||
  else
 | 
			
		||||
    rem_len += 4;
 | 
			
		||||
	
 | 
			
		||||
  return rem_len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static uint8_t* bufptr;
 | 
			
		||||
 | 
			
		||||
int32_t bufchar(uint8_t* c, int32_t count)
 | 
			
		||||
{
 | 
			
		||||
  for (int32_t i = 0; i < count; ++i)
 | 
			
		||||
    *c = *bufptr++;
 | 
			
		||||
	
 | 
			
		||||
  return count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t MQTTPacket_decodeBuf(uint8_t* buf, int32_t* value)
 | 
			
		||||
{
 | 
			
		||||
  bufptr = buf;
 | 
			
		||||
  return MQTTPacket_decode(bufchar, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculates an integer from two bytes read from the input buffer
 | 
			
		||||
 * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
 | 
			
		||||
 * @return the integer value calculated
 | 
			
		||||
 */
 | 
			
		||||
int32_t readInt(uint8_t** pptr)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t* ptr = *pptr;
 | 
			
		||||
  int32_t len = 256*(*ptr) + (*(ptr+1));
 | 
			
		||||
  *pptr += 2;
 | 
			
		||||
  return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reads one character from the input buffer.
 | 
			
		||||
 * @param pptr pointer to the input buffer - incremented by the number of bytes used & returned
 | 
			
		||||
 * @return the character read
 | 
			
		||||
 */
 | 
			
		||||
char readChar(uint8_t** pptr)
 | 
			
		||||
{
 | 
			
		||||
  char c = **pptr;
 | 
			
		||||
  (*pptr)++;
 | 
			
		||||
  return c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes one character to an output buffer.
 | 
			
		||||
 * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
 | 
			
		||||
 * @param c the character to write
 | 
			
		||||
 */
 | 
			
		||||
void writeChar(uint8_t** pptr, char c)
 | 
			
		||||
{
 | 
			
		||||
  **pptr = c;
 | 
			
		||||
  (*pptr)++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes an integer as 2 bytes to an output buffer.
 | 
			
		||||
 * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
 | 
			
		||||
 * @param anInt the integer to write
 | 
			
		||||
 */
 | 
			
		||||
void writeInt(uint8_t** pptr, int32_t anInt)
 | 
			
		||||
{
 | 
			
		||||
  **pptr = (uint8_t)(anInt / 256);
 | 
			
		||||
  (*pptr)++;
 | 
			
		||||
  **pptr = (uint8_t)(anInt % 256);
 | 
			
		||||
  (*pptr)++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Writes a "UTF" string to an output buffer.  Converts C string to length-delimited.
 | 
			
		||||
 * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
 | 
			
		||||
 * @param string the C string to write
 | 
			
		||||
 */
 | 
			
		||||
void writeCString(uint8_t** pptr, const char* string)
 | 
			
		||||
{
 | 
			
		||||
  int32_t len = strlen(string);
 | 
			
		||||
  writeInt(pptr, len);
 | 
			
		||||
  memcpy(*pptr, string, len);
 | 
			
		||||
  *pptr += len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int32_t getLenStringLen(char* ptr)
 | 
			
		||||
{
 | 
			
		||||
  int32_t len = 256*((uint8_t)(*ptr)) + (uint8_t)(*(ptr+1));
 | 
			
		||||
  return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void writeMQTTString(uint8_t** pptr, MQTTString mqttstring)
 | 
			
		||||
{
 | 
			
		||||
  if (mqttstring.lenstring.len > 0)
 | 
			
		||||
  {
 | 
			
		||||
    writeInt(pptr, mqttstring.lenstring.len);
 | 
			
		||||
    memcpy(*pptr, mqttstring.lenstring.data, mqttstring.lenstring.len);
 | 
			
		||||
    *pptr += mqttstring.lenstring.len;
 | 
			
		||||
  }
 | 
			
		||||
  else if (mqttstring.cstring)
 | 
			
		||||
    writeCString(pptr, mqttstring.cstring);
 | 
			
		||||
  else
 | 
			
		||||
    writeInt(pptr, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param mqttstring the MQTTString structure into which the data is to be read
 | 
			
		||||
 * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
 | 
			
		||||
 * @param enddata pointer to the end of the data: do not read beyond
 | 
			
		||||
 * @return 1 if successful, 0 if not
 | 
			
		||||
 */
 | 
			
		||||
int32_t readMQTTLenString(MQTTString* mqttstring, uint8_t** pptr, uint8_t* enddata)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  /* the first two bytes are the length of the string */
 | 
			
		||||
  if (enddata - (*pptr) > 1) /* enough length to read the integer? */
 | 
			
		||||
  {
 | 
			
		||||
    mqttstring->lenstring.len = readInt(pptr); /* increments pptr to point past length */
 | 
			
		||||
	
 | 
			
		||||
    if (&(*pptr)[mqttstring->lenstring.len] <= enddata)
 | 
			
		||||
    {
 | 
			
		||||
      mqttstring->lenstring.data = (char*)*pptr;
 | 
			
		||||
      *pptr += mqttstring->lenstring.len;
 | 
			
		||||
      rc = 1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  mqttstring->cstring = NULL;
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return the length of the MQTTstring - C string if there is one, otherwise the length delimited string
 | 
			
		||||
 * @param mqttstring the string to return the length of
 | 
			
		||||
 * @return the length of the string
 | 
			
		||||
 */
 | 
			
		||||
int32_t MQTTstrlen(MQTTString mqttstring)
 | 
			
		||||
{
 | 
			
		||||
  int rc = 0;
 | 
			
		||||
 | 
			
		||||
  if (mqttstring.cstring)
 | 
			
		||||
    rc = strlen(mqttstring.cstring);
 | 
			
		||||
  else
 | 
			
		||||
    rc = mqttstring.lenstring.len;
 | 
			
		||||
	
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Compares an MQTTString to a C string
 | 
			
		||||
 * @param a the MQTTString to compare
 | 
			
		||||
 * @param bptr the C string to compare
 | 
			
		||||
 * @return boolean - equal or not
 | 
			
		||||
 */
 | 
			
		||||
int32_t MQTTPacket_equals(MQTTString* a, char* bptr)
 | 
			
		||||
{
 | 
			
		||||
  int32_t alen = 0, blen = 0;
 | 
			
		||||
  char *aptr;
 | 
			
		||||
	
 | 
			
		||||
  if (a->cstring)
 | 
			
		||||
  {
 | 
			
		||||
    aptr = a->cstring;
 | 
			
		||||
    alen = strlen(a->cstring);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    aptr = a->lenstring.data;
 | 
			
		||||
    alen = a->lenstring.len;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  blen = strlen(bptr);
 | 
			
		||||
	
 | 
			
		||||
  return (alen == blen) && (strncmp(aptr, bptr, alen) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper function to read packet data from some source into a buffer
 | 
			
		||||
 * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
 * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
 * @param getfn pointer to a function which will read any number of bytes from the needed source
 | 
			
		||||
 * @return integer MQTT packet type, or -1 on error
 | 
			
		||||
 * @note  the whole message must fit into the caller's buffer
 | 
			
		||||
 */
 | 
			
		||||
int32_t MQTTPacket_read(uint8_t* buf, int32_t buflen, int32_t (*getfn)(uint8_t*, int32_t))
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = -1;
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t len = 0;
 | 
			
		||||
  int32_t rem_len = 0;
 | 
			
		||||
 | 
			
		||||
  /* 1. read the header byte.  This has the packet type in it */
 | 
			
		||||
  if ((*getfn)(buf, 1) != 1)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  len = 1;
 | 
			
		||||
  /* 2. read the remaining length.  This is variable in itself */
 | 
			
		||||
  MQTTPacket_decode(getfn, &rem_len);
 | 
			
		||||
  len += MQTTPacket_encode(buf + 1, rem_len); /* put the original remaining length back into the buffer */
 | 
			
		||||
 | 
			
		||||
  /* 3. read the rest of the buffer using a callback to supply the rest of the data */
 | 
			
		||||
  if((rem_len + len) > buflen)
 | 
			
		||||
    goto exit;
 | 
			
		||||
  if ((*getfn)(buf + len, rem_len) != rem_len)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  header.byte = buf[0];
 | 
			
		||||
  rc = header.bits.type;
 | 
			
		||||
exit:
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decodes the message length according to the MQTT algorithm, non-blocking
 | 
			
		||||
 * @param trp pointer to a transport structure holding what is needed to solve getting data from it
 | 
			
		||||
 * @param value the decoded length returned
 | 
			
		||||
 * @return integer the number of bytes read from the socket, 0 for call again, or -1 on error
 | 
			
		||||
 */
 | 
			
		||||
static int32_t MQTTPacket_decodenb(MQTTTransport *trp)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t c;
 | 
			
		||||
  int32_t rc = MQTTPACKET_READ_ERROR;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
  
 | 
			
		||||
  if (trp->len == 0)
 | 
			
		||||
  {		/* initialize on first call */
 | 
			
		||||
    trp->multiplier = 1;
 | 
			
		||||
    trp->rem_len = 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  do 
 | 
			
		||||
  {
 | 
			
		||||
    int32_t frc;
 | 
			
		||||
 | 
			
		||||
    if (trp->len >= MAX_NO_OF_REMAINING_LENGTH_BYTES)
 | 
			
		||||
      goto exit;
 | 
			
		||||
 | 
			
		||||
    if ((frc=(*trp->getfn)(trp->sck, &c, 1)) == -1)
 | 
			
		||||
      goto exit;
 | 
			
		||||
	
 | 
			
		||||
    if (frc == 0)
 | 
			
		||||
    {
 | 
			
		||||
      rc = 0;
 | 
			
		||||
      goto exit;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    ++(trp->len);
 | 
			
		||||
    trp->rem_len += (c & 127) * trp->multiplier;
 | 
			
		||||
    trp->multiplier *= 128;
 | 
			
		||||
  } while ((c & 128) != 0);
 | 
			
		||||
 | 
			
		||||
  rc = trp->len;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper function to read packet data from some source into a buffer, non-blocking
 | 
			
		||||
 * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
 * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
 * @param trp pointer to a transport structure holding what is needed to solve getting data from it
 | 
			
		||||
 * @return integer MQTT packet type, 0 for call again, or -1 on error
 | 
			
		||||
 * @note  the whole message must fit into the caller's buffer
 | 
			
		||||
 */
 | 
			
		||||
int32_t MQTTPacket_readnb(uint8_t* buf, int32_t buflen, MQTTTransport *trp)
 | 
			
		||||
{
 | 
			
		||||
  int32_t rc = -1, frc;
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
 | 
			
		||||
  switch (trp->state)
 | 
			
		||||
  {
 | 
			
		||||
    default:
 | 
			
		||||
      trp->state = 0;
 | 
			
		||||
      /*FALLTHROUGH*/
 | 
			
		||||
    case 0:
 | 
			
		||||
      /* read the header byte.  This has the packet type in it */
 | 
			
		||||
      if ((frc=(*trp->getfn)(trp->sck, buf, 1)) == -1)
 | 
			
		||||
        goto exit;
 | 
			
		||||
	
 | 
			
		||||
      if (frc == 0)
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
      trp->len = 0;
 | 
			
		||||
      ++trp->state;
 | 
			
		||||
	
 | 
			
		||||
      /*FALLTHROUGH*/
 | 
			
		||||
      /* read the remaining length.  This is variable in itself */
 | 
			
		||||
    case 1:
 | 
			
		||||
      if ((frc=MQTTPacket_decodenb(trp)) == MQTTPACKET_READ_ERROR)
 | 
			
		||||
	goto exit;
 | 
			
		||||
	
 | 
			
		||||
      if (frc == 0)
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
      trp->len = 1 + MQTTPacket_encode(buf + 1, trp->rem_len); /* put the original remaining length back into the buffer */
 | 
			
		||||
	
 | 
			
		||||
      if ((trp->rem_len + trp->len) > buflen)
 | 
			
		||||
	goto exit;
 | 
			
		||||
 | 
			
		||||
      ++trp->state;
 | 
			
		||||
      /*FALLTHROUGH*/
 | 
			
		||||
    case 2:
 | 
			
		||||
      /* read the rest of the buffer using a callback to supply the rest of the data */
 | 
			
		||||
      if ((frc=(*trp->getfn)(trp->sck, buf + trp->len, trp->rem_len)) == -1)
 | 
			
		||||
	goto exit;
 | 
			
		||||
	
 | 
			
		||||
      if (frc == 0)
 | 
			
		||||
	return 0;
 | 
			
		||||
	
 | 
			
		||||
      trp->rem_len -= frc;
 | 
			
		||||
      trp->len += frc;
 | 
			
		||||
      
 | 
			
		||||
      if (trp->rem_len)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
      header.byte = buf[0];
 | 
			
		||||
      rc = header.bits.type;
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
exit:
 | 
			
		||||
  trp->state = 0;
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										136
									
								
								Internet/MQTT/MQTTPacket/src/MQTTPacket.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								Internet/MQTT/MQTTPacket/src/MQTTPacket.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,136 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *    Xiang Rong - 442039 Add makefile to Embedded C client
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef MQTTPACKET_H_
 | 
			
		||||
#define MQTTPACKET_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(WIN32_DLL) || defined(WIN64_DLL)
 | 
			
		||||
  #define DLLImport __declspec(dllimport)
 | 
			
		||||
  #define DLLExport __declspec(dllexport)
 | 
			
		||||
#elif defined(LINUX_SO)
 | 
			
		||||
  #define DLLImport extern
 | 
			
		||||
  #define DLLExport  __attribute__ ((visibility ("default")))
 | 
			
		||||
#else
 | 
			
		||||
  #define DLLImport
 | 
			
		||||
  #define DLLExport  
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum errors
 | 
			
		||||
{
 | 
			
		||||
  MQTTPACKET_BUFFER_TOO_SHORT = -2,
 | 
			
		||||
  MQTTPACKET_READ_ERROR = -1,
 | 
			
		||||
  MQTTPACKET_READ_COMPLETE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum msgTypes
 | 
			
		||||
{
 | 
			
		||||
  CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, 
 | 
			
		||||
  SUBACK, UNSUBSCRIBE, UNSUBACK, PINGREQ, PINGRESP, DISCONNECT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Bitfields for the MQTT header byte.
 | 
			
		||||
 */
 | 
			
		||||
typedef union
 | 
			
		||||
{
 | 
			
		||||
  uint8_t byte;	                /**< the whole byte */
 | 
			
		||||
#if defined(REVERSED)
 | 
			
		||||
  struct
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t type        : 4;	/**< message type nibble */
 | 
			
		||||
    uint8_t dup         : 1;	/**< DUP flag bit */
 | 
			
		||||
    uint8_t qos         : 2;	/**< QoS value, 0, 1 or 2 */
 | 
			
		||||
    uint8_t retain      : 1;	/**< retained flag bit */
 | 
			
		||||
  } bits;
 | 
			
		||||
#else
 | 
			
		||||
  struct
 | 
			
		||||
  {
 | 
			
		||||
    uint8_t retain      : 1;	/**< retained flag bit */
 | 
			
		||||
    uint8_t qos         : 2;	/**< QoS value, 0, 1 or 2 */
 | 
			
		||||
    uint8_t dup         : 1;	/**< DUP flag bit */
 | 
			
		||||
    uint8_t type        : 4;	/**< message type nibble */
 | 
			
		||||
} bits;
 | 
			
		||||
#endif
 | 
			
		||||
} MQTTHeader;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  int32_t len;
 | 
			
		||||
  char* data;
 | 
			
		||||
} MQTTLenString;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  char* cstring;
 | 
			
		||||
  MQTTLenString lenstring;
 | 
			
		||||
} MQTTString;
 | 
			
		||||
 | 
			
		||||
#define MQTTString_initializer {NULL, {0, NULL}}
 | 
			
		||||
 | 
			
		||||
int32_t MQTTstrlen(MQTTString mqttstring);
 | 
			
		||||
 | 
			
		||||
#include "MQTTConnect.h"
 | 
			
		||||
#include "MQTTPublish.h"
 | 
			
		||||
#include "MQTTSubscribe.h"
 | 
			
		||||
#include "MQTTUnsubscribe.h"
 | 
			
		||||
#include "MQTTFormat.h"
 | 
			
		||||
 | 
			
		||||
int32_t MQTTSerialize_ack(uint8_t* buf, int32_t buflen, uint8_t type, uint8_t dup, uint16_t packetid);
 | 
			
		||||
int32_t MQTTDeserialize_ack(uint8_t* packettype, uint8_t* dup, uint16_t* packetid, uint8_t* buf, int32_t buflen);
 | 
			
		||||
 | 
			
		||||
int32_t MQTTPacket_len(int32_t rem_len);
 | 
			
		||||
int32_t MQTTPacket_equals(MQTTString* a, char* b);
 | 
			
		||||
 | 
			
		||||
int32_t MQTTPacket_encode(uint8_t* buf, int32_t length);
 | 
			
		||||
int32_t MQTTPacket_decode(int32_t (*getcharfn)(uint8_t*, int32_t), int32_t* value);
 | 
			
		||||
int32_t MQTTPacket_decodeBuf(uint8_t* buf, int32_t* value);
 | 
			
		||||
 | 
			
		||||
int32_t readInt(uint8_t** pptr);
 | 
			
		||||
char readChar(uint8_t** pptr);
 | 
			
		||||
void writeChar(uint8_t** pptr, char c);
 | 
			
		||||
void writeInt(uint8_t** pptr, int32_t anInt);
 | 
			
		||||
int32_t readMQTTLenString(MQTTString* mqttstring, uint8_t** pptr, uint8_t* enddata);
 | 
			
		||||
void writeCString(uint8_t** pptr, const char* string);
 | 
			
		||||
void writeMQTTString(uint8_t** pptr, MQTTString mqttstring);
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTPacket_read(uint8_t* buf, int32_t buflen, int32_t (*getfn)(uint8_t*, int32_t));
 | 
			
		||||
 | 
			
		||||
typedef struct 
 | 
			
		||||
{
 | 
			
		||||
  int32_t (*getfn)(void *, uint8_t*, int32_t); /* must return -1 for error, 0 for call again, or the number of bytes read */
 | 
			
		||||
  void *sck;	/* pointer to whatever the system may use to identify the transport */
 | 
			
		||||
  int32_t multiplier;
 | 
			
		||||
  int32_t rem_len;
 | 
			
		||||
  int32_t len;
 | 
			
		||||
  char state;
 | 
			
		||||
}MQTTTransport;
 | 
			
		||||
 | 
			
		||||
int32_t MQTTPacket_readnb(uint8_t* buf, int32_t buflen, MQTTTransport *trp);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* MQTTPACKET_H_ */
 | 
			
		||||
							
								
								
									
										38
									
								
								Internet/MQTT/MQTTPacket/src/MQTTPublish.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Internet/MQTT/MQTTPacket/src/MQTTPublish.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *    Xiang Rong - 442039 Add makefile to Embedded C client
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef MQTTPUBLISH_H_
 | 
			
		||||
#define MQTTPUBLISH_H_
 | 
			
		||||
 | 
			
		||||
#if !defined(DLLImport)
 | 
			
		||||
  #define DLLImport 
 | 
			
		||||
#endif
 | 
			
		||||
#if !defined(DLLExport)
 | 
			
		||||
  #define DLLExport
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTSerialize_publish(uint8_t* buf, int32_t buflen, uint8_t dup, uint8_t qos, uint8_t retained, uint16_t packetid,
 | 
			
		||||
		MQTTString topicName, uint8_t* payload, int32_t payloadlen);
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTDeserialize_publish(uint8_t* dup, uint8_t* qos, uint8_t* retained, uint16_t* packetid, MQTTString* topicName,
 | 
			
		||||
		uint8_t** payload, int32_t* payloadlen, uint8_t* buf, int32_t len);
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTSerialize_puback(uint8_t* buf, int32_t buflen, uint16_t packetid);
 | 
			
		||||
DLLExport int32_t MQTTSerialize_pubrel(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid);
 | 
			
		||||
DLLExport int32_t MQTTSerialize_pubcomp(uint8_t* buf, int32_t buflen, uint16_t packetid);
 | 
			
		||||
 | 
			
		||||
#endif /* MQTTPUBLISH_H_ */
 | 
			
		||||
							
								
								
									
										171
									
								
								Internet/MQTT/MQTTPacket/src/MQTTSerializePublish.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								Internet/MQTT/MQTTPacket/src/MQTTSerializePublish.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,171 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *    Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Determines the length of the MQTT publish packet that would be produced using the supplied parameters
 | 
			
		||||
  * @param qos the MQTT QoS of the publish (packetid is omitted for QoS 0)
 | 
			
		||||
  * @param topicName the topic name to be used in the publish  
 | 
			
		||||
  * @param payloadlen the length of the payload to be sent
 | 
			
		||||
  * @return the length of buffer needed to contain the serialized version of the packet
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_publishLength(uint8_t qos, MQTTString topicName, int32_t payloadlen)
 | 
			
		||||
{
 | 
			
		||||
  int32_t len = 2 + MQTTstrlen(topicName) + payloadlen;
 | 
			
		||||
  
 | 
			
		||||
  if (qos > 0)
 | 
			
		||||
    len += 2; /* packetid */
 | 
			
		||||
	
 | 
			
		||||
  return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes the supplied publish data into the supplied buffer, ready for sending
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
  * @param dup integer - the MQTT dup flag
 | 
			
		||||
  * @param qos integer - the MQTT QoS value
 | 
			
		||||
  * @param retained integer - the MQTT retained flag
 | 
			
		||||
  * @param packetid integer - the MQTT packet identifier
 | 
			
		||||
  * @param topicName MQTTString - the MQTT topic in the publish
 | 
			
		||||
  * @param payload byte buffer - the MQTT publish payload
 | 
			
		||||
  * @param payloadlen integer - the length of the MQTT payload
 | 
			
		||||
  * @return the length of the serialized data.  <= 0 indicates error
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_publish(uint8_t* buf, int32_t buflen, uint8_t dup, uint8_t qos, uint8_t retained, uint16_t packetid,
 | 
			
		||||
		MQTTString topicName, uint8_t* payload, int32_t payloadlen)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t *ptr = buf;
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t rem_len = 0;
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  if (MQTTPacket_len(rem_len = MQTTSerialize_publishLength(qos, topicName, payloadlen)) > buflen)
 | 
			
		||||
  {
 | 
			
		||||
    rc = MQTTPACKET_BUFFER_TOO_SHORT;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  header.bits.type = PUBLISH;
 | 
			
		||||
  header.bits.dup = dup;
 | 
			
		||||
  header.bits.qos = qos;
 | 
			
		||||
  header.bits.retain = retained;
 | 
			
		||||
  writeChar(&ptr, header.byte); /* write header */
 | 
			
		||||
 | 
			
		||||
  ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
 | 
			
		||||
 | 
			
		||||
  writeMQTTString(&ptr, topicName);
 | 
			
		||||
 | 
			
		||||
  if (qos > 0)
 | 
			
		||||
    writeInt(&ptr, packetid);
 | 
			
		||||
 | 
			
		||||
  memcpy(ptr, payload, payloadlen);
 | 
			
		||||
  ptr += payloadlen;
 | 
			
		||||
 | 
			
		||||
  rc = ptr - buf;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes the ack packet into the supplied buffer.
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
  * @param type the MQTT packet type
 | 
			
		||||
  * @param dup the MQTT dup flag
 | 
			
		||||
  * @param packetid the MQTT packet identifier
 | 
			
		||||
  * @return serialized length, or error if 0
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_ack(uint8_t* buf, int32_t buflen, uint8_t packettype, uint8_t dup, uint16_t packetid)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
  uint8_t *ptr = buf;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  if (buflen < 4)
 | 
			
		||||
  {
 | 
			
		||||
    rc = MQTTPACKET_BUFFER_TOO_SHORT;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  header.bits.type = packettype;
 | 
			
		||||
  header.bits.dup = dup;
 | 
			
		||||
  header.bits.qos = (packettype == PUBREL) ? 1 : 0;
 | 
			
		||||
  writeChar(&ptr, header.byte); /* write header */
 | 
			
		||||
 | 
			
		||||
  ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
 | 
			
		||||
  writeInt(&ptr, packetid);
 | 
			
		||||
  rc = ptr - buf;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes a puback packet into the supplied buffer.
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
  * @param packetid integer - the MQTT packet identifier
 | 
			
		||||
  * @return serialized length, or error if 0
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_puback(uint8_t* buf, int32_t buflen, uint16_t packetid)
 | 
			
		||||
{
 | 
			
		||||
  return MQTTSerialize_ack(buf, buflen, PUBACK, 0, packetid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes a pubrel packet into the supplied buffer.
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
  * @param dup integer - the MQTT dup flag
 | 
			
		||||
  * @param packetid integer - the MQTT packet identifier
 | 
			
		||||
  * @return serialized length, or error if 0
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_pubrel(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid)
 | 
			
		||||
{
 | 
			
		||||
  return MQTTSerialize_ack(buf, buflen, PUBREL, dup, packetid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes a pubrel packet into the supplied buffer.
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
  * @param packetid integer - the MQTT packet identifier
 | 
			
		||||
  * @return serialized length, or error if 0
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_pubcomp(uint8_t* buf, int32_t buflen, uint16_t packetid)
 | 
			
		||||
{
 | 
			
		||||
  return MQTTSerialize_ack(buf, buflen, PUBCOMP, 0, packetid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								Internet/MQTT/MQTTPacket/src/MQTTSubscribe.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								Internet/MQTT/MQTTPacket/src/MQTTSubscribe.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *    Xiang Rong - 442039 Add makefile to Embedded C client
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef MQTTSUBSCRIBE_H_
 | 
			
		||||
#define MQTTSUBSCRIBE_H_
 | 
			
		||||
 | 
			
		||||
#if !defined(DLLImport)
 | 
			
		||||
  #define DLLImport 
 | 
			
		||||
#endif
 | 
			
		||||
#if !defined(DLLExport)
 | 
			
		||||
  #define DLLExport
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTSerialize_subscribe(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid,
 | 
			
		||||
		int32_t count, MQTTString topicFilters[], int32_t requestedQoSs[]);
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTDeserialize_subscribe(uint8_t* dup, uint16_t* packetid,
 | 
			
		||||
		int32_t maxcount, int32_t* count, MQTTString topicFilters[], int32_t requestedQoSs[], uint8_t* buf, int32_t len);
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTSerialize_suback(uint8_t* buf, int32_t buflen, uint16_t packetid, int32_t count, int32_t* grantedQoSs);
 | 
			
		||||
DLLExport int32_t MQTTDeserialize_suback(uint16_t* packetid, int32_t maxcount, int32_t* count, int32_t grantedQoSs[], uint8_t* buf, int32_t len);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* MQTTSUBSCRIBE_H_ */
 | 
			
		||||
							
								
								
									
										140
									
								
								Internet/MQTT/MQTTPacket/src/MQTTSubscribeClient.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								Internet/MQTT/MQTTPacket/src/MQTTSubscribeClient.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Determines the length of the MQTT subscribe packet that would be produced using the supplied parameters
 | 
			
		||||
  * @param count the number of topic filter strings in topicFilters
 | 
			
		||||
  * @param topicFilters the array of topic filter strings to be used in the publish
 | 
			
		||||
  * @return the length of buffer needed to contain the serialized version of the packet
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_subscribeLength(int32_t count, MQTTString topicFilters[])
 | 
			
		||||
{
 | 
			
		||||
  int32_t len = 2; /* packetid */
 | 
			
		||||
 | 
			
		||||
  for (int32_t i = 0; i < count; ++i)
 | 
			
		||||
    len += 2 + MQTTstrlen(topicFilters[i]) + 1; /* length + topic + req_qos */
 | 
			
		||||
	
 | 
			
		||||
  return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes the supplied subscribe data into the supplied buffer, ready for sending
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied bufferr
 | 
			
		||||
  * @param dup integer - the MQTT dup flag
 | 
			
		||||
  * @param packetid integer - the MQTT packet identifier
 | 
			
		||||
  * @param count - number of members in the topicFilters and reqQos arrays
 | 
			
		||||
  * @param topicFilters - array of topic filter names
 | 
			
		||||
  * @param requestedQoSs - array of requested QoS
 | 
			
		||||
  * @return the length of the serialized data.  <= 0 indicates error
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_subscribe(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid, int32_t count,
 | 
			
		||||
		MQTTString topicFilters[], int32_t requestedQoSs[])
 | 
			
		||||
{
 | 
			
		||||
  uint8_t *ptr = buf;
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t rem_len = 0;
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  if (MQTTPacket_len(rem_len = MQTTSerialize_subscribeLength(count, topicFilters)) > buflen)
 | 
			
		||||
  {
 | 
			
		||||
    rc = MQTTPACKET_BUFFER_TOO_SHORT;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  header.byte = 0;
 | 
			
		||||
  header.bits.type = SUBSCRIBE;
 | 
			
		||||
  header.bits.dup = dup;
 | 
			
		||||
  header.bits.qos = 1;
 | 
			
		||||
  writeChar(&ptr, header.byte); /* write header */
 | 
			
		||||
 | 
			
		||||
  ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
 | 
			
		||||
 | 
			
		||||
  writeInt(&ptr, packetid);
 | 
			
		||||
 | 
			
		||||
  for (int32_t i = 0; i < count; ++i)
 | 
			
		||||
  {
 | 
			
		||||
    writeMQTTString(&ptr, topicFilters[i]);
 | 
			
		||||
    writeChar(&ptr, requestedQoSs[i]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  rc = ptr - buf;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Deserializes the supplied (wire) buffer into suback data
 | 
			
		||||
  * @param packetid returned integer - the MQTT packet identifier
 | 
			
		||||
  * @param maxcount - the maximum number of members allowed in the grantedQoSs array
 | 
			
		||||
  * @param count returned integer - number of members in the grantedQoSs array
 | 
			
		||||
  * @param grantedQoSs returned array of integers - the granted qualities of service
 | 
			
		||||
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
 | 
			
		||||
  * @param buflen the length in bytes of the data in the supplied buffer
 | 
			
		||||
  * @return error code.  1 is success, 0 is failure
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTDeserialize_suback(uint16_t* packetid, int32_t maxcount, int32_t* count, int32_t grantedQoSs[], uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  uint8_t* curdata = buf;
 | 
			
		||||
  uint8_t* enddata = NULL;
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
  int32_t mylen;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  header.byte = readChar(&curdata);
 | 
			
		||||
  if (header.bits.type != SUBACK)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
 | 
			
		||||
  enddata = curdata + mylen;
 | 
			
		||||
 | 
			
		||||
  if (enddata - curdata < 2)
 | 
			
		||||
    goto exit;
 | 
			
		||||
 | 
			
		||||
  *packetid = readInt(&curdata);
 | 
			
		||||
 | 
			
		||||
  *count = 0;
 | 
			
		||||
 | 
			
		||||
  while (curdata < enddata)
 | 
			
		||||
  {
 | 
			
		||||
    if (*count > maxcount)
 | 
			
		||||
    {
 | 
			
		||||
      rc = -1;
 | 
			
		||||
      goto exit;
 | 
			
		||||
    }
 | 
			
		||||
    grantedQoSs[(*count)++] = readChar(&curdata);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  rc = 1;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										114
									
								
								Internet/MQTT/MQTTPacket/src/MQTTSubscribeServer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								Internet/MQTT/MQTTPacket/src/MQTTSubscribeServer.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Deserializes the supplied (wire) buffer into subscribe data
 | 
			
		||||
  * @param dup integer returned - the MQTT dup flag
 | 
			
		||||
  * @param packetid integer returned - the MQTT packet identifier
 | 
			
		||||
  * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
 | 
			
		||||
  * @param count - number of members in the topicFilters and requestedQoSs arrays
 | 
			
		||||
  * @param topicFilters - array of topic filter names
 | 
			
		||||
  * @param requestedQoSs - array of requested QoS
 | 
			
		||||
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
 | 
			
		||||
  * @param buflen the length in bytes of the data in the supplied buffer
 | 
			
		||||
  * @return the length of the serialized data.  <= 0 indicates error
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTDeserialize_subscribe(uint8_t* dup, uint16_t* packetid, int32_t maxcount, int32_t* count, MQTTString topicFilters[],
 | 
			
		||||
	int32_t requestedQoSs[], uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  uint8_t* curdata = buf;
 | 
			
		||||
  uint8_t* enddata = NULL;
 | 
			
		||||
  int32_t rc = -1;
 | 
			
		||||
  int32_t mylen = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  header.byte = readChar(&curdata);
 | 
			
		||||
 | 
			
		||||
  if (header.bits.type != SUBSCRIBE)
 | 
			
		||||
    goto exit;
 | 
			
		||||
	
 | 
			
		||||
  *dup = header.bits.dup;
 | 
			
		||||
  curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
 | 
			
		||||
  enddata = curdata + mylen;
 | 
			
		||||
  *packetid = readInt(&curdata);
 | 
			
		||||
  *count = 0;
 | 
			
		||||
 | 
			
		||||
  while (curdata < enddata)
 | 
			
		||||
  {
 | 
			
		||||
    if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
 | 
			
		||||
      goto exit;
 | 
			
		||||
    
 | 
			
		||||
    if (curdata >= enddata) /* do we have enough data to read the req_qos version byte? */
 | 
			
		||||
      goto exit;
 | 
			
		||||
    
 | 
			
		||||
    requestedQoSs[*count] = readChar(&curdata);
 | 
			
		||||
    (*count)++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  rc = 1;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes the supplied suback data into the supplied buffer, ready for sending
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
  * @param packetid integer - the MQTT packet identifier
 | 
			
		||||
  * @param count - number of members in the grantedQoSs array
 | 
			
		||||
  * @param grantedQoSs - array of granted QoS
 | 
			
		||||
  * @return the length of the serialized data.  <= 0 indicates error
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_suback(uint8_t* buf, int32_t buflen, uint16_t packetid, int32_t count, int32_t* grantedQoSs)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t rc = -1;
 | 
			
		||||
  uint8_t *ptr = buf;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
	
 | 
			
		||||
  if (buflen < 2 + count)
 | 
			
		||||
  {
 | 
			
		||||
    rc = MQTTPACKET_BUFFER_TOO_SHORT;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  header.byte = 0;
 | 
			
		||||
  header.bits.type = SUBACK;
 | 
			
		||||
  writeChar(&ptr, header.byte); /* write header */
 | 
			
		||||
  ptr += MQTTPacket_encode(ptr, 2 + count); /* write remaining length */
 | 
			
		||||
  writeInt(&ptr, packetid);
 | 
			
		||||
 | 
			
		||||
  for (int32_t i = 0; i < count; ++i)
 | 
			
		||||
    writeChar(&ptr, grantedQoSs[i]);
 | 
			
		||||
 | 
			
		||||
  rc = ptr - buf;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										37
									
								
								Internet/MQTT/MQTTPacket/src/MQTTUnsubscribe.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Internet/MQTT/MQTTPacket/src/MQTTUnsubscribe.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *    Xiang Rong - 442039 Add makefile to Embedded C client
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef MQTTUNSUBSCRIBE_H_
 | 
			
		||||
#define MQTTUNSUBSCRIBE_H_
 | 
			
		||||
 | 
			
		||||
#if !defined(DLLImport)
 | 
			
		||||
  #define DLLImport 
 | 
			
		||||
#endif
 | 
			
		||||
#if !defined(DLLExport)
 | 
			
		||||
  #define DLLExport
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTSerialize_unsubscribe(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid,
 | 
			
		||||
		int32_t count, MQTTString topicFilters[]);
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTDeserialize_unsubscribe(uint8_t* dup, uint16_t* packetid, int32_t max_count, int32_t* count, MQTTString topicFilters[],
 | 
			
		||||
		uint8_t* buf, int32_t len);
 | 
			
		||||
 | 
			
		||||
DLLExport int32_t MQTTSerialize_unsuback(uint8_t* buf, int32_t buflen, uint16_t packetid);
 | 
			
		||||
DLLExport int32_t MQTTDeserialize_unsuback(uint16_t* packetid, uint8_t* buf, int32_t len);
 | 
			
		||||
 | 
			
		||||
#endif /* MQTTUNSUBSCRIBE_H_ */
 | 
			
		||||
							
								
								
									
										107
									
								
								Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeClient.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeClient.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Determines the length of the MQTT unsubscribe packet that would be produced using the supplied parameters
 | 
			
		||||
  * @param count the number of topic filter strings in topicFilters
 | 
			
		||||
  * @param topicFilters the array of topic filter strings to be used in the publish
 | 
			
		||||
  * @return the length of buffer needed to contain the serialized version of the packet
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_unsubscribeLength(int32_t count, MQTTString topicFilters[])
 | 
			
		||||
{
 | 
			
		||||
  int32_t len = 2; /* packetid */
 | 
			
		||||
 | 
			
		||||
  for (int32_t i = 0; i < count; ++i)
 | 
			
		||||
    len += 2 + MQTTstrlen(topicFilters[i]); /* length + topic*/
 | 
			
		||||
	
 | 
			
		||||
  return len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending
 | 
			
		||||
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
 | 
			
		||||
  * @param buflen the length in bytes of the data in the supplied buffer
 | 
			
		||||
  * @param dup integer - the MQTT dup flag
 | 
			
		||||
  * @param packetid integer - the MQTT packet identifier
 | 
			
		||||
  * @param count - number of members in the topicFilters array
 | 
			
		||||
  * @param topicFilters - array of topic filter names
 | 
			
		||||
  * @return the length of the serialized data.  <= 0 indicates error
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_unsubscribe(uint8_t* buf, int32_t buflen, uint8_t dup, uint16_t packetid,
 | 
			
		||||
		int32_t count, MQTTString topicFilters[])
 | 
			
		||||
{
 | 
			
		||||
  uint8_t *ptr = buf;
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t rem_len = 0;
 | 
			
		||||
  int32_t rc = -1;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  if (MQTTPacket_len(rem_len = MQTTSerialize_unsubscribeLength(count, topicFilters)) > buflen)
 | 
			
		||||
  {
 | 
			
		||||
    rc = MQTTPACKET_BUFFER_TOO_SHORT;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  header.byte = 0;
 | 
			
		||||
  header.bits.type = UNSUBSCRIBE;
 | 
			
		||||
  header.bits.dup = dup;
 | 
			
		||||
  header.bits.qos = 1;
 | 
			
		||||
  writeChar(&ptr, header.byte); /* write header */
 | 
			
		||||
  ptr += MQTTPacket_encode(ptr, rem_len); /* write remaining length */;
 | 
			
		||||
  writeInt(&ptr, packetid);
 | 
			
		||||
 | 
			
		||||
  for (int32_t i = 0; i < count; ++i)
 | 
			
		||||
    writeMQTTString(&ptr, topicFilters[i]);
 | 
			
		||||
 | 
			
		||||
  rc = ptr - buf;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Deserializes the supplied (wire) buffer into unsuback data
 | 
			
		||||
  * @param packetid returned integer - the MQTT packet identifier
 | 
			
		||||
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
 | 
			
		||||
  * @param buflen the length in bytes of the data in the supplied buffer
 | 
			
		||||
  * @return error code.  1 is success, 0 is failure
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTDeserialize_unsuback(uint16_t* packetid, uint8_t* buf, int32_t buflen)
 | 
			
		||||
{
 | 
			
		||||
  uint8_t type = 0;
 | 
			
		||||
  uint8_t dup = 0;
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
	
 | 
			
		||||
  rc = MQTTDeserialize_ack(&type, &dup, packetid, buf, buflen);
 | 
			
		||||
 | 
			
		||||
  if (type == UNSUBACK)
 | 
			
		||||
    rc = 1;
 | 
			
		||||
	
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										100
									
								
								Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeServer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								Internet/MQTT/MQTTPacket/src/MQTTUnsubscribeServer.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
#include "MQTTPacket.h"
 | 
			
		||||
#include "StackTrace.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Deserializes the supplied (wire) buffer into unsubscribe data
 | 
			
		||||
  * @param dup integer returned - the MQTT dup flag
 | 
			
		||||
  * @param packetid integer returned - the MQTT packet identifier
 | 
			
		||||
  * @param maxcount - the maximum number of members allowed in the topicFilters and requestedQoSs arrays
 | 
			
		||||
  * @param count - number of members in the topicFilters and requestedQoSs arrays
 | 
			
		||||
  * @param topicFilters - array of topic filter names
 | 
			
		||||
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
 | 
			
		||||
  * @param buflen the length in bytes of the data in the supplied buffer
 | 
			
		||||
  * @return the length of the serialized data.  <= 0 indicates error
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTDeserialize_unsubscribe(uint8_t* dup, uint16_t* packetid, int32_t maxcount, int32_t* count, MQTTString topicFilters[],
 | 
			
		||||
		uint8_t* buf, int32_t len)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  uint8_t* curdata = buf;
 | 
			
		||||
  uint8_t* enddata = NULL;
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
  int32_t mylen = 0;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  header.byte = readChar(&curdata);
 | 
			
		||||
  if (header.bits.type != UNSUBSCRIBE)
 | 
			
		||||
    goto exit;
 | 
			
		||||
  *dup = header.bits.dup;
 | 
			
		||||
 | 
			
		||||
  curdata += (rc = MQTTPacket_decodeBuf(curdata, &mylen)); /* read remaining length */
 | 
			
		||||
  enddata = curdata + mylen;
 | 
			
		||||
 | 
			
		||||
  *packetid = readInt(&curdata);
 | 
			
		||||
  *count = 0;
 | 
			
		||||
 | 
			
		||||
  while (curdata < enddata)
 | 
			
		||||
  {
 | 
			
		||||
    if (!readMQTTLenString(&topicFilters[*count], &curdata, enddata))
 | 
			
		||||
      goto exit;
 | 
			
		||||
    (*count)++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  rc = 1;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  * Serializes the supplied unsuback data into the supplied buffer, ready for sending
 | 
			
		||||
  * @param buf the buffer into which the packet will be serialized
 | 
			
		||||
  * @param buflen the length in bytes of the supplied buffer
 | 
			
		||||
  * @param packetid integer - the MQTT packet identifier
 | 
			
		||||
  * @return the length of the serialized data.  <= 0 indicates error
 | 
			
		||||
  */
 | 
			
		||||
int32_t MQTTSerialize_unsuback(uint8_t* buf, int32_t buflen, uint16_t packetid)
 | 
			
		||||
{
 | 
			
		||||
  MQTTHeader header = {0};
 | 
			
		||||
  int32_t rc = 0;
 | 
			
		||||
  uint8_t *ptr = buf;
 | 
			
		||||
 | 
			
		||||
  FUNC_ENTRY;
 | 
			
		||||
 | 
			
		||||
  if (buflen < 2)
 | 
			
		||||
  {
 | 
			
		||||
    rc = MQTTPACKET_BUFFER_TOO_SHORT;
 | 
			
		||||
    goto exit;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  header.byte = 0;
 | 
			
		||||
  header.bits.type = UNSUBACK;
 | 
			
		||||
  writeChar(&ptr, header.byte); /* write header */
 | 
			
		||||
  ptr += MQTTPacket_encode(ptr, 2); /* write remaining length */
 | 
			
		||||
  writeInt(&ptr, packetid);
 | 
			
		||||
 | 
			
		||||
  rc = ptr - buf;
 | 
			
		||||
exit:
 | 
			
		||||
  FUNC_EXIT_RC(rc);
 | 
			
		||||
  return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										78
									
								
								Internet/MQTT/MQTTPacket/src/StackTrace.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								Internet/MQTT/MQTTPacket/src/StackTrace.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 IBM Corp.
 | 
			
		||||
 *
 | 
			
		||||
 * All rights reserved. This program and the accompanying materials
 | 
			
		||||
 * are made available under the terms of the Eclipse Public License v1.0
 | 
			
		||||
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * The Eclipse Public License is available at
 | 
			
		||||
 *    http://www.eclipse.org/legal/epl-v10.html
 | 
			
		||||
 * and the Eclipse Distribution License is available at
 | 
			
		||||
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
 *
 | 
			
		||||
 * Contributors:
 | 
			
		||||
 *    Ian Craggs - initial API and implementation and/or initial documentation
 | 
			
		||||
 *    Ian Craggs - fix for bug #434081
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef STACKTRACE_H_
 | 
			
		||||
#define STACKTRACE_H_
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#define NOSTACKTRACE 1
 | 
			
		||||
 | 
			
		||||
#if defined(NOSTACKTRACE)
 | 
			
		||||
#define FUNC_ENTRY
 | 
			
		||||
#define FUNC_ENTRY_NOLOG
 | 
			
		||||
#define FUNC_ENTRY_MED
 | 
			
		||||
#define FUNC_ENTRY_MAX
 | 
			
		||||
#define FUNC_EXIT
 | 
			
		||||
#define FUNC_EXIT_NOLOG
 | 
			
		||||
#define FUNC_EXIT_MED
 | 
			
		||||
#define FUNC_EXIT_MAX
 | 
			
		||||
#define FUNC_EXIT_RC(x)
 | 
			
		||||
#define FUNC_EXIT_MED_RC(x)
 | 
			
		||||
#define FUNC_EXIT_MAX_RC(x)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#if defined(WIN32)
 | 
			
		||||
#define inline __inline
 | 
			
		||||
#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM)
 | 
			
		||||
#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1)
 | 
			
		||||
#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM)
 | 
			
		||||
#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM)
 | 
			
		||||
#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM)
 | 
			
		||||
#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1)
 | 
			
		||||
#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM)
 | 
			
		||||
#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM)
 | 
			
		||||
#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM)
 | 
			
		||||
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM)
 | 
			
		||||
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM)
 | 
			
		||||
#else
 | 
			
		||||
#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM)
 | 
			
		||||
#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1)
 | 
			
		||||
#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM)
 | 
			
		||||
#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM)
 | 
			
		||||
#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM)
 | 
			
		||||
#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1)
 | 
			
		||||
#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM)
 | 
			
		||||
#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM)
 | 
			
		||||
#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM)
 | 
			
		||||
#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM)
 | 
			
		||||
#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM)
 | 
			
		||||
 | 
			
		||||
void StackTrace_entry(const char* name, int32_t line, int32_t trace);
 | 
			
		||||
void StackTrace_exit(const char* name, int32_t line, void* return_value, int32_t trace);
 | 
			
		||||
 | 
			
		||||
void StackTrace_printStack(FILE* dest);
 | 
			
		||||
char* StackTrace_get(unsigned long);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* STACKTRACE_H_ */
 | 
			
		||||
							
								
								
									
										80
									
								
								Internet/MQTT/mqtt_interface.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								Internet/MQTT/mqtt_interface.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
#include "mqtt_interface.h"
 | 
			
		||||
#include "wizchip_conf.h"
 | 
			
		||||
#include "socket.h"
 | 
			
		||||
//#include <terminal_io.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "millis.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
uint32_t MilliTimer;
 | 
			
		||||
 | 
			
		||||
void MilliTimer_Handler(void) 
 | 
			
		||||
{
 | 
			
		||||
  MilliTimer++;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
int8_t expired(Timer* timer)
 | 
			
		||||
{
 | 
			
		||||
  int32_t left = (timer->end_time) - millis();
 | 
			
		||||
  return (left < 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void countdown_ms(Timer* timer, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
	timer->end_time = millis() + timeout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void countdown(Timer* timer, uint32_t timeout)
 | 
			
		||||
{
 | 
			
		||||
  timer->end_time = millis() + (timeout * 1000UL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t left_ms(Timer* timer)
 | 
			
		||||
{
 | 
			
		||||
  int32_t left = timer->end_time - millis();
 | 
			
		||||
  return (left < 0) ? 0 : left;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void InitTimer(Timer* timer)
 | 
			
		||||
{
 | 
			
		||||
  timer->end_time = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void NewNetwork(Network* n)
 | 
			
		||||
{
 | 
			
		||||
  //n->my_socket = 0; //initialized outside actually..
 | 
			
		||||
  n->mqttread = w5500_read;
 | 
			
		||||
  n->mqttwrite = w5500_write;
 | 
			
		||||
  n->disconnect = w5500_disconnect;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t w5500_read(Network* n, uint8_t* buffer, int32_t len, int32_t timeout_ms)
 | 
			
		||||
{
 | 
			
		||||
  if ((getSn_SR(n->my_socket) == SOCK_ESTABLISHED) && (getSn_RX_RSR(n->my_socket) > 0))
 | 
			
		||||
    return recv(n->my_socket, buffer, len);
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t w5500_write(Network* n, uint8_t* buffer, int32_t len, int32_t timeout_ms)
 | 
			
		||||
{
 | 
			
		||||
  if (getSn_SR(n->my_socket) == SOCK_ESTABLISHED)
 | 
			
		||||
    return send(n->my_socket, buffer, len);
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void w5500_disconnect(Network* n)
 | 
			
		||||
{
 | 
			
		||||
  disconnect(n->my_socket);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int32_t ConnectNetwork(Network* n, uint8_t* ip, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
  socket(n->my_socket, Sn_MR_TCP, 12345, 0);
 | 
			
		||||
  connect(n->my_socket, ip, port);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								Internet/MQTT/mqtt_interface.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								Internet/MQTT/mqtt_interface.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
#ifndef __MQTT_INTERFACE_H_
 | 
			
		||||
#define __MQTT_INTERFACE_H_
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
typedef struct Timer Timer;
 | 
			
		||||
 | 
			
		||||
struct Timer 
 | 
			
		||||
{
 | 
			
		||||
  uint32_t systick_period;
 | 
			
		||||
  uint32_t end_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct Network Network;
 | 
			
		||||
 | 
			
		||||
struct Network
 | 
			
		||||
{
 | 
			
		||||
  int32_t my_socket;
 | 
			
		||||
  int32_t (*mqttread) (Network*, uint8_t*, int32_t, int32_t);
 | 
			
		||||
  int32_t (*mqttwrite) (Network*, uint8_t*, int32_t, int32_t);
 | 
			
		||||
  void (*disconnect) (Network*);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void InitTimer(Timer*);
 | 
			
		||||
/*
 | 
			
		||||
void MilliTimer_Handler(void); 
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
int8_t expired(Timer*);
 | 
			
		||||
void countdown_ms(Timer*, uint32_t);
 | 
			
		||||
void countdown(Timer*, uint32_t);
 | 
			
		||||
int32_t left_ms(Timer*);
 | 
			
		||||
 | 
			
		||||
int32_t w5500_read(Network*, uint8_t*, int32_t, int32_t);
 | 
			
		||||
int32_t w5500_write(Network*, uint8_t*, int32_t, int32_t);
 | 
			
		||||
void w5500_disconnect(Network*);
 | 
			
		||||
void NewNetwork(Network*);
 | 
			
		||||
 | 
			
		||||
int32_t ConnectNetwork(Network*, uint8_t*, uint16_t);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user