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
This commit is contained in:
Harald Welte 2019-03-02 17:02:13 +01:00
parent 0eaa0ef796
commit e56f2b9b46
4 changed files with 160 additions and 76 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);