FIX: ResetSeqNumFlag should be included in Logon message

Generally speaking, FIX session is comprised of one or more FIX
connections. But libtrading does not support such possibility at the
moment. So reset sequence numbers when FIX connection is established
i.e. when Logon message is sent

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: parse_field() should always keep buffer->start consistent

It is a possible scenario that parse_field() is unable to find
a particular tag or unable to parse the tag even it is found
e.g. the tag has a non-numerical value. Whatever obstacle is
encountered, parse_field() must keep buffer->start value valid
i.e. always pointing to the next "tag=value" pattern.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Introduce a new session RX engine

fix_message_recv() has been the only way to get FIX-messages so far.
Such a method not only affects performance (because each time a message
is received a new buffer is allocated) but also tends to be erroneous as
this method is unable to process multiple messages stored in a socket
and leaves them corrupted.

This patch introduces a new fix_session_recv() method which is free of
fix_message_recv() drawbacks. There is a single rx_buffer per
FIX-session which is used as a storage for all FIX-messages ariving
through the socket.  fix_session_recv() is not intended to parse
FIX-messages on the fly i.e.  parse them while reading from the socket.
On the contrary, it reads as big chunk of data as possible and puts it
in rx_buffer.

Implementation notes: currently not a whole buffer is used to store
data.  Essentially, there is a zone of MAX_MESSAGE_SIZE which is not
used at all.  The purpose of such a zone is to avoid dealing with
discontinuity when a FIX-message is split into two parts which are
stored in different places within rx_buffer. An evident flaw of such an
approach is a MAX_MESSAGE_SIZE hole which is actually never used. But
there is a great advantage of not rewriting FIX-messages parsing engine
as it implicitly relies on continuity of data.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Use new FIX session RX engine

Switch from fix_message_recv() to fix_session_recv() in all tesing
tools.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Clean up and improve code

 * Make fix_session_buffer_full() function private

 * Use FIX prefix for macros to avoid polluting namespace

 * Remove unused fix_message_recv() function.

Signed-off-by: Pekka Enberg <penberg@kernel.org>
Fix up .gitignore

Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Add CheckSum verification

Perform CheckSum validity verification when a FIX message is received:

* BodyLength and CheckSum tags' values are consistent i.e. BodyLength's
  value points to the CheckSum tag.

* CheckSum value is valid i.e. it is the sum (modulo 256) of every byte
  of the message up to but not including the checksum itself.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
[ penberg@kernel.org: cleanups ]
Signed-off-by: Pekka Enberg <penberg@kernel.org>
Use -Werror GCC option

Enable -Werror GCC option to keep libtrading compilation clean.

Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: fix_session_recv() shouldn't check socket if there are data in the RX buffer

Prevent fix_session_recv() from being blocked when waiting data from the
socket. Check whether there are data in the RX buffer. If so, try to
parse the buffer first.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
[ penberg@kernel.org: cleanups ]
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Code cleanups to fix_session_recv()

 - Fix local variable declaration ordering
 - Fix formatting glitches

Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Fix a bug - RX buffer must not be freed

There is a single RX buffer per FIX session which shouldn't
be freed. Any attempts to delete it during active FIX session
are erroneous and will lead to crash

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Fix partially received message parsing

Because we do not parse incoming FIX messages on the fly we are exposed
to the following problem: we have to distinguish between the cases when
RX buffer contains partially delivered message and when the buffer
contains a garbled FIX message. In the former case we have to wait until
the missing part is delivered and parse the whole message. In the latter
case we should consider the message to be garbled and skip it. Currently
we skip the data in both cases.

The proposed solution based on the assumption that there is a maximum
message size. So if the number of bytes to be parsed is greater than
that value we are not in the case of the message that has been partially
delivered.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
[ penberg@kernel.org: cleanups ]
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Keep the client alive until SIGINT is sent

Keep the FIX client alive until the user sends SIGINT which makes it
possible to test heartbeats, for example.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Stop relying on SIGINT for automated test

