blob: 89b95de08f387cc368a6905bf435445a8ab4d555 [file] [log] [blame]
Harald Welte24173fb2018-08-24 20:37:28 +02001#include <stdint.h>
2#include <string.h>
3#include <errno.h>
4
5#include <talloc.h>
6
7#include <osmocom/core/logging.h>
8#include <osmocom/core/utils.h>
9#include <osmocom/core/msgb.h>
10#include <osmocom/core/fsm.h>
11
12#include <osmocom/abis/ipa.h>
13#include <osmocom/gsm/protocol/ipaccess.h>
14
15#include "client.h"
16#include "rspro_util.h"
17
18#define S(x) (1 << (x))
19
20static void bankd_updown_cb(struct ipa_client_conn *conn, int up)
21{
22 struct bankd_client *bc = conn->data;
23
24 printf("RSPRO link to %s:%d %s\n", conn->addr, conn->port, up ? "UP" : "DOWN");
25
26 osmo_fsm_inst_dispatch(bc->bankd_fi, up ? BDC_E_TCP_UP: BDC_E_TCP_DOWN, 0);
27}
28
29/***********************************************************************
30 * bankd connection FSM
31 ***********************************************************************/
32
33enum bankd_conn_fsm_state {
34 /* waiting for initial connectiong to remsim-bankd */
35 BDC_ST_INIT,
36 /* bankd connection established, waiting for ClientConnectRes */
37 BDC_ST_ESTABLISHED,
38 /* bankd connection etsablished, ClientConnect succeeded */
39 BDC_ST_CONNECTED,
40 /* connection lost, we're waiting for a re-establish */
41 BDC_ST_REESTABLISH,
42};
43
44static const struct value_string remsim_client_bankd_fsm_event_names[] = {
45 OSMO_VALUE_STRING(BDC_E_TCP_UP),
46 OSMO_VALUE_STRING(BDC_E_TCP_DOWN),
47 OSMO_VALUE_STRING(BDC_E_CLIENT_CONN_RES),
48 { 0, NULL }
49};
50
51#define T1_WAIT_CLIENT_CONN_RES 10
52#define T2_RECONNECT 10
53
54
55static void bdc_st_init_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
56{
57 struct bankd_client *bc = (struct bankd_client *) fi->priv;
58 int rc;
59
60 printf("onenter\n");
61 bc->bankd_conn = ipa_client_conn_create(bc, NULL, 0, bc->bankd_host, bc->bankd_port,
62 bankd_updown_cb, bankd_read_cb, NULL, bc);
63 if (!bc->bankd_conn) {
64 fprintf(stderr, "Unable to create socket: %s\n", strerror(errno));
65 exit(1);
66 }
67 /* Attempt to connect TCP socket */
68 rc = ipa_client_conn_open(bc->bankd_conn);
69 if (rc < 0) {
70 fprintf(stderr, "Unable to connect: %s\n", strerror(errno));
71 exit(1);
72 }
73}
74
75static void bdc_st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
76{
77 switch (event) {
78 case BDC_E_TCP_UP:
79 osmo_fsm_inst_state_chg(fi, BDC_ST_ESTABLISHED, T1_WAIT_CLIENT_CONN_RES, 1);
80 break;
81 default:
82 OSMO_ASSERT(0);
83 }
84}
85
86static void bdc_st_established_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
87{
88 struct bankd_client *bc = (struct bankd_client *) fi->priv;
89 RsproPDU_t *pdu;
90
91 /* FIXME: Send ClientConnReq */
92 const ClientSlot_t clslot = { .clientId = 23, .slotNr = 1 };
93 pdu = rspro_gen_ConnectClientReq(&bc->own_comp_id, &clslot);
94 bankd_send_rspro(bc, pdu);
95}
96
97static void bdc_st_established(struct osmo_fsm_inst *fi, uint32_t event, void *data)
98{
99 switch (event) {
100 case BDC_E_TCP_DOWN:
101 osmo_fsm_inst_state_chg(fi, BDC_ST_REESTABLISH, T2_RECONNECT, 2);
102 break;
103 case BDC_E_CLIENT_CONN_RES:
104 /* somehow notify the main code? */
105 osmo_fsm_inst_state_chg(fi, BDC_ST_CONNECTED, 0, 0);
106 break;
107 default:
108 OSMO_ASSERT(0);
109 }
110}
111
112static void bdc_st_connected(struct osmo_fsm_inst *fi, uint32_t event, void *data)
113{
114 switch (event) {
115 case BDC_E_TCP_DOWN:
116 osmo_fsm_inst_state_chg(fi, BDC_ST_REESTABLISH, T2_RECONNECT, 2);
117 break;
118 default:
119 OSMO_ASSERT(0);
120 }
121}
122
123static void bdc_st_reestablish_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
124{
125 struct bankd_client *bc = (struct bankd_client *) fi->priv;
126 int rc;
127
128 /* Attempt to connect TCP socket */
129 rc = ipa_client_conn_open(bc->bankd_conn);
130 if (rc < 0) {
131 fprintf(stderr, "Unable to connect RSPRO to %s:%d - %s\n",
132 bc->bankd_conn->addr, bc->bankd_conn->port, strerror(errno));
133 /* FIXME: retry? Timer? Abort? */
134 OSMO_ASSERT(0);
135 }
136}
137
138static void bdc_st_reestablish(struct osmo_fsm_inst *fi, uint32_t event, void *data)
139{
140 switch (event) {
141 case BDC_E_TCP_UP:
142 osmo_fsm_inst_state_chg(fi, BDC_ST_ESTABLISHED, T1_WAIT_CLIENT_CONN_RES, 1);
143 break;
144 default:
145 OSMO_ASSERT(0);
146 }
147}
148
149static int remsim_client_bankd_fsm_timer_cb(struct osmo_fsm_inst *fi)
150{
151 return 0;
152}
153
154static const struct osmo_fsm_state bankd_conn_fsm_states[] = {
155 [BDC_ST_INIT] = {
156 .name = "INIT",
157 .in_event_mask = S(BDC_E_TCP_UP),
158 .out_state_mask = S(BDC_ST_ESTABLISHED),
159 .action = bdc_st_init,
160 },
161 [BDC_ST_ESTABLISHED] = {
162 .name = "ESTABLISHED",
163 .in_event_mask = S(BDC_E_TCP_DOWN) | S(BDC_E_CLIENT_CONN_RES),
164 .out_state_mask = S(BDC_ST_CONNECTED) | S(BDC_ST_REESTABLISH),
165 .action = bdc_st_established,
166 .onenter = bdc_st_established_onenter,
167 },
168 [BDC_ST_CONNECTED] = {
169 .name = "CONNECTED",
170 .in_event_mask = S(BDC_E_TCP_DOWN),
171 .out_state_mask = S(BDC_ST_REESTABLISH),
172 .action = bdc_st_connected,
173 },
174 [BDC_ST_REESTABLISH] = {
175 .name = "REESTABLISH",
176 .in_event_mask = S(BDC_E_TCP_UP),
177 .out_state_mask = S(BDC_ST_ESTABLISHED),
178 .action = bdc_st_reestablish,
179 .onenter = bdc_st_reestablish_onenter,
180 },
181};
182
183struct osmo_fsm remsim_client_bankd_fsm = {
184 .name = "BANKD_CONN",
185 .states = bankd_conn_fsm_states,
186 .num_states = ARRAY_SIZE(bankd_conn_fsm_states),
187 .timer_cb = remsim_client_bankd_fsm_timer_cb,
188 .log_subsys = DMAIN,
189 .event_names = remsim_client_bankd_fsm_event_names,
190};
191
192int bankd_conn_fsm_alloc(struct bankd_client *bc)
193{
194 struct osmo_fsm_inst *fi;
195
196 fi = osmo_fsm_inst_alloc(&remsim_client_bankd_fsm, bc, bc, LOGL_DEBUG, "bankd");
197 if (!fi)
198 return -1;
199
200 bc->bankd_fi = fi;
201 /* onenter of the initial state is not automatically executed by osmo_fsm :( */
202 bdc_st_init_onenter(fi, 0);
203 return 0;
204}
205
206/***********************************************************************
207 * server connection FSM
208 ***********************************************************************/
209
210enum server_conn_fsm_state {
211 /* waiting for initial connectiong to remsim-server */
212 SRVC_ST_INIT,
213 /* server connection established, waiting for ClientConnectRes */
214 SRVC_ST_ESTABLISHED,
215 /* server connection etsablished, ClientConnect succeeded */
216 SRVC_ST_CONNECTED,
217 /* connection lost, we're waiting for a re-establish */
218 SRVC_ST_REESTABLISH,
219};
220
221static const struct value_string server_conn_fsm_event_names[] = {
222 OSMO_VALUE_STRING(SRVC_E_TCP_UP),
223 OSMO_VALUE_STRING(SRVC_E_TCP_DOWN),
224 OSMO_VALUE_STRING(SRVC_E_CLIENT_CONN_RES),
225 { 0, NULL }
226};
227
228
229static void srvc_st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data)
230{
231}
232
233static void srvc_st_established(struct osmo_fsm_inst *fi, uint32_t event, void *data)
234{
235}
236
237static void srvc_st_connected(struct osmo_fsm_inst *fi, uint32_t event, void *data)
238{
239}
240
241static void srvc_st_reestablish(struct osmo_fsm_inst *fi, uint32_t event, void *data)
242{
243}
244
245static int server_conn_fsm_timer_cb(struct osmo_fsm_inst *fi)
246{
247 return 0;
248}
249
250static const struct osmo_fsm_state server_conn_fsm_states[] = {
251 [SRVC_ST_INIT] = {
252 .name = "INIT",
253 .in_event_mask = S(SRVC_E_TCP_UP),
254 .out_state_mask = S(SRVC_ST_ESTABLISHED),
255 .action = srvc_st_init,
256 },
257 [SRVC_ST_ESTABLISHED] = {
258 .name = "ESTABLISHED",
259 .in_event_mask = S(SRVC_E_TCP_DOWN) | S(SRVC_E_CLIENT_CONN_RES),
260 .out_state_mask = S(SRVC_ST_CONNECTED) | S(SRVC_ST_REESTABLISH),
261 .action = srvc_st_established,
262 },
263 [SRVC_ST_CONNECTED] = {
264 .name = "CONNECTED",
265 .in_event_mask = S(SRVC_E_TCP_DOWN),
266 .out_state_mask = S(SRVC_ST_REESTABLISH),
267 .action = srvc_st_connected,
268 },
269 [SRVC_ST_REESTABLISH] = {
270 .name = "REESTABLISH",
271 .in_event_mask = S(SRVC_E_TCP_UP),
272 .out_state_mask = S(SRVC_ST_ESTABLISHED),
273 .action = srvc_st_reestablish,
274 },
275};
276
277struct osmo_fsm remsim_client_server_fsm = {
278 .name = "SERVER_CONN",
279 .states = server_conn_fsm_states,
280 .num_states = ARRAY_SIZE(server_conn_fsm_states),
281 .timer_cb = server_conn_fsm_timer_cb,
282 .log_subsys = DMAIN,
283 .event_names = server_conn_fsm_event_names,
284};
285
286int server_conn_fsm_alloc(struct bankd_client *bc)
287{
288 struct osmo_fsm_inst *fi;
289
290 fi = osmo_fsm_inst_alloc(&remsim_client_server_fsm, bc, bc, LOGL_DEBUG, "server");
291 if (!fi)
292 return -1;
293
294 bc->srv_fi = fi;
295 /* onenter of the initial state is not automatically executed by osmo_fsm :( */
296 ///srvc_st_init_onenter(fi, 0);
297 return 0;
298}