示例#1
0
/* -------------------------------------------------------------------
 * Public Client API Implementations
 */
hdesc_t *harmony_init(int *argc, char ***argv)
{
    hdesc_t *hdesc = (hdesc_t *) malloc(sizeof(hdesc_t));
    if (!hdesc)
        return NULL;

    if (hsession_init(&hdesc->sess) != 0) {
        free(hdesc);
        return NULL;
    }

    hdesc->mesg = HMESG_INITIALIZER;
    hdesc->state = HARMONY_STATE_INIT;

    hdesc->cmd = NULL;
    hdesc->cmd_len = hdesc->cmd_cap = 0;

    hdesc->ptr = NULL;
    hdesc->ptr_len = hdesc->ptr_cap = 0;

    hdesc->curr = HPOINT_INITIALIZER;
    hdesc->best = HPOINT_INITIALIZER;
    hdesc->errstr = NULL;

    hdesc->id = NULL;

    if (argc && argv) {
        int i, j = 1;
        int stop = 0;

        for (i = 1; i < *argc; ++i) {
            /* Stop looking for configuration directives upon "--" token. */
            if (strcmp((*argv)[i], "--") == 0)
                stop = 1;

            if (!stop && hcfg_is_cmd((*argv)[i])) {
                if (hdesc->cmd_len == hdesc->cmd_cap) {
                    if (array_grow(&hdesc->cmd, &hdesc->cmd_cap,
                                   sizeof(char *)) != 0)
                    {
                        hsession_fini(&hdesc->sess);
                        free(hdesc);
                        return NULL;
                    }
                }
                hdesc->cmd[hdesc->cmd_len++] = (*argv)[i];
            }
            else {
                (*argv)[j++] = (*argv)[i];
            }
        }

        if (j != *argc) {
            *argc = j;
            (*argv)[j] = NULL;
        }
    }

    return hdesc;
}
示例#2
0
int harmony_leave(hdesc_t *hdesc)
{
    if (hdesc->state <= HARMONY_STATE_INIT) {
        hdesc->errstr = "Descriptor not currently joined to any session.";
        errno = EINVAL;
        return -1;
    }

    hdesc->state = HARMONY_STATE_INIT;
    if (close(hdesc->socket) < 0 && debug_mode)
        perror("Error closing socket during harmony_leave()");

    /* Reset the hsession_t to prepare for hdesc reuse. */
    hsession_fini(&hdesc->sess);
    if (hsession_init(&hdesc->sess) != 0) {
        hdesc->errstr = "Internal memory allocation error.";
        return -1;
    }
    hdesc->ptr_len = 0;
    hdesc->best.id = -1;

    return 0;
}
示例#3
0
int harmony_launch(hdesc_t *hdesc, const char *host, int port)
{
    int i;

    /* Sanity check input */
    if (hdesc->sess.sig.range_len < 1) {
        hdesc->errstr = "No tuning variables defined";
        errno = EINVAL;
        return -1;
    }

    if (!host && !getenv("HARMONY_S_HOST")) {
        char *path;
        const char *home;

        /* Provide a default name, if one isn't defined. */
        if (!hdesc->sess.sig.name) {
            if (hsignature_name(&hdesc->sess.sig, "NONAME"))
                return -1;
        }

        /* Find the Active Harmony installation. */
        home = getenv("HARMONY_HOME");
        if (!home) {
            hdesc->errstr = "No host or HARMONY_HOME specified";
            return -1;
        }

        if (hcfg_set(hdesc->sess.cfg, CFGKEY_HARMONY_HOME, home) != 0) {
            hdesc->errstr = "Could not set " CFGKEY_HARMONY_HOME;
            return -1;
        }

        /* Fork a local tuning session. */
        path = sprintf_alloc("%s/libexec/session-core", home);
        hdesc->socket = socket_launch(path, NULL, NULL);
        free(path);
    }
    else {
        hdesc->socket = tcp_connect(host, port);
    }

    if (hdesc->socket < 0) {
        hdesc->errstr = strerror(errno);
        return -1;
    }

    /* Prepare a default client id, if necessary. */
    if (hdesc->id == NULL)
        hdesc->id = default_id(hdesc->socket);
    hdesc->state = HARMONY_STATE_CONNECTED;

    /* Apply argv configuration directives now, if necessary. */
    for (i = 0; i < hdesc->cmd_len; ++i) {
        char *key, *val, *cpy;
        cpy = stralloc(hdesc->cmd[i]);
        if (hcfg_parse(cpy, &key, &val) == NULL) {
            /* This should never fail, but just in case. */
            hdesc->errstr = "Internal error parsing argv config directive.";
            return -1;
        }
        if (hcfg_set(hdesc->sess.cfg, key, val) != 0) {
            hdesc->errstr = "Internal error applying argv config directive.";
            return -1;
        }
        free(cpy);
    }

    /* Prepare a Harmony message. */
    hmesg_scrub(&hdesc->mesg);
    hsession_init(&hdesc->mesg.data.session);
    hsession_copy(&hdesc->mesg.data.session, &hdesc->sess);

    return send_request(hdesc, HMESG_SESSION);
}
示例#4
0
int hmesg_deserialize(hmesg_t *mesg)
{
    char type_str[4], status_str[4];
    int count, total;
    unsigned int msgver;
    char *buf = mesg->buf;

    /* Verify HMESG_MAGIC and HMESG_VERSION */
    if (ntohl(*(unsigned int *)buf) != HMESG_MAGIC)
        goto invalid;

    if (sscanf(buf + sizeof(unsigned int), "%*4d%2x", &msgver) < 1)
        goto invalid;

    if (msgver != HMESG_VERSION)
        goto invalid;
    total = HMESG_HDRLEN;

    if (sscanf(buf + total, " :%d:%3s:%3s:%n", &mesg->dest,
               type_str, status_str, &count) < 3)
        goto invalid;
    total += count;

    count = scanstr_serial(&mesg->src_id, buf + total);
    if (count < 0) goto invalid;
    total += count;

    /* Before we overwrite this message's type, make sure memory allocated
     * from previous usage has been released.
     */
    if      (strcmp(type_str, "UNK") == 0) mesg->type = HMESG_UNKNOWN;
    else if (strcmp(type_str, "SES") == 0) mesg->type = HMESG_SESSION;
    else if (strcmp(type_str, "JOI") == 0) mesg->type = HMESG_JOIN;
    else if (strcmp(type_str, "QRY") == 0) mesg->type = HMESG_GETCFG;
    else if (strcmp(type_str, "INF") == 0) mesg->type = HMESG_SETCFG;
    else if (strcmp(type_str, "FET") == 0) mesg->type = HMESG_FETCH;
    else if (strcmp(type_str, "REP") == 0) mesg->type = HMESG_REPORT;
    else goto invalid;

    if      (strcmp(status_str, "REQ") == 0) mesg->status = HMESG_STATUS_REQ;
    else if (strcmp(status_str, "ACK") == 0) mesg->status = HMESG_STATUS_OK;
    else if (strcmp(status_str, "ERR") == 0) mesg->status = HMESG_STATUS_FAIL;
    else if (strcmp(status_str, "BSY") == 0) mesg->status = HMESG_STATUS_BUSY;
    else goto invalid;

    if (mesg->status == HMESG_STATUS_BUSY) {
        /* Busy messages contain no data. */
    }
    else if (mesg->status == HMESG_STATUS_FAIL) {
        count = scanstr_serial(&mesg->data.string, buf + total);
        if (count < 0) goto error;
        total += count;
    }
    else {
        switch (mesg->type) {
        case HMESG_SESSION:
            if (mesg->status == HMESG_STATUS_REQ) {
                hsession_init(&mesg->data.session);
                count = hsession_deserialize(&mesg->data.session, buf + total);
                if (count < 0) goto error;
                total += count;
            }
            break;

        case HMESG_JOIN:
            mesg->data.join = HSIGNATURE_INITIALIZER;
            count = hsignature_deserialize(&mesg->data.join, buf + total);
            if (count < 0) goto error;
            total += count;
            break;

        case HMESG_GETCFG:
        case HMESG_SETCFG:
            count = scanstr_serial(&mesg->data.string, buf + total);
            if (count < 0) goto error;
            total += count;
            break;

        case HMESG_FETCH:
            if (mesg->status == HMESG_STATUS_REQ) {
                if (sscanf(buf + total, " %d%n",
                           &mesg->data.fetch.best.id, &count) < 1)
                    goto invalid;
                total += count;
            }
            else if (mesg->status == HMESG_STATUS_OK) {
                mesg->data.fetch.cand = HPOINT_INITIALIZER;
                count = hpoint_deserialize(&mesg->data.fetch.cand,
                                           buf + total);
                if (count < 0) goto error;
                total += count;

                mesg->data.fetch.best = HPOINT_INITIALIZER;
                count = hpoint_deserialize(&mesg->data.fetch.best,
                                           buf + total);
                if (count < 0) goto error;
                total += count;
            }
            break;

        case HMESG_REPORT:
            if (mesg->status == HMESG_STATUS_REQ) {
                mesg->data.fetch.cand = HPOINT_INITIALIZER;
                count = hpoint_deserialize(&mesg->data.report.cand,
                                           buf + total);
                if (count < 0) goto error;
                total += count;

                if (sscanf(buf + total, " %la%n",
                           &mesg->data.report.perf, &count) < 1)
                    goto invalid;
                total += count;
            }
            break;

        default:
            goto invalid;
        }
    }
    return total;

  invalid:
    errno = EINVAL;
  error:
    return -1;
}