error_t mqttSnClientDisconnect(MqttSnClientContext *context)
{
   error_t error;
   systime_t time;

   //Make sure the MQTT-SN client context is valid
   if(context == NULL)
      return ERROR_INVALID_PARAMETER;

   //Initialize status code
   error = NO_ERROR;

   //Disconnect procedure
   while(!error)
   {
      //Get current time
      time = osGetSystemTime();

      //Check current state
      if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
      {
         //Save current time
         context->startTime = time;

         //The DISCONNECT message is sent by a client to indicate that it
         //wants to close the connection
         error = mqttSnClientSendDisconnect(context, 0);
      }
      else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
      {
         //Check whether the timeout has elapsed
         if(timeCompare(time, context->startTime + context->timeout) >= 0)
         {
            //Terminate DTLS connection
            mqttSnClientShutdownConnection(context);

            //Report a timeout error
            error = ERROR_TIMEOUT;
         }
         else if(timeCompare(time, context->retransmitStartTime +
            MQTT_SN_CLIENT_RETRY_TIMEOUT) >= 0)
         {
            //If the retry timer times out and the expected gateway's reply
            //is not received, the client retransmits the message
            error = mqttSnClientSendDisconnect(context, 0);
         }
         else
         {
            //Wait for the gateway's reply
            error = mqttSnClientProcessEvents(context, MQTT_SN_CLIENT_TICK_INTERVAL);
         }
      }
      else if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTING)
      {
         //Terminate DTLS connection
         error = mqttSnClientShutdownConnection(context);
         //Close network connection
         mqttSnClientCloseConnection(context);

         //The connection is closed
         context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
      }
      else if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTED)
      {
         //The MQTT-SN client is disconnected
         break;
      }
      else
      {
         //Invalid state
         error = ERROR_WRONG_STATE;
      }
   }

   //Any error to report?
   if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
   {
      //Close network connection
      mqttSnClientCloseConnection(context);
      //Update MQTT-SN client state
      context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
   }

   //Return status code
   return error;
}
error_t mqttSnClientDisconnect(MqttSnClientContext *context)
{
   error_t error;
   systime_t time;

    
   if(context == NULL)
      return ERROR_INVALID_PARAMETER;

    
   error = NO_ERROR;

    
   while(!error)
   {
       
      time = osGetSystemTime();

       
      if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
      {
          
         context->startTime = time;

          
          
         error = mqttSnClientSendDisconnect(context, 0);
      }
      else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
      {
          
         if(timeCompare(time, context->startTime + context->timeout) >= 0)
         {
             
            mqttSnClientShutdownConnection(context);

             
            error = ERROR_TIMEOUT;
         }
         else if(timeCompare(time, context->retransmitStartTime +
            MQTT_SN_CLIENT_RETRY_TIMEOUT) >= 0)
         {
             
             
            error = mqttSnClientSendDisconnect(context, 0);
         }
         else
         {
             
            error = mqttSnClientProcessEvents(context, MQTT_SN_CLIENT_TICK_INTERVAL);
         }
      }
      else if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTING)
      {
          
         error = mqttSnClientShutdownConnection(context);
          
         mqttSnClientCloseConnection(context);

          
         context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
      }
      else if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTED)
      {
          
         break;
      }
      else
      {
          
         error = ERROR_WRONG_STATE;
      }
   }

    
   if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
   {
       
      mqttSnClientCloseConnection(context);
       
      context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
   }

    
   return error;
}