func (p *Conn) Read() (protocommon.MsgDecodable, error) {
	if !p.BinaryMode() {
		msgStr, err := p.ReadMessage()
		if err != nil {
			return nil, err
		}
		msg, err := func() (protocommon.MsgDecodable, error) {
			if len(msgStr) == 0 {
				return &AdcKeepAlive{}, nil
			}
			pkt, err := adc.DecodePacket([]byte(msgStr + "\n"))
			if err != nil {
				return nil, err
			}
			msg := func() interface{} {
				switch tpkt := pkt.(type) {
				case *adc.BroadcastPacket:
					switch msg := pkt.Message().(type) {
					case adc.UserInfo:
						return &AdcBInfos{tpkt, &msg}
					case adc.ChatMessage:
						return &AdcBMessage{tpkt, &msg}
					case adc.SearchRequest:
						return &AdcBSearchRequest{tpkt, &msg}
					}
				case *adc.ClientPacket:
					switch msg := pkt.Message().(type) {
					case adc.GetRequest:
						return &AdcCGetFile{tpkt, &msg}
					case adc.UserInfo:
						return &AdcCInfos{tpkt, &msg}
					case adc.GetResponse:
						return &AdcCSendFile{tpkt, &msg}
					case adc.Supported:
						return &AdcCSupports{tpkt, &msg}
					case adc.Status:
						return &AdcCStatus{tpkt, &msg}
					}
				case *adc.DirectPacket:
					switch msg := pkt.Message().(type) {
					case adc.ConnectRequest:
						return &AdcDConnectToMe{tpkt, &msg}
					case adc.ChatMessage:
						return &AdcDMessage{tpkt, &msg}
					case adc.RevConnectRequest:
						return &AdcDRevConnectToMe{tpkt, &msg}
					case adc.SearchResult:
						return &AdcDSearchResult{tpkt, &msg}
					}
				case *adc.FeaturePacket:
					if msg, ok := pkt.Message().(adc.SearchRequest); ok {
						return &AdcFSearchRequest{tpkt, &msg}
					}
				case *adc.HubPacket:
					switch msg := pkt.Message().(type) {
					case adc.Password:
						return &AdcHPass{tpkt, &msg}
					case adc.Supported:
						return &AdcHSupports{tpkt, &msg}
					}
				case *adc.InfoPacket:
					switch msg := pkt.Message().(type) {
					case adc.UserCommand:
						return &AdcICommand{tpkt, &msg}
					case adc.GetPassword:
						return &AdcIGetPass{tpkt, &msg}
					case adc.HubInfo:
						return &AdcIInfos{tpkt, &msg}
					case adc.ChatMessage:
						return &AdcIMsg{tpkt, &msg}
					case adc.Disconnect:
						return &AdcIQuit{tpkt, &msg}
					case adc.SIDAssign:
						return &AdcISessionID{tpkt, &msg}
					case adc.Status:
						return &AdcIStatus{tpkt, &msg}
					case adc.Supported:
						return &AdcISupports{tpkt, &msg}
					case adc.ZOn:
						return &AdcIZon{tpkt, &msg}
					}
				}
				return nil
			}()
			if msg == nil {
				return nil, fmt.Errorf("unsupported message")
			}
			return msg, nil
		}()
		if err != nil {
			return nil, fmt.Errorf("Unable to parse: %s (%s)", err, msgStr)
		}
		log.Log(p.LogLevel(), log.LevelDebug, "[%s->c] %T %+v", p.RemoteLabel(), msg, msg)
		return msg, nil
	}
	buf, err := p.ReadBinary()
	if err != nil {
		return nil, err
	}
	return &protocommon.MsgBinary{buf}, nil  
}
Read reads a message.
package protoadc
import (
	"bytes"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base32"
	"fmt"
	"math/rand"
	"net"
	"reflect"
	"strings"
	"github.com/aler9/go-dc/adc"
	"github.com/aler9/dctk/pkg/log"
	"github.com/aler9/dctk/pkg/protocommon"
)
const (
	AdcCodeProtocolUnsupported = 41
	AdcCodeFileNotAvailable    = 51
	AdcCodeSlotsFull           = 53
)
func dcBase32Encode(in []byte) string {
	return strings.TrimRight(base32.StdEncoding.EncodeToString(in), "=")
}
func AdcRandomToken() string {
	const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	buf := make([]byte, 10)
	for i := range buf {
		buf[i] = chars[rand.Intn(len(chars))]
	}
	return string(buf)
}
func AdcCertFingerprint(cert *x509.Certificate) string {
	h := sha256.New()
	h.Write(cert.Raw)
	return "SHA256/" + dcBase32Encode(h.Sum(nil))
}
type Conn struct {
	*protocommon.BaseConn
}
func NewConn(logLevel log.Level, remoteLabel string, nconn net.Conn,
	applyReadTimeout bool, applyWriteTimeout bool) *Conn {
	p := &Conn{
		BaseConn: protocommon.NewBaseConn(logLevel, remoteLabel,
			nconn, applyReadTimeout, applyWriteTimeout, '\n'),
	}
	return p
}