Akka Streams + TCP + TLS

670 views
Skip to first unread message

Pablo Milanese

unread,
Mar 11, 2017, 4:43:07 AM3/11/17
to Akka User List
Hello !.

I am actually looking for an example of the combinations of akka.streams.javadsl.Tcp and akka.streams.javadsl.TLS to create custom SSL/TLS enabled TCP servers and clients, but I couldn't find anything .. 

I think I have resolved the akka-streams-tcp, but I can't find how can I join the TLS API on the things that I have:

Here's my code for TCP connections using akka streams:



  private val connectionsSource: Source[IncomingConnection, Future[ServerBinding]] =
   
Tcp(context.system)
     
.bind(transportConfig.getHost, transportConfig.getPort)

  private val connectionsSink: Sink[IncomingConnection, Future[Done]] =
   
Sink.foreach(handleIncomingConnection)

  private val connectionsGraph: RunnableGraph[(Future[ServerBinding], Future[Done])] =
   
connectionsSource.toMat(connectionsSink)(Keep.both)

 
private val echo: Flow[ByteString, ByteString, NotUsed] =
    Flow[ByteString]
     
.via(Framing.delimiter(ByteString("\n"), maximumFrameLength = 256, allowTruncation = true))
     
.map(_.utf8String)
     
.map { text =>
       
log.info(s"Received message: $text")
       
ByteString(text + "!!!\n")
     
}

  def handleIncomingConnection(connection: IncomingConnection) {
   
log.info(s"New client at ${connection.remoteAddress}")
   
val flowGraph = connection.flow.joinMat(echo)(Keep.both)
    flowGraph
.run()
 
}

  private val mat = connectionsGraph.run()


And from the other side, the TLS part:

( I have a Function to take the SSLContext .. but is the only thing that I have ...)

def initSslContext(): SSLContext = {
 
val password = "password"

  val keyStore = KeyStore.getInstance(KeyStore.getDefaultType)
  keyStore
.load(getClass.getResourceAsStream("/keystore"), password.toCharArray)

 
val trustStore = KeyStore.getInstance(KeyStore.getDefaultType)
  trustStore
.load(getClass.getResourceAsStream("/truststore"), password.toCharArray)

 
val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
  keyManagerFactory
.init(keyStore, password.toCharArray)

 
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
  trustManagerFactory
.init(trustStore)

 
val context = SSLContext.getInstance("TLS")
  context.init(keyManagerFactory.getKeyManagers, trustManagerFactory.getTrustManagers, new SecureRandom)

 
for (protocol <- context.getSupportedSSLParameters.getProtocols) {
   
log.info(s"Supported protocol: $protocol")
 
}
  context
}


If anyone has an example, or something I would appreciate.

Thank You!
Pablo



Konrad Malawski

unread,
Mar 12, 2017, 6:23:31 AM3/12/17
to Akka User List

--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+unsubscribe@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Pablo Milanese

unread,
Mar 13, 2017, 5:26:49 PM3/13/17
to Akka User List
Thank you !

Actually, I am writing in scala 2.12, so it's more difficult than I thought (doing the conversion) .. but, when I finished I will publish the solution in scala.

Thanks again!
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.

Konrad Malawski

unread,
Mar 13, 2017, 5:28:30 PM3/13/17
to akka...@googlegroups.com, Pablo Milanese
However I made some mistake somewhere - would be awesome if you could help me notice where the mistake was :/

-- 
Konrad `ktoso` Malawski
Akka @ Lightbend

On 13 March 2017 at 22:26:51, Pablo Milanese (pablomi...@gmail.com) wrote:

Konrad Malawski

unread,
Mar 13, 2017, 5:28:42 PM3/13/17
to akka...@googlegroups.com, Pablo Milanese
(did the conversion in a rush)

Pablo Milanese

unread,
Mar 13, 2017, 9:13:57 PM3/13/17
to Akka User List, pablomi...@gmail.com
Hello Konrad,

Of course! No problem.
I will take a look to the code.

Thank you a lot !

Pablo Milanese

unread,
Mar 14, 2017, 3:23:15 PM3/14/17
to Akka User List, pablomi...@gmail.com
Hi Konrad,

At the first view, I think the could not fnid any error .. but please take into account that I am a scala beginner :)
Now,  I am trying to test the code, and I am having a problem whe I execute the line:

val sslConfig: AkkaSSLConfig = AkkaSSLConfig.get(system)

