int
main(void)
{
    struct lgtd_client *client;
    client = lgtd_tests_insert_mock_client(FAKE_BUFFEREVENT);
    struct lgtd_proto_target_list *targets = (void *)0x2a;

    lgtd_proto_get_light_state(client, targets);

    const char expected[] = "[]";

    if (client_write_buf_idx != sizeof(expected) - 1) {
        lgtd_errx(
            1, "%d bytes written, expected %lu",
            client_write_buf_idx, sizeof(expected) - 1UL
        );
    }

    if (memcmp(expected, client_write_buf, sizeof(expected) - 1)) {
        lgtd_errx(
            1, "got %.*s instead of %s",
            client_write_buf_idx, client_write_buf, expected
        );
    }

    return 0;
}
struct lgtd_router_device_list *
lgtd_router_targets_to_devices(const struct lgtd_proto_target_list *targets)
{
    if (targets != (void *)0x2a) {
        lgtd_errx(1, "unexpected targets list");
    }

    static struct lgtd_router_device_list devices =
        SLIST_HEAD_INITIALIZER(&devices);

    static struct lgtd_lifx_gateway gw_bulb_1 = {
        .bulbs = LIST_HEAD_INITIALIZER(&gw_bulb_1.bulbs),
        .peeraddr = "[::ffff:127.0.0.1]:1"
    };
    static struct lgtd_lifx_bulb bulb_1 = {
        .addr = { 1, 2, 3, 4, 5 },
        .state = {
            .hue = 0xaaaa,
            .saturation = 0xffff,
            .brightness = 0xbbbb,
            .kelvin = 3600,
            .label = "wave",
            .power = LGTD_LIFX_POWER_ON,
            .tags = 5
        },
        .gw = &gw_bulb_1
    };
struct lgtd_router_device_list *
lgtd_router_targets_to_devices(const struct lgtd_proto_target_list *targets)
{
    if (targets != FAKE_TARGET_LIST) {
        lgtd_errx(1, "unexpected targets list");
    }

    return &device_1_only;
}
void
lgtd_router_device_list_free(struct lgtd_router_device_list *devices)
{
    if (!devices) {
        lgtd_errx(1, "the device list must be passed");
    }

    device_list_free_called = true;
}
struct lgtd_router_device_list *
lgtd_router_targets_to_devices(const struct lgtd_proto_target_list *targets)
{
    if (targets != (void *)0x2a) {
        lgtd_errx(1, "unexpected targets list");
    }

    static struct lgtd_router_device_list devices =
        SLIST_HEAD_INITIALIZER(&devices);

    return &devices;
}
int
main(void)
{
    lgtd_lifx_wire_load_packet_info_map();

    struct lgtd_lifx_gateway *gw_1 = lgtd_tests_insert_mock_gateway(1);
    struct lgtd_lifx_bulb *bulb_1 = lgtd_tests_insert_mock_bulb(gw_1, 1);
    struct lgtd_lifx_gateway *gw_2 = lgtd_tests_insert_mock_gateway(2);
    lgtd_tests_insert_mock_bulb(gw_2, 2);

    struct lgtd_lifx_packet_power_state payload = {
        .power = LGTD_LIFX_POWER_ON
    };
    struct lgtd_proto_target_list *targets;
    targets = lgtd_tests_build_target_list("1", NULL);
    lgtd_router_send(targets, LGTD_LIFX_SET_POWER_STATE, &payload);

    if (lgtd_tests_gw_pkt_queue_size != 1) {
        lgtd_errx(1, "1 packet should have been sent");
    }

    struct lgtd_lifx_gateway *recpt_gw = lgtd_tests_gw_pkt_queue[0].gw;
    struct lgtd_lifx_packet_header *hdr_queued = lgtd_tests_gw_pkt_queue[0].hdr;
    const void *pkt_queued = lgtd_tests_gw_pkt_queue[0].pkt;
    int pkt_size = lgtd_tests_gw_pkt_queue[0].pkt_size;

    if (recpt_gw != gw_1) {
        lgtd_errx(1, "the packet has been sent to the wrong gateway");
    }

    if (!lgtd_tests_lifx_header_has_flags(hdr_queued, LGTD_LIFX_ADDRESSABLE)) {
        lgtd_errx(1, "the packet header doesn't have the right protocol flags");
    }

    if (memcmp(hdr_queued->target.device_addr, bulb_1->addr, sizeof(bulb_1->addr))) {
        lgtd_errx(1, "the packet header doesn't have the right target address");
    }

    if (memcmp(gw_1->site.as_array, hdr_queued->site, sizeof(hdr_queued->site))) {
        lgtd_errx(1, "incorrect site in the headers");
    }

    if (pkt_queued != &payload) {
        lgtd_errx(1, "invalid payload");
    }

    if (pkt_size != sizeof(payload)) {
        lgtd_errx(
            1, "unexpected pkt size %d (expected %ju)",
            pkt_size, (uintmax_t)sizeof(payload)
        );
    }

    return 0;
}
Example #7
0
int
main(int argc, char *argv[], char *envp[])
{
    char progname[32] = { 0 };
    memcpy(progname, argv[0], LGTD_MIN(sizeof(progname) - 1, strlen(argv[0])));

    lgtd_daemon_setup_proctitle(argc, argv, envp);

    lgtd_configure_libevent();
    lgtd_setup_signal_handling();

    static const struct option long_opts[] = {
        {"listen",          required_argument, NULL, 'l'},
        {"command-pipe",    required_argument, NULL, 'c'},
        {"socket",          required_argument, NULL, 's'},
        {"foreground",      no_argument,       NULL, 'f'},
        {"daemonize",       no_argument,       NULL, 'd'},
        {"pidfile",         required_argument, NULL, 'p'},
        {"user",            required_argument, NULL, 'u'},
        {"group",           required_argument, NULL, 'g'},
        {"syslog",          no_argument,       NULL, 'S'},
        {"syslog-facility", required_argument, NULL, 'F'},
        {"syslog-ident",    required_argument, NULL, 'I'},
        {"no-timestamps",   no_argument,       NULL, 't'},
        {"help",            no_argument,       NULL, 'h'},
        {"verbosity",       required_argument, NULL, 'v'},
        {"version",         no_argument,       NULL, 'V'},
        {"prefix",          no_argument,       NULL, 'P'},
        {"rundir",          no_argument,       NULL, 'r'},
        {NULL,              0,                 NULL, 0}
    };
    const char short_opts[] = "l:c:s:fdp:u:g:SF:I:thv:V";

    if (argc == 1) {
        lgtd_usage(progname);
    }

    for (int rv = getopt_long(argc, argv, short_opts, long_opts, NULL);
         rv != -1;
         rv = getopt_long(argc, argv, short_opts, long_opts, NULL)) {
        switch (rv) {
        case 'l':
            (void)0;
            char *sep = strrchr(optarg, ':');
            if (!sep || !sep[1]) {
                lgtd_usage(progname);
            }
            *sep = '\0';
            if (!lgtd_listen_open(optarg, sep + 1)) {
                exit(1);
            }
            break;
        case 'c':
            if (!lgtd_command_pipe_open(optarg)) {
                exit(1);
            }
            break;
        case 's':
            if (!lgtd_listen_unix_open(optarg)) {
                exit(1);
            }
            break;
        case 'f':
            lgtd_opts.foreground = true;
            break;
        case 'd':
            lgtd_opts.foreground = false;
            break;
        case 'p':
            lgtd_opts.pidfile = optarg;
            break;
        case 'u':
            lgtd_opts.user = optarg;
            break;
        case 'g':
            lgtd_opts.group = optarg;
            break;
        case 'S':
            lgtd_opts.syslog = true;
            break;
        case 'F':
            lgtd_opts.syslog_facility = lgtd_daemon_syslog_facilitytoi(optarg);
            break;
        case 'I':
            lgtd_opts.syslog_ident = optarg;
            break;
        case 't':
            lgtd_opts.log_timestamps = false;
            break;
        case 'h':
            lgtd_usage(progname);
        case 'v':
            for (int i = 0;;) {
                const char *verbose_levels[] = {
                    "debug", "info", "warning", "error"
                };
                if (!strcasecmp(optarg, verbose_levels[i])) {
                    lgtd_opts.verbosity = i;
                    break;
                }
                if (++i == LGTD_ARRAY_SIZE(verbose_levels)) {
                    lgtd_errx(1, "Unknown verbosity level: %s", optarg);
                }
            }
            break;
        case 'V':
            printf("%s %s\n", progname, LGTD_VERSION);
            lgtd_cleanup();
            return 0;
        case 'P':
            printf(
                "%s%s\n", LGTD_INSTALL_PREFIX, LGTD_INSTALL_PREFIX[
                    LGTD_ARRAY_SIZE(LGTD_INSTALL_PREFIX) - 1
                ] != '/' ?  "/" : ""
            );
            return 0;
        case 'r':
            printf(
                "%s%s\n", LGTD_RUNTIME_DIRECTORY, LGTD_RUNTIME_DIRECTORY[
                    LGTD_ARRAY_SIZE(LGTD_RUNTIME_DIRECTORY) - 1
                ] != '/' ?  "/" : ""
            );
            return 0;
        default:
            lgtd_usage(progname);
        }
    }

    argc -= optind;
    argv += optind;

    // Ideally we should parse the syslog relation options first and call that
    // before anything can be logged:
    lgtd_log_setup();

    if (lgtd_opts.user) {
        lgtd_daemon_set_user(lgtd_opts.user);
        lgtd_daemon_set_group(lgtd_opts.group);
        // create the pidfile before we drop privileges:
        if (lgtd_opts.pidfile
            && !lgtd_daemon_write_pidfile(lgtd_opts.pidfile)) {
            lgtd_warn("couldn't write pidfile at %s", lgtd_opts.pidfile);
        }
        lgtd_daemon_drop_privileges();
    } else if (lgtd_opts.group) {
        lgtd_errx(1, "please, specify an user with the -u option");
    }

    lgtd_daemon_die_if_running_as_root_unless_requested(lgtd_opts.user);

    lgtd_lifx_wire_setup();
    if (!lgtd_lifx_discovery_setup() || !lgtd_lifx_broadcast_setup()) {
        lgtd_err(1, "can't setup lightsd");
    }

    if (!lgtd_opts.foreground) {
        lgtd_info("forking into the background now...");
        if (!lgtd_daemon_unleash()) {
            lgtd_err(1, "can't fork to the background");
        }
    }

    // update the pidfile after we've forked:
    if (lgtd_opts.pidfile && !lgtd_daemon_write_pidfile(lgtd_opts.pidfile)) {
        lgtd_warn("couldn't write pidfile at %s", lgtd_opts.pidfile);
    }

    lgtd_lifx_discovery_start();

    // update at least once: so that if no bulbs are discovered we still get a
    // clear status line.
    lgtd_daemon_update_proctitle();

    event_base_dispatch(lgtd_ev_base);

    if (lgtd_last_signal_received) {
        lgtd_info(
            "received signal %d (%s), exiting...",
            lgtd_last_signal_received, strsignal(lgtd_last_signal_received)
        );
    }

    lgtd_cleanup();

    return 0;
}
int
main(void)
{
    lgtd_lifx_wire_setup();

    struct lgtd_lifx_gateway *gw_1 = lgtd_tests_insert_mock_gateway(1);
    struct lgtd_lifx_bulb *bulb_1 = lgtd_tests_insert_mock_bulb(gw_1, 1);
    struct lgtd_lifx_gateway *gw_2 = lgtd_tests_insert_mock_gateway(2);
    struct lgtd_lifx_bulb *bulb_2 = lgtd_tests_insert_mock_bulb(gw_2, 2);
    struct lgtd_lifx_bulb *bulb_3 = lgtd_tests_insert_mock_bulb(gw_2, 3);

    const char *label = "feed";
    strcpy(bulb_1->state.label, label);
    strcpy(bulb_3->state.label, label);
    strcpy(bulb_2->state.label, "trololo");

    struct lgtd_lifx_packet_power_state payload = {
        .power = LGTD_LIFX_POWER_ON
    };
    struct lgtd_proto_target_list *targets;
    targets = lgtd_tests_build_target_list(label, NULL);
    lgtd_router_send(targets, LGTD_LIFX_SET_POWER_STATE, &payload);

    if (lgtd_tests_gw_pkt_queue_size != 2) {
        lgtd_errx(1, "2 packet should have been sent");
    }

    for (int i = 0; i != lgtd_tests_gw_pkt_queue_size; i++) {
        struct lgtd_lifx_gateway *recpt_gw = lgtd_tests_gw_pkt_queue[0].gw;
        struct lgtd_lifx_packet_header *hdr_queued = lgtd_tests_gw_pkt_queue[0].hdr;
        const void *pkt_queued = lgtd_tests_gw_pkt_queue[0].pkt;
        int pkt_size = lgtd_tests_gw_pkt_queue[0].pkt_size;


    int expected_flags = LGTD_LIFX_ADDRESSABLE|LGTD_LIFX_RES_REQUIRED;
        if (!lgtd_tests_lifx_header_has_flags(hdr_queued, expected_flags)) {
            lgtd_errx(1, "the packet header doesn't have the right protocol flags");
        }
        if (pkt_queued != &payload) {
            lgtd_errx(1, "invalid payload");
        }
        if (pkt_size != sizeof(payload)) {
            lgtd_errx(
                1, "unexpected pkt size %d (expected %ju)",
                pkt_size, (uintmax_t)sizeof(payload)
            );
        }

        if (recpt_gw == gw_1) {
            if (memcmp(hdr_queued->target.device_addr, bulb_1->addr, sizeof(bulb_1->addr))) {
                lgtd_errx(1, "the packet header doesn't have the right target address");
            }
            if (memcmp(gw_1->site.as_array, hdr_queued->site, sizeof(hdr_queued->site))) {
                lgtd_errx(1, "incorrect site in the headers");
            }
        } else if (recpt_gw == gw_2) {
            if (memcmp(hdr_queued->target.device_addr, bulb_3->addr, sizeof(bulb_3->addr))) {
                lgtd_errx(1, "the packet header doesn't have the right target address");
            }
            if (memcmp(gw_2->site.as_array, hdr_queued->site, sizeof(hdr_queued->site))) {
                lgtd_errx(1, "incorrect site in the headers");
            }
        }
    }

    return 0;
}