Go-libp2p 0.12.0

Libp2p 0.12.0 introduces a new BasicConnectionGater to filter inbound and outbound connections and makes a significant breaking change to the stream interfaces to remove some surprising behavior.

Connection Gater

The new BasicConnectionGater blocking connections to specific peers, IP addresses, and IP address subnets. These rules can optionally be persisted to a datastore.

To use this connection gater, pass it in to the libp2p constructor with the libp2p.ConnectionGater option.

Stream Interface Changes


This is release includes a significant BREAKING CHANGE to the stream interface.

Previously, Close() closed streams for writing, but left them open for reading. Unfortunately, this meant streams would not be garbage collected until either (a) an EOF had been read on the stream or (b) Reset had been called. While technically documented, this behavior was extraordinarily surprising and most libp2p applications end up misusing and leaking streams (leading to memory leaks).

In this release, Close now closes the stream for both reading and writing. Close will not wait for any form of acknowledgment. If acknowledgment is required, the caller must call CloseWrite (described below), then wait on the stream for a response (or an EOF), then call Close() to free the stream object.

To close the stream for writing only, the user should call CloseWrite(). Close write flushes any in-progress writes, then sends an EOF.

The user may now call CloseRead() to close the stream for reading only. CloseRead() will interrupt any in-progress reads with an error and prevent further reads from succeeding. At the protocol level, the behavior of CloseRead() is implementation defined.

  • Yamux and Mplex will throw away incoming data on a closed stream.
  • QUIC will return an error to the sender.

When done with a stream, the user must call either Close() or Reset() to discard the stream, even after calling CloseRead() and/or CloseWrite().

Upgrade Path

If you were using Close() as you would TCPConn.Close() or File.Close(), nothing needs to change. Previously this would have leaked resources but it will now work correctly.

If you were calling Close() intending to close the stream for writing but not for reading, call CloseWrite() instead.

If you were previously calling FullClose(stream), you should call stream.Close(). However, unlike FullClose(stream), stream.Close() will not wait for an EOF from the remote side.

If you need to close and wait to receive an EOF to confirm that all data was received, call stream.CloseWrite(), then call Read to wait for an EOF, then call stream.Close() to free the stream.

Removal of Stream Helpers


Previously, go-libp2p-core provided AwaitEOF and FullClose helpers to help work around the funky stream interfaces. These helper functions have been removed as any code using these helpers will likely need to be modified to work correctly with the new stream interfaces. Please see the upgrade path above for the stream interface changes.

Merged go-multiaddr and go-multiaddr-net

The github.com/multiformats/go-multiaddr-net package has been moved to github.com/multiformats/go-multiaddr/net. While we recommend updating imports, the types in go-multiaddr-net have been changed to type aliases to go-multiaddr/net so no user intervention is required.