]> git.lizzy.rs Git - hydra-dragonfire.git/blob - poll.go
Initial commit
[hydra-dragonfire.git] / poll.go
1 package main
2
3 import (
4         "github.com/Shopify/go-lua"
5         "github.com/anon55555/mt"
6         "reflect"
7         "time"
8 )
9
10 func l_poll(l *lua.State) int {
11         clients := make([]*Client, 0)
12
13         lua.CheckType(l, 1, lua.TypeTable)
14         i := 1
15         for {
16                 l.RawGetInt(1, i)
17                 if l.IsNil(-1) {
18                         l.Pop(1)
19                         break
20                 }
21
22                 clients = append(clients, l.ToUserData(-1).(*Client))
23                 i++
24         }
25
26         var timeout time.Duration
27         hasTimeout := false
28         if l.IsNumber(3) {
29                 timeout = time.Duration(lua.CheckNumber(l, 3) * float64(time.Second))
30                 hasTimeout = true
31         }
32
33         for {
34                 cases := make([]reflect.SelectCase, 0, len(clients)+2)
35
36                 for _, client := range clients {
37                         if client.state != csConnected {
38                                 continue
39                         }
40
41                         cases = append(cases, reflect.SelectCase{
42                                 Dir:  reflect.SelectRecv,
43                                 Chan: reflect.ValueOf(client.queue),
44                         })
45                 }
46
47                 offset := len(cases)
48
49                 if offset < 1 {
50                         l.PushBoolean(false)
51                         return 1
52                 }
53
54                 cases = append(cases, reflect.SelectCase{
55                         Dir:  reflect.SelectRecv,
56                         Chan: reflect.ValueOf(signalChannel()),
57                 })
58
59                 if hasTimeout {
60                         cases = append(cases, reflect.SelectCase{
61                                 Dir:  reflect.SelectRecv,
62                                 Chan: reflect.ValueOf(time.After(timeout)),
63                         })
64                 }
65
66                 idx, value, ok := reflect.Select(cases)
67
68                 if idx >= offset {
69                         l.PushBoolean(true)
70                         return 1
71                 }
72
73                 client := clients[idx]
74
75                 var pkt *mt.Pkt = nil
76                 if ok {
77                         pkt = value.Interface().(*mt.Pkt)
78                 } else {
79                         client.state = csDisconnected
80                 }
81
82                 for _, handler := range client.handlers {
83                         handler.handle(pkt, l, idx+1)
84                 }
85         }
86
87         panic("impossible")
88         return 0
89 }