Can you refresh or redisplay unflushed telnet input? - scala

I'm writing an old school text based telnet server that right now is a glorified chat room in Scala with Akka actor based IO. What is happening is that client the client will start to type something and then an event will happen and when it gets written, it wipes out anything that has already been typed. In the following example, Tom has started to type "say How are you?" but Fred arrives after he has only typed "say How ar" and this input is wiped out:
Tom > say How ar
Fred has arrived.
Tom >
Is there any way to get telnet to redisplay it's output buffer it hasn't flushed yet?
Here is the server:
class TcpServer(port: Int) extends Actor {
import TcpServer._
import context.system
val log = Logging(system, this)
var connectionNum: Int = 1
log.info(STARTING_SERVER)
IO(Tcp) ! Bind(self, new InetSocketAddress("0.0.0.0", port))
def receive = {
case b # Bound(localAddress) =>
log.info(PORT_BOUND, localAddress)
case c # Connected(remote, local) =>
log.info(CONNECTION_ACCEPTED)
context.actorOf(ConnectionHandler.connectionProps(sender()), s"conn$connectionNum")
connectionNum += 1
case CommandFailed(_: Bind) =>
log.error(BINDING_FAILED)
context stop self
}
}
Here is the ConnectionHandler, it's companion object, and the message case classes it uses:
class ConnectionHandler(connection: ActorRef) extends Actor {
import context._
val log = Logging(context.system, this)
connection ! Register(self)
var delegate = actorOf(Props[LoginHandler], "login")
watch(delegate)
def receive = {
case Received(data) =>
val dataString = data.utf8String.trim
log.info("Received data from connection: {}", dataString)
delegate ! Input(dataString)
case Output(content) =>
connection ! Write(ByteString(content))
case LoggedIn(user) =>
unwatch(delegate)
delegate ! PoisonPill
delegate = actorOf(UserHandler.connectionProps(user), user.name.toLowerCase)
watch(delegate)
case Terminated =>
log.warning("User delegate died unexpectedly.")
connection ! ConfirmedClose
case CloseConnection(message) =>
connection ! Write(ByteString(message + "\n"))
connection ! ConfirmedClose
log.info("User quit.")
case ConfirmedClosed =>
log.info("Connection closed.")
stop(self)
case PeerClosed =>
log.info("Connection closed by client.")
stop(self)
}
}
object ConnectionHandler {
def connectionProps(connection: ActorRef): Props = Props(new ConnectionHandler(connection))
}
case class Input(input: String)
case class Output(output: String)
case class LoggedIn(user: User)
case class CloseConnection(message: String)

Okay, after finally phrasing my google queries correctly, I found what I needed here:
Force telnet client into character mode
The basic solution is that I forced the client into character at a time mode and echo'd back the characters I care about. The bonus to this is that now I can do tab completion, command history, and make the passwords not show up.
Here is the relevant code snippet:
val controlString = ByteString('\u00ff','\u00fb','\u0001','\u00ff','\u00fb','\u0003','\u00ff','\u00fc','\u0022')
connection ! Write(controlString)

Related

I want to send second message to Actor as new Message

I have two actors for example, sender:
class ActorSender(actroReciever: ActorRef) extends Actor{
implicit val timeout = Timeout(100, TimeUnit.SECONDS)
override def receive: Receive = {
case "RUN" => {
val resp = Await.result(actroReciever ? "Msg", 100.seconds)
println("receive response " + resp)
};
case str:String => println(str)
case _ => println("Error type msg")
}
}
reciever:
class ActroReciever extends Actor{
override def receive: Receive = {
case str:String => {
val snd = sender()
snd ! "MessageFirst"
snd ! "MessageSecond"
}
}
}
And class for starting:
object Tester extends App {
val system = ActorSystem("system")
val receiver = system.actorOf(Props[ActroReciever](new ActroReciever()), "receiver")
val sender = system.actorOf(Props[ActorSender](new ActorSender(receiver)), "sender")
sender ! "RUN"
}
I want to send two messages to sender(), first as reply for "ask", second msg as "new Message", which ActorSender execute as "matching", how I can do it? Thanks
First, you know you should not use Await, right?
Second, ask (?) is not meant to be used within actors. ask creates a temporary actor which can only receive a single message. It is not your ActorSender receiving the answer, but the temporary actor created by ask. That's why you have the feeling you can only send 1 answer.
You are doing this wrong, you should simply send your message using actroReciever ! "Msg". No need to change anything on your ActroReciever.

