Esempio n. 1
0
func (h *Handshake) handleAssign(r *xio.PacketReader) (rtmfp.ResponseMessage, uint32, error) {
	if req, err := parseAssignRequest(r); err != nil {
		return nil, 0, err
	} else {
		cookie := cookies.Find(string(req.cookie))
		if cookie == nil {
			return nil, 0, errors.New("assign.cookie not found")
		}
		cookie.Lock()
		defer cookie.Unlock()
		if cookie.Xid == 0 {
			responder, encrypt, decrypt := rtmfp.ComputeSharedKeys(h, req.pubkey, req.initiator)
			cookie.Pid = req.pid
			cookie.Responder = responder
			if xid, err := session.Create(req.yid, cookie.Pid, cookie.Value(), encrypt, decrypt, h.lport, h.raddr); err != nil {
				counts.Count("handshake.session.error", 1)
				return nil, 0, errors.New(fmt.Sprintf("assign.create session = %v", err))
			} else {
				cookie.Xid = xid
				counts.Count("handshake.assign", 1)
				xlog.SssLog.Printf("[join] %s [%s] xid = %d\n", xlog.StringToHex(cookie.Pid), h.raddr, xid)
			}
			xlog.OutLog.Printf("[handshake]: new session xid = %d from [%s]\n", cookie.Xid, h.raddr)
		}
		return &assignResponse{cookie.Xid, cookie.Responder}, req.yid, nil
	}
}
Esempio n. 2
0
func New() *Cookie {
	cookies.Lock()
	defer cookies.Unlock()
	now := time.Now().UnixNano()
	buf := make([]byte, CookieSize)
	for i, v := 0, now; i < 8; i, v = i+1, v>>8 {
		buf[i] = uint8(v)
	}
	rnd := xio.NewRandomReader(now)
	for i := 0; i < 4; i++ {
		rnd.ReadBytes(buf[8:])
		value := string(buf)
		if c := cookies.values[value]; c != nil {
			continue
		}
		c := &Cookie{}
		c.value = value
		c.alloctime = now
		cookies.values[value] = c
		counts.Count("cookie.new", 1)
		return c
	}
	counts.Count("cookie.null", 1)
	return nil
}
Esempio n. 3
0
func Send(lport uint16, raddr *net.UDPAddr, data []byte) {
	if len(data) > 1400 {
		counts.Count("udp.toobig", 1)
		xlog.ErrLog.Printf("[udp]: udp-%d packet is too big, size = %d\n", lport, len(data))
	} else if srv := servers[lport]; srv == nil {
		counts.Count("udp.notfound", 1)
		xlog.ErrLog.Printf("[udp]: udp-%d not found\n", lport)
	} else {
		srv.Send(raddr, data)
	}
}
Esempio n. 4
0
func Exit(xid uint32, raddr *net.UDPAddr) {
	if clt := tcp.GetClient(); clt == nil {
		return
	} else if bs, err := newXRequest(xid, raddr, "exit", 0, nil, true); err != nil {
		counts.Count("rpc.exit.error", 1)
		xlog.ErrLog.Printf("[rpc]: rpc exit error = '%v'\n", err)
	} else {
		counts.Count("rpc.exit", 1)
		async.Call(uint64(xid), func() {
			clt.Send(bs)
		})
	}
}
Esempio n. 5
0
func (h *Handshake) handleHello(r *xio.PacketReader) (rtmfp.ResponseMessage, error) {
	if req, err := parseHelloRequest(r); err != nil {
		return nil, err
	} else {
		switch req.mode {
		default:
			return nil, errors.New(fmt.Sprintf("hello.unknown mode = 0x%02x", req.mode))
		case 0x0f:
			if s := session.FindByPid(string(req.epd)); s == nil {
				counts.Count("p2p.session.notfound", 1)
				return nil, &handshakeError{"hello.handshake.session not found", req.epd, h.raddr}
			} else if addrs, ok := s.Handshake(req.tag, h.raddr); !ok {
				counts.Count("p2p.session.hasclosed", 1)
				return nil, &handshakeError{"hello.handshake.session has been closed", req.epd, h.raddr}
			} else {
				counts.Count("p2p.handshake", 1)
				return &handshakeResponse{req.tag, addrs}, nil
			}
		case 0x0a:
			if uri, err := url.ParseRequestURI(string(req.epd)); err != nil {
				return nil, errors.New("hello.parse uri")
			} else if app := uri.Path; len(app) == 0 {
				return nil, errors.New("hello.parse app")
			} else {
				if ss := strings.Split(app, "/"); len(ss) != 1 {
					app = ""
					for _, s := range ss {
						if len(s) != 0 {
							app = s
							break
						}
					}
				}
				if len(app) == 0 || !args.IsAuthorizedApp(app) {
					counts.Count("handshake.app.unauthorized", 1)
					return nil, errors.New(fmt.Sprintf("hello.unauthorized app = %s", app))
				}
			}
			cookie := cookies.New()
			if cookie == nil {
				return nil, errors.New("hello.null cookie")
			}
			cookie.Lock()
			defer cookie.Unlock()
			counts.Count("handshake.hello", 1)
			xlog.OutLog.Printf("[handshake]: new cookie from [%s]\n", h.raddr)
			return &helloResponse{req.tag, cookie.Value()}, nil
		}
	}
}
Esempio n. 6
0
func Call(xid uint32, raddr *net.UDPAddr, callback float64, data []byte, reliable bool) {
	if clt := tcp.GetClient(); clt == nil {
		counts.Count("rpc.call.noclient", 1)
		xlog.ErrLog.Printf("[rpc]: rpc is disabled\n")
	} else if bs, err := newXRequest(xid, raddr, "call", callback, data, reliable); err != nil {
		counts.Count("rpc.call.error", 1)
		xlog.ErrLog.Printf("[rpc]: rpc call error = '%v'\n", err)
	} else {
		counts.Count("rpc.call", 1)
		async.Call(uint64(xid), func() {
			clt.Send(bs)
		})
	}
}
Esempio n. 7
0
func flush(s *Session, msgs []rtmfp.ResponseMessage) {
	lport, raddr := s.lport, s.raddr
	if data, err := rtmfp.PacketToBytes(&packet{s.yid, s.manage.lasttime, s.stmptime, msgs}); err != nil {
		counts.Count("session.tobytes.error", 1)
		xlog.ErrLog.Printf("[session]: packet to bytes error = '%v'\n", err)
		return
	} else {
		xlog.OutLog.Printf("[session]: send addr = [%s], data.len = %d\n%s\n", raddr, len(data), utils.Formatted(data))
		if data, err = rtmfp.EncodePacket(s, s.yid, data); err != nil {
			counts.Count("session.encode.error", 1)
			xlog.ErrLog.Printf("[session]: encode packet error = '%v'\n", err)
			return
		}
		udp.Send(lport, raddr, data)
	}
}
Esempio n. 8
0
func init() {
	for i := 0; i < len(groups); i++ {
		g := &groups[i]
		g.cond = sync.NewCond(&g.lock)
		g.list = list.New()
		main := func() {
			defer func() {
				if x := recover(); x != nil {
					counts.Count("async.panic", 1)
					xlog.ErrLog.Printf("[async]: panic = %v\n%s\n", x, utils.Trace())
				}
			}()
			for {
				var f func()
				g.lock.Lock()
				if e := g.list.Front(); e != nil {
					f = g.list.Remove(e).(func())
				} else {
					g.cond.Wait()
				}
				g.lock.Unlock()
				if f != nil {
					f()
				}
			}
		}
		go func() {
			for {
				main()
			}
		}()
	}
}
Esempio n. 9
0
func Find(value string) *Cookie {
	cookies.Lock()
	c := cookies.values[value]
	cookies.Unlock()
	if c == nil {
		counts.Count("cookie.notfound", 1)
	}
	return c
}
Esempio n. 10
0
func DecodeXMessage(bs []byte) *XMessage {
	x := &XMessage{}
	if err := proto.Unmarshal(bs, x); err != nil {
		counts.Count("rpc.xmessage.error", 1)
		xlog.ErrLog.Printf("[rpc]: rpc decode.xmessage error = '%v'\n", err)
		return nil
	}
	return x
}
Esempio n. 11
0
func newHandshake() *Handshake {
	h := &Handshake{}
	h.AESEngine = rtmfp.NewAESEngine()
	if err := h.SetKey(cryptkey, cryptkey); err != nil {
		utils.Panic(fmt.Sprintf("handshake init error = '%v'", err))
	}
	h.DHEngine = rtmfp.NewDHEngine()
	counts.Count("handshake.new", 1)
	return h
}
Esempio n. 12
0
func HandlePacket(lport uint16, raddr *net.UDPAddr, data []byte) {
	h := getHandshake()
	if h == nil {
		return
	}
	defer putHandshake(h)

	var err error
	if data, err = rtmfp.DecodePacket(h, data); err != nil {
		counts.Count("handshake.decode.error", 1)
		xlog.ErrLog.Printf("[handshake]: decode error = '%v'\n", err)
		return
	}
	xlog.OutLog.Printf("[handshake]: recv addr = [%s], data.len = %d\n%s\n", raddr, len(data), utils.Formatted(data))

	h.lport, h.raddr = lport, raddr

	var pkt *packet
	if pkt, err = h.handle(xio.NewPacketReader(data[6:])); err != nil {
		counts.Count("handshake.handle.error", 1)
		xlog.ErrLog.Printf("[handshake]: handle error = '%v'\n", err)
		return
	} else if pkt == nil {
		xlog.OutLog.Printf("[handshake]: response packet is empty\n")
		return
	}

	if data, err = rtmfp.PacketToBytes(pkt); err != nil {
		counts.Count("handshake.tobytes.error", 1)
		xlog.ErrLog.Printf("[handshake]: packet to bytes error = '%v'\n", err)
		return
	}
	xlog.OutLog.Printf("[handshake]: send addr = [%s], data.len = %d\n%s\n", raddr, len(data), utils.Formatted(data))

	if data, err = rtmfp.EncodePacket(h, pkt.yid, data); err != nil {
		counts.Count("handshake.encode.error", 1)
		xlog.ErrLog.Printf("[handshake]: encode packet error = '%v'\n", err)
		return
	}
	udp.Send(lport, raddr, data)
}
Esempio n. 13
0
func (s *Session) handleFlowRequest(req *flowRequest) error {
	if fr, err := s.getFlowReader(req.fid, req.signature); err != nil {
		counts.Count("session.flow.error", 1)
		return errors.New("flow.create flow reader")
	} else if fr != nil {
		fr.AddFragments(req.stageack, req.Fragments()...)
		fr.CommitAck()
		return nil
	} else {
		xlog.OutLog.Printf("[session]: xid = %d, reader.fid = %d, flow not found\n", s.xid, req.fid)
		return nil
	}
}
Esempio n. 14
0
func (s *Session) Close() {
	if s.closed {
		return
	}
	s.closed = true
	for _, fw := range s.writers {
		fw.reader.handler.OnClose()
	}
	s.send(newErrorResponse())
	counts.Count("session.close", 1)
	xlog.OutLog.Printf("[session]: xid = %d, session closed\n", s.xid)
	rpc.Exit(s.xid, s.raddr)
}
Esempio n. 15
0
func Create(yid uint32, pid string, cookie string, encrypt, decrypt []byte, lport uint16, raddr *net.UDPAddr) (uint32, error) {
	s := &Session{}
	s.xid = 0
	s.yid = yid
	s.pid = pid
	s.lport, s.raddr = lport, raddr
	s.addrs = nil
	s.cookie = cookie
	s.closed = false
	s.manage.cnt, s.manage.lasttime = 0, time.Now().UnixNano()
	s.stmptime = 0
	s.AESEngine = rtmfp.NewAESEngine()
	if err := s.SetKey(encrypt, decrypt); err != nil {
		return 0, err
	}
	s.lastfid = 0
	s.lastsid = 0
	s.mainfw = nil
	s.readers = make(map[uint64]*flowReader)
	s.writers = make(map[uint64]*flowWriter)
	s.rsplist.Init()

	sessions.Lock()
	defer sessions.Unlock()

	xid := sessions.lastxid
	for {
		xid++
		if xid == 0 {
			continue
		}
		if xid == sessions.lastxid {
			return 0, errors.New("too many sessions")
		}
		if getSessionByXid(xid) == nil {
			break
		}
	}
	s.xid = xid
	sessions.lastxid = xid
	addSessionByXid(xid, s)
	addSessionByPid(pid, s)

	m := &sessions.manages[int(xid%uint32(len(sessions.manages)))]
	m.Lock()
	m.freshlist.PushBack(s)
	m.Unlock()

	counts.Count("session.new", 1)
	return xid, nil
}
Esempio n. 16
0
func (c *Client) main() {
	for {
		conn, err := net.DialTCP("tcp4", nil, &net.TCPAddr{IP: net.ParseIP(c.ip), Port: int(c.port)})
		if err != nil {
			counts.Count("tcp.connect.error", 1)
			log.Printf("[tcp]: connect %s:%d failed '%v'\n", c.ip, c.port, err)
		} else {
			counts.Count("tcp.connect", 1)
			log.Printf("[tcp]: connect to %s\n", conn.RemoteAddr())
			conn.SetWriteBuffer(MaxSendBufferSize)
			conn.SetReadBuffer(MaxRecvBufferSize)
			conn.SetNoDelay(true)
			var once sync.Once
			sig := make(chan int)
			raise := func() {
				once.Do(func() {
					conn.Close()
					close(sig)
				})
			}
			go sender(conn, c.send, sig, raise)
			go recver(conn, c.recv, sig, raise)
			<-sig
			counts.Count("tcp.connect.close", 1)
		}
		for i := 0; i < 50; i++ {
			time.Sleep(time.Millisecond * 100)
			for {
				select {
				case <-c.send:
					continue
				default:
				}
				break
			}
		}
	}
}
Esempio n. 17
0
func (s *Server) main() {
	for {
		conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: int(s.port)})
		if err != nil {
			counts.Count("udp.listen.error", 1)
			log.Printf("[udp]: listen port %d failed '%v'\n", s.port, err)
		} else {
			counts.Count("udp.listen", 1)
			log.Printf("[udp]: listen port %d\n", s.port)
			conn.SetWriteBuffer(MaxSendBufferSize)
			conn.SetReadBuffer(MaxRecvBufferSize)
			var once sync.Once
			sig := make(chan int)
			raise := func() {
				once.Do(func() {
					conn.Close()
					close(sig)
				})
			}
			go sender(conn, s.send, sig, raise)
			go recver(conn, s.recv, sig, raise)
			<-sig
			counts.Count("udp.listen.close", 1)
		}
		for i := 0; i < 50; i++ {
			time.Sleep(time.Millisecond * 100)
			for {
				select {
				case <-s.send:
					continue
				default:
				}
				break
			}
		}
	}
}
Esempio n. 18
0
func HandlePacket(lport uint16, raddr *net.UDPAddr, xid uint32, data []byte) {
	s := FindByXid(xid)
	if s == nil {
		counts.Count("session.notfound", 1)
		return
	}
	s.Lock()
	defer s.Unlock()
	if s.closed {
		counts.Count("session.hasclosed", 1)
		return
	}
	defer s.flush()

	var err error
	if data, err = rtmfp.DecodePacket(s, data); err != nil {
		counts.Count("session.decode.error", 1)
		xlog.ErrLog.Printf("[session]: decode error = '%v'\n", err)
		return
	}
	xlog.OutLog.Printf("[session]: recv addr = [%s], data.len = %d\n%s\n", raddr, len(data), utils.Formatted(data))

	s.lport, s.raddr = lport, raddr

	if len(s.cookie) != 0 {
		cookies.Commit(s.cookie)
		s.cookie = ""
		rpc.Join(s.xid, s.raddr)
	}

	s.manage.cnt, s.manage.lasttime = 0, time.Now().UnixNano()

	if err = s.handle(xio.NewPacketReader(data[6:])); err != nil {
		counts.Count("session.handle.error", 1)
		xlog.ErrLog.Printf("[session]: handle error = '%v'\n", err)
	}
}
Esempio n. 19
0
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
			}
		}
	}
}
Esempio n. 20
0
func (s *Session) Handshake(tag []byte, raddr *net.UDPAddr) ([]*net.UDPAddr, bool) {
	s.Lock()
	defer s.Unlock()
	if s.closed {
		counts.Count("session.p2p.closed", 1)
		return nil, false
	}
	defer s.flush()

	xlog.OutLog.Printf("[session]: xid = %d, raddr = [%s], handshake to [%s]\n", s.xid, s.raddr, raddr)

	s.send(&handshakeResponse{s.pid, tag, raddr, true})

	addrs := make([]*net.UDPAddr, 1+len(s.addrs))
	addrs[0] = s.raddr
	copy(addrs[1:], s.addrs)
	return addrs, true
}
Esempio n. 21
0
func init() {
	sessions.lastxid = 0
	for i := 0; i < len(sessions.buckets); i++ {
		sessions.buckets[i].xidmap = make(map[uint32]*Session, 8192)
		sessions.buckets[i].pidmap = make(map[string]*Session, 8192)
	}
	for i := 0; i < len(sessions.manages); i++ {
		m := &sessions.manages[i]
		m.freshlist = list.New()
		m.alivelist = list.New()
		go func() {
			manage := args.Manage()
			for {
				m.Lock()
				if m.freshlist.Len() != 0 {
					m.alivelist.PushBackList(m.freshlist)
					m.freshlist.Init()
				}
				m.Unlock()
				count := 0
				if e := m.alivelist.Front(); e != nil {
					for e != nil {
						next := e.Next()
						if s := e.Value.(*Session); s.Manage() {
							delSessionByXid(s.xid)
							delSessionByPid(s.pid)
							m.alivelist.Remove(e)
							count++
							xlog.SssLog.Printf("[exit] %s [%s] xid = %d cnt = %d\n", xlog.StringToHex(s.pid), s.raddr, s.xid, s.manage.cnt)
						}
						e = next
					}
				}
				if count != 0 {
					counts.Count("session.cleanup", count)
				}
				time.Sleep(time.Millisecond * time.Duration(manage))
			}
		}()
	}
}
Esempio n. 22
0
func init() {
	handshakes.Init()
	go func() {
		for {
			handshakes.Lock()
			if e := handshakes.Back(); e != nil {
				handshakes.Remove(e)
				counts.Count("handshake.release", 1)
			}
			n := handshakes.Len()
			handshakes.Unlock()
			if n > 512 {
				time.Sleep(time.Second * 2)
			} else if n > 128 {
				time.Sleep(time.Second * 5)
			} else {
				time.Sleep(time.Second * 30)
			}
		}
	}()
}
Esempio n. 23
0
func init() {
	cookies.values = make(map[string]*Cookie, 16384)
	go func() {
		for {
			limit := time.Now().UnixNano() - int64(time.Minute)*5
			count := 0
			cookies.Lock()
			for value, cookie := range cookies.values {
				if cookie.alloctime < limit {
					delete(cookies.values, value)
					count++
				}
			}
			cookies.Unlock()
			if count != 0 {
				counts.Count("cookie.timeout", count)
			}
			time.Sleep(time.Second * 15)
		}
	}()
}
Esempio n. 24
0
func (s *Server) main() {
	for {
		ln, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IPv4zero, Port: int(s.port)})
		if err != nil {
			counts.Count("tcp.listen.error", 1)
			log.Printf("[tcp]: listen port %d failed '%v'\n", s.port, err)
		} else {
			counts.Count("tcp.listen", 1)
			for {
				if conn, err := ln.AcceptTCP(); err != nil {
					counts.Count("tcp.accept.error", 1)
					log.Printf("[tcp]: accept port %d failed '%v'\n", s.port, err)
					break
				} else {
					counts.Count("tcp.accept", 1)
					log.Printf("[tcp]: accept port %d from [%s]\n", s.port, conn.RemoteAddr())
					conn.SetWriteBuffer(MaxSendBufferSize)
					conn.SetReadBuffer(MaxRecvBufferSize)
					conn.SetNoDelay(true)
					var once sync.Once
					sig := make(chan int)
					raise := func() {
						once.Do(func() {
							conn.Close()
							close(sig)
							counts.Count("tcp.accept.close", 1)
						})
					}
					go recver(conn, s.recv, sig, raise)
				}
			}
			ln.Close()
			counts.Count("tcp.listen.close", 1)
		}
		time.Sleep(time.Second * 5)
	}
}
Esempio n. 25
0
func Start() {
	shell := func(f func()) {
		s := func() {
			defer func() {
				if x := recover(); x != nil {
					counts.Count("server.panic", 1)
					xlog.ErrLog.Printf("[server]: panic = %v\n%s\n", x, utils.Trace())
				}
			}()
			f()
		}
		for {
			s()
		}
	}
	for _, udpsrv := range udp.GetServers() {
		s := udpsrv
		f := func() {
			for {
				if lport, addr, data := s.Recv(); addr != nil && len(data) != 0 {
					if xid, err := rtmfp.PacketXid(data); err != nil {
						continue
					} else if xid == 0 {
						handshake.HandlePacket(lport, addr, data)
					} else {
						session.HandlePacket(lport, addr, xid, data)
					}
				}
			}
		}
		for i := 0; i < args.Parallel(); i++ {
			go shell(f)
		}
	}
	if s := tcp.GetServer(); s != nil {
		f := func() {
			for {
				if bs := s.Recv(); len(bs) != 0 {
					if x := rpc.DecodeXMessage(bs); x != nil {
						if b := x.Broadcast; b != nil {
							xids, data, reliable := b.Xids, b.Data, *b.Reliable
							if len(xids) == 0 || len(data) == 0 {
								continue
							}
							session.RecvPull(xids, data, reliable)
						}
						if c := x.Close; c != nil {
							xids := c.Xids
							if len(xids) == 0 {
								continue
							}
							session.CloseAll(xids)
						}
					}
				}
			}
		}
		go shell(f)
	}
	if c := tcp.GetClient(); c != nil {
		f := func() {
			for {
				if bs := c.Recv(); len(bs) != 0 {
					if x := rpc.DecodeXResponse(bs); x != nil {
						xid, data, callback, reliable := *x.Xid, x.Data, *x.Callback, *x.Reliable
						if xid == 0 || len(data) == 0 {
							continue
						}
						session.Callback(xid, data, callback, reliable)
					}
				}
			}
		}
		go shell(f)
	}
	for {
		time.Sleep(time.Minute)
	}
}
Esempio n. 26
0
func Commit(value string) {
	cookies.Lock()
	delete(cookies.values, value)
	cookies.Unlock()
	counts.Count("cookie.commit", 1)
}
Esempio n. 27
0
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
}