Skip to content

Instantly share code, notes, and snippets.

@v6ak
Created April 19, 2011 11:20
Show Gist options
  • Select an option

  • Save v6ak/927156 to your computer and use it in GitHub Desktop.

Select an option

Save v6ak/927156 to your computer and use it in GitHub Desktop.
object SomeWSHandler extends WebSocketController{
def handle() {
handleWebSocket(
connectionHandler = {
_.send("Hello from server!")
},
binaryFrameHandler = { (frame, outbound) =>
outbound send "binary msg: " + frame.binaryData
},
textFrameHandler = { (frame, outbound) =>
outbound send "text msg: " + frame.textData
frame.textData match { // match commands
case ":close!" =>
outbound send "Bye!"
outbound.close()
case _ => // Other commands are silently ignored. It this line was missing, other commands would cause scala.MatchError
}
},
closeHandler = {
println("Goodbye.")
}
)
}
}
import play.mvc.Http.Request
import RequestScope.Variable
final class RequestScope (val request: Request){
private val store = {
val Key = "__RequestScope"
val args = request.args
if(args containsKey Key){
println("load RS")
(args get Key).asInstanceOf[collection.mutable.Map[Variable[_], Any]]
}else{
println("new RS")
val map = collection.mutable.Map[Variable[_], Any]()
args.put(Key, map)
map
}
}
def update[T](variable: Variable[T], value:T){
store(variable) = value
}
def remove[T](variable: Variable[T]): Option[T] = {
val removed = store remove variable
removed.asInstanceOf[Option[T]]
}
}
object RequestScope{
final class Variable[T]
def current = new RequestScope(Request.current())
}
import play.mvc.Http.WebSocketFrame
import play.mvc.Http.WebSocketClose
import play.mvc.Http.WebSocketEvent
import play.libs.F.Promise
import play.Invoker.Suspend
import play.mvc.Http.Request
import play.mvc.Http.Inbound
import play.mvc.Http.Outbound
object WebSocketUtil {
private final val FutureKey = new RequestScope.Variable[Promise[WebSocketEvent]]
def handleWebSocket(
connectionHandler: Outbound=>Unit,
binaryFrameHandler: (WebSocketFrame, Outbound)=>Unit,
textFrameHandler: (WebSocketFrame, Outbound)=>Unit,
closeHandler: =>Unit
){
val outbound = Outbound.current()
val inbound = Inbound.current()
val request = Request.current()
val rs = RequestScope.current
// handle new sockets
if (request isNew) {
connectionHandler(outbound)
}
// handle new messages in existing socket
val newPromise = rs.remove(FutureKey)
for(promise <- newPromise){
promise.get match{
case frame: WebSocketFrame => {
if(frame isBinary){
binaryFrameHandler(frame, outbound)
}else{
textFrameHandler(frame, outbound)
}
}
case _: WebSocketClose => closeHandler/*()*/
}
}
// start waiting for next message and suspend
if (inbound isOpen) {
val eventPromise = inbound.nextEvent
rs(FutureKey) = eventPromise
request.isNew = false
throw new Suspend(eventPromise)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment