1. firefly
  2. eldis

Commits

firefly  committed bd67e15

Added a first crude implementation of the 'remote module' API; a server part integrated
with the IRC bot as well as a standalone client part that connects to the server part.
The client is in a very unfinished stage, implemented just enough so that I have
something to test with.

  • Participants
  • Parent commits 6d85f51
  • Branches default

Comments (0)

Files changed (2)

File src/bot.coffee

View file
 vm      = require 'vm'
 net     = require 'net'
 
+bs      = require './buffered-socket'
 irc     = require './irc'
 {Shell} = require './shell'
 
 			console.log err.stack
 
 #### Setup remote module server #####################################
-#moduleServer = net.createServer (socket) ->
-#	socket.on 'data', (data) ->
-#		o
+uidCounter = 0
+eidCounter = 0
+executions = {}
 
+moduleServer = net.createServer (socket) ->
+	module =
+		uid    : (++uidCounter)
+		socket : new bs.BufferedSocket socket
+
+		toString: -> "[#{@uid}]"
+	
+	send = (obj) ->
+		module.socket.write JSON.stringify obj
+		module.socket.write "\r\n"
+
+	send {
+		type    : 'handshake'
+		version : '0.0.1'
+		uid     : module.uid
+	}
+
+	module.socket.on 'data', (line) ->
+		try
+			data = JSON.parse line
+			console.log "#{module}:#{data.type}:", data
+			
+			switch data.type
+				when 'handshake'
+					console.log "Module #{module} shook hands"
+					console.log "   Module metadata:", data.metadata
+
+				when 'register'
+					console.log "Module #{module} registered command #{data.name}."
+					shell.commands[data.name] = (exec, args...) ->
+						eid = (++eidCounter)
+						executions[eid] = exec
+
+						exec.stdin.on 'data', (data) ->
+							send {
+								type  : 'input'
+								eid   : eid
+								value : data
+							}
+
+						exec.stdin.on 'end', ->
+							send {
+								type : 'input-end'
+								eid  : eid
+							}
+
+						send {
+							type      : 'execute'
+							eid       : eid
+							command   : data.name
+							arguments : args
+						}
+
+					shell.commands[data.name].manualEnd = true
+
+				when 'output'
+					console.log "Module #{module} outputted #{data.value}."
+					executions[data.eid].output data.value
+
+				when 'output-end'
+					console.log "Module #{module} ended output!"
+					executions[data.eid].end()
+
+		catch err
+			console.log "Got invalid data from #{module}:"
+			console.log line
+			send {
+				type  : 'error'
+				value : "Your request couldn't be processed."
+			}
+
+moduleServer.listen 13450
+
+#### Create bot object ##############################################
 bot =
 	modules: []
 	shell: shell

File src/client/client.coffee

View file
+events = require 'events'
+
+bs     = require '../buffered-socket'
+
+conn = bs.createSocket
+	hostname : 'localhost'
+	port     : 13450
+
+send = (obj) ->
+	conn.write JSON.stringify obj
+	conn.write "\r\n"
+
+commands   = {}
+executions = {}
+
+conn.on 'data', (line) ->
+	data = JSON.parse line
+
+	switch data.type
+		when 'handshake'
+			console.log "Got handshake from server!"
+			send {
+				type    : 'handshake'
+				version : '0.0.1'
+			}
+
+			for name of commands
+				send {
+					type : 'register'
+					name : name
+				}
+
+		when 'execute'
+			console.log "Executing #{data.command}!"
+			ex = {}
+			ex.name      = data.command # FIXME: should be data.name?
+			ex.eid       = data.eid
+			ex.arguments = data.arguments
+
+			ex.stdin     = new events.EventEmitter
+			#ex.stdout    = new events.EventEmitter
+
+			ex.output = ->
+				for arg in arguments
+					send {
+						type  : 'output'
+						eid   : @eid
+						value : arg
+					}
+
+			ex.end = ->
+				ex.output.apply ex, arguments
+
+				send {
+					type : 'output-end'
+					eid  : @eid
+				}
+
+				@output = ->
+				@end    = ->
+
+			executions[ex.eid] = ex
+			commands[ex.name].apply ex, [ex].concat data.arguments
+
+		when 'input'
+			console.log "Got input for #{data.eid}"
+
+			ex = executions[data.eid]
+			ex.stdin.emit 'data', data.value
+
+		when 'input-end'
+			console.log "End of input for #{data.eid}"
+
+			ex = executions[data.eid]
+			ex.stdin.emit 'end'
+
+addCommand = (name, func) ->
+	commands[name] = func
+
+	send {
+		type : 'register'
+		name : name
+	}
+
+addCommand '_echo', (exec, args...) ->
+	exec.end.apply exec, args
+
+addCommand 'testCommand', (exec) ->
+	exec.end "Hello from a remote module!"
+
+addCommand '_cat', (exec) ->
+	exec.stdin.on 'data', (data) ->
+		exec.output data
+	
+	exec.stdin.on 'end', ->
+		exec.end()
+