fix some warts in IO

- remove TcpPipelineHandler’s type parameter
- remove not-accept() failure test (which is completely bogus)
- add comments explaining more about TcpPipelineHandler.Init
- remove the funny “manager” from the Server example
This commit is contained in:
Roland 2013-05-08 18:10:49 +02:00
parent f3f55d4972
commit 025a91ecc2
5 changed files with 30 additions and 36 deletions

View file

@ -483,28 +483,6 @@ class TcpConnectionSpec extends AkkaSpec("akka.io.tcp.register-timeout = 500ms")
}
}
// This test is disabled on windows, as the assumption that not calling accept on a server socket means that
// no TCP level connection has been established with the client does not hold.
// RK: I think Windows is no different than any other OS in this regard, there was just a sleep() missing.
"report failed connection attempt while not accepted" in new UnacceptedConnectionTest {
run {
ignoreIfWindows()
// close instead of accept
localServerChannel.close()
// must give the OS some time to send RST from server to client
Thread.sleep(100)
EventFilter[SocketException](occurrences = 1) intercept {
selector.send(connectionActor, ChannelConnectable)
userHandler.expectMsg(CommandFailed(Connect(serverAddress)))
}
verifyActorTermination(connectionActor)
}
}
val UnboundAddress = temporaryServerAddress()
"report failed connection attempt when target is unreachable" in

View file

@ -134,9 +134,9 @@ class TcpPipelineHandler[Ctx <: PipelineContext, Cmd, Evt](
* that are not Receive events will be passed directly to the handler registered for TcpPipelineHandler.
* @tparam Ctx
*/
class TcpReadWriteAdapter[Ctx <: PipelineContext] extends PipelineStage[Ctx, ByteString, Tcp.Command, ByteString, Tcp.Event] {
class TcpReadWriteAdapter extends PipelineStage[PipelineContext, ByteString, Tcp.Command, ByteString, Tcp.Event] {
override def apply(ctx: Ctx) = new PipePair[ByteString, Tcp.Command, ByteString, Tcp.Event] {
override def apply(ctx: PipelineContext) = new PipePair[ByteString, Tcp.Command, ByteString, Tcp.Event] {
override val commandPipeline = {
data: ByteString ctx.singleCommand(Tcp.Write(data))

View file

@ -26,11 +26,7 @@ class DemoActor extends Actor {
}
//#server
object Server {
def apply(manager: ActorRef) = Props(classOf[Server], manager)
}
class Server(manager: ActorRef) extends Actor {
class Server extends Actor {
import Tcp._
import context.system
@ -38,12 +34,17 @@ class Server(manager: ActorRef) extends Actor {
IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", 0))
def receive = {
case b @ Bound(localAddress) manager ! b
case b @ Bound(localAddress)
//#do-some-logging-or-setup
context.parent ! b
//#do-some-logging-or-setup
case CommandFailed(_: Bind) context stop self
case c @ Connected(remote, local)
manager ! c
//#server
context.parent ! c
//#server
val handler = context.actorOf(Props[SimplisticHandler])
val connection = sender
connection ! Register(handler)
@ -97,8 +98,15 @@ class Client(remote: InetSocketAddress, listener: ActorRef) extends Actor {
class IODocSpec extends AkkaSpec {
class Parent extends Actor {
context.actorOf(Props[Server], "server")
def receive = {
case msg testActor forward msg
}
}
"demonstrate connect" in {
val server = system.actorOf(Server(testActor), "server1")
val server = system.actorOf(Props(classOf[Parent], this), "parent")
val listen = expectMsgType[Tcp.Bound].localAddress
val client = system.actorOf(Client(listen, testActor), "client1")

View file

@ -427,6 +427,7 @@ Accepting connections
^^^^^^^^^^^^^^^^^^^^^
.. includecode:: code/docs/io/IODocSpec.scala#server
:exclude: do-some-logging-or-setup
To create a TCP server and listen for inbound connections, a :class:`Bind`
command has to be sent to the TCP manager. This will instruct the TCP manager

View file

@ -102,7 +102,7 @@ class SslTlsSupportSpec extends AkkaSpec {
val init = new TcpPipelineHandler.Init(
new StringByteStringAdapter >>
new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'), includeDelimiter = true) >>
new TcpReadWriteAdapter[HasLogging] >>
new TcpReadWriteAdapter >>
new SslTlsSupport(sslEngine(connected.remoteAddress, client = true))) {
override def makeContext(actorContext: ActorContext): HasLogging = new HasLogging {
override def getLogger = system.log
@ -148,9 +148,16 @@ class SslTlsSupportSpec extends AkkaSpec {
val init =
new TcpPipelineHandler.Init(
new StringByteStringAdapter >>
new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'), includeDelimiter = true) >>
new TcpReadWriteAdapter[HasLogging] >>
new DelimiterFraming(maxSize = 1024, delimiter = ByteString('\n'),
includeDelimiter = true) >>
new TcpReadWriteAdapter >>
new SslTlsSupport(sslEngine(remote, client = false))) {
/*
* When creating an `Init` the abstract `makeContext` method needs to be
* implemented. If the type of the returned context does not satisfy the
* requirements of all pipeline stages, then youll get an error that
* `makeContext` has an incompatible type.
*/
override def makeContext(actorContext: ActorContext): HasLogging =
new HasLogging {
override def getLogger = log