Beispiel #1
0
/**
 * 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;
}
Beispiel #2
0
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);
  }
}
Beispiel #3
0
/**
 * 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; 
}
Beispiel #4
0
/*
 * 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; 
}
Beispiel #5
0
/**
 * 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;
}
Beispiel #6
0
/**
 * 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;
}