From e56f2b9b4646f87763d6a45cfb6fe637592a691d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 2 Mar 2019 17:02:13 +0100 Subject: [PATCH] client: Connect to server before connecting to bankd So far we skipped the client->server connection and related configuration transfer from server to client. Now, the server instructs the client to which bankd ip/port to connect. Change-Id: I76c9498089515d1a6190f3e79e143b7df3a531bd --- src/client.h | 18 ++++--- src/remsim_client.c | 59 +++++++++++++++++++--- src/remsim_client_fsm.c | 66 ++++++++++++++----------- src/simtrace2-remsim_client.c | 93 +++++++++++++++++++++++------------ 4 files changed, 160 insertions(+), 76 deletions(-) diff --git a/src/client.h b/src/client.h index 6918560..1917cb5 100644 --- a/src/client.h +++ b/src/client.h @@ -10,9 +10,10 @@ /* fsm.c */ enum bankd_conn_fsm_event { - BDC_E_TCP_UP, - BDC_E_TCP_DOWN, - BDC_E_CLIENT_CONN_RES, + BDC_E_ESTABLISH, /* instruct BDC to (re)etablish TCP connection to bankd */ + BDC_E_TCP_UP, /* notify BDC that TCP connection is up/connected */ + BDC_E_TCP_DOWN, /* notify BDC that TCP connection is down/disconnected */ + BDC_E_CLIENT_CONN_RES, /* notify BDC that ClientConnectRes has been received */ }; extern struct osmo_fsm remsim_client_bankd_fsm; @@ -31,10 +32,12 @@ struct rspro_server_conn { /* state */ struct ipa_client_conn *conn; struct osmo_fsm_inst *fi; - int (*handle_rx)(struct rspro_server_conn *conn, RsproPDU_t *pdu); + int (*handle_rx)(struct rspro_server_conn *conn, const RsproPDU_t *pdu); /* our own component ID */ struct app_comp_id own_comp_id; + /* remote component ID */ + struct app_comp_id peer_comp_id; /* configuration */ char *server_host; @@ -48,11 +51,10 @@ extern struct osmo_fsm remsim_client_server_fsm; struct bankd_client { /* connection to the remsim-server (control) */ - struct ipa_client_conn *srv_conn; - struct osmo_fsm_inst *srv_fi; + struct rspro_server_conn srv_conn; - /* our own component ID */ - struct app_comp_id own_comp_id; + /* remote component ID */ + struct app_comp_id peer_comp_id; /* connection to the remsim-bankd */ char *bankd_host; diff --git a/src/remsim_client.c b/src/remsim_client.c index 62f65f9..2f740d4 100644 --- a/src/remsim_client.c +++ b/src/remsim_client.c @@ -26,6 +26,8 @@ static int bankd_handle_msg(struct bankd_client *bc, struct msgb *msg) switch (pdu->msg.present) { case RsproPDUchoice_PR_connectClientRes: + /* Store 'identity' of bankd to in peer_comp_id */ + rspro_comp_id_retrieve(&bc->peer_comp_id, &pdu->msg.choice.connectClientRes.identity); osmo_fsm_inst_dispatch(bc->bankd_fi, BDC_E_CLIENT_CONN_RES, pdu); break; default: @@ -84,17 +86,62 @@ static void *g_tall_ctx; void __thread *talloc_asn1_ctx; int asn_debug; +/* handle incoming messages from server */ +static int srvc_handle_rx(struct rspro_server_conn *srvc, const RsproPDU_t *pdu) +{ + RsproPDU_t *resp; + + switch (pdu->msg.present) { + case RsproPDUchoice_PR_connectClientRes: + /* Store 'identity' of server in srvc->peer_comp_id */ + rspro_comp_id_retrieve(&srvc->peer_comp_id, &pdu->msg.choice.connectClientRes.identity); + osmo_fsm_inst_dispatch(srvc->fi, SRVC_E_CLIENT_CONN_RES, (void *) pdu); + break; + case RsproPDUchoice_PR_configClientReq: + /* store/set the clientID as instructed by the server */ + if (!g_client->clslot) + g_client->clslot = talloc_zero(g_client, ClientSlot_t); + *g_client->clslot = pdu->msg.choice.configClientReq.clientSlot; + /* store/set the bankd ip/port as instructed by the server */ + osmo_talloc_replace_string(g_client, &g_client->bankd_host, + rspro_IpAddr2str(&pdu->msg.choice.configClientReq.bankd.ip)); + g_client->bankd_port = ntohs(pdu->msg.choice.configClientReq.bankd.port); + /* instruct bankd FSM to connect */ + osmo_fsm_inst_dispatch(g_client->bankd_fi, BDC_E_ESTABLISH, NULL); + /* send response to server */ + resp = rspro_gen_ConfigClientRes(ResultCode_ok); + ipa_client_conn_send_rspro(srvc->conn, resp); + break; + default: + fprintf(stderr, "Unknown/Unsupported RSPRO PDU type: %u\n", pdu->msg.present); + return -1; + } + + return 0; +} + int main(int argc, char **argv) { + struct rspro_server_conn *srvc; + int rc; + g_tall_ctx = talloc_named_const(NULL, 0, "global"); g_client = talloc_zero(g_tall_ctx, struct bankd_client); - g_client->bankd_host = "localhost"; - g_client->bankd_port = 9999; - g_client->own_comp_id.type = ComponentType_remsimClient; - OSMO_STRLCPY_ARRAY(g_client->own_comp_id.name, "fixme-name"); - OSMO_STRLCPY_ARRAY(g_client->own_comp_id.software, "remsim-client"); - OSMO_STRLCPY_ARRAY(g_client->own_comp_id.sw_version, PACKAGE_VERSION); + + srvc = &g_client->srv_conn; + srvc->server_host = "localhost"; + srvc->server_port = 9998; + srvc->handle_rx = srvc_handle_rx; + srvc->own_comp_id.type = ComponentType_remsimClient; + OSMO_STRLCPY_ARRAY(srvc->own_comp_id.name, "fixme-name"); + OSMO_STRLCPY_ARRAY(srvc->own_comp_id.software, "remsim-client"); + OSMO_STRLCPY_ARRAY(srvc->own_comp_id.sw_version, PACKAGE_VERSION); + rc = server_conn_fsm_alloc(g_client, srvc); + if (rc < 0) { + fprintf(stderr, "Unable to create Server conn FSM: %s\n", strerror(errno)); + exit(1); + } asn_debug = 0; osmo_init_logging2(g_tall_ctx, &log_info); diff --git a/src/remsim_client_fsm.c b/src/remsim_client_fsm.c index d361659..06df4e0 100644 --- a/src/remsim_client_fsm.c +++ b/src/remsim_client_fsm.c @@ -57,6 +57,7 @@ enum bankd_conn_fsm_state { }; static const struct value_string remsim_client_bankd_fsm_event_names[] = { + OSMO_VALUE_STRING(BDC_E_ESTABLISH), OSMO_VALUE_STRING(BDC_E_TCP_UP), OSMO_VALUE_STRING(BDC_E_TCP_DOWN), OSMO_VALUE_STRING(BDC_E_CLIENT_CONN_RES), @@ -67,33 +68,10 @@ static const struct value_string remsim_client_bankd_fsm_event_names[] = { #define T2_RECONNECT 10 -static void bdc_st_init_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) -{ - struct bankd_client *bc = (struct bankd_client *) fi->priv; - int rc; - - printf("onenter\n"); - bc->bankd_conn = ipa_client_conn_create(bc, NULL, 0, bc->bankd_host, bc->bankd_port, - bankd_updown_cb, bankd_read_cb, NULL, bc); - if (!bc->bankd_conn) { - fprintf(stderr, "Unable to create socket: %s\n", strerror(errno)); - exit(1); - } - /* Attempt to connect TCP socket */ - rc = ipa_client_conn_open(bc->bankd_conn); - if (rc < 0) { - fprintf(stderr, "Unable to connect: %s\n", strerror(errno)); - exit(1); - } -} - static void bdc_st_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { - case BDC_E_TCP_UP: - osmo_fsm_inst_state_chg(fi, BDC_ST_ESTABLISHED, T1_WAIT_CLIENT_CONN_RES, 1); - break; - case BDC_E_TCP_DOWN: + case BDC_E_ESTABLISH: osmo_fsm_inst_state_chg(fi, BDC_ST_REESTABLISH, T2_RECONNECT, 2); break; default: @@ -107,7 +85,7 @@ static void bdc_st_established_onenter(struct osmo_fsm_inst *fi, uint32_t prev_s RsproPDU_t *pdu; /* FIXME: Send ClientConnReq */ - pdu = rspro_gen_ConnectClientReq(&bc->own_comp_id, bc->clslot); + pdu = rspro_gen_ConnectClientReq(&bc->srv_conn.own_comp_id, bc->clslot); ipa_client_conn_send_rspro(bc->bankd_conn, pdu); } @@ -142,6 +120,21 @@ static void bdc_st_reestablish_onenter(struct osmo_fsm_inst *fi, uint32_t prev_s struct bankd_client *bc = (struct bankd_client *) fi->priv; int rc; + /* re-create bankd_conn */ + if (bc->bankd_conn) { + LOGPFSML(fi, LOGL_INFO, "Destroying existing connection to bankd\n"); + ipa_client_conn_destroy(bc->bankd_conn); + bc->bankd_conn = NULL; + } + LOGPFSML(fi, LOGL_INFO, "Creating TCP connection to bankd at %s:%u\n", + bc->bankd_host, bc->bankd_port); + bc->bankd_conn = ipa_client_conn_create(bc, NULL, 0, bc->bankd_host, bc->bankd_port, + bankd_updown_cb, bankd_read_cb, NULL, bc); + if (!bc->bankd_conn) { + fprintf(stderr, "Unable to create socket: %s\n", strerror(errno)); + exit(1); + } + /* Attempt to connect TCP socket */ rc = ipa_client_conn_open(bc->bankd_conn); if (rc < 0) { @@ -166,14 +159,27 @@ static void bdc_st_reestablish(struct osmo_fsm_inst *fi, uint32_t event, void *d } } +static void bdc_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case BDC_ST_REESTABLISH: + osmo_fsm_inst_state_chg(fi, BDC_ST_REESTABLISH, T2_RECONNECT, 2); + break; + default: + OSMO_ASSERT(0); + } +} + static int remsim_client_bankd_fsm_timer_cb(struct osmo_fsm_inst *fi) { switch (fi->T) { case 2: + /* TCP reconnect failed: retry */ osmo_fsm_inst_state_chg(fi, BDC_ST_REESTABLISH, T2_RECONNECT, 2); break; case 1: - /* FIXME: close connection and re-start */ + /* no ClientConnectRes received: disconnect + reconnect */ + osmo_fsm_inst_state_chg(fi, BDC_ST_REESTABLISH, T2_RECONNECT, 2); break; default: OSMO_ASSERT(0); @@ -184,8 +190,8 @@ static int remsim_client_bankd_fsm_timer_cb(struct osmo_fsm_inst *fi) static const struct osmo_fsm_state bankd_conn_fsm_states[] = { [BDC_ST_INIT] = { .name = "INIT", - .in_event_mask = S(BDC_E_TCP_UP) | S(BDC_E_TCP_DOWN), - .out_state_mask = S(BDC_ST_ESTABLISHED) | S(BDC_ST_REESTABLISH), + .in_event_mask = 0, /* S(BDC_E_ESTABLISH) via allstate */ + .out_state_mask = S(BDC_ST_REESTABLISH), .action = bdc_st_init, }, [BDC_ST_ESTABLISHED] = { @@ -214,6 +220,8 @@ struct osmo_fsm remsim_client_bankd_fsm = { .name = "BANKD_CONN", .states = bankd_conn_fsm_states, .num_states = ARRAY_SIZE(bankd_conn_fsm_states), + .allstate_event_mask = S(BDC_E_ESTABLISH), + .allstate_action = bdc_allstate_action, .timer_cb = remsim_client_bankd_fsm_timer_cb, .log_subsys = DMAIN, .event_names = remsim_client_bankd_fsm_event_names, @@ -228,8 +236,6 @@ int bankd_conn_fsm_alloc(struct bankd_client *bc) return -1; bc->bankd_fi = fi; - /* onenter of the initial state is not automatically executed by osmo_fsm :( */ - bdc_st_init_onenter(fi, 0); return 0; } diff --git a/src/simtrace2-remsim_client.c b/src/simtrace2-remsim_client.c index 6d31d32..79da419 100644 --- a/src/simtrace2-remsim_client.c +++ b/src/simtrace2-remsim_client.c @@ -539,6 +539,8 @@ static int bankd_handle_msg(struct bankd_client *bc, struct msgb *msg) switch (pdu->msg.present) { case RsproPDUchoice_PR_connectClientRes: + /* Store 'identity' of bankd to in peer_comp_id */ + rspro_comp_id_retrieve(&bc->peer_comp_id, &pdu->msg.choice.connectClientRes.identity); osmo_fsm_inst_dispatch(bc->bankd_fi, BDC_E_CLIENT_CONN_RES, pdu); break; case RsproPDUchoice_PR_tpduCardToModem: // APDU response from card received @@ -582,6 +584,41 @@ invalid: return -1; } +/* handle incoming messages from server */ +static int srvc_handle_rx(struct rspro_server_conn *srvc, const RsproPDU_t *pdu) +{ + RsproPDU_t *resp; + + switch (pdu->msg.present) { + case RsproPDUchoice_PR_connectClientRes: + /* Store 'identity' of server in srvc->peer_comp_id */ + rspro_comp_id_retrieve(&srvc->peer_comp_id, &pdu->msg.choice.connectClientRes.identity); + osmo_fsm_inst_dispatch(srvc->fi, SRVC_E_CLIENT_CONN_RES, (void *) pdu); + break; + case RsproPDUchoice_PR_configClientReq: + /* store/set the clientID as instructed by the server */ + if (!g_client->clslot) + g_client->clslot = talloc_zero(g_client, ClientSlot_t); + *g_client->clslot = pdu->msg.choice.configClientReq.clientSlot; + /* store/set the bankd ip/port as instructed by the server */ + osmo_talloc_replace_string(g_client, &g_client->bankd_host, + rspro_IpAddr2str(&pdu->msg.choice.configClientReq.bankd.ip)); + g_client->bankd_port = ntohs(pdu->msg.choice.configClientReq.bankd.port); + /* instruct bankd FSM to connect */ + osmo_fsm_inst_dispatch(g_client->bankd_fi, BDC_E_ESTABLISH, NULL); + /* send response to server */ + resp = rspro_gen_ConfigClientRes(ResultCode_ok); + ipa_client_conn_send_rspro(srvc->conn, resp); + break; + default: + fprintf(stderr, "Unknown/Unsupported RSPRO PDU type: %u\n", pdu->msg.present); + return -1; + } + + return 0; +} + + static const struct log_info_cat default_categories[] = { [DMAIN] = { .name = "DMAIN", @@ -604,10 +641,8 @@ static void print_welcome(void) static void print_help(void) { - printf( "\t-d\t--bankd-host HOST\n" + printf( "\t-s\t--server-host HOST\n" "\t-p\t--bankd-port PORT\n" - "\t-c\t--client-id REMSIM_CLIENT_ID\n" - "\t-s\t--slot-nr REMSIM_SLOT_NUMBER\n" "\t-h\t--help\n" "\t-i\t--gsmtap-ip\tA.B.C.D\n" "\t-k\t--keep-running\n" @@ -624,10 +659,8 @@ static void print_help(void) } static const struct option opts[] = { - { "bankd-host", 1, 0, 'b' }, - { "bankd-port", 1, 0, 'p' }, - { "client-id", 1, 0, 'c' }, - { "slot-nr", 1, 0, 's' }, + { "server-host", 1, 0, 's' }, + { "server-port", 1, 0, 'p' }, { "gsmtap-ip", 1, 0, 'i' }, { "help", 0, 0, 'h' }, { "keep-running", 0, 0, 'k' }, @@ -644,16 +677,16 @@ static const struct option opts[] = { int main(int argc, char **argv) { + struct rspro_server_conn *srvc; struct st_transport *transp = ci->slot->transp; char *gsmtap_host = "127.0.0.1"; int rc; int c, ret = 1; int keep_running = 0; - int bankd_port = 9999; - int client_id = -1, slot_nr = -1; + int server_port = 9999; int if_num = 0, vendor_id = -1, product_id = -1; int config_id = -1, altsetting = 0, addr = -1; - char *bankd_host = "127.0.0.1"; + char *server_host = "127.0.0.1"; char *path = NULL; uint8_t atr_data[33] = { 0x3B, 0x00 }; // the shortest simplest ATR possible uint8_t atr_len = 2; @@ -663,21 +696,15 @@ int main(int argc, char **argv) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "b:p:c:s:hi:V:P:C:I:S:A:H:a:k", opts, &option_index); + c = getopt_long(argc, argv, "s:p:hi:V:P:C:I:S:A:H:a:k", opts, &option_index); if (c == -1) break; switch (c) { - case 'b': - bankd_host = optarg; + case 's': + server_host = optarg; break; case 'p': - bankd_port = atoi(optarg); - break; - case 'c': - client_id = atoi(optarg); - break; - case 's': - slot_nr = atoi(optarg); + server_port = atoi(optarg); break; case 'h': print_help(); @@ -726,11 +753,6 @@ int main(int argc, char **argv) goto do_exit; } - if (client_id < 0 || slot_nr < 0) { - fprintf(stderr, "You have to specify the remote SIM client ID and slot number\n"); - goto do_exit; - } - rc = libusb_init(NULL); if (rc < 0) { fprintf(stderr, "libusb initialization failed\n"); @@ -750,13 +772,20 @@ int main(int argc, char **argv) g_tall_ctx = talloc_named_const(NULL, 0, "global"); g_client = talloc_zero(g_tall_ctx, struct bankd_client); - g_client->bankd_host = bankd_host; - g_client->bankd_port = bankd_port; - g_client->own_comp_id.type = ComponentType_remsimClient; - g_client->clslot = &(ClientSlot_t){ .clientId = client_id, .slotNr = slot_nr }; - OSMO_STRLCPY_ARRAY(g_client->own_comp_id.name, "simtrace2-remsim-client"); - OSMO_STRLCPY_ARRAY(g_client->own_comp_id.software, "remsim-client"); - OSMO_STRLCPY_ARRAY(g_client->own_comp_id.sw_version, PACKAGE_VERSION); + + srvc = &g_client->srv_conn; + srvc->server_host = server_host; + srvc->server_port = server_port; + srvc->handle_rx = srvc_handle_rx; + srvc->own_comp_id.type = ComponentType_remsimClient; + OSMO_STRLCPY_ARRAY(srvc->own_comp_id.name, "simtrace2-remsim-client"); + OSMO_STRLCPY_ARRAY(srvc->own_comp_id.software, "remsim-client"); + OSMO_STRLCPY_ARRAY(srvc->own_comp_id.sw_version, PACKAGE_VERSION); + rc = server_conn_fsm_alloc(g_client, srvc); + if (rc < 0) { + fprintf(stderr, "Unable to create Server conn FSM: %s\n", strerror(errno)); + exit(1); + } asn_debug = 0; osmo_init_logging2(g_tall_ctx, &log_info);