forked from xtaci/gonet
/
main.go
134 lines (112 loc) · 2.49 KB
/
main.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
129
130
131
132
133
134
package main
import (
"encoding/binary"
"io"
"net"
"net/http"
_ "net/http/pprof"
"os"
"strconv"
"strings"
"time"
)
import (
"cfg"
. "helper"
"misc/geoip"
. "types"
)
func main() {
defer func() {
if x := recover(); x != nil {
ERR("caught panic in main()", x)
}
}()
go func() {
INFO(http.ListenAndServe("0.0.0.0:6060", nil))
}()
// start basic services
startup()
// Listen
config := cfg.Get()
service := ":8080"
if config["service"] != "" {
service = config["service"]
}
INFO("Service:", service)
tcpAddr, err := net.ResolveTCPAddr("tcp4", service)
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
INFO("Game Server OK.")
for {
conn, err := listener.AcceptTCP()
if err != nil {
WARN("accept failed", err)
continue
}
go handleClient(conn)
}
}
//----------------------------------------------- start a goroutine when a new connection is accepted
func handleClient(conn *net.TCPConn) {
defer func() {
if x := recover(); x != nil {
ERR("caught panic in handleClient", x)
}
}()
// input buffer
config := cfg.Get()
inqueue_size, err := strconv.Atoi(config["inqueue_size"])
if err != nil {
inqueue_size = DEFAULT_INQUEUE_SIZE
WARN("cannot parse inqueue_size from config", err, "using default:", inqueue_size)
}
// init
header := make([]byte, 2)
in := make(chan []byte, inqueue_size)
bufctrl := make(chan bool)
defer func() {
close(bufctrl)
close(in)
}()
// create new session
var sess Session
sess.IP = net.ParseIP(strings.Split(conn.RemoteAddr().String(), ":")[0])
NOTICE("new connection from:", sess.IP, "country:", geoip.Query(sess.IP))
// create write buffer
out := NewBuffer(&sess, conn, bufctrl)
go out.Start()
// start agent!!
go StartAgent(&sess, in, out)
for {
// header
conn.SetReadDeadline(time.Now().Add(TCP_TIMEOUT * time.Second))
n, err := io.ReadFull(conn, header)
if err != nil {
WARN("error receiving header, bytes:", n, "reason:", err)
break
}
// data
size := binary.BigEndian.Uint16(header)
data := make([]byte, size)
n, err = io.ReadFull(conn, data)
if err != nil {
WARN("error receiving msg, bytes:", n, "reason:", err)
break
}
// NOTICE: slice is passed by reference; don't re-use a single buffer.
select {
case in <- data:
case <-time.After(MAX_DELAY_IN * time.Second):
WARN("server busy or agent closed, session flag:", sess.Flag)
return
}
}
}
func checkError(err error) {
if err != nil {
ERR("Fatal error:", err)
os.Exit(-1)
}
}