func handleMessage(h messageHandler, r *xio.PacketReader) error { if code, err := r.Read8(); err != nil { return errors.New("message.read code") } else { switch code { default: return h.OnRawMessage(code, r) case 0x11: if err := r.Skip(5); err != nil { return errors.New("message.skip useless") } return handleAmfMessage(h, amf0.NewReader(r), true) case 0x14: if err := r.Skip(4); err != nil { return errors.New("message.skip useless") } return handleAmfMessage(h, amf0.NewReader(r), true) case 0x0f: if err := r.Skip(5); err != nil { return errors.New("message.skip useless") } return handleAmfMessage(h, amf0.NewReader(r), false) } } }
func parseFlowRequestSlice(r *xio.PacketReader) (*flowRequestSlice, error) { var err error flags := uint8(0) if flags, err = r.Read8(); err != nil { return nil, errors.New("flow.read flags") } data := r.Bytes() return &flowRequestSlice{flags, data}, nil }
func parseFlowRequest(r *xio.PacketReader) (*flowRequest, error) { var err error flags := uint8(0) if flags, err = r.Read8(); err != nil { return nil, errors.New("flow.read flags") } fid := uint64(0) if fid, err = r.Read7BitValue64(); err != nil { return nil, errors.New("flow.read fid") } stage, delta := uint64(0), uint64(0) if stage, err = r.Read7BitValue64(); err != nil { return nil, errors.New("flow.read stage") } if delta, err = r.Read7BitValue64(); err != nil { return nil, errors.New("flow.read delta") } signature := "" if (flags & flagsHeader) != 0 { if signature, err = r.ReadString8(); err != nil { return nil, errors.New("flow.read signature") } for { if size, err := r.Read8(); err != nil { return nil, errors.New("flow.read header content size") } else if size == 0 { break } else if n := int(size); n > r.Len() { return nil, errors.New("flows.too big header content size") } else if err = r.Skip(n); err != nil { return nil, errors.New("flows.skip header") } } } data := r.Bytes() req := &flowRequest{} req.fid = fid req.signature = signature req.stage = stage req.stageack = stage - delta req.slices = make([]*flowRequestSlice, 0, 4) req.AddSlice(&flowRequestSlice{flags, data}) return req, nil }
func parseHelloRequest(r *xio.PacketReader) (*helloRequest, error) { var err error if _, err = r.Read8(); err != nil { return nil, errors.New("hello.read ignore") } size := uint8(0) if size, err = r.Read8(); err != nil { return nil, errors.New("hello.read epd.len") } else if size <= 1 { return nil, errors.New("hello.too small epd.len") } else { size-- if int(size) > r.Len() { return nil, errors.New("hello.too big epd.len") } } mode := uint8(0) if mode, err = r.Read8(); err != nil { return nil, errors.New("hello.read mode") } epd := make([]byte, int(size)) if err = r.ReadBytes(epd); err != nil { return nil, errors.New("hello.read epd") } tag := make([]byte, 16) if err = r.ReadBytes(tag); err != nil { return nil, errors.New("hello.read tag") } return &helloRequest{epd, tag, mode}, nil }
func (h *Handshake) handle(r *xio.PacketReader) (*packet, error) { if marker, err := r.Read8(); err != nil { return nil, errors.New("packet.read marker") } else { if _, err := r.Read16(); err != nil { return nil, errors.New("packet.read time") } if marker != 0x0b { counts.Count("handshake.marker.unknown", 1) return nil, errors.New(fmt.Sprintf("packet.unknown marker = 0x%02x", marker)) } } if msg, err := rtmfp.ParseRequestMessage(r); err != nil { return nil, err } else { switch msg.Code { default: counts.Count("handshake.code.unknown", 1) return nil, errors.New(fmt.Sprintf("message.unknown code = 0x%02x", msg.Code)) case 0x30: if rsp, err := h.handleHello(msg.PacketReader); err != nil { counts.Count("handshake.hello.error", 1) return nil, err } else { return &packet{0, rsp}, nil } case 0x38: if rsp, yid, err := h.handleAssign(msg.PacketReader); err != nil { counts.Count("handshake.assign.error", 1) return nil, err } else { return &packet{yid, rsp}, nil } } } }
func ParseRequestMessage(r *xio.PacketReader) (*RequestMessage, error) { var err error code := uint8(0) if code, err = r.Read8(); err != nil { return nil, errors.New("message.read code") } else if code == 0xff { return nil, EOP } var size uint16 if size, err = r.Read16(); err != nil { return nil, errors.New("message.read size") } rlen := r.Len() mlen := int(size) if rlen < mlen { return nil, errors.New("message.bad content length") } else { data := r.Bytes()[:mlen] if err := r.Skip(mlen); err != nil { return nil, errors.New("message.skip forward") } return &RequestMessage{code, xio.NewPacketReader(data)}, nil } }
func (s *Session) handle(r *xio.PacketReader) error { if marker, err := r.Read8(); err != nil { return errors.New("packet.read marker") } else { if s.stmptime, err = r.Read16(); err != nil { return errors.New("packet.read time") } switch marker | 0xf0 { default: counts.Count("session.marker.unknown", 1) return errors.New(fmt.Sprintf("packet.unknown marker = 0x%02x", marker)) case 0xfd: if _, err = r.Read16(); err != nil { return errors.New("packet.read ping time") } case 0xf9: } } msglist := list.New() for r.Len() != 0 { if msg, err := rtmfp.ParseRequestMessage(r); err != nil { if err != rtmfp.EOP { return err } break } else { msglist.PushBack(msg) } } var lastreq *flowRequest = nil for e := msglist.Front(); e != nil; e = e.Next() { msg := e.Value.(*rtmfp.RequestMessage) if msg.Code != 0x11 && lastreq != nil { if err := s.handleFlowRequest(lastreq); err != nil { return err } lastreq = nil } switch msg.Code { default: s.Close() counts.Count("session.code.unknown", 1) return errors.New(fmt.Sprintf("message.close code = 0x%02x", msg.Code)) case 0x4c: s.Close() counts.Count("session.code.close", 1) return nil case 0x01: s.send(newKeepAliveResponse(true)) case 0x41: case 0x5e: if req, err := parseFlowErrorRequest(msg.PacketReader); err != nil { counts.Count("session.parse5e.error", 1) return err } else if fw := s.writers[req.fid]; fw != nil { fw.reader.handler.OnClose() } else { xlog.OutLog.Printf("[session]: xid = %d, writer.fid = %d, flow not found 0x5e\n", s.xid, req.fid) } case 0x51: if req, err := parseFlowAckRequest(msg.PacketReader); err != nil { counts.Count("session.parse51.error", 1) return err } else if fw := s.writers[req.fid]; fw != nil { fw.CommitAck(req.cnt, req.ack) } else { xlog.OutLog.Printf("[session]: xid = %d, writer.fid = %d, flow not found 0x51\n", s.xid, req.fid) } case 0x10: if req, err := parseFlowRequest(msg.PacketReader); err != nil { counts.Count("session.parse10.error", 1) return err } else { lastreq = req } case 0x11: if req, err := parseFlowRequestSlice(msg.PacketReader); err != nil { counts.Count("session.parse11.error", 1) return err } else if lastreq != nil { lastreq.AddSlice(req) } else { xlog.OutLog.Printf("[session]: xid = %d, not following message\n", s.xid) } } } if lastreq != nil { return s.handleFlowRequest(lastreq) } return nil }