Example #1
0
// peekMessageSize() reads, but not commits, enough bytes to determine the size of
// the next message and returns the type and size.
func (this *service) peekMessageSize() (message.MessageType, int, error) {
	var (
		b   []byte
		err error
		cnt int = 2
	)

	if this.in == nil {
		err = ErrBufferNotReady
		return 0, 0, err
	}

	// Let's read enough bytes to get the message header (msg type, remaining length)
	for {
		// If we have read 5 bytes and still not done, then there's a problem.
		if cnt > 5 {
			return 0, 0, fmt.Errorf("sendrecv/peekMessageSize: 4th byte of remaining length has continuation bit set")
		}

		// Peek cnt bytes from the input buffer.
		b, err = this.in.ReadWait(cnt)
		if err != nil {
			return 0, 0, err
		}

		// If not enough bytes are returned, then continue until there's enough.
		if len(b) < cnt {
			continue
		}

		// If we got enough bytes, then check the last byte to see if the continuation
		// bit is set. If so, increment cnt and continue peeking
		if b[cnt-1] >= 0x80 {
			cnt++
		} else {
			break
		}
	}

	// Get the remaining length of the message
	remlen, m := binary.Uvarint(b[1:])

	// Total message length is remlen + 1 (msg type) + m (remlen bytes)
	total := int(remlen) + 1 + m

	mtype := message.MessageType(b[0] >> 4)

	return mtype, total, err
}
Example #2
0
// processor() reads messages from the incoming buffer and processes them
func (this *service) processor() {
	defer func() {
		// Let's recover from panic
		if r := recover(); r != nil {
			Log.Errorc(func() string {
				return fmt.Sprintf("(%s) Recovering from panic: %v", this.cid(), r)
			})
		}

		this.wgStopped.Done()

		Log.Debugc(func() string {
			return fmt.Sprintf("(%s) Stopping processor", this.cid())
		})
		this.stop()
	}()

	this.wgStarted.Done()

	for {
		// 1. Find out what message is next and the size of the message
		p, ok := this.in.ReadBuffer()
		if !ok {
			Log.Debugc(func() string { return fmt.Sprintf("(%s) suddenly disconnect.", this.cid()) })
			return
		}
		mtype := message.MessageType((*p)[0] >> 4)

		_p := this.server.getRealBytes(p)

		msg, err := mtype.New()
		n, err := msg.Decode(_p)
		//清理指针p
		//p = nil
		_p = nil
		this.server.DestoryBytes(*p)
		if err != nil {
			Log.Errorc(func() string {
				return fmt.Sprintf("(%s) Error peeking next message: %v", this.cid(), err)
			})
			return
		}
		//     this.rmu.Unlock()

		//Log.Debugc(func() string{ return fmt.Sprintf("(%s) Received: %s", this.cid(), msg)})

		this.inStat.increment(int64(n))

		// 5. Process the read message
		err = this.processIncoming(msg)
		if err != nil {
			if err != errDisconnect {
				Log.Errorc(func() string {
					return fmt.Sprintf("(%s) Error processing %s: %v", this.cid(), msg.Name(), err)
				})
			} else {
				return
			}
		}

		// 7. Check to see if done is closed, if so, exit
		if this.isDone() {
			return
		}

	}
}