blob: 6c3ecde11202a04a1845385e39b0dcdd940f07f9 [file] [log] [blame]
Harald Welte31c0fef2017-04-16 17:26:30 +02001#include <string.h>
2#include <errno.h>
3
4#include <osmocom/core/fsm.h>
5
6#include <osmocom/ctrl/control_cmd.h>
7#include <osmocom/ctrl/control_if.h>
8
Neels Hofmeyr87e45502017-06-20 00:17:59 +02009/*! control interface lookup function for FSM's
Harald Welte31c0fef2017-04-16 17:26:30 +020010 * \param[in] data Private data passed to controlif_setup()
11 * \param[in] vline Vector of the line holding the command string
12 * \param[out] node_type type (CTRL_NODE_) that was determined
13 * \param[out] node_data private data of node that was determined
14 * \param i Current index into vline, up to which it is parsed
15 */
16static int fsm_ctrl_node_lookup(void *data, vector vline, int *node_type,
17 void **node_data, int *i)
18{
19 struct osmo_fsm *fsm = NULL;
20 struct osmo_fsm_inst *fi = NULL;;
21 const char *token = vector_slot(vline, *i);
22
23 switch (*node_type) {
24 case CTRL_NODE_ROOT:
25 if (!strcmp(token, "fsm")) {
26 const char *fsm_name;
27 (*i)++;
28 fsm_name = vector_lookup(vline, *i);
29 if (!fsm_name)
Max33c7ba62017-05-02 16:24:12 +020030 return -ERANGE;
Harald Welte31c0fef2017-04-16 17:26:30 +020031 fsm = osmo_fsm_find_by_name(fsm_name);
32 if (!fsm)
Max33c7ba62017-05-02 16:24:12 +020033 return -ENODEV;
Harald Welte31c0fef2017-04-16 17:26:30 +020034 *node_data = fsm;
35 *node_type = CTRL_NODE_FSM;
Max409e8972017-05-02 16:12:56 +020036 } else
37 return 0;
Harald Welte31c0fef2017-04-16 17:26:30 +020038 break;
39 case CTRL_NODE_FSM:
40 fsm = *node_data;
41 if (!strcmp(token, "name")) {
42 const char *inst_name;
43 (*i)++;
44 inst_name = vector_lookup(vline, *i);
45 if (!inst_name)
Max33c7ba62017-05-02 16:24:12 +020046 return -ERANGE;
Harald Welte31c0fef2017-04-16 17:26:30 +020047 fi = osmo_fsm_inst_find_by_name(fsm, inst_name);
48 if (!fi)
Max33c7ba62017-05-02 16:24:12 +020049 return -ENODEV;
Harald Welte31c0fef2017-04-16 17:26:30 +020050 *node_data = fi;
51 *node_type = CTRL_NODE_FSM_INST;
52 } else if (!strcmp(token, "id")) {
53 const char *inst_id;
54 (*i)++;
55 inst_id = vector_lookup(vline, *i);
56 if (!inst_id)
Max33c7ba62017-05-02 16:24:12 +020057 return -ERANGE;
Harald Welte31c0fef2017-04-16 17:26:30 +020058 fi = osmo_fsm_inst_find_by_id(fsm, inst_id);
59 if (!fi)
Max33c7ba62017-05-02 16:24:12 +020060 return -ENODEV;
Harald Welte31c0fef2017-04-16 17:26:30 +020061 *node_data = fi;
62 *node_type = CTRL_NODE_FSM_INST;
63 }
64 break;
65 default:
66 return 0;
67 }
68
69 return 1;
Harald Welte31c0fef2017-04-16 17:26:30 +020070}
71
72static int get_fsm_inst_state(struct ctrl_cmd *cmd, void *data)
73{
74 struct osmo_fsm_inst *fi = cmd->node;
75
76 if (!fi) {
77 cmd->reply = "No such FSM found";
78 return CTRL_CMD_ERROR;
79 }
80
81 cmd->reply = talloc_strdup(cmd, osmo_fsm_state_name(fi->fsm, fi->state));
82 return CTRL_CMD_REPLY;
83}
84CTRL_CMD_DEFINE_RO(fsm_inst_state, "state");
85
86static int get_fsm_inst_parent_name(struct ctrl_cmd *cmd, void *data)
87{
88 struct osmo_fsm_inst *fi = cmd->node;
89
90 if (!fi) {
91 cmd->reply = "No such FSM found";
92 return CTRL_CMD_ERROR;
93 }
94 if (!fi->proc.parent) {
95 cmd->reply = "No parent";
96 return CTRL_CMD_ERROR;
97 }
98 cmd->reply = talloc_strdup(cmd, fi->proc.parent->name);
99 return CTRL_CMD_REPLY;
100}
101CTRL_CMD_DEFINE_RO(fsm_inst_parent_name, "parent-name");
102
103static int get_fsm_inst_timer(struct ctrl_cmd *cmd, void *data)
104{
105 struct osmo_fsm_inst *fi = cmd->node;
106 struct timeval remaining;
107
108 if (!fi) {
109 cmd->reply = "No such FSM found";
110 return CTRL_CMD_ERROR;
111 }
112 if (osmo_timer_remaining(&fi->timer, NULL, &remaining) < 0)
113 cmd->reply = "0,0,0";
114 else
115 cmd->reply = talloc_asprintf(cmd, "%u,%ld,%ld", fi->T, remaining.tv_sec, remaining.tv_usec);
116
117 return CTRL_CMD_REPLY;
118}
119CTRL_CMD_DEFINE_RO(fsm_inst_timer, "timer");
120
121
122static int get_fsm_inst_dump(struct ctrl_cmd *cmd, void *data)
123{
124 struct osmo_fsm_inst *fi = cmd->node;
125 struct osmo_fsm_inst *child;
126
127 if (!fi) {
128 cmd->reply = "No such FSM found";
129 return CTRL_CMD_ERROR;
130 }
131
132 /* Fixed Part: Name, ID, log_level, state, timer number */
133 cmd->reply = talloc_asprintf(cmd, "'%s','%s','%s','%s',%u", fi->name, fi->id,
134 log_level_str(fi->log_level),
135 osmo_fsm_state_name(fi->fsm, fi->state), fi->T);
136
137 /* Variable Parts below */
138 if (fi->T) {
139 struct timeval remaining;
140 int rc;
141 rc = osmo_timer_remaining(&fi->timer, NULL, &remaining);
142 if (rc == 0) {
143 cmd->reply = talloc_asprintf_append(cmd->reply, ",timeout_sec=%ld,timeout_usec=%ld",
144 remaining.tv_sec, remaining.tv_usec);
145 }
146 }
147
148 if (fi->proc.parent)
149 cmd->reply = talloc_asprintf_append(cmd->reply, ",parent='%s'", fi->proc.parent->name);
150
151 llist_for_each_entry(child, &fi->proc.children, list) {
152 cmd->reply = talloc_asprintf_append(cmd->reply, ",child='%s'", child->name);
153 }
154
155 return CTRL_CMD_REPLY;
156}
157
158CTRL_CMD_DEFINE_RO(fsm_inst_dump, "dump");
159
160int osmo_fsm_ctrl_cmds_install(void)
161{
162 int rc = 0;
163
164 rc |= ctrl_cmd_install(CTRL_NODE_FSM_INST, &cmd_fsm_inst_dump);
165 rc |= ctrl_cmd_install(CTRL_NODE_FSM_INST, &cmd_fsm_inst_state);
166 rc |= ctrl_cmd_install(CTRL_NODE_FSM_INST, &cmd_fsm_inst_parent_name);
167 rc |= ctrl_cmd_install(CTRL_NODE_FSM_INST, &cmd_fsm_inst_timer);
168 rc |= ctrl_lookup_register(fsm_ctrl_node_lookup);
169
170 return rc;
171}