/* * rpmem_obc_create -- perform create request operation * * Returns error if connection has not been established yet. */ int rpmem_obc_create(struct rpmem_obc *rpc, const struct rpmem_req_attr *req, struct rpmem_resp_attr *res, const struct rpmem_pool_attr *pool_attr) { if (!rpmem_obc_is_connected(rpc)) { ERR("out-of-band connection not established"); errno = ENOTCONN; goto err_notconnected; } if (rpmem_obc_check_req(req)) goto err_req; size_t msg_size; struct rpmem_msg_create *msg = rpmem_obc_alloc_create_msg(req, pool_attr, &msg_size); if (!msg) goto err_alloc_msg; RPMEM_LOG(INFO, "sending create request message"); rpmem_hton_msg_create(msg); if (rpmem_ssh_send(rpc->ssh, msg, msg_size)) { ERR("!sending create request message failed"); goto err_msg_send; } RPMEM_LOG(NOTICE, "create request message sent"); RPMEM_LOG(INFO, "receiving create request response"); struct rpmem_msg_create_resp resp; if (rpmem_ssh_recv(rpc->ssh, &resp, sizeof(resp))) { ERR("!receiving create request response failed"); goto err_msg_recv; } RPMEM_LOG(NOTICE, "create request response received"); rpmem_ntoh_msg_create_resp(&resp); if (rpmem_obc_check_create_resp(&resp)) goto err_msg_resp; rpmem_obc_get_res(res, &resp.ibc); free(msg); return 0; err_msg_resp: err_msg_recv: err_msg_send: free(msg); err_alloc_msg: err_req: err_notconnected: return -1; }
/* * clnt_recv -- receive data */ void clnt_recv(struct rpmem_ssh *ssh, void *buff, size_t len) { int ret; ret = rpmem_ssh_recv(ssh, buff, len); UT_ASSERTeq(ret, 0); }
/* * rpmem_obc_set_attr -- perform set attributes request operation * * Returns error if connection is not already established. */ int rpmem_obc_set_attr(struct rpmem_obc *rpc, const struct rpmem_pool_attr *pool_attr) { if (!rpmem_obc_is_connected(rpc)) { ERR("out-of-band connection not established"); errno = ENOTCONN; goto err_notconnected; } struct rpmem_msg_set_attr msg; rpmem_obc_set_msg_hdr(&msg.hdr, RPMEM_MSG_TYPE_SET_ATTR, sizeof(msg)); if (pool_attr) { memcpy(&msg.pool_attr, pool_attr, sizeof(msg.pool_attr)); } else { RPMEM_LOG(INFO, "using zeroed pool attributes"); memset(&msg.pool_attr, 0, sizeof(msg.pool_attr)); } RPMEM_LOG(INFO, "sending set attributes request message"); rpmem_hton_msg_set_attr(&msg); if (rpmem_ssh_send(rpc->ssh, &msg, sizeof(msg))) { ERR("!sending set attributes request message failed"); goto err_msg_send; } RPMEM_LOG(NOTICE, "set attributes request message sent"); RPMEM_LOG(INFO, "receiving set attributes request response"); struct rpmem_msg_set_attr_resp resp; if (rpmem_ssh_recv(rpc->ssh, &resp, sizeof(resp))) { ERR("!receiving set attributes request response failed"); goto err_msg_recv; } RPMEM_LOG(NOTICE, "set attributes request response received"); rpmem_ntoh_msg_set_attr_resp(&resp); if (rpmem_obc_check_set_attr_resp(&resp)) goto err_msg_resp; return 0; err_msg_resp: err_msg_recv: err_msg_send: err_notconnected: return -1; }
/* * rpmem_obc_close -- perform close request operation * * Returns error if connection is not already established. * * NOTE: this function does not close the connection, but sends close request * message to remote node and receives a response. The connection must be * closed using rpmem_obc_disconnect function. */ int rpmem_obc_close(struct rpmem_obc *rpc, int flags) { if (!rpmem_obc_is_connected(rpc)) { errno = ENOTCONN; return -1; } struct rpmem_msg_close msg; rpmem_obc_set_msg_hdr(&msg.hdr, RPMEM_MSG_TYPE_CLOSE, sizeof(msg)); msg.flags = (uint32_t)flags; RPMEM_LOG(INFO, "sending close request message"); rpmem_hton_msg_close(&msg); if (rpmem_ssh_send(rpc->ssh, &msg, sizeof(msg))) { RPMEM_LOG(ERR, "!sending close request failed"); return -1; } RPMEM_LOG(NOTICE, "close request message sent"); RPMEM_LOG(INFO, "receiving close request response"); struct rpmem_msg_close_resp resp; if (rpmem_ssh_recv(rpc->ssh, &resp, sizeof(resp))) { RPMEM_LOG(ERR, "!receiving close request response failed"); return -1; } RPMEM_LOG(NOTICE, "close request response received"); rpmem_ntoh_msg_close_resp(&resp); if (rpmem_obc_check_close_resp(&resp)) return -1; return 0; }
/* * rpmem_ssh_open -- open ssh connection with specified node and wait for status */ struct rpmem_ssh * rpmem_ssh_open(const struct rpmem_target_info *info) { struct rpmem_ssh *ssh = rpmem_ssh_exec(info, NULL); if (!ssh) return NULL; /* * Read initial status from invoked command. * This is for synchronization purposes and to make it possible * to inform client that command's initialization failed. */ int32_t status; int ret = rpmem_ssh_recv(ssh, &status, sizeof(status)); if (ret) { if (ret == 1 || errno == ECONNRESET) ERR("%s", rpmem_ssh_strerror(ssh, errno)); else ERR("!%s", info->node); goto err_recv_status; } if (status) { ERR("%s: unexpected status received -- '%d'", info->node, status); errno = status; goto err_status; } RPMEM_LOG(INFO, "received status: %u", status); return ssh; err_recv_status: err_status: rpmem_ssh_close(ssh); return NULL; }
/* * rpmem_ssh_open -- open ssh connection with specified node */ struct rpmem_ssh * rpmem_ssh_open(const struct rpmem_target_info *info) { struct rpmem_ssh *rps = calloc(1, sizeof(*rps)); if (!rps) goto err_zalloc; char *user_at_node = get_user_at_node(info); if (!user_at_node) goto err_user_node; rps->cmd = rpmem_cmd_init(); if (!rps->cmd) goto err_cmd_init; int ret = rpmem_cmd_push(rps->cmd, get_ssh()); if (ret) goto err_push; if (info->flags & RPMEM_HAS_SERVICE) { /* port number is optional */ ret = rpmem_cmd_push(rps->cmd, "-p"); if (ret) goto err_push; ret = rpmem_cmd_push(rps->cmd, info->service); if (ret) goto err_push; } /* * Disable allocating pseudo-terminal in order to transfer binary * data safely. */ ret = rpmem_cmd_push(rps->cmd, "-T"); if (ret) goto err_push; if (info->flags & RPMEM_FLAGS_USE_IPV4) { ret = rpmem_cmd_push(rps->cmd, "-4"); if (ret) goto err_push; } /* fail if password required for authentication */ ret = rpmem_cmd_push(rps->cmd, "-oBatchMode=yes"); if (ret) goto err_push; ret = rpmem_cmd_push(rps->cmd, user_at_node); if (ret) goto err_push; ret = rpmem_cmd_push(rps->cmd, rpmem_util_cmd_get()); if (ret) goto err_push; ret = rpmem_cmd_run(rps->cmd); if (ret) goto err_run; /* * Read initial status from invoked command. * This is for synchronization purposes and to make it possible * to inform client that command's initialization failed. */ int32_t status; ret = rpmem_ssh_recv(rps, &status, sizeof(status)); if (ret) { if (ret == 1 || errno == ECONNRESET) ERR("%s", rpmem_ssh_strerror(rps)); else ERR("!%s", info->node); goto err_recv_status; } if (status) { ERR("%s: unexpected status received -- '%d'", info->node, status); goto err_status; } RPMEM_LOG(INFO, "received status: %u", status); free(user_at_node); return rps; err_status: err_recv_status: err_run: rpmem_cmd_term(rps->cmd); rpmem_cmd_wait(rps->cmd, NULL); err_push: rpmem_cmd_fini(rps->cmd); err_cmd_init: free(user_at_node); err_user_node: free(rps); err_zalloc: return NULL; }