func (rc *readConn) read() ([]byte, error) {
	for {
		// Check for abort signal
		select {
		case <-rc.ach:
			return nil, io.ErrUnexpectedEOF
		default:
		}
		// The read cannot block on anything else other than reading on the underlying connection.
		// Note that sub.Kill will unblock sub.Read. The former will be called by writeLoop when
		// it receives the abortion signal.
		chunk, err := rc.sub.Read()

		// Stitching or permanent error
		if err != nil {
			if chunk != nil {
				panic("eh")
			}
			stitchConnWriter := chain.IsStitch(err)
			// Connection termination.
			// Any non-ErrStitch error implies connection termination.
			if stitchConnWriter == nil {
				// rc.frame.Println("read carrier error:", err.Error())
				return nil, err
			}
			// Stitching
			rc.syncWrite(stitchConnWriter, rc.nread)
			continue
		}

		// Payload received
		msg, err := decodeMsg(chunk)
		if err != nil {
			rc.frame.Println("read/decode error:", err.Error())
			// Misbehaved opponent is a connection termination.
			return nil, err
		}
		switch t := msg.(type) {
		case *Sync:
			if err = rc.readSync(t); err != nil {
				rc.frame.Println("read SYNC error:", err.Error())
				// Permanent connection termination.
				return nil, err
			}
			// Retry read

		case *Ack:
			if err = rc.readAck(t); err != nil {
				rc.frame.Println("read ACK error:", err.Error())
				// Permanent connection termination.
				return nil, err
			}
			// Retry read

		case *Chunk:
			if chunk := rc.readChunk(t); chunk != nil {
				return chunk, nil
			}
			// Redundant chunk was dropped. Retry read

		default:
			panic("eh")
		}
	}
}
// read blocks until the next CHUNK is received. Meanwhile it processes incoming control messages like ACK and SYNC.
// Non-nil errors returned by read indicate irrecoverable physical errors on the underlying connection.
read blocks until the next CHUNK is received. Meanwhile it processes incoming control messages like ACK and SYNC.
Non-nil errors returned by read indicate irrecoverable physical errors on the underlying connection.
// read blocks until the next CHUNK is received . Meanwhile it processes incoming control messages like ACK and SYNC . // Non - nil errors returned by read indicate irrecoverable physical errors on the underlying connection .
func (rc *readConn) read() ([]byte, error) {
	for {
		select {
		case <-rc.ach:
			return nil, io.ErrUnexpectedEOF
		default:
		}
		chunk, err := rc.sub.Read()
		if err != nil {
			if chunk != nil {
				panic("eh")
			}
			stitchConnWriter := chain.IsStitch(err)
			if stitchConnWriter == nil {
				return nil, err
			}
			rc.syncWrite(stitchConnWriter, rc.nread)
			continue
		}
		msg, err := decodeMsg(chunk)
		if err != nil {
			rc.frame.Println("read/decode error:", err.Error())
			return nil, err
		}
		switch t := msg.(type) {
		case *Sync:
			if err = rc.readSync(t); err != nil {
				rc.frame.Println("read SYNC error:", err.Error())
				return nil, err
			}
		case *Ack:
			if err = rc.readAck(t); err != nil {
				rc.frame.Println("read ACK error:", err.Error())
				return nil, err
			}
		case *Chunk:
			if chunk := rc.readChunk(t); chunk != nil {
				return chunk, nil
			}
		default:
			panic("eh")
		}
	}
}
func ( rc * readConn ) read ( ) ( [ ] byte , error ) { for { select { case <- rc . ach : return nil , io . ErrUnexpectedEOF default : } chunk , err := rc . sub . Read ( ) if err != nil { if chunk != nil { panic ( " " ) } stitchConnWriter := chain . IsStitch ( err ) if stitchConnWriter == nil { return nil , err } rc . syncWrite ( stitchConnWriter , rc . nread ) continue } msg , err := decodeMsg ( chunk ) if err != nil { rc . frame . Println ( " " , err . Error ( ) ) return nil , err } switch t := msg . ( type ) { case * Sync : if err = rc . readSync ( t ) ; err != nil { rc . frame . Println ( " " , err . Error ( ) ) return nil , err } case * Ack : if err = rc . readAck ( t ) ; err != nil { rc . frame . Println ( " " , err . Error ( ) ) return nil , err } case * Chunk : if chunk := rc . readChunk ( t ) ; chunk != nil { return chunk , nil } default : panic ( " " ) } } }
read blocks until the next CHUNK is received.
read blocks until the next CHUNK is received .
// Check for abort signal // The read cannot block on anything else other than reading on the underlying connection. // Note that sub.Kill will unblock sub.Read. The former will be called by writeLoop when // it receives the abortion signal. // Stitching or permanent error // Connection termination. // Any non-ErrStitch error implies connection termination. // rc.frame.Println("read carrier error:", err.Error()) // Stitching // Payload received // Misbehaved opponent is a connection termination. // Permanent connection termination. // Retry read // Permanent connection termination. // Retry read // Redundant chunk was dropped. Retry read