|
|
@ -15,6 +15,7 @@ import ( |
|
|
|
|
|
|
|
|
|
|
|
"../pool" |
|
|
|
"../pool" |
|
|
|
"../rpc" |
|
|
|
"../rpc" |
|
|
|
|
|
|
|
"../util" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
type StratumServer struct { |
|
|
|
type StratumServer struct { |
|
|
@ -30,6 +31,8 @@ type StratumServer struct { |
|
|
|
luckWindow int64 |
|
|
|
luckWindow int64 |
|
|
|
luckLargeWindow int64 |
|
|
|
luckLargeWindow int64 |
|
|
|
roundShares int64 |
|
|
|
roundShares int64 |
|
|
|
|
|
|
|
sessionsMu sync.RWMutex |
|
|
|
|
|
|
|
sessions map[*Session]struct{} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type Endpoint struct { |
|
|
|
type Endpoint struct { |
|
|
@ -40,9 +43,15 @@ type Endpoint struct { |
|
|
|
|
|
|
|
|
|
|
|
type Session struct { |
|
|
|
type Session struct { |
|
|
|
sync.Mutex |
|
|
|
sync.Mutex |
|
|
|
conn *net.TCPConn |
|
|
|
conn *net.TCPConn |
|
|
|
enc *json.Encoder |
|
|
|
enc *json.Encoder |
|
|
|
ip string |
|
|
|
ip string |
|
|
|
|
|
|
|
endpoint *Endpoint |
|
|
|
|
|
|
|
difficulty int64 |
|
|
|
|
|
|
|
validJobs []*Job |
|
|
|
|
|
|
|
lastBlockHeight int64 |
|
|
|
|
|
|
|
target uint32 |
|
|
|
|
|
|
|
targetHex string |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
const ( |
|
|
@ -65,6 +74,7 @@ func NewStratum(cfg *pool.Config) *StratumServer { |
|
|
|
log.Printf("Default upstream: %s => %s", stratum.rpc().Name, stratum.rpc().Url) |
|
|
|
log.Printf("Default upstream: %s => %s", stratum.rpc().Name, stratum.rpc().Url) |
|
|
|
|
|
|
|
|
|
|
|
stratum.miners = NewMinersMap() |
|
|
|
stratum.miners = NewMinersMap() |
|
|
|
|
|
|
|
stratum.sessions = make(map[*Session]struct{}) |
|
|
|
|
|
|
|
|
|
|
|
timeout, _ := time.ParseDuration(cfg.Stratum.Timeout) |
|
|
|
timeout, _ := time.ParseDuration(cfg.Stratum.Timeout) |
|
|
|
stratum.timeout = timeout |
|
|
|
stratum.timeout = timeout |
|
|
@ -150,12 +160,14 @@ func (e *Endpoint) Listen(s *StratumServer) { |
|
|
|
} |
|
|
|
} |
|
|
|
conn.SetKeepAlive(true) |
|
|
|
conn.SetKeepAlive(true) |
|
|
|
ip, _, _ := net.SplitHostPort(conn.RemoteAddr().String()) |
|
|
|
ip, _, _ := net.SplitHostPort(conn.RemoteAddr().String()) |
|
|
|
|
|
|
|
cs := &Session{conn: conn, ip: ip, enc: json.NewEncoder(conn), endpoint: e} |
|
|
|
n += 1 |
|
|
|
n += 1 |
|
|
|
|
|
|
|
|
|
|
|
accept <- n |
|
|
|
accept <- n |
|
|
|
go func() { |
|
|
|
go func() { |
|
|
|
err = s.handleClient(conn, e, ip) |
|
|
|
err = s.handleClient(cs, e) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
|
|
|
|
s.removeSession(cs) |
|
|
|
conn.Close() |
|
|
|
conn.Close() |
|
|
|
} |
|
|
|
} |
|
|
|
<-accept |
|
|
|
<-accept |
|
|
@ -163,11 +175,12 @@ func (e *Endpoint) Listen(s *StratumServer) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *StratumServer) handleClient(conn *net.TCPConn, e *Endpoint, ip string) error { |
|
|
|
func (s *StratumServer) handleClient(cs *Session, e *Endpoint) error { |
|
|
|
cs := &Session{conn: conn, ip: ip} |
|
|
|
_, targetHex := util.GetTargetHex(e.config.Difficulty) |
|
|
|
cs.enc = json.NewEncoder(conn) |
|
|
|
cs.targetHex = targetHex |
|
|
|
connbuff := bufio.NewReaderSize(conn, MaxReqSize) |
|
|
|
|
|
|
|
s.setDeadline(conn) |
|
|
|
connbuff := bufio.NewReaderSize(cs.conn, MaxReqSize) |
|
|
|
|
|
|
|
s.setDeadline(cs.conn) |
|
|
|
|
|
|
|
|
|
|
|
for { |
|
|
|
for { |
|
|
|
data, isPrefix, err := connbuff.ReadLine() |
|
|
|
data, isPrefix, err := connbuff.ReadLine() |
|
|
@ -192,7 +205,7 @@ func (s *StratumServer) handleClient(conn *net.TCPConn, e *Endpoint, ip string) |
|
|
|
log.Printf("Malformed request: %v", err) |
|
|
|
log.Printf("Malformed request: %v", err) |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
s.setDeadline(conn) |
|
|
|
s.setDeadline(cs.conn) |
|
|
|
cs.handleMessage(s, e, &req) |
|
|
|
cs.handleMessage(s, e, &req) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -292,6 +305,25 @@ func (s *StratumServer) setDeadline(conn *net.TCPConn) { |
|
|
|
conn.SetDeadline(time.Now().Add(s.timeout)) |
|
|
|
conn.SetDeadline(time.Now().Add(s.timeout)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (s *StratumServer) registerSession(cs *Session) { |
|
|
|
|
|
|
|
s.sessionsMu.Lock() |
|
|
|
|
|
|
|
defer s.sessionsMu.Unlock() |
|
|
|
|
|
|
|
s.sessions[cs] = struct{}{} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (s *StratumServer) removeSession(cs *Session) { |
|
|
|
|
|
|
|
s.sessionsMu.Lock() |
|
|
|
|
|
|
|
defer s.sessionsMu.Unlock() |
|
|
|
|
|
|
|
delete(s.sessions, cs) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (s *StratumServer) isActive(cs *Session) bool { |
|
|
|
|
|
|
|
s.sessionsMu.RLock() |
|
|
|
|
|
|
|
defer s.sessionsMu.RUnlock() |
|
|
|
|
|
|
|
_, exist := s.sessions[cs] |
|
|
|
|
|
|
|
return exist |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *StratumServer) registerMiner(miner *Miner) { |
|
|
|
func (s *StratumServer) registerMiner(miner *Miner) { |
|
|
|
s.miners.Set(miner.Id, miner) |
|
|
|
s.miners.Set(miner.Id, miner) |
|
|
|
} |
|
|
|
} |
|
|
|