func (c *FormattedConnection) sendListener() {
	for {
		select {
		case buf := <-c.messages:
			err := c.SendSock(buf)
			if err != nil {
				log.Error("cannot send message to peer %v", err)
			}
		case <-c.stopSending:
			return
		}
	}
}
NOTE: this is left here intended to help debugging in the future.
func (c *FormattedConnection) measureSend() context.CancelFunc {
ctx, cancel := context.WithCancel(context.Background())
go func(ctx context.Context) {
timer := time.NewTimer(time.Second * 20)
select {
case <-timer.C:
i := crypto.UUIDString()
c.logger.With().Info("sending message is taking more than 20 seconds", log.String("peer", c.RemotePublicKey().String()), log.String("file", fmt.Sprintf("/tmp/stacktrace%v", i)))
buf := make([]byte, 1024)
for {
n := runtime.Stack(buf, true)
if n < len(buf) {
break
}
buf = make([]byte, 2*len(buf))
}
err := ioutil.WriteFile(fmt.Sprintf("/tmp/stacktrace%v", i), buf, 0644)
if err != nil {
c.logger.Error("ERR WIRTING FILE %v", err)
}
case <-ctx.Done():
return
}
}(ctx)
return cancel
}
package net
import (
	"errors"
	"time"
	"github.com/libonomy/libonomy-p2p/log"
	"github.com/libonomy/libonomy-p2p/p2p/config"
	"github.com/libonomy/libonomy-p2p/p2p/metrics"
	"github.com/libonomy/libonomy-p2p/p2p/net/wire/delimited"
	"github.com/libonomy/libonomy-p2p/p2p/p2pcrypto"
	"fmt"
	"io"
	"net"
	"sync"
	"github.com/libonomy/libonomy-p2p/crypto"
)
var (
	ErrClosedIncomingChannel = errors.New("unexpected closed incoming channel")
	ErrConnectionClosed = errors.New("connections was intentionally closed")
)
type ConnectionSource int
const (
	Local ConnectionSource = iota
	Remote
)
const MessageQueueSize = 250
type Connection interface {
	fmt.Stringer
	ID() string
	RemotePublicKey() p2pcrypto.PublicKey
	SetRemotePublicKey(key p2pcrypto.PublicKey)
	Created() time.Time
	RemoteAddr() net.Addr
	Session() NetworkSession
	SetSession(session NetworkSession)
	Send(m []byte) error
	Close() error
	Closed() bool
}
type FormattedConnection struct {
	logger      log.Log
	id          string  
	created     time.Time
	remotePub   p2pcrypto.PublicKey
	remoteAddr  net.Addr
	networker   networker  
	session     NetworkSession
	deadline    time.Duration
	r           formattedReader
	wmtx        sync.Mutex
	w           formattedWriter
	closed      bool
	deadliner   deadliner
	messages    chan []byte
	stopSending chan struct{}
	close       io.Closer
	msgSizeLimit int
}
type networker interface {
	HandlePreSessionIncomingMessage(c Connection, msg []byte) error
	EnqueueMessage(ime IncomingMessageEvent)
	SubscribeClosingConnections(func(c ConnectionWithErr))
	publishClosingConnection(c ConnectionWithErr)
	NetworkID() int8
}
type readWriteCloseAddresser interface {
	io.ReadWriteCloser
	deadliner
	RemoteAddr() net.Addr
}
type deadliner interface {
	SetReadDeadline(t time.Time) error
	SetWriteDeadline(t time.Time) error
}
type formattedReader interface {
	Next() ([]byte, error)
}
type formattedWriter interface {
	WriteRecord([]byte) (int, error)
}
func newConnection(conn readWriteCloseAddresser, netw networker,
	remotePub p2pcrypto.PublicKey, session NetworkSession, msgSizeLimit int, deadline time.Duration, log log.Log) *FormattedConnection {
	connection := &FormattedConnection{
		logger:       log,
		id:           crypto.UUIDString(),
		created:      time.Now(),
		remotePub:    remotePub,
		remoteAddr:   conn.RemoteAddr(),
		r:            delimited.NewReader(conn),
		w:            delimited.NewWriter(conn),
		close:        conn,
		deadline:     deadline,
		deadliner:    conn,
		networker:    netw,
		session:      session,
		messages:     make(chan []byte, MessageQueueSize),
		stopSending:  make(chan struct{}),
		msgSizeLimit: msgSizeLimit,
	}
	go connection.sendListener()
	return connection
}
func (c *FormattedConnection) ID() string {
	return c.id
}
func (c *FormattedConnection) RemoteAddr() net.Addr {
	return c.remoteAddr
}
func (c *FormattedConnection) SetRemotePublicKey(key p2pcrypto.PublicKey) {
	c.remotePub = key
}
func (c *FormattedConnection) RemotePublicKey() p2pcrypto.PublicKey {
	return c.remotePub
}
func (c *FormattedConnection) SetSession(session NetworkSession) {
	c.session = session
}
func (c *FormattedConnection) Session() NetworkSession {
	return c.session
}
func (c *FormattedConnection) String() string {
	return c.id
}
func (c *FormattedConnection) Created() time.Time {
	return c.created
}
func (c *FormattedConnection) publish(message []byte) {
	c.networker.EnqueueMessage(IncomingMessageEvent{c, message})
}