summaryrefslogtreecommitdiff
path: root/tests/test-event-serv.lua
blob: 83b9101597655b3fe0e3316efee0d6584fae323f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
local ev = require 'luxio.event'
local sio = require 'luxio.simple'

local clients = {}
local clientnr = 0

local listener = assert(sio.bind("localhost", 1234))

local function client_say(client, str)
   client.sendbuf[#client.sendbuf+1] = str
   ev.set_events(client.socket, nil, true)
end

local function client_send(client)
   if #client.sendbuf > 1 then
      client.sendbuf = { table.concat(client.sendbuf) ; _ = client.sendbuf._}
   end
   local written, err = client.socket:write(client.sendbuf[1] or "", client.sendbuf._)
   if written >= 0 then
      client.sendbuf._ = (client.sendbuf._ or 0) + written
   else
      print("Erm?", err)
      return false
   end

   if client.sendbuf._ and (client.sendbuf._ == #(client.sendbuf[1] or "")) then
      client.sendbuf = {}
   end

   if client.quitting and not client.sendbuf._ then
      ev.unregister_fd(client.socket)
      client.socket:close()
      clients[client.socket] = nil
      return false
   end

   return client.sendbuf._
end

local function do_line(client, line)
   local cmd = line:match("^%.(.-)\r?\n$")
   if cmd then
      if cmd == "quit" then
	 client:say("S: bye\n");
	 client.quitting = true
	 for sock, _client in pairs(clients) do
	    if client ~= _client then
	       _client:say(("S: Client %d is quitting\n"):format(client.nr))
	    end
	 end
	 return
      end
      client:say(("S: Unknown command: %s\n"):format(cmd))
   else
      for sock, _client in pairs(clients) do
	 _client:say(("%d: %s"):format(client.nr, line))
      end
   end
end

local function client_recv(client)
   local s, err = client.socket:read(1024)
   if (s == "") then
      -- client has closed
      for sock, _client in pairs(clients) do
	 if client ~= _client then
	    _client:say(("S: Client %d disconnected\n"):format(_client.nr))
	 end
      end
      clients[client.socket] = nil
      ev.unregister_fd(client.socket)
      client.socket:close()
      return
   end
   if (s == -1) then
      print("Erm?", err)
      return false
   end
   client.recvbuf[#client.recvbuf+1] = s
   if (s:match("\n")) then
      -- At least one newline, so process lines
      local full_s = table.concat(client.recvbuf)
      local line = full_s:match("^(.-\n)")
      full_s = full_s:match(".-\n(.*)$")
      while line do
	 do_line(client, line)
	 line = full_s:match("^(.-\n)")
	 full_s = full_s:match(".-\n(.*)$")
      end
      client.recvbuf = { full_s }
   end
   -- Always want to read more
   return true
end

function new_client()
   local newsock, addr = listener:accept()
   clientnr = clientnr + 1
   for sock, client in pairs(clients) do
      client:say(("S: New client %d from %s\n"):format(clientnr, addr))
   end
   clients[newsock] = {
      socket = newsock,
      sendbuf = {},
      recvbuf = {},
      say = client_say,
      nr = clientnr
   }
   ev.register_fd(newsock, clients[newsock], client_recv, client_send, client_err)
   ev.set_events(newsock, true)
   clients[newsock]:say("S: Welcome, say something\n")
   -- And tell us about more clients
   return true
end

ev.register_fd(listener, nil, new_client)
ev.set_events(listener, true)

function show_time()
   for sock, client in pairs(clients) do
      client:say(("S: The time, sponsored by luxio, is %s\n"):format(os.date()))
   end
   return os.time() + 30
end

ev.alarm(os.time() + 30, show_time)

ev.run()