Exemple #1
0
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);
}
Exemple #2
0
/**
 * 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);
}
Exemple #3
0
/**
 * 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);
}
Exemple #4
0
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);
}
Exemple #5
0
/**
 * 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);
}
Exemple #6
0
/**
 * 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;
}
Exemple #7
0
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;
}
Exemple #8
0
/**
 * 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);
}
Exemple #9
0
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);
}
Exemple #10
0
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);
}
Exemple #11
0
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"));
}
Exemple #12
0
/**
 * 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");
}