java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: scala/runtime/java8/JFunction1
at com.typesafe.sslconfig.util.ConfigLoader$.<init>(Configuration.scala:180)
at com.typesafe.sslconfig.util.ConfigLoader$.<clinit>(Configuration.scala)
at com.typesafe.sslconfig.ssl.SSLConfigParser.parse(Config.scala:495)
at com.typesafe.sslconfig.ssl.SSLConfigFactory$.parse(Config.scala:483)
at com.typesafe.sslconfig.akka.AkkaSSLConfig$.defaultSSLConfigSettings(AkkaSSLConfig.scala:34)
at com.typesafe.sslconfig.akka.AkkaSSLConfig$.createExtension(AkkaSSLConfig.scala:29)
at com.typesafe.sslconfig.akka.AkkaSSLConfig$.createExtension(AkkaSSLConfig.scala:19)
at akka.actor.ActorSystemImpl.registerExtension(ActorSystem.scala:899)
at akka.actor.ExtensionId.apply(Extension.scala:79)
at akka.actor.ExtensionId.apply$(Extension.scala:79)
at com.typesafe.sslconfig.akka.AkkaSSLConfig$.apply(AkkaSSLConfig.scala:24)
at com.typesafe.sslconfig.akka.AkkaSSLConfig$.apply(AkkaSSLConfig.scala:19)
at akka.actor.ExtensionId.get(Extension.scala:91)
at akka.actor.ExtensionId.get$(Extension.scala:91)
at com.typesafe.sslconfig.akka.AkkaSSLConfig$.get(AkkaSSLConfig.scala:23)
at com.paytrue.swakka.actors.channels.AbstractTcpServer.tlsStage(TcpServer.scala:88)
at com.paytrue.swakka.actors.channels.AbstractTcpServer.$anonfun$handler$1(TcpServer.scala:67)
at com.paytrue.swakka.actors.channels.AbstractTcpServer.$anonfun$handler$1$adapted(TcpServer.scala:64)
at akka.stream.impl.fusing.Map$$anon$8.onPush(Ops.scala:43)
at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:747)
at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:710)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:616)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:471)
at akka.stream.impl.fusing.GraphInterpreterShell.receive(ActorGraphInterpreter.scala:423)
at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:603)
at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:618)
at akka.actor.Actor.aroundReceive(Actor.scala:497)
at akka.actor.Actor.aroundReceive$(Actor.scala:495)
at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:529)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526)
at akka.actor.ActorCell.invoke(ActorCell.scala:495)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
at akka.dispatch.Mailbox.run(Mailbox.scala:224)
at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: java.lang.NoClassDefFoundError: scala/runtime/java8/JFunction1
... 38 more
Caused by: java.lang.ClassNotFoundException: scala.runtime.java8.JFunction1
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 38 more


Any idea ?
Thank you!

Rafał Krzewski

unread,
Mar 15, 2017, 6:41:08 AM3/15/17
to Akka User List, pablomi...@gmail.com
What JVM and Scala versions are you using? What are your project's dependency versions?
hint:
os shell> java -version
sbt> scalaVersion
sbt> libraryDependencies

cheers,
Rafał

Pablo Milanese

unread,
Mar 15, 2017, 9:42:12 AM3/15/17
to Akka User List, pablomi...@gmail.com
Buenas!

Java 1.8.0_121
Scala 2.12.1


I have no SBT .. We use Ivy in a local repository:

For example: <dependency org="com.typesafe.akka" name="akka-bundle" rev="2.4.17"/>

(All the next jars, are for scala 2.12.. for example: akka-stream_2.12)

Jars:

akka-actor.jar
akka-camel.jar
akka-protobuf.jar
akka-remote.jar
akka-slf4j.jar
akka-stream-testkit.jar
akka-stream.jar
akka-testkit.jar
config.jar
reactive-streams.jar
scala-java8-compat_2.12-0.8.0.jar
ssl-config-core_2.12.0-M3-0.2.1.jar
scala-compiler.jar
scala-library-sources.jar
scala-library.jar
scala-parser-combinators.jar
scala-reflect.jar
scala-xml.jar
scalap.jar


I think these are the most important.

Thank you !

Konrad Malawski

unread,
Mar 15, 2017, 9:50:38 AM3/15/17
to akka...@googlegroups.com, Pablo Milanese
Uhm... please use some serious dependency management tool.
You're missing ssl-config.

Please read the dependencies that the projects have, you simply are missing things from your dependencies.

-- 
Konrad `ktoso` Malawski
Akka @ Lightbend

--

Pablo Milanese

unread,
Mar 15, 2017, 10:25:42 AM3/15/17
to Akka User List, pablomi...@gmail.com
Totally agree .. However, maybe explaining my error better, can give me a clue.

I suspect that my mistake can be due to two things:

(1) Some conversion between scala - java8, given the new "compatibility" between scala 12 and java 8 ..
(2) The fact that scala 2.11 and 2.12 are not binary compatible


----------------------------
For (1):

See: "Scala and Java 8 interop is also improved for functional code, the methods that take functions can easily be called in both directions using lambda syntax. SAM types are treated uniformly - from type checking through code generation. In the class file is generated for lambda; invokedynamic is used instead.

( http://www.scala-lang.org/news/2.12.0 ) Maybe some issue still unknown? I am not sure about this point, but I mention it just in case

----------------------------

In this case, the line on which I am failing is:

TlsSupport.atop (tls)


"Previously, the defined bidiflows are:

Val tlsSupport: BidiFlow [ByteString, TLSProtocol.SslTlsOutbound, TLSProtocol.SslTlsInbound, ByteString, NotUsed] =
   
BidiFlow.fromFlows (
     
Flow [ByteString] .map (TLSProtocol.SendBytes (_)),
     
Flow [TLSProtocol.SslTlsInbound] .collect (pf))


Val tls: BidiFlow [TLSProtocol.SslTlsOutbound, ByteString, ByteString, TLSProtocol.SslTlsInbound, NotUsed] =
      TLS
(sslContext, firstSession, role)


"

Anyway, I'll look at the dependencies.
Thank you 

Pablo Milanese

unread,
Mar 15, 2017, 12:23:27 PM3/15/17
to Akka User List, pablomi...@gmail.com

I was able to resolve the issue ...
I had to change the version of .jar ssl-config-core_2.12.0-M3-0.2.1.jar
By ssl-config-core_2.12-0.2.2.jar
Thanks again
Reply all
Reply to author
Forward
0 new messages