Warning This project is in a PoC state and a lot of essentials features are missing.
More information for the protocol on the official website. Publicly available specification can be downloaded here. I know that frobd is a bad name for such program, but I couldn't come up with anything better.
It doesn't support any command line switches and is supposed to run only from the source tree. This will be rectified in the future.
It can be used as a standalone program or as a librarty (feature that I can implement upon request).
make && make test
make tcp-server
# or
make tcp-client
make graph-dot
# or
make graph-fdp
frobd is a program that listens for ECR-EFT messages on stdin and responds
to them on stdout (or different file descriptors) while forwarding some messages
through other channels. It is expected to be a part of a larger system
integrated with embedded PoS or ECR software (the client). It is planned to
handle as much as possible messages by itself (T1
-T5
, D0
-DA
, B1
-B4
,
L1
) and support unlimited number of connections, while forwarding only
essential messages to the client, taking care that it will receive only messages
relevant to an actual transaction and only from a single connected device at a
time per transaction, so it has to deal only with a small number of messages
using a simple interface.
For example a payment software can stop worrying about one ECR asking for a previous transaction status while other ECR is requesting a new transaction ;).
It should take care of protocol version negotiation, encryption, synchronisation between multiple clients, parameters delivery, printer control, etc.
It runs! It parses messages. It can reply to some messages with hard-coded responses and if enabled in the code it will forward objects to any other file descriptor.
Communication protocols are a notorious source of security vulnerabilities and plain bugs. Everything including parsing of actual data units, dealing with incomplete and/or ambiguous specification, correct operation in the presence of races between different clients, and handling incorrect input is quite expensive for companies to develop correctly and is often overlooked in exchange for delivery time and features that are demanded by business.
A good proof of my words is a table on the official website. If this specification was so easy to implement there wouldn't be a need in this monstrous compatibility matrix.
This is an attempt to create and open source implementation, that given enough demand can give a rise to reference implementation shared by different businesses, so they can concentrate on features and not on the technicalities of the protocol.
- Written in C
- Parsing is done using Ragel FSM compiler – very robust
- Doesn't use dynamic memory allocation
- Suitable for use on highly constrained devices
- Uses compilation time configurable buffer for incoming data
- No memory leaks (duh!)
- Good (but opinionated) programming style1
- Only single global variable -
g_log_level
- Plays nicely with s6 suite of tools
- Only single global variable -
- Written in C
- Late to the party, there are plenty of implementations already.
- Doesn't use dynamic memory allocation
- Can't handle messages larger than 4Kb.
- Uses VLA in couple of places.
- Far from finished
- Sending
SIGPWR
will print some internal statistics to the log - Sending
SIGINT
will enter debug console
I just wanted to write something using Ragel compiler, to gain more experience with it. And also because many commercial implementations really s*ck and that gave me a little bit of motivation to do something with my free time.
I'm well aware of C++ critique of "fibers". They mention this as a problem:
[...] it [1:N fibers] creates even bigger problem: any blocking call completely stops progress of all N fibers [...]
I consider this as an actual desirable property, to guarantee sequential access to all shared variables. The rest of critique doesn't apply to my use case.
I think most problems with fibers are because implementers need to handle arbitrary code and be very generic and with advanced scheduling. My cooperative tasks have are use-case specific and this avoids a lot of problems.
I've considered a lot of alternatives, they are all too fat: e.g. pth, qemu, etc.
I've used and idea of a special channel for Waitmsg
events from Plan 9.
Also interesting to read:
- Computer multitasking after reading this my implementation is better named multiprogramming or even multiroutining?
- Batch processing
- Spooling
- Coroutine
Footnotes
-
Yet to be achieved ↩