Beispiel #1
0
 def request_resend(self, session, start, end):
     """Send  ResendRequest message"""
     state = session.state
     logging.info("request resend from %d to %d", start, end)
     mg = FixMessage()
     mg.set(FLD_BEGIN_SEQNO, start)
     mg.set(FLD_END_SEQNO, end)
     state.recv_state = FixState.RESEND_REQUESTED
     self._transmit(session, MSG_RESEND_REQUEST, mg, admin=True)
Beispiel #2
0
    def send_testrequest(self, session):
        """Send FIX TestRequest message"""

        state = session.state
        if state.testrq_queue:
            # Do not send if pending test requests
            return
        rqid = datetime_now()
        rq = FixMessage()
        rq.set(FLD_TESTREQ_ID, rqid)
        state.testrq_queue.append(rqid)
        logging.debug("Sending test request: %s", rqid)
        self._transmit(session, MSG_TEST_REQUEST, rq)
Beispiel #3
0
    def validate(self, raw_data):
        """Convert from raw to internal FixMessage and validate it."""
        data = FixMessage.from_raw(raw_data)
        if not data.validate():
            logging.warning("disgarding message: %s", data)
            return None
        
        if data[0].find(self.version) == -1:
            # first contains wrong version number
            raise exc.SessionError, (exc.S_EVERSION)

        return data
Beispiel #4
0
    def send_login(self, session):
        """Send client login data to transport."""
        state = session.state
        hb_secs = int(session.get_conf('heartbeat_interval', 30))
        reset = session.get_conf('reset_seqno', False)
        reset_only_on_first = session.get_conf('reset_seqno_only_on_first', True)
        if reset:
            reset_seqno = (state.logon_count == 0 and reset_only_on_first) or \
                (not reset_only_on_first)
        else:
            reset_seqno = False

        lg = FixMessage()
        lg.set(FLD_HEARTBEAT_INT, hb_secs)
        lg.set(FLD_ENCRYPT_METHOD, 0)
        if reset_seqno:
            lg.set(FLD_RESET_SEQNUM_FLAG, 'Y')
            logging.warning("Reseting sequence numbers at logon (r=%d, s=%d)",
                             state.receive_seqno, state.send_seqno)
            if state.send_seqno > 1:
                state.send_seqno = 1
            if state.receive_seqno > 1:
                state.receive_seqno = 1
        self._transmit(session, MSG_LOGON, lg, admin=True)
Beispiel #5
0
    def _next_header(self, session, options=None):
        """Provide next FIX message header."""

        state = session.state
        header = FixMessage()

        header.set(FLD_SENDER_COMP_ID, session.get_conf('sender_comp_id'))
        header.set(FLD_TARGET_COMP_ID, session.get_conf('target_comp_id'))
        if options is None:
            header.set(FLD_MSG_SEQNUM, state.send_seqno)
        else:
            if options.get(FLD_MSG_SEQNUM, int) is None:
                header.set(FLD_MSG_SEQNUM, state.send_seqno)
            # merge options
            header.join(options)

        header.set(FLD_SENDING_TIME, utc_timestamp())
        return header
Beispiel #6
0
 def resend(self, session, start, end):
     """Resend message as for ResendRequest"""
     state = session.state
     logging.info("handling resend from %d to %d", start, end)
     state.send_state = FixState.RESEND_RECEIVED
     resend_mode = session.get_conf('resend_mode', 'GAPFILL')
     opts = FixMessage()
     if resend_mode == 'GAPFILL' or resend_mode == 'BUYSIDE':
         logging.info("sending SequeceReset-GapFill: next seqno = %d", state.send_seqno+1)
         opts.set(FLD_POSS_DUPFLAG, 'Y')
         opts.set(FLD_ORIG_SENDING_TIME, utc_timestamp())
         opts.set(FLD_MSG_SEQNUM, start)
         mg = FixMessage()
         mg.set(FLD_GAPFILL_FLAG, 'Y')
         mg.set(FLD_NEW_SEQNO, state.send_seqno+1)
         self._transmit(session, MSG_SEQUENCE_RESET, mg, options=opts, admin=True)
     elif resend_mode == 'RESET':
         logging.info("sending SequeceReset-Reset")
         mg = FixMessage()
         # initialize to seqno after this message (seqno is last sent seqno)
         mg.set(FLD_NEW_SEQNO, state.send_seqno+1)
         self._transmit(session, MSG_SEQUENCE_RESET, mg, options=opts, admin=True)
     elif resend_mode:
         logging.warning("unknown resend_mode: %s", resend_mode)
