-
Notifications
You must be signed in to change notification settings - Fork 104
/
SessionManager.go
153 lines (129 loc) · 3.87 KB
/
SessionManager.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package main
import (
"fmt"
"net"
"github.com/golang/glog"
)
type SessionManager struct {
config *Config // 配置
tcpListener net.Listener // TCP监听对象
sessionIDManager *SessionIDManager // 会话ID管理器
upSessionManagers map[string]*UpSessionManager // map[子账户名]矿池会话管理器
exitChannel chan bool // 退出信号
eventChannel chan interface{} // 事件循环
}
func NewSessionManager(config *Config) (manager *SessionManager) {
manager = new(SessionManager)
manager.config = config
manager.upSessionManagers = make(map[string]*UpSessionManager)
manager.exitChannel = make(chan bool, 1)
manager.eventChannel = make(chan interface{}, manager.config.Advanced.MessageQueueSize.SessionManager)
return
}
func (manager *SessionManager) Run() {
var err error
// 初始化会话管理器
manager.sessionIDManager, err = NewSessionIDManager(0xfffe)
if err != nil {
glog.Fatal("NewSessionIDManager failed: ", err)
return
}
// 启动事件循环
go manager.handleEvent()
// TCP监听
listenAddr := fmt.Sprintf("%s:%d", manager.config.AgentListenIp, manager.config.AgentListenPort)
glog.Info("startup is successful, listening: ", listenAddr)
manager.tcpListener, err = net.Listen("tcp", listenAddr)
if err != nil {
glog.Fatal("failed to listen on ", listenAddr, ": ", err)
return
}
// 为单用户模式连接矿池
if !manager.config.MultiUserMode {
manager.createUpSessionManager("")
}
for {
conn, err := manager.tcpListener.Accept()
if err != nil {
select {
case <-manager.exitChannel:
return
default:
glog.Warning("failed to accept miner connection: ", err.Error())
continue
}
}
go manager.RunDownSession(conn)
}
}
func (manager *SessionManager) Stop() {
// 退出TCP监听
manager.exitChannel <- true
manager.tcpListener.Close()
// 退出事件循环
manager.SendEvent(EventExit{})
}
func (manager *SessionManager) exit() {
// 要求所有连接退出
for _, up := range manager.upSessionManagers {
up.SendEvent(EventExit{})
}
}
func (manager *SessionManager) RunDownSession(conn net.Conn) {
// 产生 sessionID (Extranonce1)
sessionID, err := manager.sessionIDManager.AllocSessionID()
if err != nil {
glog.Warning("failed to allocate session id : ", err)
conn.Close()
return
}
down := manager.config.sessionFactory.NewDownSession(manager, conn, sessionID)
down.Init()
if down.Stat() != StatAuthorized {
// 认证失败,放弃连接
return
}
go down.Run()
manager.SendEvent(EventAddDownSession{down})
}
func (manager *SessionManager) SendEvent(event interface{}) {
manager.eventChannel <- event
}
func (manager *SessionManager) createUpSessionManager(subAccount string) (upManager *UpSessionManager) {
upManager = NewUpSessionManager(subAccount, manager.config, manager)
go upManager.Run()
manager.upSessionManagers[subAccount] = upManager
return
}
func (manager *SessionManager) addDownSession(e EventAddDownSession) {
upManager, ok := manager.upSessionManagers[e.Session.SubAccountName()]
if !ok {
upManager = manager.createUpSessionManager(e.Session.SubAccountName())
}
upManager.SendEvent(e)
}
func (manager *SessionManager) stopUpSessionManager(e EventStopUpSessionManager) {
child := manager.upSessionManagers[e.SubAccount]
if child == nil {
glog.Error("StopUpSessionManager: cannot find sub-account: ", e.SubAccount)
return
}
delete(manager.upSessionManagers, e.SubAccount)
child.SendEvent(EventExit{})
}
func (manager *SessionManager) handleEvent() {
for {
event := <-manager.eventChannel
switch e := event.(type) {
case EventAddDownSession:
manager.addDownSession(e)
case EventStopUpSessionManager:
manager.stopUpSessionManager(e)
case EventExit:
manager.exit()
return
default:
glog.Error("[SessionManager] unknown event: ", event)
}
}
}