Exemple #1
0
mqtt_message_t* mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id)
{
    init_message(connection);

    if (topic == NULL || topic[0] == '\0')
        return fail_message(connection);

    if (append_string(connection, topic, strlen(topic)) < 0)
        return fail_message(connection);

    if (qos > 0)
    {
        if ((*message_id = append_message_id(connection, 0)) == 0)
            return fail_message(connection);
    }
    else
        *message_id = 0;

    if (connection->message.length + data_length > connection->buffer_length) {
        // Not enough size in buffer -> fragment this message
        connection->message.fragmented_msg_data_offset = connection->message.length;
        memcpy(connection->buffer + connection->message.length, data, connection->buffer_length - connection->message.length);
        connection->message.length = connection->buffer_length;
        connection->message.fragmented_msg_total_length = data_length + connection->message.fragmented_msg_data_offset;
    } else {
        memcpy(connection->buffer + connection->message.length, data, data_length);
        connection->message.length += data_length;
        connection->message.fragmented_msg_total_length = 0;
    }
    return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain);
}
mqtt_message_t* mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id)
{
  init_message(connection);

  if(topic == NULL || topic[0] == '\0')
    return fail_message(connection);

  if(append_string(connection, topic, c_strlen(topic)) < 0)
    return fail_message(connection);

  if(qos > 0)
  {
    if((*message_id = append_message_id(connection, 0)) == 0)
      return fail_message(connection);
  }
  else
    *message_id = 0;

  if(connection->message.length + data_length > connection->buffer_length)
    return fail_message(connection);
  c_memcpy(connection->buffer + connection->message.length, data, data_length);
  connection->message.length += data_length;

  return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain);
}
Exemple #3
0
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection,
		uint16_t message_id) {
	if (init_message(connection) == 0) {
		return fail_message(connection);
	}
	if (append_message_id(connection, message_id) == 0)
		return fail_message(connection);
	return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0);
}
void file_sync_service(int fd, void *cookie)
{
    syncmsg msg;
    char name[1025];
    unsigned namelen;

    char *buffer = malloc(SYNC_DATA_MAX);
    if(buffer == 0) goto fail;

    for(;;) {
        D("sync: waiting for command\n");

        if(readx(fd, &msg.req, sizeof(msg.req))) {
            fail_message(fd, "command read failure");
            break;
        }
        namelen = ltohl(msg.req.namelen);
        if(namelen > 1024) {
            fail_message(fd, "invalid namelen");
            break;
        }
        if(readx(fd, name, namelen)) {
            fail_message(fd, "filename read failure");
            break;
        }
        name[namelen] = 0;

        msg.req.namelen = 0;
        D("sync: '%s' '%s'\n", (char*) &msg.req, name);

        switch(msg.req.id) {
        case ID_STAT:
            if(do_stat(fd, name)) goto fail;
            break;
        case ID_LIST:
            if(do_list(fd, name)) goto fail;
            break;
        case ID_SEND:
            if(do_send(fd, name, buffer)) goto fail;
            break;
        case ID_RECV:
            if(do_recv(fd, name, buffer)) goto fail;
            break;
        case ID_QUIT:
            goto fail;
        default:
            fail_message(fd, "unknown command");
            goto fail;
        }
    }

fail:
    if(buffer != 0) free(buffer);
    D("sync: done\n");
    adb_close(fd);
}
mqtt_message_t* mqtt_msg_unsubscribe_topic(mqtt_connection_t* connection, const char* topic)
{
  if(topic == NULL || topic[0] == '\0')
    return fail_message(connection);

  if(append_string(connection, topic, c_strlen(topic)) < 0)
    return fail_message(connection);

  return &connection->message;
}
Exemple #6
0
static int handle_send_link(int s, char *path, char *buffer)
{
    syncmsg msg;
    unsigned int len;
    int ret;

    if(readx(s, &msg.data, sizeof(msg.data)))
        return -1;

    if(msg.data.id != ID_DATA) {
        fail_message(s, "invalid data message: expected ID_DATA");
        return -1;
    }

    len = ltohl(msg.data.size);
    if(len > SYNC_DATA_MAX) {
        fail_message(s, "oversize data message");
        return -1;
    }
    if(readx(s, buffer, len))
        return -1;

    ret = symlink(buffer, path);
    if(ret && errno == ENOENT) {
        if(mkdirs(path) != 0) {
            fail_errno(s);
            return -1;
        }
        ret = symlink(buffer, path);
    }
    if(ret) {
        fail_errno(s);
        return -1;
    }

    if(readx(s, &msg.data, sizeof(msg.data)))
        return -1;

    if(msg.data.id == ID_DONE) {
        msg.status.id = ID_OKAY;
        msg.status.msglen = 0;
        if(writex(s, &msg.status, sizeof(msg.status)))
            return -1;
    } else {
        fail_message(s, "invalid data message: expected ID_DONE");
        return -1;
    }

    return 0;
}
mqtt_message_t* mqtt_msg_subscribe_topic(mqtt_connection_t* connection, const char* topic, int qos)
{
  if(topic == NULL || topic[0] == '\0')
    return fail_message(connection);

  if(append_string(connection, topic, c_strlen(topic)) < 0)
    return fail_message(connection);

  if(connection->message.length + 1 > connection->buffer_length)
    return fail_message(connection);
  connection->buffer[connection->message.length++] = qos;

  return &connection->message;
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id)
{
  init_message(connection);

  if(topic == NULL || topic[0] == '\0')
    return fail_message(connection);

  if((*message_id = append_message_id(connection, 0)) == 0)
    return fail_message(connection);

  if(append_string(connection, topic, strlen(topic)) < 0)
    return fail_message(connection);

  return fini_message(connection, MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0);
}
mqtt_message_t* mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id)
{
  init_message(connection);
  if(append_message_id(connection, message_id) == 0)
    return fail_message(connection);
  return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0);
}
Exemple #10
0
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id)
{
  init_message(connection);
  if(append_message_id(connection, message_id) == 0)
    return fail_message(connection);
  return fini_message(connection, MQTT_MSG_TYPE_PUBREL, 0, 1, 0);
}
mqtt_message_t* mqtt_msg_subscribe_init(mqtt_connection_t* connection, uint16_t *message_id)
{
  init_message(connection);

  if((*message_id = append_message_id(connection, 0)) == 0)
    return fail_message(connection);

  return &connection->message;
}
Exemple #12
0
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id)
{
  init_message(connection);

  if(topic == NULL || topic[0] == '\0')
    return fail_message(connection);

  if((*message_id = append_message_id(connection, 0)) == 0)
    return fail_message(connection);

  if(append_string(connection, topic, strlen(topic)) < 0)
    return fail_message(connection);

  if(connection->message.length + 1 > connection->buffer_length)
    return fail_message(connection);
  connection->buffer[connection->message.length++] = qos;

  return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0);
}
Exemple #13
0
static mqtt_message_t* fini_message(mqtt_connection_t* connection, int type, int dup, int qos, int retain)
{
    int message_length = connection->message.length - MQTT_MAX_FIXED_HEADER_SIZE;
    int total_length = message_length;
    int encoded_length = 0;
    uint8_t encoded_lens[4] = {0};
    // Check if we have fragmented message and update total_len
    if (connection->message.fragmented_msg_total_length) {
        total_length = connection->message.fragmented_msg_total_length - MQTT_MAX_FIXED_HEADER_SIZE;
    }

    // Encode MQTT message length
    int len_bytes = 0; // size of encoded message length
    do {
        encoded_length = total_length % 128;
        total_length /= 128;
        if (total_length > 0) {
            encoded_length |= 0x80;
        }
        encoded_lens[len_bytes] = encoded_length;
        len_bytes++;
    } while (total_length > 0);

    // Sanity check for MQTT header
    if (len_bytes + 1 > MQTT_MAX_FIXED_HEADER_SIZE) {
        return fail_message(connection);
    }

    // Save the header bytes
    connection->message.length = message_length + len_bytes + 1; // msg len + encoded_size len + type (1 byte)
    int offs = MQTT_MAX_FIXED_HEADER_SIZE - 1 - len_bytes;
    connection->message.data = connection->buffer + offs;
    connection->message.fragmented_msg_data_offset -= offs;
    // type byte
    connection->buffer[offs++] =  ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1);
    // length bytes
    for (int j = 0; j<len_bytes; j++) {
        connection->buffer[offs++] = encoded_lens[j];
    }

    return &connection->message;
}
Exemple #14
0
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection) {
	if (init_message(connection) == 0) {
		return fail_message(connection);
	}
	return fini_message(connection, MQTT_MSG_TYPE_DISCONNECT, 0, 0, 0);
}
mqtt_message_t* mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info)
{
  struct mqtt_connect_variable_header* variable_header;

  init_message(connection);

  if(connection->message.length + sizeof(*variable_header) > connection->buffer_length)
    return fail_message(connection);
  variable_header = (void*)(connection->buffer + connection->message.length);
  connection->message.length += sizeof(*variable_header);

  variable_header->lengthMsb = 0;
  variable_header->lengthLsb = 4;
  c_memcpy(variable_header->magic, "MQTT", 4);
  variable_header->version = 4;
  variable_header->flags = 0;
  variable_header->keepaliveMsb = info->keepalive >> 8;
  variable_header->keepaliveLsb = info->keepalive & 0xff;

  if(info->clean_session)
    variable_header->flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;

  if(info->client_id != NULL && info->client_id[0] != '\0')
  {
    if(append_string(connection, info->client_id, c_strlen(info->client_id)) < 0)
      return fail_message(connection);
  }
  else
    return fail_message(connection);

  if(info->will_topic != NULL && info->will_topic[0] != '\0')
  {
    if(append_string(connection, info->will_topic, c_strlen(info->will_topic)) < 0)
      return fail_message(connection);

    if(append_string(connection, info->will_message, c_strlen(info->will_message)) < 0)
      return fail_message(connection);

    variable_header->flags |= MQTT_CONNECT_FLAG_WILL;
    if(info->will_retain)
      variable_header->flags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
    variable_header->flags |= (info->will_qos & 3) << 3;
  }

  if(info->username != NULL && info->username[0] != '\0')
  {
    if(append_string(connection, info->username, c_strlen(info->username)) < 0)
      return fail_message(connection);

    variable_header->flags |= MQTT_CONNECT_FLAG_USERNAME;
  }

  if(info->password != NULL && info->password[0] != '\0')
  {
    if(append_string(connection, info->password, c_strlen(info->password)) < 0)
      return fail_message(connection);

    variable_header->flags |= MQTT_CONNECT_FLAG_PASSWORD;
  }

  return fini_message(connection, MQTT_MSG_TYPE_CONNECT, 0, 0, 0);
}
Exemple #16
0
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection) {
	if (init_message(connection) == 0) {
		return fail_message(connection);
	}
	return fini_message(connection, MQTT_MSG_TYPE_PINGRESP, 0, 0, 0);
}
Exemple #17
0
static int handle_send_file(int s, char *path, uid_t uid,
        gid_t gid, mode_t mode, char *buffer, bool do_unlink)
{
    syncmsg msg;
    unsigned int timestamp = 0;
    int fd;

    fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
    if(fd < 0 && errno == ENOENT) {
        if(mkdirs(path) != 0) {
            if(fail_errno(s))
                return -1;
            fd = -1;
        } else {
            fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
        }
    }
    if(fd < 0 && errno == EEXIST) {
        fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode);
    }
    if(fd < 0) {
        if(fail_errno(s))
            return -1;
        fd = -1;
    } else {
        if(fchown(fd, uid, gid) != 0) {
            fail_errno(s);
            errno = 0;
        }

        /*
         * fchown clears the setuid bit - restore it if present.
         * Ignore the result of calling fchmod. It's not supported
         * by all filesystems. b/12441485
         */
        fchmod(fd, mode);
    }

    for(;;) {
        unsigned int len;

        if(readx(s, &msg.data, sizeof(msg.data)))
            goto fail;

        if(msg.data.id != ID_DATA) {
            if(msg.data.id == ID_DONE) {
                timestamp = ltohl(msg.data.size);
                break;
            }
            fail_message(s, "invalid data message");
            goto fail;
        }
        len = ltohl(msg.data.size);

        if(syc_size_enabled == 1) {
            if(len > SYNC_DATA_MAX) {
                fail_message(s, "oversize data message");
                goto fail;
            } else {
                unsigned int total = 0;
                while (total < len) {
                    int count = len - total;
                    if (count > SYNC_DATA_MAX_CUSTOMIZE) {
                        count = SYNC_DATA_MAX_CUSTOMIZE;
                    }

                    if(readx(s, buffer, count))
                        goto fail;

                    if(fd < 0)
                        continue;
                    if(writex(fd, buffer, count)) {
                        int saved_errno = errno;
                        adb_close(fd);
                        if (do_unlink) adb_unlink(path);
                        fd = -1;
                        errno = saved_errno;
                        if(fail_errno(s)) return -1;
                    }

                    total += count;
                }
            }
        }else {
        if(len > SYNC_DATA_MAX) {
            fail_message(s, "oversize data message");
            goto fail;
        }
        if(readx(s, buffer, len))
            goto fail;

        if(fd < 0)
            continue;
        if(writex(fd, buffer, len)) {
            int saved_errno = errno;
            adb_close(fd);
            if (do_unlink) adb_unlink(path);
            fd = -1;
            errno = saved_errno;
            if(fail_errno(s)) return -1;
        }
    }
    }

    if(fd >= 0) {
        struct utimbuf u;
        adb_close(fd);
        selinux_android_restorecon(path, 0);
        u.actime = timestamp;
        u.modtime = timestamp;
        utime(path, &u);

        msg.status.id = ID_OKAY;
        msg.status.msglen = 0;
        if(writex(s, &msg.status, sizeof(msg.status)))
            return -1;
    }
    return 0;

