106 #include <sys/ioctl.h>
117 #ifdef FIX8_HAVE_GETOPT_H
131 using namespace FIX8;
148 { {
'S',
"Send one message, optionally save before send" }, &
MyMenu::send_msg },
176 int main(
int argc,
char **argv)
179 bool server(
false), reliable(
false);
180 string clcf, replay_file;
184 const char *gresult(getenv(
"LINES"));
185 if (gresult && *gresult)
187 const string result(gresult);
188 const int nlines(stoi(result));
193 #ifdef FIX8_HAVE_GETOPT_LONG
194 option long_options[]
196 {
"help", 0, 0,
'h' },
197 {
"version", 0, 0,
'v' },
198 {
"log", 1, 0,
'l' },
199 {
"config", 1, 0,
'c' },
200 {
"replay", 1, 0,
'p' },
201 {
"server", 0, 0,
's' },
202 {
"send", 1, 0,
'S' },
203 {
"receive", 1, 0,
'R' },
204 {
"lines", 1, 0,
'L' },
205 {
"quiet", 0, 0,
'q' },
206 {
"reliable", 0, 0,
'r' },
210 while ((val = getopt_long (argc, argv,
GETARGLIST.c_str(), long_options, 0)) != -1)
212 while ((val = getopt (argc, argv,
GETARGLIST.c_str())) != -1)
219 cout <<
"Released under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3. See <http://fsf.org/> for details." << endl;
221 case ':':
case '?':
return 1;
223 case 'l': GlobalLogger::set_global_filename(optarg);
break;
224 case 'p': replay_file = optarg;
break;
225 case 'c': clcf = optarg;
break;
226 case 's': server =
true;
break;
227 case 'S':
next_send = stoul(optarg);
break;
228 case 'R': next_receive = stoul(optarg);
break;
229 case 'L': lines = stoul(optarg);
break;
230 case 'q':
quiet =
true;
break;
231 case 'r': reliable =
true;
break;
246 const string conf_file(server ? clcf.empty() ?
"myfix_server.xml" : clcf : clcf.empty() ?
"myfix_client.xml" : clcf);
256 unique_ptr<FIX8::SessionInstanceBase> inst(ms->create_server_instance());
258 inst->session_ptr()->control() |= Session::printnohb;
259 glout_info <<
"client(" << ++scnt <<
") connection established.";
260 inst->start(
true,
next_send, next_receive);
261 cout <<
"Session(" << scnt <<
") finished." << endl;
267 unique_ptr<ClientSessionBase>
271 mc->session_ptr()->control() |= Session::printnohb;
275 const LoginParameters& lparam(mc->session_ptr()->get_login_parameters());
276 mc->start(
false,
next_send, next_receive, lparam._davi());
282 MyMenu mymenu(*mc->session_ptr(), 0, cout, &cm);
287 if (!replay_file.empty() && mymenu.load_msgs(replay_file))
293 if (mymenu.get_msg_cnt())
294 cout <<
'[' << mymenu.get_msg_cnt() <<
"] msgs; ";
295 cout <<
"?=help > " << flush;
297 mymenu.get_istr().get(ch);
299 if (mymenu.get_istr().bad() || ch == 0x3 || !mymenu.process(ch))
303 mymenu.get_tty().unset_raw_mode();
308 cerr <<
"exception: " << e.
what() << endl;
312 cerr <<
"exception: " << e.what() << endl;
316 cout <<
"terminated." << endl;
323 return enforce(seqnum, msg) || msg->
process(_router);
329 cout << get_session_state_string(before) <<
" => " << get_session_state_string(after) << endl;
335 return enforce(seqnum, msg) || msg->
process(_router);
341 cout << get_session_state_string(before) <<
" => " << get_session_state_string(after) << endl;
348 get_ostr() <<
"Key\tCommand" << endl;
349 get_ostr() <<
"===\t=======" << endl;
350 for (
const auto& pp : _handlers)
351 get_ostr() << pp.first._key <<
'\t' << pp.first._help << endl;
359 _ostr <<
"Enter number of lines per page (currently=" << _cm->get_lpp() <<
"): " << flush;
361 if (!_cm->GetString(_tty, str).empty())
362 _cm->set_lpp(stoi(str));
369 if (!_session.is_shutdown())
372 get_ostr() <<
"logout..." << endl;
382 um.
setdesc(
"harness -- menu driven f8 test client/server");
383 um.
add(
's',
"server",
"run in server mode (default client mode)");
384 um.
add(
'h',
"help",
"help, this screen");
385 um.
add(
'v',
"version",
"print version then exit");
386 um.
add(
'l',
"log",
"global log filename");
387 um.
add(
'p',
"replay",
"name of fix input file to send on connect");
388 um.
add(
'c',
"config",
"xml config (default: myfix_client.xml or myfix_server.xml)");
389 um.
add(
'q',
"quiet",
"do not print fix output");
390 um.
add(
'R',
"receive",
"set next expected receive sequence number");
391 um.
add(
'L',
"lines",
"set number of screen lines in the console menu (default 50)");
392 um.
add(
'S',
"send",
"set next send sequence number");
393 um.
add(
'r',
"reliable",
"start in reliable mode");
412 _cm->CreateMsgs(_tty, _lst);
421 _ostr << pp.first <<
": " << pp.second << endl;
428 _cm->EditMsgs(_tty, _lst);
435 _cm->DeleteMsgs(_tty, _lst);
442 _cm->DeleteAllMsgs(_tty, _lst);
449 for (
auto *pp : _lst)
457 if (_lst.size() && _cm->get_yn(
"Send messages? (y/n):",
true))
465 for (
const auto *pp : _lst)
466 _ostr << *pp << endl;
473 unique_ptr<Message> msg(_cm->RemoveMsg(_tty, _lst));
478 bool save(_cm->get_yn(
"Save message after send? (y/n):",
true));
482 _ostr <<
"Enter filename: " << flush;
483 _cm->GetString(_tty, fname);
485 if (_cm->get_yn(
"Send message? (y/n):",
true))
487 _session.send(msg.get(),
false);
488 if (save && !fname.empty())
489 save_msg(fname, msg.get());
498 #if !defined FIX8_RAW_MSG_SUPPORT
499 cerr << endl <<
"RAW_MSG_SUPPORT support not enabled. Run configure with --enable-rawmsgsupport" << endl;
502 _ostr << endl << fname <<
" exists, will append message" << endl;
503 ofstream ofs(fname.c_str(), ios::app);
506 cerr <<
Str_error(errno,
"Could not open file");
509 ofs << msg->get_rawmsg() << endl;
517 if (_session.control() & Session::printnohb)
519 _session.control().clear(Session::printnohb);
520 _session.control().set(Session::print);
521 get_ostr() <<
"Heartbeat display on";
525 _session.control().clear(Session::print);
526 _session.control().set(Session::printnohb);
527 get_ostr() <<
"Heartbeat display off";
535 ifstream ifs(fname.c_str());
538 cerr <<
Str_error(errno,
"Could not open file");
543 unsigned loaded(0), skipped(0);
559 if (_session.get_sid().same_side_sender_comp_id(sci) && _session.get_sid().same_side_target_comp_id(tci))
570 _ostr << loaded <<
" msgs loaded, " << skipped <<
" msgs skipped" << endl;
579 _ostr <<
"Playback (*.playback) files in ";
581 _ostr << _getcwd(cwd,
sizeof(cwd)) << endl;
582 if (system(
"dir *.playback"));
584 _ostr << getcwd(cwd,
sizeof(cwd)) << endl;
585 if (system(
"ls -l *.playback"));
588 _ostr <<
"Enter filename: " << flush;
590 if (!_cm->GetString(_tty, fname).empty())
static void init()
Initialise the random number generator.
F8API std::string Str_error(const int err, const char *str=0)
virtual bool operator()(const FIX8::TEX::ExecutionReport *msg)
#define FIX8_MAX_FLD_LENGTH
F8API BaseField * remove(const unsigned short fnum, Presence::const_iterator itr)
bool add(const char sw, const std::string &lsw, const std::string &help)
ExecutionReport (8), application, 326 fields, 16 groups.
Logout (5), admin, 3 fields, 0 groups.
virtual bool is_admin() const
void state_change(const FIX8::States::SessionStates before, const FIX8::States::SessionStates after)
const F8MetaCntx & ctx()
Compiler generated metadata object, accessed through this function.
NewOrderSingle (D), application, 243 fields, 11 groups.
int main(int argc, char **argv)
void setdesc(const std::string &desc)
void print(std::ostream &os) const
MessageBase * Header() const
#define FIX8_MAX_MSG_LENGTH
bool handle_application(const unsigned seqnum, const FIX8::Message *&msg)
F8API const Package_info & package_info()
const string GETARGLIST("hl:svqc:R:S:rp:L:")
virtual bool operator()(const FIX8::TEX::NewOrderSingle *msg)
virtual bool process(Router &rt) const
void sig_handler(int sig)
const unsigned short Common_SendingTime(52)
bool term_received(false)
A complete Fix message with header, body and trailer.
void state_change(const FIX8::States::SessionStates before, const FIX8::States::SessionStates after)
int hypersleep< h_seconds >(unsigned amt)
bool handle_application(const unsigned seqnum, const FIX8::Message *&msg)
const char * what() const
bool exist(const std::string &fname)
Convenient program help/usage wrapper. Generates a standardised usage message.
Reliable Client wrapper. This client attempts to recover from disconnects and login rejects...