Commit f166cce ("fix: Keep the client alive until SIGINT is sent") causes make
check to fail as follows after 10 or so iterations:

  Server is listening to port 9000 using 'fix' protocol...
  Logon OK
  Logout FAILED
  make: *** [check] Error 1
  FAILURE

Relying on sleep timing is inherently broken for automated tests. Add a new
command line option '-i' to FIX test client that causes the client to send a
logout message immediately.

Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Use permanent buffers for message transmission

Each time a FIX message is transmitted a pair TX buffers are allocated.
This could be easily avoided by introducing a permanent pair of per
FIX session buffers which are to be reused if needed.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
[ penberg@kernel.org: cleanups ]
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Process resend requests

If a Resend Request message is received a single Sequence Reset
(Gap Fill mode) is sent back to cover the whole range of missed
messages.

It is quite reasonable to assume that one should use a reliable
transport protocol e.g. TCP/IP. In such a case there is a much
more powerful engine is responsible for data integrity than
simple FIX messages' sequence numbers. Moreover, we are getting
it just for free. Hence, Resend Request indicates that there is
a dramatic error on either side of communication link and FIX
connection should be closed immediately.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Track incoming message sequence numbers

If an incoming message's sequence number does not equal to the
expected incoming sequence number then FIX logout is initiated.
This approach is justified for the reliable network transport
protocols e.g. TCP/IP which ensure data integrity.

fix_session_resend_request() is presented for compatibility
purposes and is not used actually. But if the aforementioned
logic if changed, one will initiate Resend Request procedures.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Use permanent buffer for message receipt

At the moment, each time the incoming data are unparsed
a new struct fix_message is allocated which is rather
wasteful because of numerous alloc/free operations.

This patch suggests using a permanent per-session pointer
pointing to the most recently unparsed FIX message. If
parsing was successful then this pointer is to be used
for further analysis.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
fix: Code cleanups

1. MsgSeqNum is a mandatory tag with a separate field within the struct

2. Prevent passing bad pointers to buffer_delete i.e. freeing memory on
   a wrong address.

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
FIX: A new testing suite

This commit introduces a new FIX protocol testing suite. The main
idea is to test FIX functionality against the predetermined set of
test cases. Each test case contains of a number of FIX messages for
two parties: FIX server and FIX client respectively. Each message may
be considered as an expected behavior of each party according to the
FIX protocol specification. Hence, any deviation from the expected
behavior could be considered as a violence to protocol specification
and indicates the libtrading implementation error.

Below are details to current FIX testing suite realization:
* Each test case involves two counterparts: the server and the client
* Server is a passive side. Client is an active one. That is to say
the client makes the server respond by sending it FIX messages.
* Each test case should have its own file.
* Each test case file contains of a number of lines.
* Each line represent a single FIX message.
* Lines that start with 'c' ('C') belong to the client.
* Lines that start with 's' ('S') belong to the server.
* One do not have to specify every field within a FIX message.
Only those fields are to be specified that are to be verified.
* The server receives incoming messages and verifies them agains the
expected ones i.e. the messages that have been read from the test case
file.
* The client transmits the messages which have been markes with
'c' ('C') and verifies the messages received from the server against
the 's' ('S') - messages.
* Logon and Logout are performed automatically. So Logon and Logout
messages should not be specified in a test case file. Any attempts to
perform multiple logons will lead to the test case failure.

Consider an example of a test case file:
c35=1\x0134=2\x01
s35=0\x0134=2\x01

This test case will result in the following messages flow:
* Client ---> Server: Logon initiate
* Server ---> Client: Logon accept
* Client ---> Server: Test Request
* Server verifies the incoming message: only tags 35 and 34 are
verified because only these tags were specified in the test case
file (they should be equal to 1 and 2 respectively)
* Server ---> Client: HeartBeat
* Client verifies the incoming message: only tags 35 and 34 are
verified because only these tags were specified in the test case
file (they should be equal to 0 and 2 respectively)
* Client ---> Server: Logout
* Server ---> Client: Logout accept

Signed-off-by: Marat Stanichenko <mstanichenko@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>