X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=client.go;h=b177a073844805b4942bf5b3acfef2b80f073887;hb=HEAD;hp=13795e5ecfced6d50d57502fab03ea9a885e2943;hpb=fae336d1a2d613fd00640ed6ccbb9eb386086c82;p=hydra-dragonfire.git diff --git a/client.go b/client.go index 13795e5..b177a07 100644 --- a/client.go +++ b/client.go @@ -2,8 +2,8 @@ package main import ( "errors" - "github.com/anon55555/mt" "github.com/dragonfireclient/hydra-dragonfire/convert" + "github.com/dragonfireclient/mt" "github.com/yuin/gopher-lua" "net" "sync" @@ -25,28 +25,43 @@ type Component interface { } type Client struct { - mu sync.Mutex address string state clientState conn mt.Peer - queue chan *mt.Pkt - wildcard bool - subscribed map[string]struct{} + muConn sync.Mutex + queue chan Event components map[string]Component + muComp sync.Mutex + table *lua.LTable userdata *lua.LUserData } var clientFuncs = map[string]lua.LGFunction{ - "address": l_client_address, - "state": l_client_state, - "connect": l_client_connect, - "poll": l_client_poll, - "close": l_client_close, - "enable": l_client_enable, - "subscribe": l_client_subscribe, - "unsubscribe": l_client_unsubscribe, - "wildcard": l_client_wildcard, - "send": l_client_send, + "address": l_client_address, + "state": l_client_state, + "connect": l_client_connect, + "poll": l_client_poll, + "close": l_client_close, + "enable": l_client_enable, + "send": l_client_send, +} + +type EventError struct { + err string +} + +func (evt EventError) handle(l *lua.LState, val lua.LValue) { + l.SetField(val, "type", lua.LString("error")) + l.SetField(val, "error", lua.LString(evt.err)) +} + +type EventDisconnect struct { + client *Client +} + +func (evt EventDisconnect) handle(l *lua.LState, val lua.LValue) { + l.SetField(val, "type", lua.LString("disconnect")) + evt.client.state = csDisconnected } func getClient(l *lua.LState) *Client { @@ -65,20 +80,9 @@ func getClients(l *lua.LState) []*Client { return clients } -func getStrings(l *lua.LState) []string { - n := l.GetTop() - - strs := make([]string, 0, n-1) - for i := 2; i <= n; i++ { - strs = append(strs, l.CheckString(i)) - } - - return strs -} - func (client *Client) closeConn() { - client.mu.Lock() - defer client.mu.Unlock() + client.muConn.Lock() + defer client.muConn.Unlock() if client.state == csConnected { client.conn.Close() @@ -90,9 +94,8 @@ func l_client(l *lua.LState) int { client.address = l.CheckString(1) client.state = csNew - client.wildcard = false - client.subscribed = map[string]struct{}{} client.components = map[string]Component{} + client.table = l.NewTable() client.userdata = l.NewUserData() client.userdata.Value = client l.SetMetatable(client.userdata, l.GetTypeMetatable("hydra.client")) @@ -105,7 +108,9 @@ func l_client_index(l *lua.LState) int { client := getClient(l) key := l.CheckString(2) - if fun, exists := clientFuncs[key]; exists { + if key == "data" { + l.Push(client.table) + } else if fun, exists := clientFuncs[key]; exists { l.Push(l.NewFunction(fun)) } else if component, exists := client.components[key]; exists { l.Push(component.push()) @@ -154,46 +159,39 @@ func l_client_connect(l *lua.LState) int { client.state = csConnected client.conn = mt.Connect(conn) - client.queue = make(chan *mt.Pkt, 1024) + client.queue = make(chan Event, 1024) go func() { for { pkt, err := client.conn.Recv() if err == nil { - client.mu.Lock() - for _, component := range client.components { - component.process(&pkt) - } - _, subscribed := client.subscribed[string(convert.PushPktType(&pkt))] - client.mu.Unlock() - - if subscribed || client.wildcard { - client.queue <- &pkt + client.muComp.Lock() + for _, comp := range client.components { + comp.process(&pkt) } + client.muComp.Unlock() } else if errors.Is(err, net.ErrClosed) { - close(client.queue) + client.queue <- EventDisconnect{client: client} return + } else { + client.queue <- EventError{err: err.Error()} } } }() - client.mu.Lock() - for _, component := range client.components { - component.connect() + client.muComp.Lock() + for _, comp := range client.components { + comp.connect() } - client.mu.Unlock() + client.muComp.Unlock() return 0 } func l_client_poll(l *lua.LState) int { client := getClient(l) - _, pkt, timeout := doPoll(l, []*Client{client}) - - l.Push(convert.PushPkt(l, pkt)) - l.Push(lua.LBool(timeout)) - return 2 + return doPoll(l, []*Client{client}) } func l_client_close(l *lua.LState) int { @@ -204,61 +202,40 @@ func l_client_close(l *lua.LState) int { func l_client_enable(l *lua.LState) int { client := getClient(l) - client.mu.Lock() - defer client.mu.Unlock() + n := l.GetTop() + + client.muComp.Lock() + defer client.muComp.Unlock() + + for i := 2; i <= n; i++ { + name := l.CheckString(i) - for _, compname := range getStrings(l) { - if component, exists := client.components[compname]; !exists { - switch compname { + if comp, exists := client.components[name]; !exists { + switch name { case "auth": - component = &Auth{} + comp = &CompAuth{} case "map": - component = &Map{} + comp = &CompMap{} + case "pkts": + comp = &CompPkts{} default: - panic("invalid component: " + compname) + panic("invalid component: " + name) } - client.components[compname] = component - component.create(client, l) + client.components[name] = comp + comp.create(client, l) } } return 0 } -func l_client_subscribe(l *lua.LState) int { - client := getClient(l) - client.mu.Lock() - defer client.mu.Unlock() - - for _, pkt := range getStrings(l) { - client.subscribed[pkt] = struct{}{} - } - - return 0 -} - -func l_client_unsubscribe(l *lua.LState) int { - client := getClient(l) - client.mu.Lock() - defer client.mu.Unlock() - - for _, pkt := range getStrings(l) { - delete(client.subscribed, pkt) - } - - return 0 -} - -func l_client_wildcard(l *lua.LState) int { - client := getClient(l) - client.wildcard = l.ToBool(2) - return 0 -} - func l_client_send(l *lua.LState) int { client := getClient(l) + client.muConn.Lock() + defer client.muConn.Unlock() + if client.state != csConnected { panic("not connected") } @@ -266,12 +243,9 @@ func l_client_send(l *lua.LState) int { cmd := convert.ReadCmd(l) doAck := l.ToBool(4) - client.mu.Lock() - defer client.mu.Unlock() - if client.state == csConnected { ack, err := client.conn.SendCmd(cmd) - if err != nil { + if err != nil && !errors.Is(err, net.ErrClosed) { panic(err) }