diff options
Diffstat (limited to 'mgmtd/mgmt_fe_adapter.c')
| -rw-r--r-- | mgmtd/mgmt_fe_adapter.c | 154 | 
1 files changed, 153 insertions, 1 deletions
diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c index 8ae473fb66..b20e36ce0c 100644 --- a/mgmtd/mgmt_fe_adapter.c +++ b/mgmtd/mgmt_fe_adapter.c @@ -1101,6 +1101,47 @@ done:  	return ret;  } +static int fe_adapter_send_rpc_reply(struct mgmt_fe_session_ctx *session, +				     uint64_t req_id, uint8_t result_type, +				     const struct lyd_node *result) +{ +	struct mgmt_msg_rpc_reply *msg; +	uint8_t **darrp = NULL; +	int ret; + +	msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc_reply, 0, +					MTYPE_MSG_NATIVE_RPC_REPLY); +	msg->refer_id = session->session_id; +	msg->req_id = req_id; +	msg->code = MGMT_MSG_CODE_RPC_REPLY; +	msg->result_type = result_type; + +	if (result) { +		darrp = mgmt_msg_native_get_darrp(msg); +		ret = yang_print_tree_append(darrp, result, result_type, 0); +		if (ret != LY_SUCCESS) { +			__log_err("Error building rpc-reply result for client %s session-id %" PRIu64 +				  " req-id %" PRIu64 " result type %u", +				  session->adapter->name, session->session_id, +				  req_id, result_type); +			goto done; +		} +	} + +	__dbg("Sending rpc-reply from adapter %s to session-id %" PRIu64 +	      " req-id %" PRIu64 " len %u", +	      session->adapter->name, session->session_id, req_id, +	      mgmt_msg_native_get_msg_len(msg)); + +	ret = fe_adapter_send_native_msg(session->adapter, msg, +					 mgmt_msg_native_get_msg_len(msg), +					 false); +done: +	mgmt_msg_native_free_msg(msg); + +	return ret; +} +  static int fe_adapter_send_edit_reply(struct mgmt_fe_session_ctx *session,  				      uint64_t req_id, const char *xpath)  { @@ -1271,7 +1312,7 @@ static void fe_adapter_handle_edit(struct mgmt_fe_session_ctx *session,  	}  	xpath = mgmt_msg_native_xpath_data_decode(msg, msg_len, data); -	if (!xpath || !data) { +	if (!xpath) {  		fe_adapter_send_error(session, msg->req_id, false, -EINVAL,  				      "Invalid message");  		return; @@ -1361,6 +1402,96 @@ static void fe_adapter_handle_edit(struct mgmt_fe_session_ctx *session,  }  /** + * fe_adapter_handle_rpc() - Handle an RPC message from an FE client. + * @session: the client session. + * @msg_raw: the message data. + * @msg_len: the length of the message data. + */ +static void fe_adapter_handle_rpc(struct mgmt_fe_session_ctx *session, +				  void *__msg, size_t msg_len) +{ +	struct mgmt_msg_rpc *msg = __msg; +	const struct lysc_node *snode; +	const char *xpath, *data; +	uint64_t req_id = msg->req_id; +	uint64_t clients; +	int ret; + +	__dbg("Received RPC request from client %s for session-id %" PRIu64 +	      " req-id %" PRIu64, +	      session->adapter->name, session->session_id, msg->req_id); + +	xpath = mgmt_msg_native_xpath_data_decode(msg, msg_len, data); +	if (!xpath) { +		fe_adapter_send_error(session, req_id, false, -EINVAL, +				      "Invalid message"); +		return; +	} + +	if (session->txn_id != MGMTD_TXN_ID_NONE) { +		fe_adapter_send_error(session, req_id, false, -EINPROGRESS, +				      "Transaction in progress txn-id: %" PRIu64 +				      " for session-id: %" PRIu64, +				      session->txn_id, session->session_id); +		return; +	} + +	snode = lys_find_path(ly_native_ctx, NULL, xpath, 0); +	if (!snode) { +		fe_adapter_send_error(session, req_id, false, -ENOENT, +				      "No such path: %s", xpath); +		return; +	} + +	if (snode->nodetype == LYS_RPC) +		clients = +			mgmt_be_interested_clients(xpath, +						   MGMT_BE_XPATH_SUBSCR_TYPE_RPC); +	else if (snode->nodetype == LYS_ACTION) +		clients = +			mgmt_be_interested_clients(xpath, +						   MGMT_BE_XPATH_SUBSCR_TYPE_CFG); +	else { +		fe_adapter_send_error(session, req_id, false, -EINVAL, +				      "Not an RPC or action path: %s", xpath); +		return; +	} + +	if (!clients) { +		__dbg("No backends implement xpath: %s for txn-id: %" PRIu64 +		      " session-id: %" PRIu64, +		      xpath, session->txn_id, session->session_id); + +		fe_adapter_send_error(session, req_id, false, -ENOENT, +				      "No backends implement xpath: %s", xpath); +		return; +	} + +	/* Start a RPC Transaction */ +	session->txn_id = mgmt_create_txn(session->session_id, +					  MGMTD_TXN_TYPE_RPC); +	if (session->txn_id == MGMTD_SESSION_ID_NONE) { +		fe_adapter_send_error(session, req_id, false, -EINPROGRESS, +				      "Failed to create an RPC transaction"); +		return; +	} + +	__dbg("Created new rpc txn-id: %" PRIu64 " for session-id: %" PRIu64, +	      session->txn_id, session->session_id); + +	/* Create an RPC request under the transaction */ +	ret = mgmt_txn_send_rpc(session->txn_id, req_id, clients, +				msg->request_type, xpath, data, +				mgmt_msg_native_data_len_decode(msg, msg_len)); +	if (ret) { +		/* destroy the just created txn */ +		mgmt_destroy_txn(&session->txn_id); +		fe_adapter_send_error(session, req_id, false, -EINPROGRESS, +				      "Failed to create an RPC transaction"); +	} +} + +/**   * Handle a native encoded message from the FE client.   */  static void fe_adapter_handle_native_msg(struct mgmt_fe_client_adapter *adapter, @@ -1384,6 +1515,9 @@ static void fe_adapter_handle_native_msg(struct mgmt_fe_client_adapter *adapter,  	case MGMT_MSG_CODE_EDIT:  		fe_adapter_handle_edit(session, msg, msg_len);  		break; +	case MGMT_MSG_CODE_RPC: +		fe_adapter_handle_rpc(session, msg, msg_len); +		break;  	default:  		__log_err("unknown native message session-id %" PRIu64  			  " req-id %" PRIu64 " code %u to FE adapter %s", @@ -1623,6 +1757,24 @@ int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,  	return ret;  } +int mgmt_fe_adapter_send_rpc_reply(uint64_t session_id, uint64_t txn_id, +				   uint64_t req_id, LYD_FORMAT result_type, +				   const struct lyd_node *result) +{ +	struct mgmt_fe_session_ctx *session; +	int ret; + +	session = mgmt_session_id2ctx(session_id); +	if (!session || session->txn_id != txn_id) +		return -1; + +	ret = fe_adapter_send_rpc_reply(session, req_id, result_type, result); + +	mgmt_destroy_txn(&session->txn_id); + +	return ret; +} +  int mgmt_fe_adapter_send_edit_reply(uint64_t session_id, uint64_t txn_id,  				    uint64_t req_id, bool unlock, bool commit,  				    const char *xpath, int16_t error,  | 