Beispiel #7
0
    def handle_admin(self, session, msgtype, seqno, data):
        """Handle FIX administrative messages."""
        
        logging.debug("Administrative message %s [%d] received", msgtype, seqno)

        state = session.state
        if msgtype == MSG_REJECT:
            session.received(data)
            state.receive_seqno += 1

        elif msgtype == MSG_TEST_REQUEST:
            test_id = data.get(FLD_TESTREQ_ID)
            logging.info("TestRequest received: %s", test_id)
            hb = FixMessage()
            hb.set(FLD_TESTREQ_ID, test_id)
            self._transmit(session, MSG_HEARTBEAT, hb, admin=True)
            state.receive_seqno += 1

        elif msgtype == MSG_HEARTBEAT:
            logging.info("Heartbeat received [%d]", seqno)
            state.receive_seqno += 1
            state.hb_count = 0
            try:
                reqid = data.get(FLD_TESTREQ_ID)
                logging.debug("Response test request: %s [ql=%d]",
                              reqid, len(state.testrq_queue))
                if reqid == state.testrq_queue[0]:
                    state.testrq_queue.pop(0)
            except:
                pass

        elif msgtype == MSG_RESEND_REQUEST:
            begin_seqno = data.get(FLD_BEGIN_SEQNO, int)
            end_seqno = data.get(FLD_END_SEQNO, int)
            logging.info("ResendRequest received [%d, %d]", begin_seqno, end_seqno)
            self.resend(session, begin_seqno, end_seqno)
            state.receive_seqno += 1

        elif msgtype == MSG_SEQUENCE_RESET:
            logging.debug("received SequenceReset: %s", str(data))
            state.receive_seqno += 1
            gap_fill = data.get(FLD_GAPFILL_FLAG)
            new_seqno = data.get(FLD_NEW_SEQNO, int)
            logging.info("SequenceReset, gap_fill=%s, msg_seqno=%d, new_seqno=%d",
                             gap_fill, seqno, new_seqno)
            if gap_fill == 'Y':
                logging.warning("GapFill: reset last received seqno to %d", new_seqno)
                state.receive_seqno = new_seqno 
            else:
                logging.warning("Reset: reset last receive seqno to %d", new_seqno)
                state.receive_seqno = new_seqno 
                
        elif msgtype == MSG_LOGOUT:
            # this propably happens mostly on server side
            logging.info("Logout received")
            session.received(data)
            state.receive_seqno += 1
            session.close()

        else:
            logging.warning("Unknown admin message type: %s", msgtype)
Beispiel #8
0
    def login_auth(self, session, data):
        """Verify login."""

        session.remove_timer("logon")
        state = session.state
        msgtype = data.get(FLD_MSG_TYPE, str)
        seqno = data.get(FLD_MSG_SEQNUM, int)

        # waiting for Logon response message
        if msgtype == MSG_LOGOUT:
            msg = data.get(58)
            logging.error("received LOGOUT: %s", msg)
            raise exc.SessionError, (exc.S_EINMESSAGE, msg)
 
        elif msgtype != MSG_LOGON:
            logging.error("received %s message in LOGIN state", msgtype)
            raise exc.SessionError, (exc.S_EINMESSAGE)

        if seqno != state.receive_seqno:
            if seqno > state.receive_seqno:
                logging.warning('LOGON: excepted [%d] <  [%d] message: missing seqnos',
                                state.receive_seqno, seqno)
                state.recv_state = FixState.RESEND_REQUESTED
                state.send_state = FixState.NORMAL
                state.resend_seqno = seqno
                #self.request_resend(state.receive_seqno+1, 0)
            else:
                # unexpected seqno for login (message seqno < receive_seqno)
                logging.error('LOGON: excepted [%d] >  [%d] message: failing ...',
                              state.receive_seqno, seqno)
                raise exc.SessionError, (exc.S_ESEQNO)

        if not session.is_server:
            # client part when all OK
            #state.receive_seqno = seqno
            #logging.debug("set last received seqno to %d", state.receive_seqno)
            state.status = FixState.IN_SESSION
            # per FIX protocol send TestRequest after successfull Logon
            if state.recv_state != FixState.RESEND_REQUESTED:
                self.send_testrequest(session)

        elif session.is_server:
            # server part when all OK
            logging.debug("Creating LOGON reply ...")
            # reply
            clnt_hb = data.get(FLD_HEARTBEAT_INT, int)
            session.set_conf('heartbeat_interval', clnt_hb)

            lg = FixMessage()
            lg.set(FLD_HEARTBEAT_INT, clnt_hb)
            reset_flag = data.get(FLD_RESET_SEQNUM_FLAG)
            if reset_flag == 'Y':
                loggging.warning("Reseting sequence numbers at logon (r=%d, s=%d)",
                                 state.receive_seqno, state.send_seqno)
                lg.set(FLD_RESET_SEQNUM_FLAG, 'Y')
                state.send_seqno = 1
                state.receive_seqno = 1
            lg.set(FLD_ENCRYPT_METHOD, 0)
            state.status = FixState.IN_SESSION
            self._transmit(session, MSG_LOGON, lg, admin=True)

        # test if resend request need to be sent 
        if state.recv_state == FixState.RESEND_REQUESTED:
            self.request_resend(session, state.receive_seqno, 0)
        else:
            state.receive_seqno += 1

        state.logon_count += 1
        state.hb_count = 0

        # check if login messages forwarded...
        if session.get_conf("forward_logon", True):
            session.received(data)
            
        save_secs = int(session.get_conf('session_save_interval', -1))
        if save_secs > 0:
            callback = functools.partial(state.save,
                                         session.get_conf('session_save_path', ''))
            session.add_periodic(callback, save_secs, "session_saver")
        elif save_secs == 0:
            session.state.save(session.get_conf('session_save_path'))

        logging.debug("end of LOGIN sequence: %s", str(state))
        return True