Scalanet is an asynchronous, strongly typed, resource-managed networking library, written in Scala with support for a variety of network technologies. What does all that mean?
- Resource managed. Scalanet makes it as easy as possible to send and receive messages without having to open or close connections.
- Asynchronous. Scalanet is non-blocking. In this regard, it is like netty, however, unlike netty, Scalanet uses reactive programming idioms.
- Technology support. Out of the box, Scalanet supports TCP and UDP (with other internet and non-internet technologies to come) but through an abstraction called the Peer Group, allows for the addition of other transports or more complex p2p overlays (kademlia, ethereum, etc). The Peer Group provides a consistent interface whatever your networking approach.
It is well suited to peer-to-peer apps but supports client-server too.
As mentioned, the foundation of Scalanet is the notion of a Peer Group. From a practical standpoint, a peer group allows an application to use a variety of network technologies with a consistent interface. More abstractly, it defines
- an address space and
- a context in which communication can happen.
- TODO: quality of service
A Peer Group could be something like scalanet's UDPPeerGroup
where the addresses are IP:port combos and the set of
peers allowed to communicate is basically anybody on the IP network in question (the internet, an office network, etc).
Equally, a Peer Group could be something like an Ethereum network where addresses are public keys and the peers
are anybody who talks the RLPx protocol. Equally, a peer group could be an integration test with the address space {Alice, Bob, Charlie}
and the peers are all in the same JVM. Scalanet will not limit you in this regard.
Peer groups can implement arbitrary enrolment and encryption schemes, so are suitable for implementing secure messaging overlays. Typically, on the internet, limiting the context of communication (aka zoning) is performed by firewalls. The idea is so ubiquitous that it may not have struck you that this is a hack. Peer groups are designed to support more elegant solutions, generally using cryptography instead of firewall provisioning.
Here is a picture of the structure of the library for a few sample applications:
The easiest way to get started is to send and receive data over TCP, using the library just like netty. Have a look at the TCPPeerGroupSpec test case or the following code.
// import some peer group classes
import io.iohk.scalanet.peergroup._
// message sending can be controlled using either
// monix, cat-effect, cats EitherT or scala Futures
// depending on your taste.
import io.iohk.scalanet.peergroup.future._
import scala.concurrent.Future
import java.net.InetSocketAddress
import java.nio.ByteBuffer
val config = TCPPeerGroup.Config(new InetSocketAddress(???))
val tcp = TCPPeerGroup.createOrThrow(config)
// send a message
val messageF: Future[Unit] = tcp.sendMessage(new InetSocketAddress("example.com", 80), ByteBuffer.wrap("Hello!".getBytes))
// receive messages
tcp.messageStream.foreach((b: ByteBuffer) => ())
Two main branches are maintained: develop
and master
.
master
contains the latest stable version of the library.
develop
is the place you want to merge to if submitting PRs.
Scalanet is capable of building against Scala 2.12.10 and 2.13.4
This guide will be using version 2.13.4 build: mill csm[2.13.4]...
next to a multi-build mill __.
To build the codebase, we use mill. Assuming you have mill installed correctly, you can build and test the codebase with
mill csm[2.13.4].__.test -or-
mill __.test
A single test suite can be executed with the single
helper command, for example:
mill csm[2.13.4].scalanet.ut.single io.iohk.scalanet.crypto.SignatureVerificationSpec -or-
mill __.scalanet.ut.single io.iohk.scalanet.crypto.SignatureVerificationSpec
Have a look here for how to publish multiple modules.
The latest build on the develop
branch is always published to Sonatype according to the Circle CI config.
To use it in a downstream project add the snapshots to the resolvers, e.g. in build.sbt
:
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
To publish new release to maven central:
- Create release branch
realease/versionFromVersionFile
- Create a PR from release branch to
master
branch - Merge release PR to
master
, tag merge commit and push it - Create merge back PR from
master
todevelop
bumping appropriate version inversionFile/version
, e.g.mill versionFile.setNextVersion --bump minor
, to make sure no more updates are sent to the released snapshot
In order to keep the code format consistent, we use scalafmt.
The CI build will fail if code is not formatted, but the project contains a githook that means you do not have to think about. To set this up:
- Install coursier, the
coursier
command must work. ./install-scalafmt.sh
(might require sudo).cp pre-commit .git/hooks/pre-commit
You can also create issues in github at https://github.com/input-output-hk/scalanet/issues.