[[remsim-bankd]]
== osmo-remsim-bankd

The `osmo-remsim-bankd` (SIM Bank Daemon) manages one given SIM bank.
The initial implementation supports a PC/SC driver to expose any PC/SC
compatible card readers as SIM bank.

`osmo-remsim-bankd` initially connects via a RSPRO control connection to
`osmo-remsim-server` at startup, and will in turn receive a set of
initial [client,slot]:[bankd,slot] mappings.  These mappings determine
which slot on the client (corresponding to a modem) is mapped to which
slot on the SIM bank.  Mappings can be updated by `osmo-remsim-server`
at any given point in time.

`osmo-remsim-bankd` implements a RSPRO server, where it listens to
connections from `osmo-remsim-clients`.

As PC/SC only offers a blocking API, there is one thread per PC/SC slot.
This thread will perform blocking I/O on the socket towards the client,
and blocking API calls on PC/SC.

In terms of thread handling, we do:

* accept() handling in [spare] worker threads
** this means blocking I/O can be used, as each worker thread only has
   one TCP connection
** client identifies itself with client:slot
** lookup mapping based on client:slot (using mutex for protection)
** open the reader based on the lookup result

The worker threads initially don't have any mapping to a specific
reader, and that mapping is only established at a later point after the
client has identified itself.  The advantage is that the entire bankd
can live without any non-blocking I/O.

The main thread handles the connection to `osmo-remsim-server`, where it
can also use non-blocking I/O.  However, re-connection would be
required, to avoid stalling all banks/cards in the event of a connection
loss to the server.

worker threads have the following states:
* INIT (just started)
* ACCEPTING (they're blocking in the accept() call on the server socket fd)
* CONNECTED_WAIT_ID (TCP established, but peer not yet identified itself)
* CONNECTED_CLIENT (TCP established, client has identified itself, no mapping)
* CONNECTED_CLIENT_MAPPED (TCP established, client has identified itself, mapping exists)
* CONNECTED_CLIENT_MAPPED_CARD (TCP established, client identified, mapping exists, card opened)
* CONNECTED_SERVER (TCP established, server has identified itself)

Once the client disconnects, or any other error occurs (such as card I/O
errors), the worker thread either returns to INIT state (closing client
socket and reader), or it terminates.  Termination would mean that the
main thread would have to do non-blocking join to detect client
termination and then re-spawn clients, so the "return to INIT state"
approach seems to make more sense.


=== Running

`osmo-remsim-bankd` currently has the following command-line options:

==== SYNOPSIS

*osmo-remsim-bankd* [-h] [-V] [-d LOGOPT] -i A.B.C.D [-p <1-65535>] [-b <1-1023>] [-n <1-1023>] [-I A.B.C.D] [-P <1-65535> ]

==== OPTIONS

*-h, --help*::
  Print a short help message about the supported options
*-V, --version*::
  Print the software version number
*-d, --debug LOGOPT*::
  Configure the logging verbosity, see <<remsim_logging>>.
*-i, --server-host A.B.C.D*::
  Specify the remote IP address/hostname of the `osmo-remsim-server` to
  which this bankd shall establish its RSPRO control connection.  Do not specify a loopback
  address or localhost, as this would in most cases result in a broken configuration where
  a [usually remote] remsim-client attempts to reach the bankd via loopback, which doesn't work.
*-p, --server-port <1-65535>*::
  Specify the remote TCP port number of the `osmo-remsim-server` to which
  this bankd shall establish its RSPRO control connection
*-b, --bank-id <1-1023>*::
  Specify the numeric bank identifier of the SIM bank this bankd
  instance operates.  Must be unique among all banks connecting to the
  same `osmo-remsim-server`.
*-n, --num-slots <1-1023>*::
  Specify the number of slots that this bankd handles.
*-I, --bind-IP A.B.C.D*::
  Specify the local IP address to which the socket for incoming connections
  from `osmo-remsim-clients` is bound to.
*-P, --bind-port <1-65535>*::
  Specify the local TCP port to which the socket for incoming connections
  from `osmo-remsim-client`s is bound to.
*-s, --permit-shared-pcsc*::
  Specify whether the PC/SC readers should be accessed in SCARD_SHARE_SHARED
  mode, instead of the default (SCARD_SHARE_EXCLUSIVE).  Shared mode would
  permit multiple application programs to access a single reader/slot/card
  concurrently.  This is potentially dangerous as the two programs operate
  without knowledge of each other, and either of them might modify the card
  state (such as the currently selected file, validated PIN, etc.) in a
  way not expected by the other application.


==== Examples
.remsim-server is on 10.2.3.4, cardreader has 5 slots:
----
osmo-remsim-bankd -i 10.2.3.4 -n 5
----
.remsim-server is on 10.2.3.4, cardreader has 4 slots, local ip is 10.5.4.3
----
osmo-remsim-bankd -i 10.2.3.4 -n 4 -I 10.5.4.3
----

=== Logging

`osmo-remsim-bankd` currently logs to stdout only, and the logging
verbosity is not yet configurable.  However, as the libosmocore logging
framework is used, extending this is an easy modification.

=== `bankd_pcsc_slots.csv` CSV file

bankd expects a CSV file `bankd_pcsc_slots.csv` in the current working directory at startup.

This CSV file specifies the mapping between the string names of the PCSC
readers and the RSPRO bandk/slot numbers.  The format is as follows:

* first column: bankd number
* second column: slot number within bankd
* third column: extended POSIX regular expression matching the slot

.Example: CSV file mapping bankd slots 0..4 to an ACS ACR33U-A1 reader slots
----
"1","0","ACS ACR33 ICC Reader 00 00"
"1","1","ACS ACR33 ICC Reader 00 01"
"1","2","ACS ACR33 ICC Reader 00 02"
"1","3","ACS ACR33 ICC Reader 00 03"
"1","4","ACS ACR33 ICC Reader 00 04"
----

You can obtain the exact string to use as PC/SC reader name from the output of the
`pcsc_scan` utility (part of pcsc-lite package).  The tool will produce output like:

.Example: Output of `pcsc_scan` utility on a system with a single reader installed
----
Scanning present readers...
0: Alcor Micro AU9560 00 00
----

In this example, there's only a single PC/SC reader available, and it has a string of
"Alcor Micro AU9560 00 00" which needs to be used in the CSV file.

NOTE:: If the reader name contains any special characters, they might need to be escaped according
to the extended POSIX regular expression syntax. See `man 7 regex` for a reference.

.Example: CSV file mapping bankd slots 0..7 to a sysmoOCTSIM:
----
"1","0","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 00"
"1","1","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 01"
"1","2","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 02"
"1","3","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 03"
"1","4","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 04"
"1","5","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 05"
"1","6","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 06"
"1","7","sysmocom sysmoOCTSIM \[CCID\] \(ab19180f3335355320202034463a15ff\) [0-9]{2} 07"
----

In the above example, the +\[CCID\]+ and the +\(serialnumber\)+ both had to be escaped.

The +[0-9]\{2\}+ construct exists to perform wildcard matching, no matter which particular two-digit number
pcscd decides to use.

.Example: CSV file mapping bankd slot 0 to a OMNIKEY 3x21 Smart Card Reader:
----
"1","0","HID Global OMNIKEY 3x21 Smart Card Reader \[OMNIKEY 3x21 Smart Card Reader\] 00 00"
----

