package conn import ( "fmt" "io" "net" "time" lgbl "github.com/ipfs/go-libp2p/loggables" ic "github.com/ipfs/go-libp2p/p2p/crypto" peer "github.com/ipfs/go-libp2p/p2p/peer" mpool "gx/ipfs/QmRQhVisS8dmPbjBUthVkenn81pBxrx1GxE281csJhm2vL/go-msgio/mpool" manet "gx/ipfs/QmYVqhVfbK4BKvbW88Lhm26b3ud14sTBvcm1H7uWUx1Fkp/go-multiaddr-net" u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util" context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context" logging "gx/ipfs/Qmazh5oNUVsDZTs2g59rq8aYQqwpss8tcUWQzor5sCCEuH/go-log" ma "gx/ipfs/QmcobAGsCjYt5DXoq9et9L8yR8er7o7Cu3DTvpaq12jYSz/go-multiaddr" ) var log = logging.Logger("conn") // ReleaseBuffer puts the given byte array back into the buffer pool, // first verifying that it is the correct size func ReleaseBuffer(b []byte) { log.Debugf("Releasing buffer! (cap,size = %d, %d)", cap(b), len(b)) mpool.ByteSlicePool.Put(uint32(cap(b)), b) } // singleConn represents a single connection to another Peer (IPFS Node). type singleConn struct { local peer.ID remote peer.ID maconn manet.Conn event io.Closer } // newConn constructs a new connection func newSingleConn(ctx context.Context, local, remote peer.ID, maconn manet.Conn) (Conn, error) { ml := lgbl.Dial("conn", local, remote, maconn.LocalMultiaddr(), maconn.RemoteMultiaddr()) conn := &singleConn{ local: local, remote: remote, maconn: maconn, event: log.EventBegin(ctx, "connLifetime", ml), } log.Debugf("newSingleConn %p: %v to %v", conn, local, remote) return conn, nil } // close is the internal close function, called by ContextCloser.Close func (c *singleConn) Close() error { defer func() { if c.event != nil { c.event.Close() c.event = nil } }() // close underlying connection return c.maconn.Close() } // ID is an identifier unique to this connection. func (c *singleConn) ID() string { return ID(c) } func (c *singleConn) String() string { return String(c, "singleConn") } func (c *singleConn) LocalAddr() net.Addr { return c.maconn.LocalAddr() } func (c *singleConn) RemoteAddr() net.Addr { return c.maconn.RemoteAddr() } func (c *singleConn) LocalPrivateKey() ic.PrivKey { return nil } func (c *singleConn) RemotePublicKey() ic.PubKey { return nil } func (c *singleConn) SetDeadline(t time.Time) error { return c.maconn.SetDeadline(t) } func (c *singleConn) SetReadDeadline(t time.Time) error { return c.maconn.SetReadDeadline(t) } func (c *singleConn) SetWriteDeadline(t time.Time) error { return c.maconn.SetWriteDeadline(t) } // LocalMultiaddr is the Multiaddr on this side func (c *singleConn) LocalMultiaddr() ma.Multiaddr { return c.maconn.LocalMultiaddr() } // RemoteMultiaddr is the Multiaddr on the remote side func (c *singleConn) RemoteMultiaddr() ma.Multiaddr { return c.maconn.RemoteMultiaddr() } // LocalPeer is the Peer on this side func (c *singleConn) LocalPeer() peer.ID { return c.local } // RemotePeer is the Peer on the remote side func (c *singleConn) RemotePeer() peer.ID { return c.remote } // Read reads data, net.Conn style func (c *singleConn) Read(buf []byte) (int, error) { return c.maconn.Read(buf) } // Write writes data, net.Conn style func (c *singleConn) Write(buf []byte) (int, error) { return c.maconn.Write(buf) } // ID returns the ID of a given Conn. func ID(c Conn) string { l := fmt.Sprintf("%s/%s", c.LocalMultiaddr(), c.LocalPeer().Pretty()) r := fmt.Sprintf("%s/%s", c.RemoteMultiaddr(), c.RemotePeer().Pretty()) lh := u.Hash([]byte(l)) rh := u.Hash([]byte(r)) ch := u.XOR(lh, rh) return peer.ID(ch).Pretty() } // String returns the user-friendly String representation of a conn func String(c Conn, typ string) string { return fmt.Sprintf("%s (%s) <-- %s %p --> (%s) %s", c.LocalPeer(), c.LocalMultiaddr(), typ, c, c.RemoteMultiaddr(), c.RemotePeer()) }