diff --git a/README.md b/README.md index ea93237..d591cf1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # gopenfusion -A toy fusionfall packet protocol implementation written in Go. +A toy implementation of the Fusionfall Packet Protocol written in Go. ## Generating structures diff --git a/build.sh b/build.sh index de628c8..df9cfa3 100755 --- a/build.sh +++ b/build.sh @@ -1,7 +1,5 @@ #!/bin/sh mkdir -p bin -cd server -go build -o ../bin/server -cd ../ +go build -o ./bin/server echo 'Done' \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..eae135b --- /dev/null +++ b/main.go @@ -0,0 +1,8 @@ +package main + +import "github.com/CPunch/GopenFusion/server" + +func main() { + server := server.NewLoginServer() + server.Start() +} diff --git a/server/client.go b/server/client.go index 2865e82..49af5ba 100644 --- a/server/client.go +++ b/server/client.go @@ -1,4 +1,4 @@ -package main +package server import ( "encoding/binary" @@ -16,14 +16,14 @@ const ( ) type Client struct { - server *Server + server Server conn net.Conn e_key []byte fe_key []byte whichKey int } -func newClient(server *Server, conn net.Conn) *Client { +func newClient(server Server, conn net.Conn) *Client { return &Client{ server: server, conn: conn, @@ -97,7 +97,7 @@ func (client *Client) ClientHandler() { log.Printf("Client %p panic'd! %v", client, err) } client.conn.Close() - client.server.unregister <- client + client.server.Disconnect(client) }() tmp := make([]byte, 4, protocol.CN_PACKET_BUFFER_SIZE) @@ -125,7 +125,7 @@ func (client *Client) ClientHandler() { // dispatch packet log.Printf("Got packet ID: %x, with a sizeof: %d\n", typeID, sz) pkt := protocol.NewPacket(tmp[4:sz]) - client.server.handlePacket(client, typeID, pkt) + client.server.HandlePacket(client, typeID, pkt) // reset tmp tmp = tmp[:4] diff --git a/server/loginserver.go b/server/loginserver.go new file mode 100644 index 0000000..9db3e8f --- /dev/null +++ b/server/loginserver.go @@ -0,0 +1,87 @@ +package server + +import ( + "fmt" + "log" + "net" + + "github.com/CPunch/GopenFusion/protocol" +) + +type LoginServer struct { + listener net.Listener + clients map[*Client]bool + unregister chan *Client +} + +func NewLoginServer() *LoginServer { + listener, err := net.Listen("tcp", ":23000") + if err != nil { + log.Fatal(err) + } + + return &LoginServer{ + listener: listener, + clients: make(map[*Client]bool), + unregister: make(chan *Client), + } +} + +func (server *LoginServer) Start() { + log.Print("Server hosted on 127.0.0.1:23000") + + for { + select { + case client := <-server.unregister: + delete(server.clients, client) + fmt.Printf("Client %p disconnected\n", client) + default: + conn, err := server.listener.Accept() + if err != nil { + log.Println("Connection error: ", err) + return + } + + client := newClient(server, conn) + server.clients[client] = true + go client.ClientHandler() + fmt.Printf("Client %p connected\n", client) + } + } +} + +func (server *LoginServer) HandlePacket(client *Client, typeID uint32, pkt *protocol.Packet) { + switch typeID { + case protocol.P_CL2LS_REQ_LOGIN: + var loginPkt protocol.SP_CL2LS_REQ_LOGIN + pkt.Decode(&loginPkt) + + // TODO: for now, we're a dummy server + client.AcceptLogin(loginPkt.SzID, loginPkt.IClientVerC, 1, []protocol.SP_LS2CL_REP_CHAR_INFO{}) + case protocol.P_CL2LS_REQ_CHECK_CHAR_NAME: + var charPkt protocol.SP_CL2LS_REQ_CHECK_CHAR_NAME + pkt.Decode(&charPkt) + + client.Send(&protocol.SP_LS2CL_REP_CHECK_CHAR_NAME_SUCC{ + SzFirstName: charPkt.SzFirstName, + SzLastName: charPkt.SzLastName, + }, protocol.P_LS2CL_REP_CHECK_CHAR_NAME_SUCC) + case protocol.P_CL2LS_REQ_SAVE_CHAR_NAME: + var charPkt protocol.SP_CL2LS_REQ_SAVE_CHAR_NAME + pkt.Decode(&charPkt) + + client.Send(&protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_SUCC{ + IPC_UID: 1, + ISlotNum: charPkt.ISlotNum, + IGender: charPkt.IGender, + SzFirstName: charPkt.SzFirstName, + SzLastName: charPkt.SzLastName, + }, protocol.P_LS2CL_REP_SAVE_CHAR_NAME_SUCC) + default: + log.Printf("[WARN] unsupported packet ID: %x\n", typeID) + } +} + +func (server *LoginServer) Disconnect(client *Client) { + server.unregister <- client +} diff --git a/server/server.go b/server/server.go index 4cf778d..b792ff0 100644 --- a/server/server.go +++ b/server/server.go @@ -1,88 +1,10 @@ -package main +package server import ( - "fmt" - "log" - "net" - "github.com/CPunch/GopenFusion/protocol" ) -type Server struct { - listener net.Listener - clients map[*Client]bool - unregister chan *Client -} - -func newServer() *Server { - listener, err := net.Listen("tcp", ":23000") - if err != nil { - log.Fatal(err) - } - - return &Server{ - listener: listener, - clients: make(map[*Client]bool), - unregister: make(chan *Client), - } -} - -func (server *Server) Start() { - log.Print("Server hosted on 127.0.0.1:23000") - - for { - select { - case client := <-server.unregister: - delete(server.clients, client) - fmt.Printf("Client %p disconnected\n", client) - default: - conn, err := server.listener.Accept() - if err != nil { - log.Println("Connection error: ", err) - return - } - - client := newClient(server, conn) - server.clients[client] = true - go client.ClientHandler() - fmt.Printf("Client %p connected\n", client) - } - } -} - -func (server *Server) handlePacket(client *Client, typeID uint32, pkt *protocol.Packet) { - switch typeID { - case protocol.P_CL2LS_REQ_LOGIN: - var loginPkt protocol.SP_CL2LS_REQ_LOGIN - pkt.Decode(&loginPkt) - - // TODO: for now, we're a dummy server - client.AcceptLogin(loginPkt.SzID, loginPkt.IClientVerC, 1, []protocol.SP_LS2CL_REP_CHAR_INFO{}) - case protocol.P_CL2LS_REQ_CHECK_CHAR_NAME: - var charPkt protocol.SP_CL2LS_REQ_CHECK_CHAR_NAME - pkt.Decode(&charPkt) - - client.Send(&protocol.SP_LS2CL_REP_CHECK_CHAR_NAME_SUCC{ - SzFirstName: charPkt.SzFirstName, - SzLastName: charPkt.SzLastName, - }, protocol.P_LS2CL_REP_CHECK_CHAR_NAME_SUCC) - case protocol.P_CL2LS_REQ_SAVE_CHAR_NAME: - var charPkt protocol.SP_CL2LS_REQ_SAVE_CHAR_NAME - pkt.Decode(&charPkt) - - client.Send(&protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_SUCC{ - IPC_UID: 1, - ISlotNum: charPkt.ISlotNum, - IGender: charPkt.IGender, - SzFirstName: charPkt.SzFirstName, - SzLastName: charPkt.SzLastName, - }, protocol.P_LS2CL_REP_SAVE_CHAR_NAME_SUCC) - default: - log.Printf("[WARN] unsupported packet ID: %x\n", typeID) - } -} - -func main() { - server := newServer() - server.Start() +type Server interface { + HandlePacket(client *Client, typeID uint32, pkt *protocol.Packet) + Disconnect(client *Client) }