示例#1
0
文件: myfix.hpp 项目: BoSiC/fix8
	FIX8::f8String& get_string(FIX8::f8String& to)
	{
		char buff[128] {};
		_tty.unset_raw_mode();
		_istr.getline(buff, sizeof(buff));
		_tty.set_raw_mode();
		return to = buff;
	}
示例#2
0
文件: myfix.cpp 项目: fix8/fix8
//-----------------------------------------------------------------------------------------
int main(int argc, char **argv)
{
	int val;
	bool server(false), reliable(false), once(false), dump(false), multi(false);
	string clcf, session;

#ifdef FIX8_HAVE_GETOPT_LONG
	option long_options[]
	{
		{ "help",		0,	0,	'h' },
		{ "version",	0,	0,	'v' },
		{ "log",			1,	0,	'l' },
		{ "delimiter",	1,	0,	'D' },
		{ "config",		1,	0,	'c' },
		{ "session",	1,	0,	'N' },
		{ "once",	   0,	0,	'o' },
		{ "server",		0,	0,	's' },
		{ "multi",		0,	0,	'm' },
		{ "send",		1,	0,	'S' },
		{ "receive",	1,	0,	'R' },
		{ "quiet",		0,	0,	'q' },
		{ "reliable",	0,	0,	'r' },
		{ "dump",		0,	0,	'd' },
		{ 0 },
	};

	while ((val = getopt_long (argc, argv, GETARGLIST.c_str(), long_options, 0)) != -1)
#else
	while ((val = getopt (argc, argv, GETARGLIST.c_str())) != -1)
#endif
	{
      switch (val)
		{
		case 'v':
			cout << argv[0] << " for " FIX8_PACKAGE " version " FIX8_VERSION << endl;
			cout << "Released under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3. See <http://fsf.org/> for details." << endl;
			return 0;
		case ':': case '?': return 1;
		case 'h': print_usage(); return 0;
		case 'l': GlobalLogger::set_global_filename(optarg); break;
		case 'D': GlobalLogger::set_delimiter(optarg); break;
		case 'c': clcf = optarg; break;
		case 's': server = true; break;
		case 'N': session = optarg; break;
		case 'm': multi = true; break;
		case 'o': once = true; break;
		case 'S': next_send = stoul(optarg); break;
		case 'R': next_receive = stoul(optarg); break;
		case 'q': quiet = true; break;
		case 'r': reliable = true; break;
		case 'd': dump = true; break;
		default: break;
		}
	}

	RandDev::init();

	signal(SIGTERM, sig_handler);
	signal(SIGINT, sig_handler);
#ifndef _MSC_VER
	signal(SIGQUIT, sig_handler);
#endif

	bool restore_tty(false);

	try
	{
		const string conf_file(server ? clcf.empty() ? "myfix_server.xml" : clcf : clcf.empty() ? "myfix_client.xml" : clcf);
		f8_atomic<unsigned> scnt(0);

		if (dump)
		{
			XmlElement *root(XmlElement::Factory(conf_file));
			if (root)
				cout << *root << endl;
			else
				cerr << "Failed to parse " << conf_file << endl;
			return 0;
		}

		if (server)
		{
			if (multi)	// demonstrate use of multi session server manager
			{
				unique_ptr<ServerManager> sm(new ServerManager);
				sm->add(new ServerSession<myfix_session_server>(TEX::ctx(), conf_file, "TEX1"));
				sm->add(new ServerSession<myfix_session_server>(TEX::ctx(), conf_file, "TEX2"));

				vector<thread> thrds;
				while (!term_received)
				{
					ServerSessionBase *srv(sm->select());
					if (srv)
					{
						thrds.push_back(thread ([&]() { server_process(srv, ++scnt, true); }));
						hypersleep<h_seconds>(1);
					}
				}
				for_each(thrds.begin(), thrds.end(), [](thread& tt) { if (tt.joinable()) tt.join(); });
			}
			else	// serial server instances only
			{
				unique_ptr<ServerSessionBase> srv(new ServerSession<myfix_session_server>(TEX::ctx(), conf_file, "TEX"));

				while (!term_received)
				{
					if (!srv->poll())
						continue;
					server_process(srv.get(), ++scnt);
					if (once)
						break;
				}
			}
		}
		else
		{
			if (multi)	// demonstrate use of multi session client manager
			{
				const f8String cl1("DLD1"), cl2("DLD2");
				ClientManager cm;
				cm.add(cl1, reliable ? new ReliableClientSession<myfix_session_client>(TEX::ctx(), conf_file, cl1)
											: new ClientSession<myfix_session_client>(TEX::ctx(), conf_file, cl1));
				cm.add(cl2, reliable ? new ReliableClientSession<myfix_session_client>(TEX::ctx(), conf_file, cl2)
											: new ClientSession<myfix_session_client>(TEX::ctx(), conf_file, cl2));

				ClientSessionBase *csb(cm.for_each_if([&](ClientSessionBase *pp)
				{
					if (!quiet)
						pp->session_ptr()->control() |= Session::printnohb;
					pp->start(false, next_send, next_receive, pp->session_ptr()->get_login_parameters()._davi());
					// if you use ReliableClientSession, you need to return true here always
					return reliable ? true : States::is_live(pp->session_ptr()->get_session_state());
				}));

				if (csb)
					cerr << csb->_session_name << " failed to start" << endl;

				vector<thread> thrds;
				cm.for_each_if([&](ClientSessionBase *pp)
				{
					// we should be running client_process however this won't work
					// since two threads can't share the same console
					thrds.push_back(thread ([=]()		// use copy closure
					{
						MyMenu mymenu(*pp->session_ptr(), 0, cout);
						hypersleep<h_seconds>(1 + RandDev::getrandom(10));
						mymenu.new_order_single();	// send an order and then logout
						mymenu.do_logout();
					}));
					return true;
				});

				for_each(thrds.begin(), thrds.end(), [](thread& tt) { if (tt.joinable()) tt.join(); });
			}
			else	// single client only
			{
				const string my_session(session.empty() ? "DLD1" : session);
				unique_ptr<ClientSessionBase>
					mc(reliable ? new ReliableClientSession<myfix_session_client>(TEX::ctx(), conf_file, my_session)
									: new ClientSession<myfix_session_client>(TEX::ctx(), conf_file, my_session));
				if (!quiet)
					mc->session_ptr()->control() |= Session::printnohb;
				mc->start(false, next_send, next_receive, mc->session_ptr()->get_login_parameters()._davi());
				client_process(mc.get());
			}
		}
	}
	catch (f8Exception& e)
	{
		cerr << "exception: " << e.what() << endl;
		restore_tty = true;
		glout_error << e.what();
	}
	catch (exception& e)	// also catches Poco::Net::NetException
	{
		cerr << "std::exception: " << e.what() << endl;
		restore_tty = true;
		glout_error << e.what();
	}
	catch (...)
	{
		cerr << "unknown exception" << endl;
		restore_tty = true;
		glout_error << "unknown exception";
	}

	if (restore_tty && !server)
		save_tty.unset_raw_mode();

	if (term_received)
		cout << endl << "terminated." << endl;
	return 0;
}