mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-23 08:03:51 +01:00
Refactor servers
This commit is contained in:
@@ -27,7 +27,7 @@ func makeSignInFailureResp(respID RespID) []byte {
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
func makeSignInResp(username string) []byte {
|
||||
func (session *Session) makeSignInResp(username string) []byte {
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
// delete me:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package signserver
|
||||
|
||||
//revive:disable
|
||||
|
||||
type RespID uint16
|
||||
|
||||
//go:generate stringer -type=RespID
|
||||
|
||||
@@ -3,104 +3,115 @@ package signserver
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/Andoryuuta/Erupe/network"
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Session holds state for the sign server connection.
|
||||
type Session struct {
|
||||
sync.Mutex
|
||||
logger *zap.Logger
|
||||
sid int
|
||||
server *Server
|
||||
rawConn *net.Conn
|
||||
cryptConn *network.CryptConn
|
||||
}
|
||||
|
||||
func (session *Session) fail() {
|
||||
session.server.Lock()
|
||||
delete(session.server.sessions, session.sid)
|
||||
session.server.Unlock()
|
||||
func (s *Session) fail() {
|
||||
s.server.Lock()
|
||||
delete(s.server.sessions, s.sid)
|
||||
s.server.Unlock()
|
||||
|
||||
}
|
||||
|
||||
func (session *Session) work() {
|
||||
func (s *Session) work() {
|
||||
for {
|
||||
pkt, err := session.cryptConn.ReadPacket()
|
||||
pkt, err := s.cryptConn.ReadPacket()
|
||||
if err != nil {
|
||||
session.fail()
|
||||
s.fail()
|
||||
return
|
||||
}
|
||||
|
||||
err = session.handlePacket(pkt)
|
||||
err = s.handlePacket(pkt)
|
||||
if err != nil {
|
||||
session.fail()
|
||||
s.fail()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (session *Session) handlePacket(pkt []byte) error {
|
||||
func (s *Session) handlePacket(pkt []byte) error {
|
||||
sugar := s.logger.Sugar()
|
||||
|
||||
bf := byteframe.NewByteFrameFromBytes(pkt)
|
||||
reqType := string(bf.ReadNullTerminatedBytes())
|
||||
switch reqType {
|
||||
case "DLTSKEYSIGN:100":
|
||||
fallthrough
|
||||
case "DSGN:100":
|
||||
session.handleDSGNRequest(bf)
|
||||
break
|
||||
err := s.handleDSGNRequest(bf)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
case "DELETE:100":
|
||||
loginTokenString := string(bf.ReadNullTerminatedBytes())
|
||||
_ = loginTokenString
|
||||
characterID := bf.ReadUint32()
|
||||
|
||||
fmt.Printf("Got delete request for character ID: %v\n", characterID)
|
||||
fmt.Printf("remaining unknown data:\n%s\n", hex.Dump(bf.DataFromCurrent()))
|
||||
sugar.Infof("Got delete request for character ID: %v\n", characterID)
|
||||
sugar.Infof("remaining unknown data:\n%s\n", hex.Dump(bf.DataFromCurrent()))
|
||||
default:
|
||||
fmt.Printf("Got unknown request type %s, data:\n%s\n", reqType, hex.Dump(bf.DataFromCurrent()))
|
||||
sugar.Infof("Got unknown request type %s, data:\n%s\n", reqType, hex.Dump(bf.DataFromCurrent()))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (session *Session) handleDSGNRequest(bf *byteframe.ByteFrame) error {
|
||||
func (s *Session) handleDSGNRequest(bf *byteframe.ByteFrame) error {
|
||||
|
||||
reqUsername := string(bf.ReadNullTerminatedBytes())
|
||||
reqPassword := string(bf.ReadNullTerminatedBytes())
|
||||
reqUnk := string(bf.ReadNullTerminatedBytes())
|
||||
fmt.Printf("Got sign in request:\n\tUsername: %s\n\tPassword %s\n\tUnk: %s\n", reqUsername, reqPassword, reqUnk)
|
||||
|
||||
s.server.logger.Info(
|
||||
"Got sign in request",
|
||||
zap.String("reqUsername", reqUsername),
|
||||
zap.String("reqPassword", reqPassword),
|
||||
zap.String("reqUnk", reqUnk),
|
||||
)
|
||||
|
||||
// TODO(Andoryuuta): remove plaintext password storage if this ever becomes more than a toy project.
|
||||
var (
|
||||
id int
|
||||
password string
|
||||
)
|
||||
err := session.server.db.QueryRow("SELECT id, password FROM users WHERE username = $1", reqUsername).Scan(&id, &password)
|
||||
err := s.server.db.QueryRow("SELECT id, password FROM users WHERE username = $1", reqUsername).Scan(&id, &password)
|
||||
var serverRespBytes []byte
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
fmt.Printf("No rows for username %s\n", reqUsername)
|
||||
s.logger.Info("Account not found", zap.String("reqUsername", reqUsername))
|
||||
serverRespBytes = makeSignInFailureResp(SIGN_EAUTH)
|
||||
break
|
||||
case err != nil:
|
||||
serverRespBytes = makeSignInFailureResp(SIGN_EABORT)
|
||||
fmt.Println("Got error on SQL query!")
|
||||
fmt.Println(err)
|
||||
s.logger.Warn("Got error on SQL query", zap.Error(err))
|
||||
break
|
||||
default:
|
||||
if reqPassword == password {
|
||||
fmt.Println("Passwords match!")
|
||||
serverRespBytes = makeSignInResp(reqUsername)
|
||||
s.logger.Info("Passwords match!")
|
||||
serverRespBytes = s.makeSignInResp(reqUsername)
|
||||
} else {
|
||||
fmt.Println("Passwords don't match!")
|
||||
s.logger.Info("Passwords don't match!")
|
||||
serverRespBytes = makeSignInFailureResp(SIGN_EPASS)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
err = session.cryptConn.SendPacket(serverRespBytes)
|
||||
err = s.cryptConn.SendPacket(serverRespBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -7,55 +7,81 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/Andoryuuta/Erupe/config"
|
||||
"github.com/Andoryuuta/Erupe/network"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Config struct allows configuring the server.
|
||||
type Config struct {
|
||||
DB *sql.DB
|
||||
ListenAddr string
|
||||
Logger *zap.Logger
|
||||
DB *sql.DB
|
||||
ErupeConfig *config.Config
|
||||
}
|
||||
|
||||
// Server is a MHF sign server.
|
||||
type Server struct {
|
||||
sync.Mutex
|
||||
sid int
|
||||
sessions map[int]*Session
|
||||
db *sql.DB
|
||||
listenAddr string
|
||||
listener net.Listener
|
||||
logger *zap.Logger
|
||||
erupeConfig *config.Config
|
||||
sid int
|
||||
sessions map[int]*Session
|
||||
db *sql.DB
|
||||
listener net.Listener
|
||||
isShuttingDown bool
|
||||
}
|
||||
|
||||
// NewServer creates a new Server type.
|
||||
func NewServer(config *Config) *Server {
|
||||
s := &Server{
|
||||
sid: 0,
|
||||
sessions: make(map[int]*Session),
|
||||
db: config.DB,
|
||||
listenAddr: config.ListenAddr,
|
||||
logger: config.Logger,
|
||||
erupeConfig: config.ErupeConfig,
|
||||
sid: 0,
|
||||
sessions: make(map[int]*Session),
|
||||
db: config.DB,
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Start starts the server in a new goroutine.
|
||||
func (s *Server) Start() error {
|
||||
l, err := net.Listen("tcp", s.listenAddr)
|
||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", s.erupeConfig.Sign.Port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.listener = l
|
||||
//defer l.Close()
|
||||
|
||||
go s.acceptClients()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown exits the server gracefully.
|
||||
func (s *Server) Shutdown() {
|
||||
s.logger.Debug("Shutting down")
|
||||
|
||||
s.Lock()
|
||||
s.isShuttingDown = true
|
||||
s.Unlock()
|
||||
|
||||
// This will cause the acceptor goroutine to error and exit gracefully.
|
||||
s.listener.Close()
|
||||
}
|
||||
|
||||
func (s *Server) acceptClients() {
|
||||
for {
|
||||
conn, err := s.listener.Accept()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
// Check if we are shutting down and exit gracefully if so.
|
||||
s.Lock()
|
||||
shutdown := s.isShuttingDown
|
||||
s.Unlock()
|
||||
|
||||
if shutdown {
|
||||
break
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
go s.handleConnection(s.sid, conn)
|
||||
@@ -64,7 +90,7 @@ func (s *Server) acceptClients() {
|
||||
}
|
||||
|
||||
func (s *Server) handleConnection(sid int, conn net.Conn) {
|
||||
fmt.Println("Got connection to sign server")
|
||||
s.logger.Info("Got connection to sign server", zap.String("remoteaddr", conn.RemoteAddr().String()))
|
||||
|
||||
// Client initalizes the connection with a one-time buffer of 8 NULL bytes.
|
||||
nullInit := make([]byte, 8)
|
||||
@@ -75,15 +101,19 @@ func (s *Server) handleConnection(sid int, conn net.Conn) {
|
||||
return
|
||||
}
|
||||
|
||||
// Create a new session.
|
||||
session := &Session{
|
||||
logger: s.logger,
|
||||
server: s,
|
||||
rawConn: &conn,
|
||||
cryptConn: network.NewCryptConn(conn),
|
||||
}
|
||||
|
||||
// Add the session to the server's sessions map.
|
||||
s.Lock()
|
||||
s.sessions[sid] = session
|
||||
s.Unlock()
|
||||
|
||||
// Do the session's work.
|
||||
session.work()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user