00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef _MSC_VER
00021 #include "stdafx.h"
00022 #else
00023 #include "config.h"
00024 #endif
00025 #include "CallStack.h"
00026
00027 #include "Message.h"
00028 #include "Utility.h"
00029 #include "Values.h"
00030 #include <iomanip>
00031
00032 namespace FIX
00033 {
00034 std::auto_ptr<DataDictionary> Message::s_dataDictionary;
00035
00036 Message::Message()
00037 : m_header( message_order( message_order::header ) ),
00038 m_trailer( message_order( message_order::trailer ) ),
00039 m_validStructure( true ) {}
00040
00041 Message::Message( const std::string& string, bool validate )
00042 throw( InvalidMessage )
00043 : m_header( message_order( message_order::header ) ),
00044 m_trailer( message_order( message_order::trailer ) ),
00045 m_validStructure( true )
00046 {
00047 setString( string, validate );
00048 }
00049
00050 Message::Message( const std::string& string,
00051 const DataDictionary& dataDictionary,
00052 bool validate )
00053 throw( InvalidMessage )
00054 : m_header( message_order( message_order::header ) ),
00055 m_trailer( message_order( message_order::trailer ) ),
00056 m_validStructure( true )
00057 {
00058 setString( string, validate, &dataDictionary, &dataDictionary );
00059 }
00060
00061 Message::Message( const std::string& string,
00062 const DataDictionary& sessionDataDictionary,
00063 const DataDictionary& applicationDataDictionary,
00064 bool validate )
00065 throw( InvalidMessage )
00066 : m_header( message_order( message_order::header ) ),
00067 m_trailer( message_order( message_order::trailer ) ),
00068 m_validStructure( true )
00069 {
00070 setStringHeader( string );
00071 if( isAdmin() )
00072 setString( string, validate, &sessionDataDictionary, &sessionDataDictionary );
00073 else
00074 setString( string, validate, &sessionDataDictionary, &applicationDataDictionary );
00075 }
00076
00077 bool Message::InitializeXML( const std::string& url )
00078 { QF_STACK_PUSH(Message::InitializeXML)
00079
00080 try
00081 {
00082 std::auto_ptr<DataDictionary> p =
00083 std::auto_ptr<DataDictionary>(new DataDictionary(url));
00084 s_dataDictionary = p;
00085 return true;
00086 }
00087 catch( ConfigError& )
00088 { return false; }
00089
00090 QF_STACK_POP
00091 }
00092
00093 void Message::reverseRoute( const Header& header )
00094 { QF_STACK_PUSH(Message::reverseRoute)
00095
00096
00097 BeginString beginString;
00098 SenderCompID senderCompID;
00099 TargetCompID targetCompID;
00100
00101 m_header.removeField( beginString.getField() );
00102 m_header.removeField( senderCompID.getField() );
00103 m_header.removeField( targetCompID.getField() );
00104
00105 if( header.isSetField( beginString ) )
00106 {
00107 header.getField( beginString );
00108 if( beginString.getValue().size() )
00109 m_header.setField( beginString );
00110
00111 OnBehalfOfLocationID onBehalfOfLocationID;
00112 DeliverToLocationID deliverToLocationID;
00113
00114 m_header.removeField( onBehalfOfLocationID.getField() );
00115 m_header.removeField( deliverToLocationID.getField() );
00116
00117 if( beginString >= BeginString_FIX41 )
00118 {
00119 if( header.isSetField( onBehalfOfLocationID ) )
00120 {
00121 header.getField( onBehalfOfLocationID );
00122 if( onBehalfOfLocationID.getValue().size() )
00123 m_header.setField( DeliverToLocationID( onBehalfOfLocationID ) );
00124 }
00125
00126 if( header.isSetField( deliverToLocationID ) )
00127 {
00128 header.getField( deliverToLocationID );
00129 if( deliverToLocationID.getValue().size() )
00130 m_header.setField( OnBehalfOfLocationID( deliverToLocationID ) );
00131 }
00132 }
00133 }
00134
00135 if( header.isSetField( senderCompID ) )
00136 {
00137 header.getField( senderCompID );
00138 if( senderCompID.getValue().size() )
00139 m_header.setField( TargetCompID( senderCompID ) );
00140 }
00141
00142 if( header.isSetField( targetCompID ) )
00143 {
00144 header.getField( targetCompID );
00145 if( targetCompID.getValue().size() )
00146 m_header.setField( SenderCompID( targetCompID ) );
00147 }
00148
00149
00150 OnBehalfOfCompID onBehalfOfCompID;
00151 OnBehalfOfSubID onBehalfOfSubID;
00152 DeliverToCompID deliverToCompID;
00153 DeliverToSubID deliverToSubID;
00154
00155 m_header.removeField( onBehalfOfCompID.getField() );
00156 m_header.removeField( onBehalfOfSubID.getField() );
00157 m_header.removeField( deliverToCompID.getField() );
00158 m_header.removeField( deliverToSubID.getField() );
00159
00160 if( header.isSetField( onBehalfOfCompID ) )
00161 {
00162 header.getField( onBehalfOfCompID );
00163 if( onBehalfOfCompID.getValue().size() )
00164 m_header.setField( DeliverToCompID( onBehalfOfCompID ) );
00165 }
00166
00167 if( header.isSetField( onBehalfOfSubID ) )
00168 {
00169 header.getField( onBehalfOfSubID );
00170 if( onBehalfOfSubID.getValue().size() )
00171 m_header.setField( DeliverToSubID( onBehalfOfSubID ) );
00172 }
00173
00174 if( header.isSetField( deliverToCompID ) )
00175 {
00176 header.getField( deliverToCompID );
00177 if( deliverToCompID.getValue().size() )
00178 m_header.setField( OnBehalfOfCompID( deliverToCompID ) );
00179 }
00180
00181 if( header.isSetField( deliverToSubID ) )
00182 {
00183 header.getField( deliverToSubID );
00184 if( deliverToSubID.getValue().size() )
00185 m_header.setField( OnBehalfOfSubID( deliverToSubID ) );
00186 }
00187
00188 QF_STACK_POP
00189 }
00190
00191 std::string Message::toString( int beginStringField,
00192 int bodyLengthField,
00193 int checkSumField ) const
00194 { QF_STACK_PUSH(Message::toString)
00195
00196 std::string str;
00197 return toString( str, beginStringField, bodyLengthField, checkSumField );
00198
00199 QF_STACK_POP
00200 }
00201
00202 std::string& Message::toString( std::string& str,
00203 int beginStringField,
00204 int bodyLengthField,
00205 int checkSumField ) const
00206 { QF_STACK_PUSH(Message::toString)
00207
00208 int length = bodyLength( beginStringField, bodyLengthField, checkSumField );
00209 m_header.setField( IntField(bodyLengthField, length) );
00210 m_trailer.setField( CheckSumField(checkSumField, checkSum(checkSumField)) );
00211
00212 m_header.calculateString( str, true );
00213 FieldMap::calculateString( str, false );
00214 m_trailer.calculateString( str, false );
00215
00216 return str;
00217
00218 QF_STACK_POP
00219 }
00220
00221 std::string Message::toXML() const
00222 { QF_STACK_PUSH(Message::toXML)
00223
00224 std::string str;
00225 return toXML( str );
00226
00227 QF_STACK_POP
00228 }
00229
00230 std::string& Message::toXML( std::string& str ) const
00231 { QF_STACK_PUSH(Message::toXML)
00232
00233 std::stringstream stream;
00234 stream << "<message>" << std::endl
00235 << std::setw(2) << " " << "<header>" << std::endl
00236 << toXMLFields(getHeader(), 4)
00237 << std::setw(2) << " " << "</header>" << std::endl
00238 << std::setw(2) << " " << "<body>" << std::endl
00239 << toXMLFields(*this, 4)
00240 << std::setw(2) << " " << "</body>" << std::endl
00241 << std::setw(2) << " " << "<trailer>" << std::endl
00242 << toXMLFields(getTrailer(), 4)
00243 << std::setw(2) << " " << "</trailer>" << std::endl
00244 << "</message>";
00245
00246 return str = stream.str();
00247
00248 QF_STACK_POP
00249 }
00250
00251 std::string Message::toXMLFields(const FieldMap& fields, int space) const
00252 { QF_STACK_PUSH(Message::toXMLFields)
00253
00254 std::stringstream stream;
00255 FieldMap::iterator i;
00256 std::string name;
00257 for(i = fields.begin(); i != fields.end(); ++i)
00258 {
00259 int field = i->first;
00260 std::string value = i->second.getString();
00261
00262 stream << std::setw(space) << " " << "<field ";
00263 if(s_dataDictionary.get() && s_dataDictionary->getFieldName(field, name))
00264 {
00265 stream << "name=\"" << name << "\" ";
00266 }
00267 stream << "number=\"" << field << "\"";
00268 if(s_dataDictionary.get()
00269 && s_dataDictionary->getValueName(field, value, name))
00270 {
00271 stream << " enum=\"" << name << "\"";
00272 }
00273 stream << ">";
00274 stream << "<![CDATA[" << value << "]]>";
00275 stream << "</field>" << std::endl;
00276 }
00277
00278 FieldMap::g_iterator j;
00279 for(j = fields.g_begin(); j != fields.g_end(); ++j)
00280 {
00281 std::vector<FieldMap*>::const_iterator k;
00282 for(k = j->second.begin(); k != j->second.end(); ++k)
00283 {
00284 stream << std::setw(space) << " " << "<group>" << std::endl
00285 << toXMLFields(*(*k), space+2)
00286 << std::setw(space) << " " << "</group>" << std::endl;
00287 }
00288 }
00289
00290 return stream.str();
00291
00292 QF_STACK_POP
00293 }
00294
00295 void Message::setString( const std::string& string,
00296 bool doValidation,
00297 const DataDictionary* pSessionDataDictionary,
00298 const DataDictionary* pApplicationDataDictionary )
00299 throw( InvalidMessage )
00300 { QF_STACK_PUSH(Message::setString)
00301
00302 clear();
00303
00304 std::string::size_type pos = 0;
00305 int count = 0;
00306 std::string msg;
00307
00308 static int const headerOrder[] =
00309 {
00310 FIELD::BeginString,
00311 FIELD::BodyLength,
00312 FIELD::MsgType
00313 };
00314
00315 field_type type = header;
00316
00317 while ( pos < string.size() )
00318 {
00319 FieldBase field = extractField( string, pos, pSessionDataDictionary, pApplicationDataDictionary );
00320 if ( count < 3 && headerOrder[ count++ ] != field.getField() )
00321 if ( doValidation ) throw InvalidMessage("Header fields out of order");
00322
00323 if ( isHeaderField( field, pSessionDataDictionary ) )
00324 {
00325 if ( type != header )
00326 {
00327 if(m_field == 0) m_field = field.getField();
00328 m_validStructure = false;
00329 }
00330
00331 if ( field.getField() == FIELD::MsgType )
00332 msg = field.getString();
00333
00334 m_header.setField( field, false );
00335
00336 if ( pSessionDataDictionary )
00337 setGroup( "_header_", field, string, pos, getHeader(), *pSessionDataDictionary );
00338 }
00339 else if ( isTrailerField( field, pSessionDataDictionary ) )
00340 {
00341 type = trailer;
00342 m_trailer.setField( field, false );
00343
00344 if ( pSessionDataDictionary )
00345 setGroup( "_trailer_", field, string, pos, getTrailer(), *pSessionDataDictionary );
00346 }
00347 else
00348 {
00349 if ( type == trailer )
00350 {
00351 if(m_field == 0) m_field = field.getField();
00352 m_validStructure = false;
00353 }
00354
00355 type = body;
00356 setField( field, false );
00357
00358 if ( pApplicationDataDictionary )
00359 setGroup( msg, field, string, pos, *this, *pApplicationDataDictionary );
00360 }
00361 }
00362
00363 if ( doValidation )
00364 validate();
00365
00366 QF_STACK_POP
00367 }
00368
00369 void Message::setGroup( const std::string& msg, const FieldBase& field,
00370 const std::string& string,
00371 std::string::size_type& pos, FieldMap& map,
00372 const DataDictionary& dataDictionary )
00373 { QF_STACK_PUSH(Message::setGroup)
00374
00375 int group = field.getField();
00376 int delim;
00377 const DataDictionary* pDD = 0;
00378 if ( !dataDictionary.getGroup( msg, group, delim, pDD ) ) return ;
00379 Group* pGroup = 0;
00380
00381 while ( pos < string.size() )
00382 {
00383 std::string::size_type oldPos = pos;
00384 FieldBase field = extractField( string, pos, &dataDictionary, &dataDictionary, pGroup );
00385 if ( (field.getField() == delim)
00386 || (pGroup == 0 && pDD->isField(field.getField())) )
00387 {
00388 if ( pGroup )
00389 {
00390 map.addGroup( group, *pGroup, false );
00391 delete pGroup; pGroup = 0;
00392 }
00393 pGroup = new Group( field.getField(), delim, pDD->getOrderedFields() );
00394 }
00395 else if ( !pDD->isField( field.getField() ) )
00396 {
00397 if ( pGroup )
00398 {
00399 map.addGroup( group, *pGroup, false );
00400 delete pGroup; pGroup = 0;
00401 }
00402 pos = oldPos;
00403 return ;
00404 }
00405
00406 if ( !pGroup ) return ;
00407 pGroup->setField( field, false );
00408 setGroup( msg, field, string, pos, *pGroup, *pDD );
00409 }
00410
00411 QF_STACK_POP
00412 }
00413
00414 bool Message::setStringHeader( const std::string& string )
00415 { QF_STACK_PUSH(Message::setStringHeader)
00416
00417 clear();
00418
00419 std::string::size_type pos = 0;
00420 int count = 0;
00421
00422 while ( pos < string.size() )
00423 {
00424 FieldBase field = extractField( string, pos );
00425 if ( count < 3 && headerOrder[ count++ ] != field.getField() )
00426 return false;
00427
00428 if ( isHeaderField( field ) )
00429 m_header.setField( field, false );
00430 else break;
00431 }
00432 return true;
00433
00434 QF_STACK_POP
00435 }
00436
00437 bool Message::isHeaderField( int field )
00438 { QF_STACK_PUSH(Message::isHeaderField)
00439
00440 switch ( field )
00441 {
00442 case FIELD::BeginString:
00443 case FIELD::BodyLength:
00444 case FIELD::MsgType:
00445 case FIELD::SenderCompID:
00446 case FIELD::TargetCompID:
00447 case FIELD::OnBehalfOfCompID:
00448 case FIELD::DeliverToCompID:
00449 case FIELD::SecureDataLen:
00450 case FIELD::MsgSeqNum:
00451 case FIELD::SenderSubID:
00452 case FIELD::SenderLocationID:
00453 case FIELD::TargetSubID:
00454 case FIELD::TargetLocationID:
00455 case FIELD::OnBehalfOfSubID:
00456 case FIELD::OnBehalfOfLocationID:
00457 case FIELD::DeliverToSubID:
00458 case FIELD::DeliverToLocationID:
00459 case FIELD::PossDupFlag:
00460 case FIELD::PossResend:
00461 case FIELD::SendingTime:
00462 case FIELD::OrigSendingTime:
00463 case FIELD::XmlDataLen:
00464 case FIELD::XmlData:
00465 case FIELD::MessageEncoding:
00466 case FIELD::LastMsgSeqNumProcessed:
00467 case FIELD::OnBehalfOfSendingTime:
00468 case FIELD::ApplVerID:
00469 case FIELD::CstmApplVerID:
00470 case FIELD::NoHops:
00471 return true;
00472 default:
00473 return false;
00474 };
00475
00476 QF_STACK_POP
00477 }
00478
00479 bool Message::isHeaderField( const FieldBase& field,
00480 const DataDictionary* pD )
00481 { QF_STACK_PUSH(Message::isHeaderField)
00482
00483 if ( isHeaderField( field.getField() ) ) return true;
00484 if ( pD ) return pD->isHeaderField( field.getField() );
00485 return false;
00486
00487 QF_STACK_POP
00488 }
00489
00490 bool Message::isTrailerField( int field )
00491 { QF_STACK_PUSH(Message::isTrailerField)
00492
00493 switch ( field )
00494 {
00495 case FIELD::SignatureLength:
00496 case FIELD::Signature:
00497 case FIELD::CheckSum:
00498 return true;
00499 default:
00500 return false;
00501 };
00502
00503 QF_STACK_POP
00504 }
00505
00506 bool Message::isTrailerField( const FieldBase& field,
00507 const DataDictionary* pD )
00508 { QF_STACK_PUSH(Message::isTrailerField)
00509
00510 if ( isTrailerField( field.getField() ) ) return true;
00511 if ( pD ) return pD->isTrailerField( field.getField() );
00512 return false;
00513
00514 QF_STACK_POP
00515 }
00516
00517 SessionID Message::getSessionID( const std::string& qualifier ) const
00518 throw( FieldNotFound )
00519 { QF_STACK_PUSH(Message::getSessionID)
00520
00521 BeginString beginString;
00522 SenderCompID senderCompID;
00523 TargetCompID targetCompID;
00524
00525 getHeader().getField( beginString );
00526 getHeader().getField( senderCompID );
00527 getHeader().getField( targetCompID );
00528
00529 return SessionID( beginString, senderCompID, targetCompID, qualifier );
00530
00531 QF_STACK_POP
00532 }
00533
00534 void Message::setSessionID( const SessionID& sessionID )
00535 { QF_STACK_PUSH(Message::setSessionID)
00536
00537 getHeader().setField( sessionID.getBeginString() );
00538 getHeader().setField( sessionID.getSenderCompID() );
00539 getHeader().setField( sessionID.getTargetCompID() );
00540
00541 QF_STACK_POP
00542 }
00543
00544 void Message::validate()
00545 { QF_STACK_PUSH(Message::validate)
00546
00547 try
00548 {
00549 const BodyLength& aBodyLength = FIELD_GET_REF( m_header, BodyLength );
00550
00551 if ( aBodyLength != bodyLength() )
00552 {
00553 std::stringstream text;
00554 text << "Expected BodyLength=" << bodyLength()
00555 << ", Recieved BodyLength=" << (int)aBodyLength;
00556 throw InvalidMessage(text.str());
00557 }
00558
00559 const CheckSum& aCheckSum = FIELD_GET_REF( m_trailer, CheckSum );
00560
00561 if ( aCheckSum != checkSum() )
00562 {
00563 std::stringstream text;
00564 text << "Expected CheckSum=" << checkSum()
00565 << ", Recieved CheckSum=" << (int)aCheckSum;
00566 throw InvalidMessage(text.str());
00567 }
00568 }
00569 catch ( FieldNotFound& )
00570 {
00571 throw InvalidMessage("BodyLength or CheckSum missing");
00572 }
00573 catch ( IncorrectDataFormat& )
00574 {
00575 throw InvalidMessage("BodyLength or Checksum has wrong format");
00576 }
00577
00578 QF_STACK_POP
00579 }
00580 }