forked from padeir0/gna
-
Notifications
You must be signed in to change notification settings - Fork 0
/
listener.go
128 lines (113 loc) · 2.32 KB
/
listener.go
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
package gna
import (
"encoding/gob"
"fmt"
"log"
"net"
"os"
"os/signal"
"sync"
"time"
)
var (
stdReadTimeout = 15 * time.Second
stdWriteTimeout = 15 * time.Second
stdTPS = 20 // ticks per second
)
/*SetReadTimeout sets the default read timeout for
every player*/
func SetReadTimeout(d time.Duration) {
stdReadTimeout = d
}
/*SetWriteTimeout sets the default write timeout for
every player*/
func SetWriteTimeout(d time.Duration) {
stdWriteTimeout = d
}
/*SetMaxTPS sets the default tickrate of instances*/
func SetMaxTPS(tps int) {
stdTPS = tps
}
/*Register is a convenience method that wraps
gob.Register() underhood*/
func Register(dt ...interface{}) {
for i := range dt {
gob.Register(dt[i])
}
}
/*RunServer starts the listener and the instance*/
func RunServer(addr string, ins Instance) error {
l := listener{
mainIns: ins,
}
return l.start(addr)
}
type listener struct {
mainIns Instance
idGen id
}
/*start setups the server and starts it, it starts the listener and instance in
different goroutines*/
func (sr *listener) start(addr string) error {
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
listener, err := net.ListenTCP("tcp", tcpAddr)
if err != nil {
return err
}
defer listener.Close()
chConns := make(chan *net.TCPConn)
go connRecv(listener, chConns)
go RunInstance(sr.mainIns)
fmt.Println("listening on: ", addr)
return sr.listen(chConns)
}
/*listen is responsible for the auth of each Player and
to safely terminate the mainInstance*/
func (sr *listener) listen(conns chan *net.TCPConn) error {
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
for {
select {
case conn := <-conns:
p := newPlayer(sr.idGen.newID(), conn)
go func() {
sr.mainIns.Auth(p)
if p.shouldStart {
if p.grp == nil {
p.SetInstance(sr.mainIns)
}
p.start()
}
}()
case <-sig:
fmt.Println("Stopping server...")
sr.mainIns.Terminate()
return nil
}
}
}
func connRecv(l *net.TCPListener, out chan *net.TCPConn) {
for {
conn, err := l.AcceptTCP()
if err != nil {
log.Print(err) //TODO remove logging
if _, ok := err.(*net.OpError); ok {
return
}
continue
}
out <- conn
}
}
type id struct {
i uint64
mu sync.Mutex
}
func (x *id) newID() uint64 {
var out uint64
x.mu.Lock()
out = x.i
x.i++
x.mu.Unlock()
return out
}