fail:
    if(fd >= 0)
        adb_close(fd);
    if (do_unlink) adb_unlink(path);
    return -1;
}
Exemple #18
0
static int fail_errno(int s)
{
    return fail_message(s, strerror(errno));
}
static int handle_send_file(int s, char *path, mode_t mode, char *buffer)
{
    syncmsg msg;
    unsigned int timestamp = 0;
    int fd;

    fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
    if(fd < 0 && errno == ENOENT) {
        mkdirs(path);
        fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode);
    }
    if(fd < 0 && errno == EEXIST) {
        fd = adb_open_mode(path, O_WRONLY, mode);
    }
    if(fd < 0) {
        if(fail_errno(s))
            return -1;
        fd = -1;
    }

    for(;;) {
        unsigned int len;

        if(readx(s, &msg.data, sizeof(msg.data)))
            goto fail;

        if(msg.data.id != ID_DATA) {
            if(msg.data.id == ID_DONE) {
                timestamp = ltohl(msg.data.size);
                break;
            }
            fail_message(s, "invalid data message");
            goto fail;
        }
        len = ltohl(msg.data.size);
        if(len > SYNC_DATA_MAX) {
            fail_message(s, "oversize data message");
            goto fail;
        }
        if(readx(s, buffer, len))
            goto fail;

        if(fd < 0)
            continue;
        if(writex(fd, buffer, len)) {
            int saved_errno = errno;
            adb_close(fd);
            adb_unlink(path);
            fd = -1;
            errno = saved_errno;
            if(fail_errno(s)) return -1;
        }
    }

    if(fd >= 0) {
        struct utimbuf u;
        adb_close(fd);
        u.actime = timestamp;
        u.modtime = timestamp;
        utime(path, &u);

        msg.status.id = ID_OKAY;
        msg.status.msglen = 0;
        if(writex(s, &msg.status, sizeof(msg.status)))
            return -1;
    }
    return 0;

fail:
    if(fd >= 0)
        adb_close(fd);
    adb_unlink(path);
    return -1;
}