//------------------------------------------------------------------------------------------------- size_t Message::encode(f8String& to) const { char output[MAX_MSG_LENGTH + HEADER_CALC_OFFSET], *ptr(output); const size_t msgLen(encode(&ptr)); to.assign(ptr, msgLen); return to.size(); }
/*! Construct from string ctor. \param from string to construct field from \param rlm pointer to the realmbase for this field (if available) */ Field (const f8String& from, const RealmBase *rlm=0) : BaseField(field) { if (from.size() == _sec_only) // 19981231-23:59:59 Poco::DateTimeParser::parse(_fmt_sec, from, _value, _tzdiff); else if (from.size() == _with_ms) // 19981231-23:59:59.123 Poco::DateTimeParser::parse(_fmt_ms, from, _value, _tzdiff); }
//------------------------------------------------------------------------------------------------- unsigned MessageBase::extract_header(const f8String& from, char *len, char *mtype) { const char *dptr(from.data()); const size_t flen(from.size()); char tag[MAX_MSGTYPE_FIELD_LEN], val[MAX_FLD_LENGTH]; unsigned s_offset(0), result; if ((result = extract_element(dptr, flen, tag, val))) { if (*tag != '8') return 0; s_offset += result; if ((result = extract_element(dptr + s_offset, flen - s_offset, tag, len))) { if (*tag != '9') return 0; s_offset += result; if ((result = extract_element(dptr + s_offset, flen - s_offset, tag, mtype))) { if (*tag != '3' || *(tag + 1) != '5') return 0; s_offset += result; } } } return s_offset; }
/*! Send message over socket. \param msg message string to send \return number of bytes sent */ int send(const f8String& msg) { unsigned remaining(msg.size()), wrdone(0); const char *data(msg.data()); while (remaining > 0) { const int wrtSz(_sock->sendBytes(data + wrdone, remaining)); if (wrtSz < 0) { switch(errno) { case EAGAIN: #if defined EWOULDBLOCK && EAGAIN != EWOULDBLOCK case EWOULDBLOCK: #endif continue; default: throw PeerResetConnection("send: connection gone"); } } wrdone += wrtSz; remaining -= wrtSz; } return wrdone; }
//------------------------------------------------------------------------------------------------- bool FilePersister::put(const unsigned seqnum, const f8String& what) { if (!_opened || !seqnum) return false; if (_index.find(seqnum) != _index.end()) { glout_error << "Error: seqnum " << seqnum << " already persisted in: " << _dbIname; return false; } if (lseek(_iod, 0, SEEK_END) < 0) { glout_error << "Error: could not seek to index end for seqnum persitence: " << _dbIname; return false; } off_t offset; if ((offset = lseek(_fod, 0, SEEK_END)) < 0) { glout_error << "Error: could not seek to end for seqnum persitence: " << _dbFname; return false; } IPrec iprec(seqnum, offset, static_cast<unsigned>(what.size())); if (write (_iod, static_cast<void *>(&iprec), sizeof(IPrec)) != sizeof(IPrec)) { glout_error << "Error: could not write index record for seqnum " << seqnum << " to: " << _dbIname; return false; } if (write (_fod, what.data(), static_cast<unsigned>(what.size())) != static_cast<ssize_t>(what.size())) { glout_error << "Error: could not write record for seqnum " << seqnum << " to: " << _dbFname; return false; } return _index.insert({seqnum, iprec._prec}).second; }
//------------------------------------------------------------------------------------------------- unsigned Message::encode(f8String& to) const { char msg[MAX_MSG_LENGTH], hmsg[MAX_MSG_LENGTH]; size_t sz(0), hsz(0); #if defined CODECTIMING ostringstream gerr; gerr << "encode(" << _msgType << "):"; IntervalTimer itm; #endif if (!_header) throw MissingMessageComponent("header"); Fields::const_iterator fitr(_header->_fields.find(Common_MsgType)); static_cast<msg_type *>(fitr->second)->set(_msgType); _header->encode(msg, sz); MessageBase::encode(msg, sz); if (!_trailer) throw MissingMessageComponent("trailer"); _trailer->encode(msg, sz); const unsigned msgLen(sz); // checksummable msglength if ((fitr = _header->_fields.find(Common_BeginString)) == _header->_fields.end()) throw MissingMandatoryField(Common_BeginString); _header->_fp.clear(Common_BeginString, FieldTrait::suppress); fitr->second->encode(hmsg, hsz); #if defined MSGRECYCLING _header->_fp.set(Common_BeginString, FieldTrait::suppress); // in case we want to reuse #endif if ((fitr = _header->_fields.find(Common_BodyLength)) == _header->_fields.end()) throw MissingMandatoryField(Common_BodyLength); _header->_fp.clear(Common_BodyLength, FieldTrait::suppress); static_cast<body_length *>(fitr->second)->set(msgLen); fitr->second->encode(hmsg, hsz); #if defined MSGRECYCLING _header->_fp.set(Common_BodyLength, FieldTrait::suppress); // in case we want to reuse #endif ::memcpy(hmsg + hsz, msg, sz); hsz += sz; if ((fitr = _trailer->_fields.find(Common_CheckSum)) == _trailer->_fields.end()) throw MissingMandatoryField(Common_CheckSum); static_cast<check_sum *>(fitr->second)->set(fmt_chksum(calc_chksum(hmsg, hsz))); _trailer->_fp.clear(Common_CheckSum, FieldTrait::suppress); fitr->second->encode(hmsg, hsz); #if defined MSGRECYCLING _trailer->_fp.set(Common_CheckSum, FieldTrait::suppress); // in case we want to reuse #endif #if defined CODECTIMING gerr << itm.Calculate(); GlobalLogger::log(gerr.str()); #endif to.assign(hmsg, hsz); return to.size(); }
//------------------------------------------------------------------------------------------------- unsigned MessageBase::decode(const f8String& from, unsigned s_offset, unsigned ignore, bool permissive_mode) { const unsigned fsize(static_cast<unsigned>(from.size()) - ignore), npos(0xffffffff); unsigned pos(static_cast<unsigned>(_pos.size())), last_valid_pos(npos); const char *dptr(from.data()); char tag[FIX8_MAX_FLD_LENGTH], val[FIX8_MAX_FLD_LENGTH]; size_t last_valid_offset(0); for (unsigned result; s_offset <= fsize && (result = extract_element(dptr + s_offset, fsize - s_offset, tag, val));) { const unsigned short tv(fast_atoi<unsigned short>(tag)); Presence::const_iterator itr(_fp.get_presence().find(tv)); if (itr == _fp.get_presence().end()) { if (permissive_mode) { if (last_valid_pos == npos) { last_valid_pos = pos; last_valid_offset = s_offset; } _unknown.append(dptr + s_offset, result); s_offset += result; continue; } break; } s_offset += result; if (itr->_field_traits.has(FieldTrait::present)) { if (!itr->_field_traits.has(FieldTrait::automatic)) throw DuplicateField(tv); } else { const BaseEntry *be(_ctx.find_be(tv)); if (!be) throw UnknownField(tv); BaseField *bf(be->_create._do(val, be->_rlm, -1)); add_field_decoder(tv, ++pos, bf); itr->_field_traits.set(FieldTrait::present); // check if repeating group and num elements > 0 if (itr->_field_traits.has(FieldTrait::group) && has_group_count(bf)) s_offset = decode_group(nullptr, tv, from, s_offset, ignore); } } const unsigned short missing(_fp.find_missing()); if (missing) { const BaseEntry *tbe(_ctx.find_be(missing)); ostringstream ostr; ostr << tbe->_name << " (" << missing << ')'; throw MissingMandatoryField(ostr.str()); } return permissive_mode && last_valid_pos == pos ? static_cast<unsigned>(last_valid_offset) : s_offset; }
//------------------------------------------------------------------------------------------------- Message *Message::factory(const F8MetaCntx& ctx, const f8String& from) { Message *msg(0); f8String len, mtype; if (extract_header(from, len, mtype)) { const unsigned mlen(fast_atoi<unsigned>(len.c_str())); const BaseMsgEntry *bme(ctx._bme.find_ptr(mtype)); if (!bme) throw InvalidMessage(mtype); msg = bme->_create(); #if defined PERMIT_CUSTOM_FIELDS if (ctx._ube) ctx._ube->post_msg_ctor(msg); #endif #if defined CODECTIMING ostringstream gerr; gerr << "decode(" << mtype << "):"; IntervalTimer itm; #endif msg->decode(from); #if defined CODECTIMING gerr << itm.Calculate(); GlobalLogger::log(gerr.str()); #endif static_cast<body_length *>(msg->_header->_fields.find(Common_BodyLength)->second)->set(mlen); Fields::const_iterator fitr(msg->_header->_fields.find(Common_MsgType)); static_cast<msg_type *>(fitr->second)->set(mtype); #if defined POPULATE_METADATA msg->check_set_rlm(fitr->second); #endif const char *pp(from.data() + from.size() - 7); if (*pp != '1' || *(pp + 1) != '0') // 10=XXX^A throw InvalidMessage(from); if (!ctx.has_flag(F8MetaCntx::noverifychksum)) // permit chksum calculation to be skipped { const f8String chksum(pp + 3, 3); static_cast<check_sum *>(msg->_trailer->_fields.find(Common_CheckSum)->second)->set(chksum); const unsigned chkval(fast_atoi<unsigned>(chksum.c_str())), mchkval(calc_chksum(from, 0, from.size() - 7)); if (chkval != mchkval) throw BadCheckSum(mchkval); } } else { //cerr << "Message::factory throwing" << endl; throw InvalidMessage(from); } return msg; }
//------------------------------------------------------------------------------------------------- bool MemcachedPersister::initialise(const f8String& config_str, const f8String& key_base, bool purge) { if (_cache) return true; _key_base = key_base; _cache = memcached(config_str.c_str(), config_str.size()); if (!(_server_count = memcached_server_count(_cache))) { glout_error << "Error: no memcached servers were configured for " << _key_base; return false; } return purge ? memcached_success(memcached_flush(_cache, 0)) : true; }
//------------------------------------------------------------------------------------------------- unsigned MessageBase::decode_group(GroupBase *grpbase, const unsigned short fnum, const f8String& from, unsigned s_offset, unsigned ignore) { unsigned result; if (!(grpbase = find_add_group(fnum, grpbase))) throw InvalidRepeatingGroup(fnum, FILE_LINE); const unsigned fsize(static_cast<unsigned>(from.size()) - ignore); const char *dptr(from.data()); char tag[FIX8_MAX_FLD_LENGTH], val[FIX8_MAX_FLD_LENGTH]; for (bool ok(true); ok && s_offset < fsize; ) { unique_ptr<MessageBase> grp(grpbase->create_group(false)); // shallow create for (unsigned pos(0); s_offset < fsize && (result = extract_element(dptr + s_offset, fsize - s_offset, tag, val));) { const unsigned tv(fast_atoi<unsigned>(tag)); Presence::const_iterator itr(grp->_fp.get_presence().end()); if (grp->_fp.get(tv, itr, FieldTrait::present)) // already present; next group? break; if (pos == 0 && grp->_fp.getPos(tv, itr) != 1) // first field in group is mandatory throw MissingRepeatingGroupField(tv); const BaseEntry *be(_ctx.find_be(tv)); if (!be || !grp->_fp.has(tv, itr)) // unknown field or field not found in sub-group - end of repeats? { ok = false; break; } s_offset += result; BaseField *bf(be->_create._do(val, be->_rlm, -1)); grp->add_field(tv, itr, ++pos, bf, false); grp->_fp.set(tv, itr, FieldTrait::present); // is present // nested group (check if not zero elements) if (grp->_fp.is_group(tv, itr) && has_group_count(bf)) s_offset = grp->decode_group(grpbase, tv, from, s_offset, ignore); } const unsigned short missing(grp->_fp.find_missing()); if (missing) { const BaseEntry *tbe(_ctx.find_be(missing)); ostringstream ostr; ostr << tbe->_name << " (" << missing << ')'; throw MissingMandatoryField(ostr.str()); } *grpbase << grp.release(); } return s_offset; }
void extract_element_test(f8String msg, f8String expect_tag, f8String expect_val) { char cVal[MAX_FLD_LENGTH]; char cTag[MAX_FLD_LENGTH]; MessageBase::extract_element(msg.c_str(), static_cast<unsigned>(msg.length()), cTag, cVal); EXPECT_EQ(expect_val, f8String(cVal)); EXPECT_EQ(expect_tag, f8String(cTag)); f8String sVal; f8String sTag; MessageBase::extract_element(msg.c_str(), static_cast<unsigned>(msg.length()), sTag, sVal); EXPECT_EQ(expect_val, sVal); EXPECT_EQ(expect_tag, sTag); }
//------------------------------------------------------------------------------------------------- unsigned MessageBase::decode_group(const unsigned short fnum, const f8String& from, const unsigned offset) { unsigned s_offset(offset), result; GroupBase *grpbase(find_group(fnum)); if (!grpbase) throw InvalidRepeatingGroup(fnum); const unsigned fsize(from.size()); const char *dptr(from.data()); char tag[MAX_FLD_LENGTH], val[MAX_FLD_LENGTH]; for (bool ok(true); ok && s_offset < fsize; ) { scoped_ptr<MessageBase> grp(grpbase->create_group()); for (unsigned pos(0); s_offset < fsize && (result = extract_element(dptr + s_offset, fsize - s_offset, tag, val));) { const unsigned tv(fast_atoi<unsigned>(tag)); Presence::const_iterator itr(grp->_fp.get_presence().end()); if (grp->_fp.get(tv, itr, FieldTrait::present)) // already present; next group? break; if (pos == 0 && grp->_fp.getPos(tv, itr) != 1) // first field in group is mandatory throw MissingRepeatingGroupField(tv); const BaseEntry *be(_ctx._be.find_ptr(tv)); if (!be) throw InvalidField(tv); if (!grp->_fp.has(tv, itr)) // field not found in sub-group - end of repeats? { ok = false; break; } s_offset += result; grp->add_field(tv, itr, ++pos, be->_create(val, be->_rlm, -1), false); grp->_fp.set(tv, itr, FieldTrait::present); // is present if (grp->_fp.is_group(tv, itr)) // nested group s_offset = grp->decode_group(tv, from, s_offset); } const unsigned short missing(grp->_fp.find_missing()); if (missing) { const BaseEntry& tbe(_ctx._be.find_ref(missing)); ostringstream ostr; ostr << tbe._name << " (" << missing << ')'; throw MissingMandatoryField(ostr.str()); } *grpbase += grp.release(); } return s_offset; }
//------------------------------------------------------------------------------------------------- bool FilePersister::get(const unsigned seqnum, f8String& to) const { if (!_opened || !seqnum || _index.empty()) return false; Index::const_iterator itr(_index.find(seqnum)); if (itr == _index.end()) { glout_warn << "Warning: index does not contain seqnum: " << seqnum << " in: " << _dbIname; return false; } if (lseek(_fod, itr->second._offset, SEEK_SET) < 0) { glout_error << "Error: could not seek to correct index location for get: " << _dbFname; return false; } char buff[FIX8_MAX_MSG_LENGTH]; if (read (_fod, buff, itr->second._size) != itr->second._size) { glout_error << "Error: could not read message record for seqnum " << seqnum << " from: " << _dbFname; return false; } to.assign(buff, itr->second._size); return true; }
//------------------------------------------------------------------------------------------------- Message *Message::factory(const F8MetaCntx& ctx, const f8String& from) { Message *msg(0); char mtype[MAX_MSGTYPE_FIELD_LEN] = {}, len[MAX_MSGTYPE_FIELD_LEN] = {}; if (extract_header(from, len, mtype)) { const unsigned mlen(fast_atoi<unsigned>(len)); const BaseMsgEntry *bme(ctx._bme.find_ptr(mtype)); if (!bme) throw InvalidMessage(mtype); msg = bme->_create(); #if defined CODECTIMING IntervalTimer itm; #endif msg->decode(from); #if defined CODECTIMING _decode_timings._cpu_used += itm.Calculate().AsDouble(); ++_decode_timings._msg_count; #endif static_cast<body_length *>(msg->_header->_fields.find(Common_BodyLength)->second)->set(mlen); Fields::const_iterator fitr(msg->_header->_fields.find(Common_MsgType)); static_cast<msg_type *>(fitr->second)->set(mtype); #if defined POPULATE_METADATA msg->check_set_rlm(fitr->second); #endif const char *pp(from.data() + from.size() - 7); if (*pp != '1' || *(pp + 1) != '0') // 10=XXX^A throw InvalidMessage(from); if (!ctx.has_flag(F8MetaCntx::noverifychksum)) // permit chksum calculation to be skipped { const f8String chksum(pp + 3, 3); static_cast<check_sum *>(msg->_trailer->_fields.find(Common_CheckSum)->second)->set(chksum); const unsigned chkval(fast_atoi<unsigned>(chksum.c_str())), mchkval(calc_chksum(from, 0, from.size() - 7)); if (chkval != mchkval) throw BadCheckSum(mchkval); } } else { //cerr << "Message::factory throwing" << endl; throw InvalidMessage(from); } return msg; }
//------------------------------------------------------------------------------------------------- unsigned MessageBase::decode(const f8String& from, const unsigned offset) { unsigned s_offset(offset), result; const unsigned fsize(from.size()); const char *dptr(from.data()); char tag[MAX_FLD_LENGTH], val[MAX_FLD_LENGTH]; for (unsigned pos(_pos.size()); s_offset <= fsize && (result = extract_element(dptr + s_offset, fsize - s_offset, tag, val));) { const unsigned tv(fast_atoi<unsigned>(tag)); const BaseEntry *be(_ctx._be.find_ptr(tv)); #if defined PERMIT_CUSTOM_FIELDS if (!be && (!_ctx._ube || (be = _ctx._ube->find_ptr(tv)) == 0)) #else if (!be) #endif throw InvalidField(tv); Presence::const_iterator itr(_fp.get_presence().end()); if (!_fp.has(tv, itr)) break; s_offset += result; if (_fp.get(tv, itr, FieldTrait::present)) { if (!_fp.get(tv, itr, FieldTrait::automatic)) throw DuplicateField(tv); } else { add_field(tv, itr, ++pos, be->_create(val, be->_rlm, -1), false); if (_fp.is_group(tv, itr)) s_offset = decode_group(tv, from, s_offset); } } const unsigned short missing(_fp.find_missing()); if (missing) { const BaseEntry& tbe(_ctx._be.find_ref(missing)); ostringstream ostr; ostr << tbe._name << " (" << missing << ')'; throw MissingMandatoryField(ostr.str()); } return s_offset; }
//------------------------------------------------------------------------------------------------- Message *Message::factory(const F8MetaCntx& ctx, const f8String& from, bool no_chksum, bool permissive_mode) { char mtype[MAX_MSGTYPE_FIELD_LEN] = {}, len[MAX_MSGTYPE_FIELD_LEN] = {}; const size_t hlen(extract_header(from, len, mtype)); if (!hlen) { //cerr << "Message::factory throwing" << endl; throw InvalidMessage(from); } const unsigned mlen(fast_atoi<unsigned>(len)); const BaseMsgEntry *bme(ctx._bme.find_ptr(mtype)); if (!bme) throw InvalidMessage(mtype); Message *msg(bme->_create._do()); #if defined CODECTIMING IntervalTimer itm; #endif msg->decode(from, hlen, 7, permissive_mode); // skip already decoded mandatory 8, 9, 35 and 10 #if defined CODECTIMING _decode_timings._cpu_used += itm.Calculate().AsDouble(); ++_decode_timings._msg_count; #endif msg->_header->get_body_length()->set(mlen); msg->_header->get_msg_type()->set(mtype); #if defined POPULATE_METADATA msg->check_set_rlm(fitr->second); #endif const char *pp(from.data() + from.size() - 7); if (*pp != '1' || *(pp + 1) != '0') // 10=XXX^A throw InvalidMessage(from); if (!no_chksum) // permit chksum calculation to be skipped { const f8String chksum(pp + 3, 3); msg->_trailer->get_check_sum()->set(chksum); const unsigned chkval(fast_atoi<unsigned>(chksum.c_str())), mchkval(calc_chksum(from, 0, from.size() - 7)); if (chkval != mchkval) throw BadCheckSum(mchkval); } return msg; }
//------------------------------------------------------------------------------------------------- bool FilePersister::put(const unsigned seqnum, const f8String& what) { if (!_opened || !seqnum) return false; if (_index.find(seqnum) != _index.end()) { ostringstream eostr; eostr << "Error seqnum " << seqnum << " already persisted in: " << _dbIname; GlobalLogger::log(eostr.str()); return false; } if (lseek(_iod, 0, SEEK_END) < 0) { ostringstream eostr; eostr << "Error could not seek to index end for seqnum persitence: " << _dbIname; GlobalLogger::log(eostr.str()); return false; } off_t offset; if ((offset = lseek(_fod, 0, SEEK_END)) < 0) { ostringstream eostr; eostr << "Error could not seek to end for seqnum persitence: " << _dbFname; GlobalLogger::log(eostr.str()); return false; } IPrec iprec(seqnum, offset, what.size()); if (write (_iod, static_cast<void *>(&iprec), sizeof(IPrec)) != sizeof(IPrec)) { ostringstream eostr; eostr << "Error could not write index record for seqnum " << seqnum << " to: " << _dbIname; GlobalLogger::log(eostr.str()); return false; } if (write (_fod, what.data(), sizeof(what.size())) != sizeof(what.size())) { ostringstream eostr; eostr << "Error could not write record for seqnum " << seqnum << " to: " << _dbFname; GlobalLogger::log(eostr.str()); return false; } return _index.insert(Index::value_type(seqnum, iprec._prec)).second; }
//------------------------------------------------------------------------------------------------- unsigned MessageBase::decode(const f8String& from, unsigned s_offset, unsigned ignore) { unsigned result; const unsigned fsize(from.size() - ignore); const char *dptr(from.data()); char tag[MAX_FLD_LENGTH], val[MAX_FLD_LENGTH]; for (unsigned pos(_pos.size()); s_offset <= fsize && (result = extract_element(dptr + s_offset, fsize - s_offset, tag, val));) { const unsigned short tv(fast_atoi<unsigned short>(tag)); Presence::const_iterator itr(_fp.get_presence().find(tv)); if (itr == _fp.get_presence().end()) break; s_offset += result; if (itr->_field_traits.has(FieldTrait::present)) { if (!itr->_field_traits.has(FieldTrait::automatic)) throw DuplicateField(tv); } else { const BaseEntry *be(_ctx.find_be(tv)); if (!be) throw InvalidField(tv); BaseField *bf(be->_create._do(val, be->_rlm, -1)); add_field_decoder(tv, ++pos, bf); itr->_field_traits.set(FieldTrait::present); // check if repeating group and num elements > 0 if (itr->_field_traits.has(FieldTrait::group) && static_cast<Field<int, 0> *>(bf)->get() > 0) s_offset = decode_group(tv, from, s_offset, ignore); } } const unsigned short missing(_fp.find_missing()); if (missing) { const BaseEntry *tbe(_ctx.find_be(missing)); ostringstream ostr; ostr << tbe->_name << " (" << missing << ')'; throw MissingMandatoryField(ostr.str()); } return s_offset; }
//------------------------------------------------------------------------------------------------- bool FIXReader::read(f8String& to) // read a complete FIX message { char msg_buf[_max_msg_len] = {}; int result(sockRead(msg_buf, _bg_sz)); if (result == static_cast<int>(_bg_sz)) { char bt; size_t offs(_bg_sz); do // get the last chrs of bodylength and ^A { if (sockRead(&bt, 1) != 1) return false; if (!isdigit(bt) && bt != default_field_separator) throw IllegalMessage(msg_buf); msg_buf[offs++] = bt; } while (bt != default_field_separator && offs < _max_msg_len); to.assign(msg_buf, offs); f8String tag, bgstr, len; unsigned result; if ((result = MessageBase::extract_element(to.data(), to.size(), tag, bgstr))) { if (tag != "8") throw IllegalMessage(to); if (bgstr != _session.get_ctx()._beginStr) // invalid FIX version throw InvalidVersion(bgstr); if ((result = MessageBase::extract_element(to.data() + result, to.size() - result, tag, len))) { if (tag != "9") throw IllegalMessage(to); const unsigned mlen(fast_atoi<unsigned>(len.c_str())); if (mlen == 0 || mlen > _max_msg_len - _bg_sz - _chksum_sz) // invalid msglen throw InvalidBodyLength(mlen); // read the body if ((result = sockRead(msg_buf, mlen) != static_cast<int>(mlen))) return false; // read the checksum if ((result = sockRead(msg_buf + mlen, _chksum_sz) != static_cast<int>(_chksum_sz))) return false; to.append(msg_buf, mlen + _chksum_sz); _session.update_received(); //string ts; //cerr << GetTimeAsStringMS(ts, &_session.get_last_received(), 9) << endl; return true; } } throw IllegalMessage(to); } return false; }
char get_key(const f8String& prompt=std::string(), bool echo=false) const { char ch(0); _is.clear(); if (!prompt.empty()) _os << prompt << std::flush; _is.get(ch); if (!_is.bad() && ch != 0x3 && ch != 0xa) { if (echo) _os << ch; return ch; } return 0; }
//------------------------------------------------------------------------------------------------- bool BDBPersister::get(const unsigned seqnum, f8String& to) const { if (!_opened || !seqnum) return false; KeyDataBuffer buffer(seqnum); KeyDataPair keyPair(buffer); int retval(_db->get(0, &keyPair._key, &keyPair._data, 0)); if (retval) { ostringstream ostr; ostr << "Could not get " << seqnum << '(' << db_strerror(retval) << ')'; GlobalLogger::log(ostr.str()); return false; } to.assign(buffer.dataBuf_); return true; }
int send(const f8String& from) { _output.push_back(from); return static_cast<int>(from.length()); }
/*! Write a string message to the underlying socket. \param from Message (string) to write \return number of bytes written */ int send(const f8String& from) { return _writer.send(from.data(), from.size()); }
//------------------------------------------------------------------------------------------------- unsigned MessageBase::extract_trailer(const f8String& from, f8String& chksum) { f8String tag; return extract_element(from.data() + from.size() - 7, 6, tag, chksum); }
/*! Construct from string ctor. \param from string to construct field from \param rlm pointer to the realmbase for this field (if available) */ Field (const f8String& from, const RealmBase *rlm=0) : BaseField(field, rlm), _value(fast_atoi<int>(from.c_str())) {}
//------------------------------------------------------------------------------------------------- bool Session::process(const f8String& from) { unsigned seqnum(0); try { const f8String::size_type fpos(from.find("34=")); if (fpos == f8String::npos) { //cerr << "Session::process throwing for " << from << endl; throw InvalidMessage(from); } seqnum = fast_atoi<unsigned>(from.data() + fpos + 3, default_field_separator); bool retry_plog(false); if (_plogger && _plogger->has_flag(Logger::inbound)) { if (_state != States::st_wait_for_logon) plog(from, 1); else retry_plog = true; } const Message *msg(Message::factory(_ctx, from, _loginParameters._no_chksum_flag, _loginParameters._permissive_mode_flag)); if (!msg) { GlobalLogger::log("Fatal: factory failed to generate a valid message"); return false; } if ((_control & printnohb) && msg->get_msgtype() != Common_MsgType_HEARTBEAT) cout << *msg << endl; else if (_control & print) cout << *msg << endl; bool result(false), admin_result(msg->is_admin() ? handle_admin(seqnum, msg) : true); if (msg->get_msgtype().size() > 1) goto application_call; else switch(msg->get_msgtype()[0]) { default: application_call: if (activation_check(seqnum, msg)) result = handle_application(seqnum, msg); break; case Common_MsgByte_HEARTBEAT: result = handle_heartbeat(seqnum, msg); break; case Common_MsgByte_TEST_REQUEST: result = handle_test_request(seqnum, msg); break; case Common_MsgByte_RESEND_REQUEST: result = handle_resend_request(seqnum, msg); break; case Common_MsgByte_REJECT: result = handle_reject(seqnum, msg); break; case Common_MsgByte_SEQUENCE_RESET: result = handle_sequence_reset(seqnum, msg); break; case Common_MsgByte_LOGOUT: result = handle_logout(seqnum, msg); break; case Common_MsgByte_LOGON: result = handle_logon(seqnum, msg); break; } ++_next_receive_seq; if (retry_plog) plog(from, 1); if (_persist) { f8_scoped_spin_lock guard(_per_spl, _connection->get_pmodel() == pm_coro); _persist->put(_next_send_seq, _next_receive_seq); //cout << "Persisted:" << _next_send_seq << " and " << _next_receive_seq << endl; } delete msg; return result && admin_result; } catch (f8Exception& e) { //cerr << "process:: f8exception" << ' ' << seqnum << ' ' << e.what() << endl; log(e.what()); if (!e.force_logoff()) { send(generate_reject(seqnum, e.what())); } else { if (_state == States::st_logon_received && !_loginParameters._silent_disconnect) { send(generate_logout(e.what()), true, 0, true); // so it won't increment do_state_change(States::st_logoff_sent); } stop(); } } catch (Poco::Net::NetException& e) { //cerr << "process:: Poco::Net::NetException" << endl; log(e.what()); } catch (exception& e) { //cerr << "process:: std::exception" << endl; log(e.what()); } return false; }
/*! Print this field to the supplied buffer, update size written. \param to buffer to print to \param sz current size of buffer payload stream */ void print(char *to, size_t& sz) const { sz += _value.copy(to, _value.size()); }
/*! Construct from string ctor. \param from string to construct field from \param rlm pointer to the realmbase for this field (if available) */ Field (const f8String& from, const RealmBase *rlm=0) : BaseField(field, rlm), _value(fast_atof(from.c_str())), _precision(2) {}
//------------------------------------------------------------------------------------------------- unsigned MessageBase::decode(const f8String& from, unsigned s_offset, unsigned ignore, bool permissive_mode) { const unsigned fsize(static_cast<unsigned>(from.size()) - ignore), npos(0xffffffff); unsigned pos(static_cast<unsigned>(_pos.size())), last_valid_pos(npos); const char *dptr(from.data()); char tag[FIX8_MAX_FLD_LENGTH], val[FIX8_MAX_FLD_LENGTH]; size_t last_valid_offset(0); for (unsigned result; s_offset <= fsize && (result = extract_element(dptr + s_offset, fsize - s_offset, tag, val));) { unsigned short tv(fast_atoi<unsigned short>(tag)); Presence::const_iterator itr(_fp.get_presence().find(tv)); if (itr == _fp.get_presence().end()) { unknown_field: if (permissive_mode) { if (last_valid_pos == npos) { last_valid_pos = pos; last_valid_offset = s_offset; } _unknown.append(dptr + s_offset, result); s_offset += result; continue; } break; } s_offset += result; if (itr->_field_traits.has(FieldTrait::present)) { if (!itr->_field_traits.has(FieldTrait::automatic)) throw DuplicateField(tv); } else for(unsigned ii(0); ii < 2; ++ii) { const BaseEntry *be(_ctx.find_be(tv)); if (!be) throw UnknownField(tv); BaseField *bf(be->_create._do(val, be->_rlm, -1)); add_field_decoder(tv, ++pos, bf); itr->_field_traits.set(FieldTrait::present); // check if repeating group and num elements > 0 if (itr->_field_traits.has(FieldTrait::group) && has_group_count(bf)) s_offset = decode_group(nullptr, tv, from, s_offset, ignore); if (itr->_ftype != FieldTrait::ft_Length || tv == Common_BodyLength) // this type expects next field to be data break; const unsigned val_sz(fast_atoi<unsigned>(val)); if(val_sz > FIX8_MAX_FLD_LENGTH - 1) throw f8Exception("Value size too large"); result = extract_element_fixed_width(dptr + s_offset, fsize - s_offset, val_sz, tag, val); if (!result) throw MissingMandatoryField("Unable to extract fixed width field"); const unsigned short lasttv(tv); tv = fast_atoi<unsigned short>(tag); if ((itr = _fp.get_presence().find(tv)) == _fp.get_presence().end()) goto unknown_field; if (itr->_ftype != FieldTrait::ft_data || lasttv + 1 != tv) // next field must be data, tag must be 1 greater than length tag break; s_offset += result; } } const unsigned short missing(_fp.find_missing()); if (missing) { const BaseEntry *tbe(_ctx.find_be(missing)); ostringstream ostr; ostr << tbe->_name << " (" << missing << ')'; throw MissingMandatoryField(ostr.str()); } return permissive_mode && last_valid_pos == pos ? static_cast<unsigned>(last_valid_offset) : s_offset; }
/*!empty function \param msg message string to be sent \return return the message length*/ int send(const f8String& msg) { return static_cast<int>(msg.length()); }