1 /*
2     Copyright (C) 2008-2017, Millistream Market Data <support@millistream.com>
3 
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the GNU Lesser General Public License as published by
6     the Free Software Foundation, either version 3 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU Lesser General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 
17 */
18 
19 #ifndef MDF_H
20 #define MDF_H 1
21 
22 #ifndef _STDINT_H
23 # if _MSC_VER < 1600 && _MSC_VER > 0
24 #  define uint32_t unsigned __int32
25 #  define uint64_t unsigned __int64
26 # else
27 #  include <stdint.h>
28 # endif
29 #endif
30 
31 #if defined _WIN32 || defined _WIN64
32 # ifdef DLL_EXPORT
33 #  define LIBSPEC __declspec(dllexport)
34 # else
35 #  define LIBSPEC __declspec(dllimport)
36 # endif
37 #else
38 # define LIBSPEC
39 #endif
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 typedef enum {
46 	MDF_OPT_FD,
47 	MDF_OPT_ERROR,
48 	MDF_OPT_RCV_BYTES,
49 	MDF_OPT_SENT_BYTES,
50 	MDF_OPT_DATA_CALLBACK_FUNCTION,
51 	MDF_OPT_DATA_CALLBACK_USERDATA,
52 	MDF_OPT_STATUS_CALLBACK_FUNCTION,
53 	MDF_OPT_STATUS_CALLBACK_USERDATA,
54 	MDF_OPT_CONNECT_TIMEOUT,
55 	MDF_OPT_HEARTBEAT_INTERVAL,
56 	MDF_OPT_HEARTBEAT_MAX_MISSED,
57 	MDF_OPT_TCP_NODELAY,
58 	MDF_OPT_NO_ENCRYPTION,
59 	MDF_OPT_TIME_DIFFERENCE
60 } MDF_OPTION;
61 
62 typedef enum {
63 	MDF_ERR_NO_ERROR,
64 	MDF_ERR_NO_MEM,
65 	MDF_ERR_MSG_OOB,
66 	MDF_ERR_TEMPLATE_OOB,
67 	MDF_ERR_UNKNOWN_TEMPLATE,
68 	MDF_ERR_ARGUMENT,
69 	MDF_ERR_CONNECTED,
70 	MDF_ERR_NOT_CONNECTED,
71 	MDF_ERR_CONNECT,
72 	MDF_ERR_MSG_TO_LARGE,
73 	MDF_ERR_CONNECTION_IDLE,
74 	MDF_ERR_DISCONNECTED,
75 	MDF_ERR_AUTHFAIL
76 } MDF_ERROR;
77 
78 typedef enum {
79 	MDF_STATUS_LOOKUP = 0,
80 	MDF_STATUS_CONNECTING,
81 	MDF_STATUS_CONNECTED,
82 	MDF_STATUS_DISCONNECTED,
83 	MDF_STATUS_READYTOLOGON
84 } MDF_CONN_STATUS;
85 
86 /* The opaque API handle */
87 typedef struct mdf_s *mdf_t;
88 
89 /* Create a new API handle, this should be the first function
90  * to call in your application. The handle is not thread-safe
91  * but different threads can access different handles simultaneously.
92  *
93  * Please also note SIGPIPE will be disabled by this function, and
94  * it will NOT be restored in mdf_destroy(). So if your application
95  * depends upon SIGPIPE you will have to re set the signal after the
96  * call to mdf_create(). */
97 LIBSPEC mdf_t mdf_create ();
98 
99 /* Destroy the API handle, open connections will be automatically closed
100  * and any remaining message chains will also be destroyed */
101 LIBSPEC void mdf_destroy (mdf_t handle);
102 
103 /* Return the message reference, class and instrument reference of the
104  * current message in the stream. Also proceeds the internal position
105  * to the next message in the stream.
106  *
107  * Returns true (1) if there was a message to return or false (0)
108  * if there is no more messages in the stream. */
109 LIBSPEC int mdf_get_next_message (mdf_t handle, int *message_reference, int *message_class, uint64_t *instrument_reference);
110 
111 /* Return the tag and value of the current field in the message and
112  * proceed the internal position to the next field in the message.
113  *
114  * Returns true (1) if there was a field to return or false (0)
115  * if there is no more fields in the message. */
116 LIBSPEC int mdf_get_next_field (mdf_t handle, uint32_t *tag, char **value);
117 
118 /* Return the value of the specified option. The data value points to
119  * will be filled in accordingly and can be relied upon only if the
120  * function returns true (1) */
121 LIBSPEC int mdf_get_property (mdf_t handle, MDF_OPTION option, ...);
122 
123 /* Sets the specified option to the specified value. value can be set
124  * to NULL in order to unset the option. */
125 LIBSPEC int mdf_set_property (mdf_t handle, MDF_OPTION option, void *value);
126 
127 /* If a callback function has been set, it will be called
128  * whenever there is messages to consume */
129 typedef void (*mdf_data_callback)(void *userdata, mdf_t handle);
130 
131 /* If a status callback function has been set, it will be called
132  * whenever the status of the connection changes */
133 typedef void (*mdf_status_callback)(void *userdata, MDF_CONN_STATUS status, const char *host, const char *ip);
134 
135 /* Connects to the first server in the servers string which can be a
136  * comma separated list of "server:port" where server can be a host name or
137  * a raw ip address (IPv6 must be enclosed in brackets "[address]", if the
138  * first server does not respond in time, the next will be tried and so on
139  * until there is no more servers in the list.
140  *
141  * Returns true (1) if a connection with a server was possible and false (0)
142  * if connection failed with every server on the list */
143 LIBSPEC int mdf_connect (mdf_t handle, const char *servers);
144 
145 /* Disconnects a connected handle. Safe to call even if the connection
146  * is already down. */
147 LIBSPEC void mdf_disconnect (mdf_t handle);
148 
149 /* Consumes any bytes from the server (if any), if a complete transaction
150  * has been received, any defined callback function will be called.
151  * timeout is the time in seconds to wait for data from the server, if
152  * zero the function will return immediately if there is no data to consume.
153  *
154  * Returns 1 if there is messages to decode and no callback function
155  * was defined, 0 if the function timeouts and -1 if there was an
156  * error.
157 */
158 LIBSPEC int mdf_consume (mdf_t handle, const int timeout);
159 
160 
161 /* Message Chains - Functions to send data into the Millistream system. */
162 
163 /* Opaque handler to the message chain */
164 typedef struct mdf_message_s *mdf_message_t;
165 
166 /* Create a new message chain */
167 LIBSPEC mdf_message_t mdf_message_create ();
168 
169 /* Adds a new message to the message chain, if there is an empty message in the chain
170  * that message will be reused and no memory will be allocated.
171  * Use message_reference to define which message to send.
172  *
173  * Returns true (1) if a new message was added (or an old was reused) and
174  * false (0) if there was an error. */
175 LIBSPEC int mdf_message_add (mdf_message_t message, const uint64_t instrument_reference, const int message_reference);
176 
177 /* remove the current message from the message chain, i.e mark it to be reused.
178  * The current message pointer will change to the previous message in the chain
179  * if there is any, so repeated calls will reset the whole chain.
180  *
181  * Returns true (1) if there are more messages in the chain or false (0)
182  * if the message chain is empty. */
183 LIBSPEC int mdf_message_del (mdf_message_t message);
184 
185 /* Resets the message chain so it can be reused. The same as
186  * calling mdf_message_del() until it returns false (0). */
187 LIBSPEC void mdf_message_reset (mdf_message_t message);
188 
189 /* Serialise the message chain to a base64 encoded string and store the result in *result
190  * it's the responsibility of the caller to free *result once the value is used.
191  *
192  * Returns true (1) if the serialization was successfull or false (0) if not */
193 LIBSPEC int mdf_message_serialize (const mdf_message_t message, char **result);
194 
195 /* Deserialize the message chain from the base64 encoded string and store the result
196  * in message.
197  *
198  * Returns true(1) if the deserialization was successfull of false (0) if not */
199 LIBSPEC int mdf_message_deserialize (const mdf_message_t message, const char * const data);
200 
201 /* Destroys the message chain and frees all memory */
202 LIBSPEC void mdf_message_destroy (mdf_message_t message);
203 
204 /* Adds a space separated list of unsigned integers to the current message */
205 LIBSPEC int mdf_message_add_list (mdf_message_t message, const uint32_t tag, const char *value);
206 
207 /* Adds a numeric field to the current message */
208 LIBSPEC int mdf_message_add_numeric (mdf_message_t message, const uint32_t tag, const char *value);
209 
210 /* Adds a scaled unsigned integer numeric field to the current message */
211 LIBSPEC int mdf_message_add_uint (mdf_message_t message, const uint32_t tag, uint64_t value, int decimals);
212 
213 /* Adds a scaled signed integer numeric field to the current message */
214 LIBSPEC int mdf_message_add_int (mdf_message_t message, const uint32_t tag, int64_t value, int decimals);
215 
216 /* Adds a string field to the current message */
217 LIBSPEC int mdf_message_add_string (mdf_message_t message, const uint32_t tag, const char * value);
218 
219 /* Adds a date field to the current message */
220 LIBSPEC int mdf_message_add_date (mdf_message_t message, const uint32_t tag, const char *value);
221 
222 /* Adds a date field to the current message */
223 LIBSPEC int mdf_message_add_date2 (mdf_message_t message, const uint32_t tag, const int year, const int mon, const int day);
224 
225 /* Adds a time field to the current message */
226 LIBSPEC int mdf_message_add_time (mdf_message_t message, const uint32_t tag, const char *value);
227 
228 /* Adds a time field to the current message */
229 LIBSPEC int mdf_message_add_time2 (mdf_message_t message, const uint32_t tag, const int hour, const int min, const int sec, int msec);
230 
231 /* Adds a time field to the current message */
232 LIBSPEC int mdf_message_add_time3 (mdf_message_t message, const uint32_t tag, const int hour, const int min, const int sec, int nsec);
233 
234 /* Return the total number of messages in the chain */
235 LIBSPEC int mdf_message_get_num (mdf_message_t message);
236 
237 /* Return the number of active messages in the chain */
238 LIBSPEC int mdf_message_get_num_active (mdf_message_t message);
239 
240 /* Change insref from insref_src to insref_dst, also move the messages from message_src to message_dst if they point to different messages */
241 LIBSPEC int mdf_message_move (const mdf_message_t message_src, const mdf_message_t message_dst, const uint64_t insref_src, const uint64_t insref_dst);
242 
243 /* Send the message chain to the server */
244 LIBSPEC int mdf_message_send (mdf_t handle, mdf_message_t message);
245 
246 #ifdef __cplusplus
247 }
248 #endif
249 
250 #endif
251