Skip to content

Instantly share code, notes, and snippets.

@volgar1x
Last active December 26, 2015 01:19
Show Gist options
  • Save volgar1x/7070084 to your computer and use it in GitHub Desktop.
Save volgar1x/7070084 to your computer and use it in GitHub Desktop.
package org.photon.login
import com.twitter.util.Future
trait NetworkSession {
type TFut = Future[this.type]
type NetworkService <: org.photon.login.NetworkService
def service: NetworkService
def write(o: Any): TFut
def flush(): TFut
def close(): TFut
def !(o: Any) = write(o) flatMap (_.flush())
}
trait NetworkService {
type TFut = Future[this.type]
type NetworkSession <: org.photon.login.NetworkSession
def boot(): TFut
def kill(): TFut
def connected: Seq[NetworkSession]
}
trait NetworkComponent {
val networkService: NetworkService
}
package org.photon.login
import io.netty.channel.{ChannelInitializer, ChannelFuture}
import com.twitter.util.{Future, Promise}
import io.netty.util.concurrent.GenericFutureListener
import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioServerSocketChannel
import java.net.InetSocketAddress
import scala.collection.mutable.ArrayBuffer
import io.netty.channel.socket.SocketChannel
import io.netty.util.AttributeKey
trait NetworkComponentImpl extends NetworkComponent { self: ConfigurationComponent =>
val networkConfig = config.atKey("photon.network.login")
val networkPort = config.getInt("port")
val networkService = new NetworkServiceImpl
implicit class ChannelFutureExtension(val fut: ChannelFuture) extends AnyVal {
def onCompleted(fn: ChannelFuture => Unit) = fut.addListener(new GenericFutureListener[Nothing] {
def operationComplete(future: Nothing) = fn(fut)
})
def toTw[T](fn: => T, promise: Promise[T] = Promise[T]): Promise[T] = {
onCompleted(_ => promise.setValue(fn))
promise
}
}
class NetworkServiceImpl extends NetworkService {
type NetworkSession = this.type
private val server = new ServerBootstrap()
.group(new NioEventLoopGroup, new NioEventLoopGroup)
.channel(classOf[NioServerSocketChannel])
.childHandler(new NetworkHandlerImpl)
.register().sync().channel
private[NetworkComponentImpl] val sessions = ArrayBuffer.empty[NetworkSession]
def connected = sessions.toSeq
def boot(): TFut = server.bind(new InetSocketAddress(networkPort)) toTw(this)
def kill(): TFut = server.close() toTw(this)
}
class NetworkHandlerImpl extends ChannelInitializer[SocketChannel] {
private val sessionAttr = new AttributeKey[NetworkSessionImpl]("photon.network.login.session")
def initChannel(ch: SocketChannel) {
val session = new NetworkSessionImpl(ch)
ch.attr(sessionAttr).set(session)
ch.pipeline
.addLast("protocol", ???)
.addLast("dispatcher", ???)
}
}
class NetworkSessionImpl(channel: SocketChannel) extends NetworkSession {
type NetworkService = networkService.type
private val closePromise = channel.closeFuture() toTw(this)
val closeFuture: TFut = closePromise
def service = networkService
def write(o: Any): TFut = channel.write(o) toTw(this)
def flush(): TFut = {
channel.flush()
Future(this)
}
def close(): TFut = {
channel.close()
closeFuture
}
override def !(o: Any): TFut = channel.writeAndFlush(o) toTw(this)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment