/** * Sends message from controlelr to the specified agent. The message payload can * be NULL, in which case only the header will be sent. * * @param[in] inst - Controller instance * @param[in] agent_type - Agent to which the message to be sent * @param[in] msg_type - Message type * @param[in] msg_buf - Message payload (encoded) * @param[in] msg_len - Size of the message payload * * @returns RW_STATUS_SUCCESS on success, RW_STATUS_FAILURE otherwise. */ static rw_status_t controller_send_to_agent( rwcli_controller_t* inst, rwcli_transport_mode_t agent_type, rwcli_msg_type_t msg_type, uint8_t* msg_buf, unsigned msg_len) { int nw = 0; rwcli_agent_msg_hdr_t msg_hdr = { .msg_len = msg_len, .msg_type = msg_type }; // First write the header nw = write(inst->agent_channels[agent_type].in.fd.write, (const void*)(&msg_hdr), sizeof(rwcli_agent_msg_hdr_t)); if (nw <= 0) { RWTRACE_ERROR(inst->trace_ctxt, RWTRACE_CATEGORY_RWCLI, "\nSHELL: Error writing to CLI-AGENT %s\n", strerror(errno)); return RW_STATUS_FAILURE; } if (msg_buf) { nw = write(inst->agent_channels[agent_type].in.fd.write, msg_buf, msg_len); if (nw <= 0) { RWTRACE_ERROR(inst->trace_ctxt, RWTRACE_CATEGORY_RWCLI, "\nSHELL: Error writing to CLI-AGENT %s\n", strerror(errno)); return RW_STATUS_FAILURE; } } return RW_STATUS_SUCCESS; }
void rwdts_appconf_xact_add_issue(rwdts_appconf_t *ac, rwdts_xact_t *xact, rw_status_t rs, const char *errstr) { RW_ASSERT_TYPE(ac, rwdts_appconf_t); if (xact) { RW_ASSERT_TYPE(xact, rwdts_xact_t); rwdts_appconf_xact_t *appx = (rwdts_appconf_xact_t *)xact->group[ac->group->id]->scratch; RW_ASSERT_TYPE(appx, rwdts_appconf_xact_t); int idx = appx->errs_ct++; appx->errs = realloc(appx->errs, sizeof(appx->errs[0]) * appx->errs_ct); appx->errs[idx].str = strdup(errstr); appx->errs[idx].rs = rs; appx->errs[idx].corrid = 0; //?? // Send to error_report also rwdts_member_send_error(xact, NULL, NULL, ac->apih, NULL, rs, errstr); } else if (ac->group && ac->group->xact) { RW_ASSERT_TYPE(ac->group->xact, rwdts_xact_t); rwdts_member_send_error(ac->group->xact, NULL, NULL, ac->apih, NULL, rs, errstr); } else { if (ac->apih) { RWTRACE_CRIT(ac->apih->rwtrace_instance, RWTRACE_CATEGORY_RWTASKLET, "%s: No xact, rs=%d, errstr=%s\n", __FUNCTION__, rs, errstr); } else { DTS_PRINT("%s: No xact, rs=%d, errstr=%s\n", __FUNCTION__, rs, errstr); } } if (ac->apih) { RWTRACE_ERROR(ac->apih->rwtrace_instance, RWTRACE_CATEGORY_RWTASKLET, "APPCONF xact issue for group %d, rs %d, errstr '%s'\n", ac->group->id, rs, errstr); } else { DTS_PRINT("APPCONF xact issue for group %d, rs %d, errstr '%s'\n", ac->group->id, rs, errstr); } }
/** * Recevie a message from the agent. * * In the message the first 4bytes provide the message length. The rest is the * NetconfResp protobuf or rwcli_internal_rsp_t. * * @param[in] inst - RW.CLI controller instance * @param[in] agent_type - Agent type (netconf/rwmsg) from which message to be * received. * @param[out] msg_len - Length for the received message. * * @returns RW_STATUS_SUCCESS on success, RW_STATUS_FAILURE otherwise. */ static rw_status_t controller_recv_from_agent( rwcli_controller_t* inst, rwcli_transport_mode_t agent_type, unsigned *msg_len) { ssize_t nread = read(inst->agent_channels[agent_type].out.fd.read, msg_len, sizeof(unsigned)); if (nread <= 0) { if (errno != EAGAIN && errno != EINTR) { RWTRACE_ERROR(inst->trace_ctxt, RWTRACE_CATEGORY_RWCLI, "\nSHELL: Error reading from CLI-AGENT: %s", strerror(errno)); } return RW_STATUS_FAILURE; } if (*msg_len == 0) { // no reply return RW_STATUS_FAILURE; } if (*msg_len > inst->recv_buf_len) { free(inst->recv_buf); inst->recv_buf = (uint8_t*)calloc(sizeof(uint8_t), *msg_len); inst->recv_buf_len = *msg_len; } // Read until we received the complete message size_t nr = 0; size_t remaining = *msg_len; nread = 0; do { nr = read(inst->agent_channels[agent_type].out.fd.read, inst->recv_buf + nread, remaining); if (nr <= 0) { RWTRACE_ERROR(inst->trace_ctxt, RWTRACE_CATEGORY_RWCLI, "\nSHELL: Error reading from CLI-AGENT %s\n", strerror(errno)); return RW_STATUS_FAILURE; } nread += nr; remaining -= nr; RW_ASSERT(remaining >= 0); } while(remaining); return RW_STATUS_SUCCESS; }
/* * Recevie a message from the agent. * * In the message the first 4bytes provide the message length. The rest is the * NetconfResp protobuf. */ static rw_status_t recv_msg_from_agent(unsigned *msg_len) { ssize_t nread = read(rwcli_agent_ch.out.fd.read, msg_len, sizeof(unsigned)); if (nread <= 0) { if (errno != EINTR) { RWTRACE_ERROR(rwcli_trace, RWTRACE_CATEGORY_RWCLI, "\nSHELL: Error reading from CLI-AGENT: %s", strerror(errno)); } return RW_STATUS_FAILURE; } if (*msg_len == 0) { // no reply return RW_STATUS_FAILURE; } if (*msg_len > recv_buf_len) { free(recv_buf); recv_buf = (uint8_t*)calloc(sizeof(uint8_t), *msg_len); recv_buf_len = *msg_len; } // Read until we received the complete message size_t nr = 0; size_t remaining = *msg_len; nread = 0; do { nr = read(rwcli_agent_ch.out.fd.read, recv_buf + nread, remaining); if (recv <= 0) { RWTRACE_ERROR(rwcli_trace, RWTRACE_CATEGORY_RWCLI, "\nSHELL: Error reading from CLI-AGENT %s\n", strerror(errno)); return RW_STATUS_FAILURE; } nread += nr; remaining -= nr; RW_ASSERT(remaining >= 0); } while(remaining); return RW_STATUS_SUCCESS; }
/** * This method will be invoked whene the rw.cli executes a command and * requires a transport to send the message. */ static rw_status_t messaging_hook(NetconfReq *req, NetconfRsp **rsp) { // Send message to the CLI-AGENT and wait for a message back unsigned msg_len = netconf_req__get_packed_size(NULL, req); uint8_t msg_buf[msg_len]; rw_status_t status; netconf_req__pack(NULL, req, msg_buf); if (rwcli_agent_ch.in.fd.write == -1) { RWTRACE_CRIT(rwcli_trace, RWTRACE_CATEGORY_RWCLI, "Messaging not initialized, failed to execute the command"); return RW_STATUS_FAILURE; } // Consume any prvious unread messages on the stream consume_unread_agent_messages(); // TODO handle EPIPE write(rwcli_agent_ch.in.fd.write, (const void*)(&msg_len), sizeof(unsigned)); write(rwcli_agent_ch.in.fd.write, msg_buf, msg_len); RWTRACE_DEBUG(rwcli_trace, RWTRACE_CATEGORY_RWCLI, "\nSHELL: sent %d bytes to CLI-AGENT", msg_len); status = recv_msg_from_agent(&msg_len); if (status != RW_STATUS_SUCCESS) { *rsp = NULL; return status; } RWTRACE_DEBUG(rwcli_trace, RWTRACE_CATEGORY_RWCLI, "\nSHELL: received %u bytes from CLI-AGENT msglen\n", msg_len); rw_resp = netconf_rsp__unpack(NULL, msg_len, recv_buf); if (rw_resp == NULL) { RWTRACE_ERROR(rwcli_trace, RWTRACE_CATEGORY_RWCLI, "\nReceived message unpack failed\n"); *rsp = NULL; return RW_STATUS_FAILURE; } *rsp = rw_resp; return RW_STATUS_SUCCESS; }
/** * Handler for Netconf message type. Sends the encoded the NetconfReq protobuf * and receives the decoded NetconfRsp protobuf. * * @param[in] inst - RW.CLI Controller instance * @param[in] req - Netconf Request decoded protobuf * @param[out] rsp - Netconf response (decoded) * * @returns RW_STATUS_SUCCESS on success, RW_STATUS_FAILURE otherwise. */ static rw_status_t controller_handle_rwnetconf_msg( rwcli_controller_t* inst, NetconfReq* req, NetconfRsp **rsp) { unsigned recv_msg_len = 0; unsigned msg_len = netconf_req__get_packed_size(NULL, req); uint8_t msg_buf[msg_len]; rw_status_t status; // Encode the protobuf netconf_req__pack(NULL, req, msg_buf); status = controller_execute(inst, inst->agent_type, RWCLI_MSG_TYPE_RW_NETCONF, msg_buf, msg_len, &recv_msg_len); if (status != RW_STATUS_SUCCESS) { *rsp = NULL; return status; } // Decode the response inst->resp = netconf_rsp__unpack(NULL, recv_msg_len, inst->recv_buf); if (inst->resp == NULL) { RWTRACE_ERROR(inst->trace_ctxt, RWTRACE_CATEGORY_RWCLI, "\nReceived message unpack failed\n"); *rsp = NULL; return RW_STATUS_FAILURE; } // The response is stored in the controller to be deleted later after the // response is processed by the RW.CLI plugin. *rsp = inst->resp; return RW_STATUS_SUCCESS; }