mirror of
https://github.com/fluencelabs/scala-multiaddr
synced 2025-03-15 07:40:51 +00:00
Merge pull request #2 from fluencelabs/docs-and-refactoring
Docs, readme and refactoring
This commit is contained in:
commit
974c3bb8d2
19
.travis.yml
Normal file
19
.travis.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
sudo: required
|
||||||
|
|
||||||
|
language: scala
|
||||||
|
scala:
|
||||||
|
- 2.12.5
|
||||||
|
jdk:
|
||||||
|
- oraclejdk8
|
||||||
|
|
||||||
|
# These directories are cached to S3 at the end of the build
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.ivy2/cache
|
||||||
|
- $HOME/.sbt/boot
|
||||||
|
- $HOME/.sbt/launchers
|
||||||
|
|
||||||
|
before_cache:
|
||||||
|
# Tricks to avoid unnecessary cache updates
|
||||||
|
- find $HOME/.sbt -name "*.lock" | xargs rm
|
||||||
|
- find $HOME/.ivy2 -name "ivydata-*.properties" | xargs rm
|
75
README.md
75
README.md
@ -1 +1,74 @@
|
|||||||
# scala-multiaddr
|
# scala-multiaddr
|
||||||
|
|
||||||
|
> [multiaddr](https://github.com/multiformats/multiaddr) implementation in scala
|
||||||
|
|
||||||
|
Multiaddr is a standard way to represent addresses that:
|
||||||
|
|
||||||
|
- Support any standard network protocols.
|
||||||
|
- Self-describe (include protocols).
|
||||||
|
- Have a binary packed format.
|
||||||
|
- Have a nice string representation.
|
||||||
|
- Encapsulate well.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// Bintray repo is used so far. Migration to Maven Central is planned
|
||||||
|
resolvers += Resolver.bintrayRepo("fluencelabs", "releases")
|
||||||
|
|
||||||
|
libraryDependencies += "one.fluence" %%% "scala-multiaddr" % "0.0.1"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
#### Simple
|
||||||
|
|
||||||
|
```scala
|
||||||
|
import fluence.multiaddr.Multiaddr
|
||||||
|
|
||||||
|
val addr = "/ip4/127.0.0.1/tcp/1234"
|
||||||
|
// construct from a string (ErrorMessage return error message in ther parsing process)
|
||||||
|
val mEither: Either[ErrorMessage, Multiaddr] = Multiaddr(addr)
|
||||||
|
val m = mEither.right.get
|
||||||
|
|
||||||
|
// true
|
||||||
|
m.address == "/ip4/127.0.0.1/tcp/1234"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Protocols
|
||||||
|
|
||||||
|
```scala
|
||||||
|
// get the multiaddr protocol description objects
|
||||||
|
m.protoParameters
|
||||||
|
|
||||||
|
//List(
|
||||||
|
// StringProtoParameter(IP4, "127.0.0.1"),
|
||||||
|
// IntProtoParameter(TCP, 1234),
|
||||||
|
// EmptyProtoParameter(HTTP)
|
||||||
|
//)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### En/decapsulate
|
||||||
|
|
||||||
|
```scala
|
||||||
|
m.encapsulate(Multiaddr.unsafe("/sctp/5678"))
|
||||||
|
// Multiaddr(/ip4/127.0.0.1/tcp/1234/sctp/5678,List(StringProtoParameter(IP4,127.0.0.1), IntProtoParameter(TCP,1234), IntProtoParameter(SCTP,5678)))
|
||||||
|
m.decapsulate("/tcp") // up to + inc last occurrence of subaddr
|
||||||
|
// Multiaddr(/ip4/127.0.0.1,List(StringProtoParameter(IP4,127.0.0.1)))
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Tunneling
|
||||||
|
|
||||||
|
Multiaddr allows expressing tunnels very nicely.
|
||||||
|
|
||||||
|
```scala
|
||||||
|
val addr = Multiaddr.unsafe("/ip4/192.168.0.13/tcp/80")
|
||||||
|
val proxy = Multiaddr.unsafe("/ip4/10.20.30.40/tcp/443")
|
||||||
|
val addrOverProxy := proxy.encapsulate(m)
|
||||||
|
// /ip4/10.20.30.40/tcp/443/ip4/192.168.0.13/tcp/80
|
||||||
|
|
||||||
|
val proxyAgain = addrOverProxy.decapsulate(addr)
|
||||||
|
// /ip4/10.20.30.40/tcp/443
|
||||||
|
```
|
@ -17,37 +17,77 @@
|
|||||||
|
|
||||||
package fluence.multiaddr
|
package fluence.multiaddr
|
||||||
|
|
||||||
case class Multiaddr private(stringAddress: String, protocolsWithParameters: List[(Protocol, Option[String])]) {
|
import fluence.multiaddr.Multiaddr.ErrorMessage
|
||||||
override def toString: String = stringAddress
|
|
||||||
|
/**
|
||||||
|
* Multiaddress representation by string and list of protocols.
|
||||||
|
*/
|
||||||
|
case class Multiaddr private(address: String, protoParameters: List[ProtoParameter]) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a given Multiaddr, returning the resulting joined Multiaddr.
|
* Encapsulates a Multiaddr in another Multiaddr.
|
||||||
*
|
*
|
||||||
* @return new joined Multiaddr
|
* Spec about encapsulate:
|
||||||
|
* https://github.com/multiformats/multiaddr#encapsulation-based-on-context
|
||||||
|
*
|
||||||
|
* val m = Multiaddr("/ip4/127.0.0.1/tcp/1234")
|
||||||
|
* println(m.encapsulate(Multiaddr.unsafe("/sctp/5678")).right.get.address)
|
||||||
|
* "/ip4/127.0.0.1/tcp/1234/sctp/5678"
|
||||||
|
*
|
||||||
|
* @param addr Multiaddr to add into this Multiaddr
|
||||||
|
* @return new Multiaddr
|
||||||
*/
|
*/
|
||||||
def encapsulate(addr: Multiaddr): Either[Throwable, Multiaddr] = {
|
def encapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = Multiaddr(address + addr.address)
|
||||||
Multiaddr(stringAddress + addr.toString)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
|
* Decapsulates a Multiaddr from another Multiaddr.
|
||||||
|
*
|
||||||
|
* Spec about encapsulate and decapsulate:
|
||||||
|
* https://github.com/multiformats/multiaddr#encapsulation-based-on-context
|
||||||
|
*
|
||||||
|
* val m = Multiaddr("/ip4/127.0.0.1/tcp/1234/sctp/5678")
|
||||||
|
* println(m.decapsulate(Multiaddr.unsafe("/sctp/5678")).right.get.address)
|
||||||
|
* "/ip4/127.0.0.1/tcp/1234"
|
||||||
|
*
|
||||||
|
* @param addr Multiaddr to remove from this Multiaddr
|
||||||
*
|
*
|
||||||
* @return decapsulated Multiaddr
|
* @return decapsulated Multiaddr
|
||||||
*/
|
*/
|
||||||
def decapsulate(addr: Multiaddr): Either[Throwable, Multiaddr] = {
|
def decapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = decapsulate(addr.address)
|
||||||
val strAddr = addr.toString
|
|
||||||
val lastIndex = stringAddress.lastIndexOf(strAddr)
|
/**
|
||||||
|
* Possibility to decapsulate by part of address.
|
||||||
|
*
|
||||||
|
* Spec about encapsulate and decapsulate:
|
||||||
|
* https://github.com/multiformats/multiaddr#encapsulation-based-on-context
|
||||||
|
*
|
||||||
|
* val m = Multiaddr("/ip4/127.0.0.1/tcp/1234/sctp/5678")
|
||||||
|
* println(m.decapsulate("/sctp").right.get.address)
|
||||||
|
* "/ip4/127.0.0.1/tcp/1234"
|
||||||
|
*
|
||||||
|
* @param addr Multiaddr to remove from this Multiaddr
|
||||||
|
* @return decapsulated Multiaddr
|
||||||
|
*/
|
||||||
|
def decapsulate(addr: String): Either[ErrorMessage, Multiaddr] = {
|
||||||
|
val lastIndex = address.lastIndexOf(addr)
|
||||||
if (lastIndex < 0)
|
if (lastIndex < 0)
|
||||||
Right(this.copy())
|
Right(this)
|
||||||
else
|
else
|
||||||
Multiaddr(stringAddress.slice(0, lastIndex))
|
Multiaddr(address.slice(0, lastIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object Multiaddr {
|
object Multiaddr {
|
||||||
|
|
||||||
def apply(addr: String): Either[Throwable, Multiaddr] = MultiaddrParser.parse(addr).map {
|
type ErrorMessage = String
|
||||||
case (trimmed, protocols) => new Multiaddr(trimmed, protocols)
|
|
||||||
|
/**
|
||||||
|
* Parse and validate multiaddr string.
|
||||||
|
*/
|
||||||
|
def apply(addr: String): Either[ErrorMessage, Multiaddr] = MultiaddrParser.parse(addr).map {
|
||||||
|
case (trimmed, protoParameters) => new Multiaddr(trimmed, protoParameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def unsafe(addr: String): Multiaddr = apply(addr).right.get
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,22 @@
|
|||||||
|
|
||||||
package fluence.multiaddr
|
package fluence.multiaddr
|
||||||
|
|
||||||
|
import fluence.multiaddr.Multiaddr.ErrorMessage
|
||||||
|
import fluence.multiaddr.Protocol._
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
|
import scala.util.Try
|
||||||
|
|
||||||
private[multiaddr] object MultiaddrParser {
|
private[multiaddr] object MultiaddrParser {
|
||||||
|
|
||||||
def parse(addr: String): Either[Throwable, (String, List[(Protocol, Option[String])])] = {
|
def parse(addr: String): Either[ErrorMessage, (String, List[ProtoParameter])] = {
|
||||||
if (!addr.startsWith("/")) {
|
if (!addr.startsWith("/")) {
|
||||||
Left(new IllegalArgumentException("Address must be started with '/'."))
|
Left("Address must be started with '/'.")
|
||||||
} else {
|
} else {
|
||||||
val parts = addr.stripPrefix("/").stripSuffix("/").split("/").toList
|
val parts = addr.stripPrefix("/").stripSuffix("/").split("/").toList
|
||||||
|
|
||||||
if (parts.isEmpty) {
|
if (parts.isEmpty) {
|
||||||
Left(new IllegalArgumentException("Address must be non-empty."))
|
Left("Address must be non-empty.")
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
parsePrepared(parts).map(protocols ⇒ (addr.stripSuffix("/"), protocols))
|
parsePrepared(parts).map(protocols ⇒ (addr.stripSuffix("/"), protocols))
|
||||||
@ -36,31 +40,53 @@ private[multiaddr] object MultiaddrParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def parsePrepared(list: List[String]): Either[Throwable, List[(Protocol, Option[String])]] = {
|
private def parseParameter(parameter: String, protocol: Protocol): Either[String, ProtoParameter] = {
|
||||||
|
protocol match {
|
||||||
|
case TCP | UDP | SCTP ⇒
|
||||||
|
Try(parameter.toInt).toEither.right
|
||||||
|
.map(n ⇒ IntProtoParameter(protocol, n))
|
||||||
|
.left
|
||||||
|
.map(_ ⇒ s"Parameter for protocol $protocol must be a number.")
|
||||||
|
case _ ⇒
|
||||||
|
Right(StringProtoParameter(protocol, parameter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def parsePrepared(list: List[String]): Either[ErrorMessage, List[ProtoParameter]] = {
|
||||||
|
|
||||||
@tailrec
|
@tailrec
|
||||||
def parseRec(
|
def parseRec(
|
||||||
list: List[String],
|
list: List[String],
|
||||||
res: Either[Throwable, List[(Protocol, Option[String])]]
|
accum: Either[ErrorMessage, List[ProtoParameter]]
|
||||||
): Either[Throwable, List[(Protocol, Option[String])]] = {
|
): Either[ErrorMessage, List[ProtoParameter]] = {
|
||||||
list match {
|
list match {
|
||||||
case Nil ⇒ res
|
case Nil ⇒ accum
|
||||||
case head :: tail ⇒
|
case head :: tail ⇒
|
||||||
//todo per-protocol validation
|
//todo per-protocol validation
|
||||||
val protocolOp = Protocol.withNameOption(head)
|
val protocolOp = Protocol.withNameOption(head)
|
||||||
|
|
||||||
protocolOp match {
|
protocolOp match {
|
||||||
case None ⇒
|
case None ⇒
|
||||||
Left(new IllegalArgumentException(s"There is no protocol with name '$head'."))
|
Left(s"There is no protocol with name '$head'.")
|
||||||
case Some(protocol) ⇒
|
case Some(protocol) ⇒
|
||||||
protocol.size match {
|
protocol.size match {
|
||||||
case 0 ⇒ parseRec(tail, res.map(els ⇒ els :+ (protocol, None)))
|
case 0 ⇒
|
||||||
|
parseRec(tail, accum.map(els ⇒ els :+ EmptyProtoParameter(protocol)))
|
||||||
case _ ⇒
|
case _ ⇒
|
||||||
tail match {
|
tail match {
|
||||||
case Nil ⇒
|
case Nil ⇒
|
||||||
Left(new IllegalArgumentException(s"There is no parameter for protocol with name '$head'."))
|
Left(s"There is no parameter for protocol with name '$head'.")
|
||||||
case innerHead :: innerTail ⇒
|
case parameter :: innerTail ⇒
|
||||||
parseRec(innerTail, res.map(els ⇒ els :+ (protocol, Some(innerHead))))
|
val partialResult =
|
||||||
|
for {
|
||||||
|
elements ← accum
|
||||||
|
parameter ← parseParameter(parameter, protocol)
|
||||||
|
} yield elements :+ parameter
|
||||||
|
|
||||||
|
parseRec(
|
||||||
|
innerTail,
|
||||||
|
partialResult
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
core/src/main/scala/fluence/multiaddr/ProtoParameter.scala
Normal file
25
core/src/main/scala/fluence/multiaddr/ProtoParameter.scala
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package fluence.multiaddr
|
||||||
|
|
||||||
|
sealed trait ProtoParameter
|
||||||
|
|
||||||
|
//todo generalize parameters per protocol type
|
||||||
|
case class EmptyProtoParameter(protocol: Protocol) extends ProtoParameter
|
||||||
|
case class StringProtoParameter(protocol: Protocol, parameter: String) extends ProtoParameter
|
||||||
|
case class IntProtoParameter(protocol: Protocol, parameter: Int) extends ProtoParameter
|
@ -61,4 +61,7 @@ object Protocol extends Enum[Protocol] {
|
|||||||
case object P2PWebrtcStar extends Protocol(275, 0, "p2p-webrtc-star")
|
case object P2PWebrtcStar extends Protocol(275, 0, "p2p-webrtc-star")
|
||||||
case object P2PWebrtcDirect extends Protocol(276, 0, "p2p-webrtc-direct")
|
case object P2PWebrtcDirect extends Protocol(276, 0, "p2p-webrtc-direct")
|
||||||
case object P2PCircuit extends Protocol(290, 0, "p2p-circuit")
|
case object P2PCircuit extends Protocol(290, 0, "p2p-circuit")
|
||||||
|
|
||||||
|
//custom
|
||||||
|
case object GRPC extends Protocol(1001, 0, "grpc")
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package fluence.multiaddr
|
package fluence.multiaddr
|
||||||
|
|
||||||
|
import fluence.multiaddr.Multiaddr.ErrorMessage
|
||||||
import org.scalatest.{Matchers, WordSpec}
|
import org.scalatest.{Matchers, WordSpec}
|
||||||
|
|
||||||
class MultiaddrParseSpec extends WordSpec with Matchers {
|
class MultiaddrParseSpec extends WordSpec with Matchers {
|
||||||
@ -27,7 +28,7 @@ class MultiaddrParseSpec extends WordSpec with Matchers {
|
|||||||
"throw exception if there is no leading '/'" in {
|
"throw exception if there is no leading '/'" in {
|
||||||
val m = Multiaddr("ip4/127.0.0.1/tcp/123")
|
val m = Multiaddr("ip4/127.0.0.1/tcp/123")
|
||||||
m.isLeft shouldBe true
|
m.isLeft shouldBe true
|
||||||
m.left.get.getMessage shouldBe "Address must be started with '/'."
|
m.left.get shouldBe "Address must be started with '/'."
|
||||||
}
|
}
|
||||||
|
|
||||||
"parse correct multiaddresses right" in {
|
"parse correct multiaddresses right" in {
|
||||||
@ -35,59 +36,65 @@ class MultiaddrParseSpec extends WordSpec with Matchers {
|
|||||||
val m1Either = Multiaddr(addr1)
|
val m1Either = Multiaddr(addr1)
|
||||||
m1Either.isRight shouldBe true
|
m1Either.isRight shouldBe true
|
||||||
val m1 = m1Either.right.get
|
val m1 = m1Either.right.get
|
||||||
m1.protocolsWithParameters shouldBe List((IP4, Some("127.0.0.1")), (TCP, Some("123")))
|
|
||||||
m1.stringAddress shouldBe addr1
|
m1.protoParameters shouldBe List(StringProtoParameter(IP4, "127.0.0.1"), IntProtoParameter(TCP, 123))
|
||||||
|
m1.address shouldBe addr1
|
||||||
|
|
||||||
val addr2 = "/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/5000/https"
|
val addr2 = "/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/5000/https"
|
||||||
val m2Either = Multiaddr(addr2)
|
val m2Either = Multiaddr(addr2)
|
||||||
m2Either.isRight shouldBe true
|
m2Either.isRight shouldBe true
|
||||||
val m2 = m2Either.right.get
|
val m2 = m2Either.right.get
|
||||||
m2.protocolsWithParameters shouldBe List((IP6, Some("2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095")), (UDP, Some("5000")), (HTTPS, None))
|
|
||||||
m2.stringAddress shouldBe addr2
|
m2.protoParameters shouldBe List(
|
||||||
|
StringProtoParameter(IP6, "2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095"),
|
||||||
|
IntProtoParameter(UDP, 5000),
|
||||||
|
EmptyProtoParameter(HTTPS)
|
||||||
|
)
|
||||||
|
m2.address shouldBe addr2
|
||||||
}
|
}
|
||||||
|
|
||||||
"throw exception if there is no protocol" in {
|
"throw exception if there is no protocol" in {
|
||||||
val m = Multiaddr("/ip4/127.0.0.1/tc/123")
|
val m = Multiaddr("/ip4/127.0.0.1/tc/123")
|
||||||
m.isLeft shouldBe true
|
m.isLeft shouldBe true
|
||||||
m.left.get.getMessage shouldBe "There is no protocol with name 'tc'."
|
m.left.get shouldBe "There is no protocol with name 'tc'."
|
||||||
}
|
}
|
||||||
|
|
||||||
"throw exception if there is no parameter in protocol with parameter" in {
|
"throw exception if there is no parameter in protocol with parameter" in {
|
||||||
val m = Multiaddr("/ip4/127.0.0.1/tcp/")
|
val m = Multiaddr("/ip4/127.0.0.1/tcp/")
|
||||||
m.isLeft shouldBe true
|
m.isLeft shouldBe true
|
||||||
m.left.get.getMessage shouldBe "There is no parameter for protocol with name 'tcp'."
|
m.left.get shouldBe "There is no parameter for protocol with name 'tcp'."
|
||||||
}
|
}
|
||||||
|
|
||||||
"encapsulate and decapsulate correct multiaddr" in {
|
"encapsulate and decapsulate correct multiaddr" in {
|
||||||
val addr1 = "/ip4/127.0.0.1/tcp/123"
|
val addr1 = "/ip4/127.0.0.1/tcp/123"
|
||||||
val m1Either = Multiaddr(addr1)
|
val m1 = Multiaddr.unsafe(addr1)
|
||||||
m1Either.isRight shouldBe true
|
|
||||||
val m1 = m1Either.right.get
|
|
||||||
|
|
||||||
val addr2 = "/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/5000/https"
|
val addr2 = "/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/5000/https"
|
||||||
val m2Either = Multiaddr(addr2)
|
val m2 = Multiaddr.unsafe(addr2)
|
||||||
m2Either.isRight shouldBe true
|
|
||||||
val m2 = m2Either.right.get
|
|
||||||
|
|
||||||
val m3Either = m1.encapsulate(m2)
|
val m3Either = m1.encapsulate(m2)
|
||||||
m3Either.isRight shouldBe true
|
m3Either.isRight shouldBe true
|
||||||
val m3 = m3Either.right.get
|
val m3 = m3Either.right.get
|
||||||
|
|
||||||
val result = List((IP4, Some("127.0.0.1")), (TCP, Some("123")), (IP6, Some("2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095")), (UDP, Some("5000")), (HTTPS, None))
|
val result = List(
|
||||||
m3.protocolsWithParameters shouldBe result
|
StringProtoParameter(IP4, "127.0.0.1"),
|
||||||
m3.stringAddress shouldBe (addr1 + addr2)
|
IntProtoParameter(TCP, 123),
|
||||||
|
StringProtoParameter(IP6, "2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095"),
|
||||||
|
IntProtoParameter(UDP, 5000),
|
||||||
|
EmptyProtoParameter(HTTPS)
|
||||||
|
)
|
||||||
|
m3.protoParameters shouldBe result
|
||||||
|
m3.address shouldBe (addr1 + addr2)
|
||||||
|
|
||||||
m3.decapsulate(m2).right.get.stringAddress shouldBe addr1
|
m3.decapsulate(m2).right.get.address shouldBe addr1
|
||||||
}
|
}
|
||||||
|
|
||||||
"decapsulate correct multiaddr" in {
|
"decapsulate correct multiaddr" in {
|
||||||
val addr1 = "/ip4/127.0.0.1/udp/1234/sctp/5678"
|
val addr1 = "/ip4/127.0.0.1/udp/1234/sctp/5678"
|
||||||
val m1Either = Multiaddr(addr1)
|
val m1 = Multiaddr.unsafe(addr1)
|
||||||
m1Either.isRight shouldBe true
|
|
||||||
val m1 = m1Either.right.get
|
|
||||||
|
|
||||||
val decapsulated = m1.decapsulate(Multiaddr("/sctp/5678").right.get).right.get
|
val decapsulated = m1.decapsulate(Multiaddr("/sctp/5678").right.get).right.get
|
||||||
decapsulated.stringAddress shouldBe "/ip4/127.0.0.1/udp/1234"
|
decapsulated.address shouldBe "/ip4/127.0.0.1/udp/1234"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user