Exemple #1
0
static void
listen_callback(
    int socket_id,
    void *cookie,
    int read_ready,
    int write_ready,
    int error_seen)
{
    AIM_LOG_TRACE("Accepting CLI client");

    int fd;
    if ((fd = accept(listen_socket, NULL, NULL)) < 0) {
        AIM_LOG_ERROR("Failed to accept on CLI socket: %s", strerror(errno));
        return;
    }

    struct client *client = aim_zmalloc(sizeof(*client));
    client->fd = fd;
    client->write_pvs = aim_pvs_buffer_create();
    client->ucli = ucli_create("ivs", NULL, NULL);

    indigo_error_t rv = ind_soc_socket_register(fd, client_callback, client);
    if (rv < 0) {
        AIM_LOG_ERROR("Failed to register CLI client socket: %s", indigo_strerror(rv));
        return;
    }
}
Exemple #2
0
/**
 * Basic output function for all log messages.
 */
static void
aim_log_output__(aim_log_t* l, const char* fname, const char* file,
                 int line, const char* fmt, va_list vargs)
{
    aim_pvs_t* msg;
    char* pmsg;

    msg = aim_pvs_buffer_create();
    if(AIM_BIT_GET(l->options, AIM_LOG_OPTION_TIMESTAMP)) {
        aim_log_time__(msg);
    }
    aim_vprintf(msg, fmt, vargs);
    if(l->options & (1 << AIM_LOG_OPTION_FUNC)) {
        aim_printf(msg, " [%s]", fname);
    }
    if(l->options & (1 << AIM_LOG_OPTION_FILE_LINE)) {
        aim_printf(msg, " [%s:%d]", file, line);
    }
    aim_printf(msg, "\n");
    pmsg = aim_pvs_buffer_get(msg);
    aim_printf(l->pvs, "%s", pmsg);
    aim_free(pmsg);
    aim_pvs_destroy(msg);
}
Exemple #3
0
static void
client_callback(
    int socket_id,
    void *cookie,
    int read_ready,
    int write_ready,
    int error_seen)
{
    struct client *client = cookie;
    AIM_ASSERT(socket_id == client->fd);

    if (error_seen) {
        int socket_error = 0;
        socklen_t len = sizeof(socket_error);
        getsockopt(socket_id, SOL_SOCKET, SO_ERROR, &socket_error, &len);
        AIM_LOG_INFO("Error seen on CLI socket: %s", strerror(socket_error));
        destroy_client(client);
        return;
    }

    if (read_ready) {
        int c;
        if ((c = read(client->fd, client->read_buffer+client->read_buffer_offset,
                      READ_BUFFER_SIZE - client->read_buffer_offset)) < 0) {
            AIM_LOG_ERROR("read failed: %s", strerror(errno));
            return;
        }

        client->read_buffer_offset += c;

        if (c == 0) {
            /* Peer has shutdown their write side */
            if (client->write_buffer_len == 0 &&
                    aim_pvs_buffer_size(client->write_pvs) == 0) {
                destroy_client(client);
            } else {
                /* We'll destroy the client once we've finished writing to it */
                ind_soc_data_in_pause(client->fd);
                client->read_finished = true;
            }
            return;
        }

        /* Process each complete line */
        char *newline;
        char *start = client->read_buffer;
        int remaining = client->read_buffer_offset;
        while ((newline = memchr(start, '\n', remaining))) {
            *newline = '\0';
            ucli_dispatch_string(client->ucli, client->write_pvs, start);
            remaining -= newline - start + 1;
            start = newline + 1;
        }

        /* Move incomplete line (which may be empty) to the beginning of the read buffer */
        if (client->read_buffer != start) {
            memmove(client->read_buffer, start, remaining);
            client->read_buffer_offset = remaining;
        } else if (client->read_buffer_offset == READ_BUFFER_SIZE) {
            AIM_LOG_WARN("Disconnecting CLI client due to too-long line");
            destroy_client(client);
            return;
        }

        if (aim_pvs_buffer_size(client->write_pvs) > 0) {
            ind_soc_data_out_ready(socket_id);
        }
    }

    if (write_ready) {
        /* Copy PVS data into our write buffer and reset PVS */
        if (client->write_buffer == NULL) {
            client->write_buffer = aim_pvs_buffer_get(client->write_pvs);
            client->write_buffer_len = aim_pvs_buffer_size(client->write_pvs);
            client->write_buffer_offset = 0;
            /* aim_pvs_buffer_reset has a bug, workaround it */
            aim_pvs_destroy(client->write_pvs);
            client->write_pvs = aim_pvs_buffer_create();
        }

        int c = send(client->fd,
                     client->write_buffer+client->write_buffer_offset,
                     client->write_buffer_len-client->write_buffer_offset,
                     MSG_NOSIGNAL);
        if (c <= 0) {
            AIM_LOG_ERROR("write failed: %s", strerror(errno));
            destroy_client(client);
            return;
        }

        client->write_buffer_offset += c;

        /* Free our write buffer if we're finished with it */
        if (client->write_buffer_len == client->write_buffer_offset) {
            aim_free(client->write_buffer);
            client->write_buffer_len = client->write_buffer_offset = 0;
            client->write_buffer = NULL;
            if (aim_pvs_buffer_size(client->write_pvs) == 0) {
                ind_soc_data_out_clear(client->fd);
                if (client->read_finished) {
                    destroy_client(client);
                }
            }
        }
    }
}
Exemple #4
0
int aim_main(int argc, char* argv[])
{
    int i;

    {
        const char* tstStrings[] = { "This", "is", "a", "complete", "sentence." };
        char* join = aim_strjoin(" ", tstStrings, AIM_ARRAYSIZE(tstStrings));
        if(strcmp(join, "This is a complete sentence.")) {
            printf("fail: join='%s'\n", join);
        }
        AIM_FREE(join);
    }

    for(i = 0; i < argc; i++) {
        aim_printf(&aim_pvs_stdout, "arg%d: '%s'\n", i, argv[i]);
    }

    {
        /* Test data */
        char data[2500];
        memset(data, 0xFF, sizeof(data));
        aim_printf(&aim_pvs_stdout, "data is %{data}", data, sizeof(data));
    }

    {
        char* sdata = "DEADBEEFCAFE";
        char* data;
        int size;
        aim_sparse(&sdata, &aim_pvs_stdout, "{data}", &data, &size);
        aim_printf(&aim_pvs_stdout, "data is %{data}\n", data, size);
        aim_free(data);
    }

    utest_list();

    AIM_LOG_MSG("Should print 1-27");
    AIM_LOG_MSG("%d %d %d %d %d %d %d %d %d "
                "%d %d %d %d %d %d %d %d %d "
                "%d %d %d %d %d %d %d %d %d",
                1, 2, 3, 4, 5, 6, 7, 8, 9,
                10, 11, 12, 13, 14, 15, 16, 17, 18,
                19, 20, 21, 22, 23, 24, 25, 26, 27);


    aim_printf(&aim_pvs_stdout, "aim_pvs_stdout from %s:%d\n",
               __FILE__, __LINE__);


    {
        char c;
        aim_pvs_t* pvs = aim_pvs_buffer_create();
        aim_printf(pvs, "\nConsider ");
        aim_printf(pvs, "%s ", "the");
        aim_printf(pvs, "alphabet: ");
        for(c = 'A'; c <= 'Z'; c++) {
            aim_printf(pvs, "%c", c);
        }
        aim_printf(pvs, "\n");
        {
            char* s = aim_pvs_buffer_get(pvs);
            aim_printf(&aim_pvs_stdout, "first: %s", s);
            free(s);
            aim_printf(pvs, "(second)");
            s = aim_pvs_buffer_get(pvs);
            aim_printf(&aim_pvs_stdout, "second: %s", s);
            free(s);
            aim_pvs_destroy(pvs);
        }
        {
            aim_ratelimiter_t rl;
            aim_ratelimiter_init(&rl, 10, 5, NULL);

            /* 5 (6?) tokens available at t=0 */
            assert(aim_ratelimiter_limit(&rl, 0) == 0);
            assert(aim_ratelimiter_limit(&rl, 0) == 0);
            assert(aim_ratelimiter_limit(&rl, 0) == 0);
            assert(aim_ratelimiter_limit(&rl, 0) == 0);
            assert(aim_ratelimiter_limit(&rl, 0) == 0);
            assert(aim_ratelimiter_limit(&rl, 0) == 0);
            assert(aim_ratelimiter_limit(&rl, 0) < 0);

            /* Another token at t=10 */
            assert(aim_ratelimiter_limit(&rl, 10) == 0);
            assert(aim_ratelimiter_limit(&rl, 10) < 0);

            /* Nothing at t=15 */
            assert(aim_ratelimiter_limit(&rl, 15) < 0);

            /* 4 more tokens granted by t=50 */
            assert(aim_ratelimiter_limit(&rl, 50) == 0);
            assert(aim_ratelimiter_limit(&rl, 50) == 0);
            assert(aim_ratelimiter_limit(&rl, 50) == 0);
            assert(aim_ratelimiter_limit(&rl, 50) == 0);
            assert(aim_ratelimiter_limit(&rl, 50) < 0);
        }
        {
            aim_printf(&aim_pvs_stdout, "valgrind_status=%d\n",
                       aim_valgrind_status());
        }

        AIM_LOG_MSG("%{aim_error}", AIM_ERROR_PARAM);
    }

    return 0;
}