Akka scala-io ask and wait for respone

I'm using scala-io in my akka actors, in my case I need to send request and wait for response, in official docs (http://doc.akka.io/docs/akka/snapshot/scala/io-tcp.html) I can see the answer is asynchronous.
How can I wait for response, can I use somehow ? (ask) pattern
class SocketClient(remoteAddress: InetSocketAddress, listener: ActorRef) extends Actor {
import Tcp._
import context.system
IO(Tcp) ! Connect(remoteAddress)
def receive = {
case CommandFailed(_: Connect) =>
listener ! ConnectFailure
context stop self
case Connected(remote, local) =>
listener ! ConnectSuccess
val connection = sender
connection ! Register(self)
context become {
case data: ByteString =>
connection ! Write(data)
case CommandFailed(w: Write) =>
Logger.error(s"Error during writing")
case Received(data) =>
listener ! data
case Disconnect =>
connection ! Close
case _: ConnectionClosed =>
Logger.error(s"Connection has been closed ${remoteAddress.getAddress}")
context stop self
}
}
}
Can I use something like:
connection ? Write(data)
Yes, but you should take in account the fact that ask-pattern allows you to receive only first reply from actor.
In your case it's connection, which may reply some additional or even unrelated objects (it depends on back-pressure/acknowledgement mode you choose. For example, if you use Write - you may receive the written (to the socket) object's acknowledge instead of response.
You can avoid it by:
using NoAck as an AckEvent (see http://doc.akka.io/docs/akka/snapshot/scala/io-tcp.html, Throttling Reads and Writes section).
use atomic requests/replies (no multi-part)
use one actor per protocol (per each "ping-pong" sequence)
In other words, ask pattern just creates own internal actor per message and make it a sender, so all replies (for this particular message) are going to this micro-actor. When it receives first reply - future (returned by ?) becomes completed - and internal actor destroyed (so other replies will be ignored).
Also, connection automatically replies to registered (by Register message) listener instead of sender - so you should create mediate actor:
class Asker(connection: ActorRef) extends Actor {
import Tcp._
connection ! Register(self);
def receive = {
case x =>
val parent = sender()
connection ! x
context become {case x => parent ! x; context.unbecome()}
}
}
trait TcpAskSupport {
self: Actor =>
def asker(connection: ActorRef) =
context.child(connection.path.name + "Asker")
.getOrElse(system.actorOf(Props(classOf[Asker], connection),
connection.path.name + "Asker"))
}
Usage example:
class Client extends Actor with TcpAskSupport {
import Tcp._
import context.system
IO(Tcp) ! Connect(new InetSocketAddress("61.91.16.168", 80))
implicit val timeout = Timeout(new FiniteDuration(5, SECONDS))
def receive = {
case CommandFailed(_: Connect) =>
println("connect failed")
context stop self
case c # Connected(remote, local) =>
println("Connected" + c)
val connection = sender()
asker(connection) ? Write(ByteString("GET /\n", "UTF-8"), NoAck) onComplete {
case x => println("Response" + x)
}
case x => println("[ERROR] Received" + x)
}
}

Can akka actors pass messages back to the client a scenerio like this

I have some pseudo code that I was hoping some with experience could tell me if akka would be used like this, and if not, how I could re-work my design to fit into akka's best practice.
class Article(val words: Word) {
val tokens: List[Word]
}
class Word(..) {
def parseWords() {
val word = .....
tokenActor ! word // this is suppose to add the word to the tokens List
}
}
So the pattern is basically I will create a Article which will have a word object. Then the word object will start doing some parsing, and at times it needs to pass data back to the Article object to "share memory by communicating" like in Go's coroutines.
I know Scala had an inbox type system but not going forward we are suppose to use Akka, but I find that Akka has poor documention when it comes to examples etc.
Can someone tell me if the above design is possible? And could I use this inside of a play application?
A sample for you.
Here Tokenizer takes seq of items to parse and gives them out to Parser to do the parsing.
Parser than reports back results to the Tokenizer.
import akka.actor._
import com.typesafe.config.ConfigFactory
case object Go
case object Done
case object GoAway
class Tokenizer(items: Seq[String]) extends Actor {
val kid = context.actorOf(Props[Parser])
var tokens: List[String] = List.empty
override def receive: akka.actor.Actor.Receive = {
case Go => // start process
items.foreach(kid ! _)
kid ! GoAway
case Done => // report results
println(tokens.mkString(":"))
self ! PoisonPill // shut down
case s: String => // data from kid
tokens = s :: tokens
}
}
class Parser extends Actor {
override def receive: Receive = {
case GoAway =>
sender ! Done
self ! PoisonPill // or context.stop(self)
case s: String =>
s.split("\\.").foreach(sender ! _)
}
}
object G extends App {
val config = ConfigFactory.parseString("" +
"akka.loglevel=DEBUG\n" +
"akka.debug.lifecycle=on\n" +
"akka.debug.receive=on\n" +
"akka.debug.event-stream=on\n" +
"akka.debug.unhandled=on\n" +
""
)
val system = ActorSystem("mine", config)
val doer = system.actorOf(Props(new Tokenizer(Seq("191.168.1.1", "192.168.1.2"))))
doer ! Go
system.shutdown()
system.awaitTermination()
}

futures used with actors in Akka

I want to create a server/client system using akka remoting. At first I create a simple remote Server. (I wrote the code below for testing purposes and to clarify my concepts so it really doesn't do much.)
I want my client to send a username and a password to the server which the server can verify and reply back. At first I create a client actor. From my client object I send this actor the username and password (I use future here). The client actor then uses another future to send this username and password to the server.
The server in my code gets the username and password and prints it out. The problem is I dont get anything back from the server. Since I used a future to send the information to the server, it should reply back with a result. This is where I think I have a conceptual problem. Going through the akka documentation did not clarify this. But I an sure I am messing up something very basic. The server code is:
EDITED after suggestions from TrustNoOne and cmbaxter.
package server
import collection.mutable
import akka.actor._
import com.typesafe.config.ConfigFactory
import shared._
import shared.CaseClass._
object Server extends App {
val system = ActorSystem("ServerSystem",
ConfigFactory.parseString("""
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
netty.tcp {
hostname = 127.0.0.1
port = 5555
}
}
}
"""))
system.actorOf(Props[ServerActorClass], "ServerActor")
}
class ServerActorClass extends Actor {
def receive = {
case userPass: UserPass => {
sender ! verified()
println(userPass)
}
case testMsg: String => println("Got a msg"+ testMsg)
}
}
The client code is:
package client
import ...
object Client extends App {
val system = ActorSystem("ClientSystem",
ConfigFactory.parseString("""
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
netty.tcp {
hostname = 127.0.0.1
port = 0
}
}
}
"""))
val clientActor = system.actorOf(Props[ClientActor], name = "ClientActor") //the local actor
implicit val timout = Timeout(50 seconds)
val f = ask(clientActor, UserPass("a","b"))
f.onSuccess {
case GO => println("Got something back from Client actor") //Still doesn't happen!
}
}
class ClientActor extends Actor {
// create the remote actor
val server = context.actorFor("akka.tcp://ServerSystem#127.0.0.1:5555/user/ServerActor")
implicit val timout = Timeout(1 seconds)
def receive = {
case a: String => println("back" + a)
case a: UserPass => {
val f: Future[Any] = (server ? a)
f.onSuccess {
case response: verified => {
println("Got something back from server") //Does happen now!
val asker = sender()
asker ! GO()
}
case response: verificationFailed => {
val asker = sender()
asker ! NO()
}
}
}
}
}
Case classes that are shared by both the client and the server:
package shared
case object CaseClass {
case class verified //Server msg to acknowledge user and pass successful verification
case class verificationFailed //Server msg saying user pass verification failed
case class GO
case class NO
case class UserPass(user:String, pass:String)
I want to know what I am doing wrong. If someone could explain rather than just point out the problem, it would be great, since I am looking to learn.
In the server actor, you're sending the response like this:
sender ! CaseClass.verified
You are actually sending the "verified" class companion object back to the client. You should either make the verified class a case object or send back to the client a verified instance:
sender ! CaseClass.verified()
You are doing other (unrelated) errors:
closing over sender in the future callback (make a local alias val replyTo = sender())
not respecting naming conventions (capital letters, etc)
using deprecated "actorFor". you have to use actorSelection (see akka docs)
You're exiting without waiting for a response.
implicit val timout = Timeout(50 seconds)
val f: Future[Any] = clientActor ? UserPass("s","a")
f.onSuccess {
case GO => println("Got something back from Client actor") //Doesnt happen!
}
That sets up a handler for a callback, but then your program just exists.
Minimally, you could scala.concurrent.Await.result(f)

How do I disconnect a Scala Remote Actor?

In scala it is very easy to make a connection to a remote actor, but the documentation does not tell me anything about disconnecting. Simply throwing away the reference does not work, because remote actors are actors, so these won't be collected until stopped. So how do I disconnect?
This does not Terminate after exit:
import actors.{DaemonActor,remote}
import remote.{RemoteActor,Node}
object SimpleClient{
val messageHandler = new DaemonActor{
def act{
loop{
react{
case message:String =>
println("got message: " + message)
case _ =>
}
}
}
start
}
def main(args:Array[String]){
val server = RemoteActor.select(Node("localhost",9999),'server)
server.send('Connect,messageHandler)
var exit = false
while(!exit){
val message = Console.readLine
if(message == "exit" || message == "quit") {
exit = true
server ! 'Disconnect
}
else
server ! message
}
}
}
This is the Server:
import actors.{Actor,OutputChannel}
import actors.remote.RemoteActor
object Server extends Actor{
val clients = new collection.mutable.HashSet[OutputChannel[Any]]
def act{
loop{
react{
case 'Connect =>
clients += sender
case 'Disconnect =>
clients -= sender
case message:String =>
for(client <- clients)
client ! message
}
}
}
def main(args:Array[String]){
start
RemoteActor.alive(9999)
RemoteActor.register('server,this)
}
}
[Disclaimer: I'm PO of Akka]
May I suggest taking a look at Akka, which was built with Remote Actors in mind from day 1?
www.akka.io
Your question is not really clear enough about what problem you think you are experiencing. Actors do not "connect" to each other (like a socket). You send an actor a message because you have a reference to it (or a proxy, in the case of remote actors).
Having such a reference does not prevent the actor (either actor) from shutting down. If there are no longer any references to an actor and it is not running, there is nothing to stop it being garbage-collected
The Reactor trait defines protected[actors] def exit(): Nothing which the actor can call itself upon reception of a message telling it to do so.
sealed trait Msg
case object Apoptosis extends Msg
// ... more messages
class RRActor extends Reactor[Msg] {
def act = loop {
react {
// ... Whatever messages the actor handles
case Apoptosis => this.exit
}
}
}
Edit: I have not tested this ever with remote actors.
Here's a working version of your source, with pertinent changes commented inline:
import actors.{DaemonActor,remote}
import remote.{RemoteActor,Node}
case class Send(message: String)
case object Disconnect
object SimpleClient{
val messageHandler = new DaemonActor{
def act{
// keep the reference to the proxy inside the client-side actor
val server = RemoteActor.select(Node("localhost",9999),'server)
server ! 'Connect
loop{
react{
case message:String =>
println("got message: " + message)
case Send(message) => server ! message
case Disconnect => {
// disconnect and exit the client-side actor
server ! 'Disconnect //'
exit
}
case _ =>
}
}
}
start
}
def main(args:Array[String]){
var exit = false
while(!exit){
val message = Console.readLine
if(message == "exit" || message == "quit") {
exit = true
// tell the client-side actor to exit
messageHandler ! Disconnect
} else {
messageHandler ! Send(message)
}
}
}
}