Beispiel #1
0
func createMoldPacket(startSeqNum, count int) (bs []byte, err error) {
	defer errs.PassE(&err)
	type moldUDP64 struct {
		Session        string `struc:"[10]byte"`
		SequenceNumber uint64
		MessageCount   uint16
	}
	type moldUDP64MessageBlock struct {
		MessageLength int16 `struc:"sizeof=Payload"`
		Payload       []uint8
	}

	errs.Check(startSeqNum >= 0)
	errs.Check(count >= 0 && count < 1000)
	mh := moldUDP64{
		Session:        "00TestSess",
		SequenceNumber: uint64(startSeqNum),
		MessageCount:   uint16(count),
	}
	var bb bytes.Buffer
	errs.CheckE(struc.Pack(&bb, &mh))
	for i := 0; i < count; i++ {
		mb := moldUDP64MessageBlock{
			Payload: generateIttoMessage(startSeqNum + i),
		}
		errs.CheckE(struc.Pack(&bb, &mb))
	}
	bs = bb.Bytes()
	return
}
Beispiel #2
0
func (c *conn) ReadMessage() (m Message, err error) {
	defer errs.PassE(&err)
	for c.messageReader.N == 0 {
		errs.CheckE(c.readBsuHeader())
	}

	c.rbuf.Reset()
	var b [2]byte
	var n int
	_, err = io.ReadFull(&c.messageReader, b[:])
	errs.CheckE(err)
	log.Printf("rcv bytes %v", b)
	n, err = c.rbuf.Write(b[:])
	errs.CheckE(err)
	errs.Check(n == len(b))
	h := MessageHeader{
		Length: uint8(b[0]),
		Type:   MessageType(b[1]),
	}
	log.Printf("rcv header %#v", h)
	io.CopyN(&c.rbuf, &c.messageReader, int64(h.Length)-2)
	f := MessageFactory[h.Type]
	errs.Check(f != nil)
	m = f()
	errs.CheckE(binary.Read(&c.rbuf, binary.LittleEndian, m))
	log.Printf("rcv %#v\n", m)
	return
}
Beispiel #3
0
func (s *replayServer) run() {
	type moldudp64request struct {
		Session        string
		SequenceNumber uint64
		MessageCount   uint16
	}

	laddr, err := net.ResolveUDPAddr("udp", s.laddr)
	errs.CheckE(err)
	conn, err := net.ListenUDP("udp", laddr)
	errs.CheckE(err)
	defer conn.Close()
	buf := make([]byte, 20, 65536)
	for {
		n, addr, err := conn.ReadFromUDP(buf)
		errs.CheckE(err)
		if n != 20 {
			log.Printf("ignore wrong request from %s: %v\n", addr, buf)
			continue
		}
		req := &moldudp64request{
			Session:        string(buf[0:10]),
			SequenceNumber: binary.BigEndian.Uint64(buf[10:18]),
			MessageCount:   binary.BigEndian.Uint16(buf[18:20]),
		}
		go func() {
			const MAX_MESSAGES = (1500 - 34 - 20) / 40
			log.Printf("got request: %v\n", req)
			//num := int(req.SequenceNumber) - 10
			num := int(req.MessageCount)
			if num <= 0 {
				num = 1
			} else if num > MAX_MESSAGES {
				num = MAX_MESSAGES
			}
			resp, err := createMoldPacket(int(req.SequenceNumber), num)
			errs.CheckE(err)
			errs.Check(len(resp) < 1500-34)

			if s.sleepEnabled {
				sleep := time.Duration(250+2500/num) * time.Millisecond
				log.Printf("sleeping for %s\n", sleep)
				time.Sleep(sleep)
			}
			log.Printf("send response: %v\n", resp)
			n, err = conn.WriteToUDP(resp, addr)
			errs.CheckE(err)
			errs.Check(n == len(resp), n, len(resp))
		}()
	}
}
Beispiel #4
0
func (p *reusingProcessor) ProcessPacket(data []byte, ci gopacket.CaptureInfo, decoded []gopacket.DecodingLayer) (err error) {
	defer errs.PassE(&err)
	p.pkt = reusingPacket{
		data:   data,
		ci:     ci,
		layers: decoded,
	}
	p.m = applicationMessage{
		flows:     p.m.flows[:0],
		timestamp: p.pkt.Timestamp(),
	}
	p.handler.HandlePacket(&p.pkt)
	for _, layer := range decoded {
		//log.Printf("%#v", layer)
		switch l := layer.(type) {
		case gopacket.NetworkLayer:
			p.m.flows = append(p.m.flows, l.NetworkFlow())
		case *layers.UDP:
			p.m.flows = append(p.m.flows, l.TransportFlow())
		case *miax.MachTop:
			p.messageNum = l.MachPackets
			p.messageIndex = 0
			p.nextSeqNums = p.nextSeqNums[:0]
		case *miax.Mach:
			errs.Check(len(p.nextSeqNums) < p.messageNum, len(p.nextSeqNums), p.messageNum)
			p.nextSeqNums = append(p.nextSeqNums, l.SequenceNumber)
		case miax.TomMessage:
			errs.Check(p.messageIndex < p.messageNum, p.messageIndex, p.messageNum)
			p.m.layer = l
			p.m.seqNum = p.nextSeqNums[p.messageIndex]
			p.messageIndex++
			p.handler.HandleMessage(&p.m)
		case *bats.BSU:
			p.m.seqNum = uint64(l.Sequence)
		case bats.PitchMessage:
			p.m.layer = l
			p.handler.HandleMessage(&p.m)
			p.m.seqNum++
		case *nasdaq.MoldUDP64:
			p.m.seqNum = l.SequenceNumber
		case nasdaq.IttoMessage:
			p.m.layer = l
			p.handler.HandleMessage(&p.m)
			p.m.seqNum++
		}
	}
	return
}
Beispiel #5
0
func parseSymbol(data []byte) packet.OptionId {
	errs.Check(len(data) >= 6)
	var b [8]byte
	copy(b[:], data)
	oid := packet.OptionIdFromUint64(binary.LittleEndian.Uint64(b[:]))
	return oid
}
Beispiel #6
0
func (mc *MessageCommon) setHeader(Type MessageType) (err error) {
	defer errs.PassE(&err)
	mc.Header.Type = Type
	mc.Header.Length = uint8(MessageLength[Type])
	errs.Check(mc.Header.Length != 0)
	return
}
Beispiel #7
0
func WriteMessage(w io.Writer, m Message) (err error) {
	defer errs.PassE(&err)
	errs.CheckE(m.encodePayload())
	var mt MessageType
	switch m.(type) {
	case *MessageDebug:
		mt = TypeDebug
	case *MessageLoginAccepted:
		mt = TypeLoginAccepted
	case *MessageLoginRejected:
		mt = TypeLoginRejected
	case *MessageSequencedData:
		mt = TypeSequencedData
	case *MessageHeartbeat:
		mt = TypeHeartbeat
	case *MessageEnd:
		mt = TypeEnd
	case *MessageLoginRequest:
		mt = TypeLoginRequest
	case *MessageUnsequencedData:
		mt = TypeUnsequencedData
	case *MessageClientHeartbeat:
		mt = TypeClientHeartbeat
	case *MessageLogout:
		mt = TypeLogout
	}
	errs.CheckE(m.getCommon().setHeader(mt))
	errs.CheckE(binary.Write(w, binary.BigEndian, m.getHeader()))
	n, err := w.Write(m.getCommon().Payload)
	errs.CheckE(err)
	errs.Check(n == len(m.getCommon().Payload))
	return
}
Beispiel #8
0
func ReadMessage(r io.Reader) (m Message, err error) {
	defer errs.PassE(&err)
	var mc MessageCommon
	errs.CheckE(binary.Read(r, binary.BigEndian, &mc.Header))
	mc.Payload = make([]byte, mc.Header.Length-1)
	n, err := r.Read(mc.Payload)
	errs.CheckE(err)
	errs.Check(n == len(mc.Payload), n, len(mc.Payload))
	switch mc.Header.Type {
	case TypeDebug:
		m = &MessageDebug{}
	case TypeLoginAccepted:
		m = &MessageLoginAccepted{}
	case TypeLoginRejected:
		m = &MessageLoginRejected{}
	case TypeSequencedData:
		m = &MessageSequencedData{}
	case TypeHeartbeat:
		m = &MessageHeartbeat{}
	case TypeEnd:
		m = &MessageEnd{}
	case TypeLoginRequest:
		m = &MessageLoginRequest{}
	case TypeUnsequencedData:
		m = &MessageUnsequencedData{}
	case TypeClientHeartbeat:
		m = &MessageClientHeartbeat{}
	case TypeLogout:
		m = &MessageLogout{}
	}
	*m.getCommon() = mc
	errs.CheckE(m.decodePayload())
	return
}
Beispiel #9
0
func (s *SesMServerConn) login() (err error) {
	defer errs.PassE(&err)
	m, err := s.mconn.ReadMessage() //////// miax conn
	errs.CheckE(err)
	lr, ok := m.(*miax.SesMLoginRequest)
	errs.Check(ok)
	// проверка, что мы не хотим рефреш
	errs.Check(0 == lr.ReqSeqNum)
	res := miax.SesMLoginResponse{
		LoginStatus:   miax.LoginStatusSuccess,
		HighestSeqNum: uint64(s.src.CurrentSequence()),
	}
	errs.CheckE(s.mconn.WriteMessageSimple(&res))
	log.Printf("login done")
	return
}
Beispiel #10
0
func (m *Mach) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) (err error) {
	defer errs.PassE(&err)
	errs.Check(len(data) >= 12)
	length := binary.LittleEndian.Uint16(data[8:10])
	errs.Check(len(data) >= int(length))
	*m = Mach{
		SequenceNumber: binary.LittleEndian.Uint64(data[0:8]),
		Length:         length,
		Type:           data[10],
		SessionNumber:  data[11],
		BaseLayer: layers.BaseLayer{
			Contents: data[:12],
			Payload:  data[12:length],
		},
	}
	return nil
}
Beispiel #11
0
func (p *packetWriter) WriteMessage(m Message) (err error) {
	defer errs.PassE(&err)
	m.getCommon().setHeader(m.Type())
	errs.CheckE(binary.Write(&p.mb, binary.LittleEndian, m))
	p.bh.Count++
	errs.Check(p.bh.Count != 0)
	return
}
Beispiel #12
0
func (c *conn) readSize() (err error) {
	defer errs.PassE(&err)
	errs.Check(c.messageReader.N == 0, c.messageReader.N)
	var s uint16
	errs.CheckE(binary.Read(c.rw, binary.LittleEndian, &s))
	log.Printf("rcv SesM size %d\n", s)
	c.messageReader = io.LimitedReader{R: c.rw, N: int64(s)}
	return
}
Beispiel #13
0
func (mc *MessageCommon) setHeader(Type MessageType) error {
	var payloadSize int
	switch Type {
	case TypeDebug, TypeSequencedData, TypeUnsequencedData:
		payloadSize = len(mc.Payload)
	case TypeLoginAccepted:
		payloadSize = 30
	case TypeLoginRejected:
		payloadSize = 1
	case TypeLoginRequest:
		payloadSize = 46
	}
	errs.Check(payloadSize == len(mc.Payload), payloadSize, len(mc.Payload))
	errs.Check(payloadSize < math.MaxUint16)
	mc.Header.Type = Type
	mc.Header.Length = uint16(payloadSize) + 1
	return nil
}
Beispiel #14
0
func (m *MessageLoginAccepted) encodePayload() (err error) {
	m.Payload = make([]byte, 30)
	copy(m.Payload[0:10], []byte(m.Session))
	errs.Check(m.SequenceNumber > 0)
	copy(m.Payload[10:30], []byte(fmt.Sprintf("%020d", m.SequenceNumber)))
	m.Header.Type = TypeLoginAccepted
	m.Header.Length = uint16(len(m.Payload) + 1)
	return nil
}
Beispiel #15
0
func (f *tomLayerFactory) Create(layerType gopacket.LayerType) gopacket.DecodingLayer {
	d := int(layerType - gopacket.LayerType(TOM_LAYERS_BASE_NUM))
	if d < 0 || d > 255 {
		panic("FIXME")
		//return gopacket.LayerTypeZero // FIXME
	}
	m := TomMessageTypeMetadata[d]
	errs.Check(m.LayerType == layerType)
	return m.CreateLayer()
}
Beispiel #16
0
func (b *book) ApplyOperation(operation SimOperation) {
	oid := operation.GetOptionId()
	errs.Check(oid.Valid())
	os, ok := b.options[oid]
	if !ok {
		os = NewOptionState(b.newOptionSideState)
		b.options[oid] = os
	}
	os.Side(operation.GetSide()).updateLevel(operation)
}
Beispiel #17
0
func (m *MachTop) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) (err error) {
	defer errs.PassE(&err)
	*m = MachTop{
		BaseLayer: layers.BaseLayer{data, data},
		tps:       m.tps[:0], // reuse the slice storage
	}
	for len(data) > 0 {
		errs.Check(len(data) >= 12)
		length := int(binary.LittleEndian.Uint16(data[8:10]))
		errs.Check(length <= len(data), length, len(data))
		m.tps = append(m.tps, packet.TypedPayload{
			Type:    LayerTypeMach,
			Payload: data[:length],
		})
		m.MachPackets++
		data = data[length:]
	}
	return
}
Beispiel #18
0
func (s *spinServerConn) run() {
	defer errs.Catch(func(ce errs.CheckerError) {
		log.Printf("caught %s\n", ce)
	})
	defer s.conn.Close()
	errs.CheckE(s.login())
	cancelSendImageAvail := make(chan struct{})
	defer func() {
		// close channel only if not already closed
		select {
		case _, ok := <-cancelSendImageAvail:
			if !ok {
				return
			}
		default:
		}
		close(cancelSendImageAvail)
	}()
	go s.sendImageAvail(cancelSendImageAvail)

	m, err := s.bconn.ReadMessage()
	errs.CheckE(err)
	req, ok := m.(*bats.MessageSpinRequest)
	errs.Check(ok)
	close(cancelSendImageAvail)

	seq := s.src.CurrentSequence()
	errs.Check(int(req.Sequence) <= seq, req.Sequence, seq)
	res := bats.MessageSpinResponse{
		Sequence: req.Sequence,
		Count:    uint32(seq) - req.Sequence + 1,
		Status:   bats.SpinStatusAccepted,
	}
	errs.CheckE(s.bconn.WriteMessageSimple(&res))
	errs.CheckE(s.sendAll(int(req.Sequence), seq+1))
	s.waitForMcast(seq)
	res2 := bats.MessageSpinFinished{
		Sequence: req.Sequence,
	}
	errs.CheckE(s.bconn.WriteMessageSimple(&res2))
	log.Println("spin finished")
}
Beispiel #19
0
func NewNasdaqExchangeSimulatorServer(c Config) (es ExchangeSimulator, err error) {
	errs.Check(c.Protocol == "nasdaq")
	errs.Check(!c.Interactive)
	es = &exchangeNasdaq{
		glimpse: &glimpseServer{
			laddr:          ":16001",
			snapshotSeqNum: 5,
		},
		replay: &replayServer{
			laddr:        ":17001",
			sleepEnabled: true,
		},
		mcast: &mcastServer{
			laddr: c.LocalAddr,
			raddr: c.FeedAddr,
			seq:   1000,
			pps:   1,
		},
	}
	return
}
Beispiel #20
0
func (s *mcastServer) run() {
	errs.Check(s.pps != 0)
	laddr, err := net.ResolveUDPAddr("udp", s.laddr)
	errs.CheckE(err)
	raddr, err := net.ResolveUDPAddr("udp", s.raddr)
	errs.CheckE(err)
	conn, err := net.DialUDP("udp", laddr, raddr)
	errs.CheckE(err)
	for {
		p, err := createMoldPacket(s.seq, 1)
		errs.CheckE(err)
		log.Printf("send mcast: %v\n", p)
		n, err := conn.Write(p)
		errs.CheckE(err)
		errs.Check(n == len(p), n, len(p))

		delay := time.Duration(1000/s.pps) * time.Millisecond
		time.Sleep(delay)
		s.seq++
	}
	defer conn.Close()
}
Beispiel #21
0
func (p *packetWriter) Flush() (err error) {
	defer errs.PassE(&err)
	length := p.mb.Len() + 8
	errs.Check(length <= math.MaxUint16, length)
	p.bh.Length = uint16(length)
	errs.CheckE(binary.Write(&p.pb, binary.LittleEndian, p.bh))
	_, err = p.mb.WriteTo(&p.pb)
	errs.CheckE(err)
	_, err = p.w.Write(p.pb.Bytes())
	errs.CheckE(err)
	p.Reset()
	return
}
Beispiel #22
0
func (c *conn) readBsuHeader() (err error) {
	defer errs.PassE(&err)
	errs.Check(c.messageReader.N == 0, c.messageReader.N)
	var h BsuHeader
	errs.CheckE(binary.Read(c.rw, binary.LittleEndian, &h))
	log.Printf("rcv BSU header %#v", h)
	if h.Sequence != 0 {
		errs.Check(h.Sequence == c.nextSeqNum, h.Sequence, c.nextSeqNum)
		c.nextSeqNum += uint32(h.Count)
	}
	if h.Unit == 0 {
		errs.Check(h.Sequence == 0, h.Sequence)
	} else {
		if c.unit == 0 {
			c.unit = int(h.Unit)
		} else {
			errs.Check(c.unit == int(h.Unit), c.unit, h.Unit)
		}
	}
	c.messageReader = io.LimitedReader{R: c.rw, N: int64(h.Length) - 8}
	return
}
Beispiel #23
0
func (s *spinServerConn) login() (err error) {
	defer errs.PassE(&err)
	m, err := s.bconn.ReadMessage()
	errs.CheckE(err)
	_, ok := m.(*bats.MessageLogin)
	errs.Check(ok)
	res := bats.MessageLoginResponse{
		Status: bats.LoginAccepted,
	}
	errs.CheckE(s.bconn.WriteMessageSimple(&res))
	log.Printf("login done")
	return
}
Beispiel #24
0
func (a *Analyzer) book(oid packet.OptionId, side packet.MarketSide) (bs *bookStat) {
	errs.Check(side == packet.MarketSideBid || side == packet.MarketSideAsk)
	key := OptionSide{
		Oid:  oid,
		Side: side,
	}
	var ok bool
	if bs, ok = a.bookStats[key]; !ok {
		bs = &bookStat{}
		a.bookStats[key] = bs
	}
	return
}
Beispiel #25
0
func (r *Reporter) SaveBookSizeHistogram() {
	errs.Check(r.analyzer != nil)
	fileName := filepath.Join(r.outDir, "book_size_hist.tsv")
	file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	errs.CheckE(err)
	defer file.Close()
	bsh := r.analyzer.BookSizeHist()
	_, err = fmt.Fprintf(file, "size\tbooks\tsample\n")
	errs.CheckE(err)
	for _, bsv := range bsh {
		_, err = fmt.Fprintf(file, "%d\t%d\t%v\n", bsv.Levels, bsv.OptionNumber, bsv.Sample)
		errs.CheckE(err)
	}
}
Beispiel #26
0
func (mms *miaxMessageSource) generateRefreshResponse(RefreshType byte, seqNum int) (m miax.MachMessage) {
	u32, u16 := uint32(seqNum), uint16(seqNum)
	switch RefreshType {
	case miax.SesMRefreshSeriesUpdate:
		m = &miax.MachSeriesUpdate{
			NanoTime:         u32,                                             //Product Add/Update Time. Time at which this product is added/updated on MIAX system today.
			ProductID:        u32,                                             //MIAX Product ID mapped to a given option. It is assigned per trading session and is valid for that session.
			UnderlyingSymbol: [11]byte{'q', 'w', 'e', 'r', 't', 'y'},          //Stock Symbol for the option
			SecuritySymbol:   [6]byte{'q', 'w', 'e', 'r', 't', 'y'},           //Option Security Symbol
			ExpirationDate:   [8]byte{'2', '0', '1', '5', '1', '2', '1', '2'}, //Expiration date of the option in YYYYMMDD format
			StrikePrice:      u32 % 10 * 1000,                                 //Explicit strike price of the option. Refer to data types for field processing notes
			CallPut:          'C',                                             //Option Type “C” = Call "P" = Put
			OpeningTime:      [8]byte{'0', '9', ':', '3', '0', ':', '0', '0'}, //Expressed in HH:MM:SS format. Eg: 09:30:00
			ClosingTime:      [8]byte{'1', '6', ':', '1', '5', ':', '0', '0'}, //Expressed in HH:MM:SS format. Eg: 16:15:00
			RestrictedOption: 'Y',                                             //“Y” = MIAX will accept position closing orders only “N” = MIAX will accept open and close positions
			LongTermOption:   'Y',                                             //“Y” = Far month expiration (as defined by MIAX rules) “N” = Near month expiration (as defined by MIAX rules)
			Active:           'A',                                             //Indicates if this symbol is tradable on MIAX in the current session:“A” = Active “I” = Inactive (not tradable)
			BBOIncrement:     'P',                                             //This is the Minimum Price Variation as agreed to by the Options industry (penny pilot program) and as published by MIAX
			AcceptIncrement:  'P',
		}
	case miax.SesMRefreshToM:
		m = &miax.MachDoubleSidedToMCompact{
			NanoTime:      u32,
			ProductID:     u32,
			BidPrice:      u16,
			BidSize:       u16,
			BidPriority:   u16,
			OfferPrice:    u16,
			OfferSize:     u16,
			OfferPriority: u16,
		}
		if 0 == seqNum%2 {
			m = &miax.MachDoubleSidedToMWide{
				NanoTime:      u32,
				ProductID:     u32,
				BidPrice:      u32,
				BidSize:       u32,
				BidPriority:   u32,
				OfferPrice:    u32,
				OfferSize:     u32,
				OfferPriority: u32,
			}
		}
	default:
		errs.Check(false)
	}
	m.SetType(m.GetType())
	return
}
Beispiel #27
0
func (r *Reporter) SaveSubscriptions() {
	fileName := filepath.Join(r.outDir, "subscription-all")
	file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	errs.CheckE(err)
	defer file.Close()
	errs.Check(r.analyzer != nil)
	arr := make([]uint64, 0, len(r.analyzer.optionIds))
	for oid := range r.analyzer.optionIds {
		arr = append(arr, oid)
	}
	sort.Sort(uint64Slice(arr))
	for _, oid := range arr {
		_, err = fmt.Fprintf(file, "%0#16x\n", oid)
		errs.CheckE(err)
	}
}
Beispiel #28
0
func (r *Reporter) SaveOrderCollisionsHistogram() {
	errs.Check(r.analyzer != nil)
	orderHists := r.analyzer.OrdersHashCollisionHist()
	for i, ohs := range orderHists {
		fileName := filepath.Join(r.outDir, fmt.Sprintf("order_collision_hist_%d.tsv", i))
		file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
		errs.CheckE(err)
		defer file.Close()
		_, err = fmt.Fprintf(file, "maxCollisions\tbuckets\n")
		errs.CheckE(err)
		for _, h := range ohs {
			_, err = fmt.Fprintf(file, "%d\t%d\n", h.Bin, h.Count)
			errs.CheckE(err)
		}
	}
}
Beispiel #29
0
func (l *TobLogger) AfterBookUpdate(book sim.Book, operation sim.SimOperation) bool {
	errs.Check(l.consumeOps != 0)
	l.curOps++
	if l.curOps < l.consumeOps {
		return false
	}
	l.curOps = 0
	l.hasOldTob = false
	if l.lastOptionId.Invalid() {
		return false
	}
	l.bid.update(book, l.lastOptionId, true)
	l.ask.update(book, l.lastOptionId, true)

	return l.bid.updated() || l.ask.updated()
}
Beispiel #30
0
func loadDictReverse(rDict io.Reader) map[string]int {
	r := csv.NewReader(rDict)
	records, err := r.ReadAll()
	errs.CheckE(err)
	avtName2Oid := make(map[string]int)
	for _, rec := range records {
		errs.Check(len(rec) == 2, "bad csv record", rec)
		if rec[0] == "avtSymbol" && rec[1] == "exchangeId" {
			continue // header
		}
		name := rec[0]
		oid, err := strconv.Atoi(rec[1])
		errs.CheckE(err, rec)
		avtName2Oid[name] = oid
	}
	return avtName2Oid
}