/* ------------------------------------------------------------------- * 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; }
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; }
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); }
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; }