106 #include <sys/ioctl.h>
117 #ifdef FIX8_HAVE_GETOPT_H
133 const string GETARGLIST(
"hl:svqc:R:S:rb:p:u:o");
172 int main(
int argc,
char **argv)
175 bool server(
false), once(
false), reliable(
false);
179 #ifdef FIX8_HAVE_GETOPT_LONG
180 option long_options[]
182 {
"help", 0, 0,
'h' },
183 {
"version", 0, 0,
'v' },
184 {
"once", 0, 0,
'o' },
185 {
"log", 1, 0,
'l' },
186 {
"config", 1, 0,
'c' },
187 {
"server", 0, 0,
's' },
188 {
"batch", 1, 0,
'b' },
189 {
"send", 1, 0,
'S' },
190 {
"receive", 1, 0,
'R' },
191 {
"quiet", 0, 0,
'q' },
192 {
"reliable", 0, 0,
'r' },
193 {
"preload", 1, 0,
'p' },
194 {
"update", 1, 0,
'u' },
198 while ((val = getopt_long (argc, argv,
GETARGLIST.c_str(), long_options, 0)) != -1)
200 while ((val = getopt (argc, argv,
GETARGLIST.c_str())) != -1)
207 cout <<
"Released under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3. See <http://fsf.org/> for details." << endl;
209 case ':':
case '?':
return 1;
212 case 'c': clcf = optarg;
break;
216 case 's': server =
true;
break;
217 case 'o': once =
true;
break;
218 case 'S':
next_send = stoul(optarg);
break;
219 case 'R': next_receive = stoul(optarg);
break;
220 case 'q':
quiet =
false;
break;
221 case 'r': reliable =
true;
break;
236 const string conf_file(server ? clcf.empty() ?
"hf_server.xml" : clcf : clcf.empty() ?
"hf_client.xml" : clcf);
248 unique_ptr<FIX8::SessionInstanceBase> inst(ms->create_server_instance());
252 sostr <<
"client(" << ++scnt <<
") connection established.";
256 cout << (pm ==
FIX8::pm_pipeline ?
"Pipelined" :
"Threaded") <<
" mode." << endl;
257 if (inst->session_ptr()->get_connection()->is_secure())
258 cout <<
"Session is secure (SSL)" << endl;
260 while (!inst->session_ptr()->is_shutdown())
261 FIX8::hypersleep<FIX8::h_milliseconds>(100);
262 cout <<
"Session(" << scnt <<
") finished." << endl;
264 #if defined FIX8_CODECTIMING
265 FIX8::Message::report_codec_timings(
"server");
273 unique_ptr<FIX8::ClientSessionBase>
281 mc->start(
false,
next_send, next_receive, mc->session_ptr()->get_login_parameters()._davi());
283 mc->start(
false,
next_send, next_receive);
285 MyMenu mymenu(*mc->session_ptr(), 0, cout);
286 cout << endl <<
"Menu started. Press '?' for help..." << endl << endl;
287 if (mc->session_ptr()->get_connection()->is_secure())
288 cout <<
"Session is secure (SSL)" << endl;
292 mymenu.get_tty().set_raw_mode();
295 cout <<
"Coroutine mode." << endl;
301 mc->session_ptr()->get_connection()->reader_execute();
310 if (select(1, &rfds, 0, 0, &tv) > 0)
312 if (read (0, &ch, 1) < 0)
317 cout <<
"Sending messages..." << endl;
319 while(mymenu.send_all_preloaded(coro, mc->session_ptr()))
320 mc->session_ptr()->get_connection()->reader_execute();
322 else if (ch == 0x3 || !mymenu.process(ch))
329 cout << (pm ==
FIX8::pm_pipeline ?
"Pipelined" :
"Threaded") <<
" mode." << endl;
330 while(!mymenu.get_istr().get(ch).bad() && !
term_received && ch != 0x3 && mymenu.process(ch))
334 #if defined FIX8_CODECTIMING
335 FIX8::Message::report_codec_timings(
"client");
337 if (!mc->session_ptr()->is_shutdown())
338 mc->session_ptr()->stop();
340 mymenu.get_tty().unset_raw_mode();
345 cerr <<
"exception: " << e.
what() << endl;
349 cerr <<
"exception: " << e.what() << endl;
353 cout <<
"terminated." << endl;
363 cout <<
"Enter number of NewOrderSingle msgs to batch preload:";
365 _tty.unset_raw_mode();
374 static unsigned oid(10000);
376 oistr <<
"ord" << ++oid <<
'-' << num;
389 #if defined FIX8_PREENCODE_MSG_SUPPORT
394 cout << _session.cached() <<
" NewOrderSingle msgs preloaded." << endl;
396 send_all_preloaded();
405 cout <<
"Enter number of NewOrderSingle msgs to send:";
408 _tty.unset_raw_mode();
411 for (
unsigned ii(0); ii < num; ++ii)
413 cout << endl << num <<
" NewOrderSingle msgs sent" << endl;
421 static unsigned oid(0);
423 oistr <<
"ord" << ++oid;
444 const unsigned tosend(_session.size());
445 cout <<
"Sending " << tosend <<
" NewOrderSingle msgs ..." << flush;
447 while (_session.cached())
455 cout <<
'\r' << snt <<
" NewOrderSingle msgs sent ";
459 cout << endl << snt <<
" NewOrderSingle msgs sent." << endl;
472 while (_session.cached())
476 if (!(ptr = _session.pop()))
487 return _session.cached();
495 cout << _session.size() <<
" NewOrderSingle msgs currently preloaded." << endl;
499 cout <<
"Enter number of NewOrderSingle msgs to preload:";
501 _tty.unset_raw_mode();
506 cout <<
"loading..." << endl;
507 for (
unsigned ii(0); ii < num; ++ii)
509 static unsigned oid(10000);
511 oistr <<
"ord" << ++oid <<
'-' << num;
524 #if defined FIX8_PREENCODE_MSG_SUPPORT
530 cout << _session.
size() <<
" NewOrderSingle msgs preloaded." << endl;
539 get_ostr() <<
"Key\tCommand" << endl;
540 get_ostr() <<
"===\t=======" << endl;
541 for (
const auto& pp : _handlers)
542 get_ostr() << pp.first._key <<
'\t' << pp.first._help << endl;
550 if (!_session.is_shutdown())
552 FIX8::hypersleep<FIX8::h_seconds>(2);
560 um.
setdesc(
"hftest -- f8 HF test client/server");
561 um.
add(
's',
"server",
"run in server mode (default client mode)");
562 um.
add(
'h',
"help",
"help, this screen");
563 um.
add(
'v',
"version",
"print version then exit");
564 um.
add(
'l',
"log",
"global log filename");
565 um.
add(
'c',
"config",
"xml config (default: hf_client.xml or hf_server.xml)");
566 um.
add(
'o',
"once",
"for server, allow one client session then exit");
567 um.
add(
'q',
"quiet",
"do not print fix output (default yes)");
568 um.
add(
'b',
"batch",
"if using batch send, number of messages in each batch (default 1000)");
569 um.
add(
'p',
"preload",
"if batching or preloading, default number of messages to create");
570 um.
add(
'R',
"receive",
"set next expected receive sequence number");
571 um.
add(
'S',
"send",
"set next send sequence number");
572 um.
add(
'r',
"reliable",
"start in reliable mode");
573 um.
add(
'u',
"update",
"message count update frequency (default 5000)");
581 return enforce(seqnum, msg) || msg->
process(_router);
587 static unsigned oid(0), eoid(0);
597 oistr <<
"ord" << ++oid;
627 unsigned remaining_qty(qty()), cum_qty(0);
628 while (remaining_qty > 0)
631 remaining_qty -= trdqty;
636 eistr <<
"exec" << ++eoid;
639 <<
new FIX8::TEX::OrderID(oistr.str())
657 static int exrecv(0);
660 cout <<
'\r' << exrecv <<
" ExecutionReport msgs received ";
669 return enforce(seqnum, msg) || msg->
process(_router);
void sig_handler(int sig)
static void init()
Initialise the random number generator.
bool handle_application(const unsigned seqnum, const FIX8::Message *&msg)
Connection * get_connection()
const char HandlInst_AUTOMATED_EXECUTION_ORDER_PRIVATE_NO_BROKER_INTERVENTION('1')
virtual bool operator()(const FIX8::TEX::ExecutionReport *msg)
const char ExecTransType_NEW('0')
Fix8 Base Session. User sessions are derived from this class.
unsigned preload_count(0)
const char TimeInForce_FILL_OR_KILL('4')
Field< char, 59 > TimeInForce
const string GETARGLIST("hl:svqc:R:S:rb:p:u:o")
static T getrandom(const T range=0)
bool add(const char sw, const std::string &lsw, const std::string &help)
Field< char, 39 > OrdStatus
ExecutionReport (8), application, 326 fields, 16 groups.
Field< Boolean, 113 > ReportToExch
F8API unsigned copy_legal(MessageBase *to, bool force=false) const
Logout (5), admin, 3 fields, 0 groups.
Field< char, 40 > OrdType
ProcessModel
Supported session process models.
const char OrdStatus_FILLED('2')
bool handle_application(const unsigned seqnum, const FIX8::Message *&msg)
bool term_received(false)
const F8MetaCntx & ctx()
Compiler generated metadata object, accessed through this function.
NewOrderSingle (D), application, 243 fields, 11 groups.
void setdesc(const std::string &desc)
Field< char, 21 > HandlInst
void print(std::ostream &os) const
const char OrdType_LIMIT('2')
Field< f8String, 11 > ClOrdID
virtual bool operator()(const FIX8::TEX::NewOrderSingle *msg)
virtual bool process(Router &rt) const
Field< char, 20 > ExecTransType
std::set< const XmlElement *, EntityOrderComp > XmlSet
A complete Fix message with header, body and trailer.
int main(int argc, char **argv)
const char OrdStatus_CANCELED('4')
Field template. There will ONLY be partial template specialisations of this template.
Field< char, 29 > LastCapacity
const char OrdStatus_PARTIALLY_FILLED('1')
void set_tcp_cork_flag(bool way) const
bool writer_poll(const Poco::Timespan &ts=Poco::Timespan()) const
Field< f8String, 37 > OrderID
unsigned update_count(5000)
Field< Qty, 38 > OrderQty
static void set_global_filename(const std::string &from)
Field< f8String, 55 > Symbol
const char OrdStatus_REJECTED('8')
const char OrdStatus_NEW('0')
const char * what() const
unsigned batch_size(1000)
const char ExecType_NEW('0')
static bool log(const std::string &what, Logger::Level lev=Logger::Info, const char *fl=nullptr, unsigned int val=0)
Field< Qty, 151 > LeavesQty
Convenient program help/usage wrapper. Generates a standardised usage message.
Reliable Client wrapper. This client attempts to recover from disconnects and login rejects...
Field< f8String, 17 > ExecID