void fb_mqtt_unsubscribe(FbMqtt *mqtt, const gchar *topic1, ...) { const gchar *topic; FbMqttMessage *msg; FbMqttPrivate *priv; va_list ap; g_return_if_fail(FB_IS_MQTT(mqtt)); g_return_if_fail(fb_mqtt_connected(mqtt, FALSE)); priv = mqtt->priv; /* Facebook requires a message identifier, use QoS1 */ msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_UNSUBSCRIBE, FB_MQTT_MESSAGE_FLAG_QOS1); fb_mqtt_message_write_mid(msg, &priv->mid); /* Message identifier */ fb_mqtt_message_write_str(msg, topic1); /* First topic */ va_start(ap, topic1); while ((topic = va_arg(ap, const gchar*)) != NULL) { fb_mqtt_message_write_str(msg, topic); /* Remaining topics */ } va_end(ap); fb_mqtt_write(mqtt, msg); g_object_unref(msg); }
/** * Unsubscribes from one or more topics. * * @param mqtt The #fb_mqtt. * @param topic1 The first topic name. * @param ... Additional topic names, NULL-terminated. **/ void fb_mqtt_unsubscribe(fb_mqtt_t *mqtt, const gchar *topic1, ...) { fb_mqtt_msg_t *msg; va_list ap; const gchar *topic; g_return_if_fail(mqtt != NULL); if (G_UNLIKELY(!fb_mqtt_connected(mqtt, TRUE))) return; /* Facebook requires a message identifier, use QoS1 */ msg = fb_mqtt_msg_new(FB_MQTT_MSG_TYPE_UNSUBSCRIBE, FB_MQTT_MSG_FLAG_QOS1); fb_mqtt_msg_write_mid(msg, &mqtt->mid); /* Message identifier */ fb_mqtt_msg_write_str(msg, topic1); /* First topic */ va_start(ap, topic1); while ((topic = va_arg(ap, const gchar*)) != NULL) fb_mqtt_msg_write_str(msg, topic); /* Remaining topics */ va_end(ap); fb_mqtt_write(mqtt, msg); fb_mqtt_msg_free(msg); }
/** * Connects to the MQTT service. This first establishes an SSL based * socket. Then it sends the initial connection packet with optional * arguments, which correspond to the flags provided. The arguments * must be passed in order: client identifier, will topic, will * message, username, and password (not required). The arguments must * be in a string format. * * @param mqtt The #fb_mqtt. * @param timeout The keep-alive timeout (seconds). * @param flags The #fb_mqtt_connect_flags. * @param cid The client identifier. * @param ... Additional arguments in order, NULL-terminated. **/ void fb_mqtt_connect(fb_mqtt_t *mqtt, guint8 flags, const gchar *cid, ...) { fb_mqtt_msg_t *msg; va_list ap; const gchar *str; g_return_if_fail(mqtt != NULL); if (G_UNLIKELY(fb_mqtt_connected(mqtt, FALSE))) return; /* Facebook always sends a CONNACK, use QoS1 */ flags |= FB_MQTT_CONNECT_FLAG_QOS1; msg = fb_mqtt_msg_new(FB_MQTT_MSG_TYPE_CONNECT, 0); fb_mqtt_msg_write_str(msg, FB_MQTT_NAME); /* Protocol name */ fb_mqtt_msg_write_byte(msg, FB_MQTT_VERS); /* Protocol version */ fb_mqtt_msg_write_byte(msg, flags); /* Flags */ fb_mqtt_msg_write_u16(msg, FB_MQTT_KA); /* Keep alive */ fb_mqtt_msg_write_str(msg, cid); /* Client identifier */ va_start(ap, cid); while ((str = va_arg(ap, const gchar*)) != NULL) fb_mqtt_msg_write_str(msg, str); va_end(ap); fb_mqtt_write(mqtt, msg); fb_mqtt_msg_free(msg); fb_mqtt_timeout(mqtt); }
void fb_mqtt_disconnect(FbMqtt *mqtt) { FbMqttMessage *msg; if (G_UNLIKELY(!fb_mqtt_connected(mqtt, FALSE))) { return; } msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_DISCONNECT, 0); fb_mqtt_write(mqtt, msg); g_object_unref(msg); fb_mqtt_close(mqtt); }
/** * Disconnects from the MQTT service. This cleanly disconnects from the * MQTT services, rather than killing the socket stream. This closes * the #fb_mqtt via #fb_mqtt_close(). * * @param mqtt The #fb_mqtt. **/ void fb_mqtt_disconnect(fb_mqtt_t *mqtt) { fb_mqtt_msg_t *msg; g_return_if_fail(mqtt != NULL); if (G_UNLIKELY(!fb_mqtt_connected(mqtt, FALSE))) return; msg = fb_mqtt_msg_new(FB_MQTT_MSG_TYPE_DISCONNECT, 0); fb_mqtt_write(mqtt, msg); fb_mqtt_msg_free(msg); fb_mqtt_close(mqtt); }
/** * Implemented #b_event_handler for sending a PING request. * * @param data The user defined data, which is #fb_mqtt. * @param fd The event file descriptor. * @param cond The #b_input_condition. * * @return FALSE to prevent continued event handling. **/ static gboolean fb_mqtt_cb_ping(gpointer data, gint fd, b_input_condition cond) { fb_mqtt_t *mqtt = data; fb_mqtt_msg_t *msg; msg = fb_mqtt_msg_new(FB_MQTT_MSG_TYPE_PINGREQ, 0); fb_mqtt_write(mqtt, msg); fb_mqtt_msg_free(msg); mqtt->tev = 0; fb_mqtt_timeout(mqtt); return FALSE; }
static gboolean fb_mqtt_cb_ping(gpointer data) { FbMqtt *mqtt = data; FbMqttMessage *msg; FbMqttPrivate *priv = mqtt->priv; msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_PINGREQ, 0); fb_mqtt_write(mqtt, msg); g_object_unref(msg); priv->tev = 0; fb_mqtt_timeout(mqtt); return FALSE; }
/** * Publishes a message to MQTT service. * * @param mqtt The #fb_mqtt. * @param topic The message topic. * @param pload The #GByteArray payload or NULL. **/ void fb_mqtt_publish(fb_mqtt_t *mqtt, const gchar *topic, const GByteArray *pload) { fb_mqtt_msg_t *msg; g_return_if_fail(mqtt != NULL); if (G_UNLIKELY(!fb_mqtt_connected(mqtt, TRUE))) return; /* Message identifier not required, but for consistency use QoS1 */ msg = fb_mqtt_msg_new(FB_MQTT_MSG_TYPE_PUBLISH, FB_MQTT_MSG_FLAG_QOS1); fb_mqtt_msg_write_str(msg, topic); /* Message topic */ fb_mqtt_msg_write_mid(msg, &mqtt->mid); /* Message identifier */ if (pload != NULL) fb_mqtt_msg_write(msg, pload->data, pload->len); fb_mqtt_write(mqtt, msg); fb_mqtt_msg_free(msg); }
void fb_mqtt_connect(FbMqtt *mqtt, guint8 flags, const GByteArray *pload) { FbMqttMessage *msg; g_return_if_fail(!fb_mqtt_connected(mqtt, FALSE)); g_return_if_fail(pload != NULL); /* Facebook always sends a CONNACK, use QoS1 */ flags |= FB_MQTT_CONNECT_FLAG_QOS1; msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_CONNECT, 0); fb_mqtt_message_write_str(msg, FB_MQTT_NAME); /* Protocol name */ fb_mqtt_message_write_byte(msg, FB_MQTT_LEVEL); /* Protocol level */ fb_mqtt_message_write_byte(msg, flags); /* Flags */ fb_mqtt_message_write_u16(msg, FB_MQTT_KA); /* Keep alive */ fb_mqtt_message_write(msg, pload->data, pload->len); fb_mqtt_write(mqtt, msg); fb_mqtt_timeout(mqtt); g_object_unref(msg); }
void fb_mqtt_publish(FbMqtt *mqtt, const gchar *topic, const GByteArray *pload) { FbMqttMessage *msg; FbMqttPrivate *priv; g_return_if_fail(FB_IS_MQTT(mqtt)); g_return_if_fail(fb_mqtt_connected(mqtt, FALSE)); priv = mqtt->priv; /* Message identifier not required, but for consistency use QoS1 */ msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_PUBLISH, FB_MQTT_MESSAGE_FLAG_QOS1); fb_mqtt_message_write_str(msg, topic); /* Message topic */ fb_mqtt_message_write_mid(msg, &priv->mid); /* Message identifier */ if (pload != NULL) { fb_mqtt_message_write(msg, pload->data, pload->len); } fb_mqtt_write(mqtt, msg); g_object_unref(msg); }
void fb_mqtt_read(FbMqtt *mqtt, FbMqttMessage *msg) { FbMqttMessage *nsg; FbMqttPrivate *priv; FbMqttMessagePrivate *mriv; GByteArray *wytes; gchar *str; guint8 chr; guint16 mid; g_return_if_fail(FB_IS_MQTT(mqtt)); g_return_if_fail(FB_IS_MQTT_MESSAGE(msg)); priv = mqtt->priv; mriv = msg->priv; fb_util_debug_hexdump(FB_UTIL_DEBUG_INFO, mriv->bytes, "Reading %d (flags: 0x%0X)", mriv->type, mriv->flags); switch (mriv->type) { case FB_MQTT_MESSAGE_TYPE_CONNACK: if (!fb_mqtt_message_read_byte(msg, NULL) || !fb_mqtt_message_read_byte(msg, &chr)) { break; } if (chr != FB_MQTT_ERROR_SUCCESS) { fb_mqtt_error(mqtt, chr, _("Connection failed (%u)"), chr); return; } priv->connected = TRUE; fb_mqtt_ping(mqtt); g_signal_emit_by_name(mqtt, "connect"); return; case FB_MQTT_MESSAGE_TYPE_PUBLISH: if (!fb_mqtt_message_read_str(msg, &str)) { break; } if ((mriv->flags & FB_MQTT_MESSAGE_FLAG_QOS1) || (mriv->flags & FB_MQTT_MESSAGE_FLAG_QOS2)) { if (mriv->flags & FB_MQTT_MESSAGE_FLAG_QOS1) { chr = FB_MQTT_MESSAGE_TYPE_PUBACK; } else { chr = FB_MQTT_MESSAGE_TYPE_PUBREC; } if (!fb_mqtt_message_read_mid(msg, &mid)) { break; } nsg = fb_mqtt_message_new(chr, 0); fb_mqtt_message_write_u16(nsg, mid); fb_mqtt_write(mqtt, nsg); g_object_unref(nsg); } wytes = g_byte_array_new(); fb_mqtt_message_read_r(msg, wytes); g_signal_emit_by_name(mqtt, "publish", str, wytes); g_byte_array_free(wytes, TRUE); g_free(str); return; case FB_MQTT_MESSAGE_TYPE_PUBREL: if (!fb_mqtt_message_read_mid(msg, &mid)) { break; } nsg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_PUBCOMP, 0); fb_mqtt_message_write_u16(nsg, mid); /* Message identifier */ fb_mqtt_write(mqtt, nsg); g_object_unref(nsg); return; case FB_MQTT_MESSAGE_TYPE_PINGRESP: fb_mqtt_ping(mqtt); return; case FB_MQTT_MESSAGE_TYPE_PUBACK: case FB_MQTT_MESSAGE_TYPE_PUBCOMP: case FB_MQTT_MESSAGE_TYPE_SUBACK: case FB_MQTT_MESSAGE_TYPE_UNSUBACK: return; default: fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL, _("Unknown packet (%u)"), mriv->type); return; } /* Since no case returned, there was a parse error. */ fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL, _("Failed to parse message")); }
/** * Read a #GByteArray to the #fb_mqtt. * * @param mqtt The #fb_mqtt. * @param bytes The #GByteArray. **/ void fb_mqtt_read(fb_mqtt_t *mqtt, fb_mqtt_msg_t *msg) { fb_mqtt_msg_t *nsg; GByteArray *wytes; gchar *str; guint8 chr; guint16 mid; g_return_if_fail(mqtt != NULL); g_return_if_fail(msg != NULL); fb_util_hexdump(msg->bytes, 2, "Reading %d (flags: 0x%0X)", msg->type, msg->flags); switch (msg->type) { case FB_MQTT_MSG_TYPE_CONNACK: if (!fb_mqtt_msg_read_byte(msg, NULL) || !fb_mqtt_msg_read_byte(msg, &chr)) { break; } if (chr != FB_MQTT_ERROR_SUCCESS) { fb_mqtt_error(mqtt, chr, "Connection failed (%u)", chr); return; } mqtt->connected = TRUE; fb_mqtt_ping(mqtt); FB_MQTT_FUNC(mqtt, connack); return; case FB_MQTT_MSG_TYPE_PUBLISH: if (!fb_mqtt_msg_read_str(msg, &str)) break; if ((msg->flags & FB_MQTT_MSG_FLAG_QOS1) || (msg->flags & FB_MQTT_MSG_FLAG_QOS2)) { if (msg->flags & FB_MQTT_MSG_FLAG_QOS1) chr = FB_MQTT_MSG_TYPE_PUBACK; else chr = FB_MQTT_MSG_TYPE_PUBREC; if (!fb_mqtt_msg_read_mid(msg, &mid)) break; nsg = fb_mqtt_msg_new(chr, 0); fb_mqtt_msg_write_u16(nsg, mid); fb_mqtt_write(mqtt, nsg); fb_mqtt_msg_free(nsg); } wytes = g_byte_array_new(); fb_mqtt_msg_read_r(msg, wytes); FB_MQTT_FUNC(mqtt, publish, str, wytes); g_byte_array_free(wytes, TRUE); g_free(str); return; case FB_MQTT_MSG_TYPE_PUBREL: if (!fb_mqtt_msg_read_mid(msg, &mid)) break; nsg = fb_mqtt_msg_new(FB_MQTT_MSG_TYPE_PUBCOMP, 0); fb_mqtt_msg_write_u16(nsg, mid); /* Message identifier */ fb_mqtt_write(mqtt, nsg); fb_mqtt_msg_free(nsg); return; case FB_MQTT_MSG_TYPE_PINGRESP: fb_mqtt_ping(mqtt); return; case FB_MQTT_MSG_TYPE_PUBACK: case FB_MQTT_MSG_TYPE_PUBCOMP: case FB_MQTT_MSG_TYPE_SUBACK: case FB_MQTT_MSG_TYPE_UNSUBACK: return; default: fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL, "Unknown packet (%u)", msg->type); return; } /* Since no case returned, there was a parse error. */ fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL, "Failed to parse message"); }