Broken networking
This commit is contained in:
parent
7a44092b2f
commit
35d8ebc459
95
cmd/client/main.go
Normal file
95
cmd/client/main.go
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sshpong/internal/netwrk"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
lobbyChan := make(chan netwrk.LobbyPlayerStatus)
|
||||||
|
interrupter := make(chan netwrk.Interrupter)
|
||||||
|
messageOutput := make(chan *netwrk.LobbyMessage)
|
||||||
|
inputChan := make(chan string)
|
||||||
|
|
||||||
|
fmt.Println("Welcome to sshpong!")
|
||||||
|
fmt.Println("Please enter your username")
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
for scanner.Scan() {
|
||||||
|
text := scanner.Text()
|
||||||
|
inputChan <- text
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
username, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error reading from your shit bro...")
|
||||||
|
}
|
||||||
|
|
||||||
|
go netwrk.ConnectToLobby(username, messageOutput, lobbyChan, interrupter)
|
||||||
|
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case msg := <-interrupter:
|
||||||
|
fmt.Println(msg.Message)
|
||||||
|
default:
|
||||||
|
n, err := os.Stdin.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error reading from stdin")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
input := string(buf[:n])
|
||||||
|
args := strings.Fields(input)
|
||||||
|
switch args[0] {
|
||||||
|
case "invite":
|
||||||
|
if args[1] != "" {
|
||||||
|
messageOutput <- &netwrk.LobbyMessage{
|
||||||
|
PlayerId: username,
|
||||||
|
Type: "invite",
|
||||||
|
Content: args[1],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Println("Please provide a player to invite ")
|
||||||
|
}
|
||||||
|
case "chat":
|
||||||
|
if args[1] != "" {
|
||||||
|
messageOutput <- &netwrk.LobbyMessage{
|
||||||
|
PlayerId: username,
|
||||||
|
Type: "chat",
|
||||||
|
Content: strings.Join(args[1:], " "),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "/":
|
||||||
|
if args[1] != "" {
|
||||||
|
messageOutput <- &netwrk.LobbyMessage{
|
||||||
|
PlayerId: username,
|
||||||
|
Type: "chat",
|
||||||
|
Content: strings.Join(args[1:], " "),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "quit":
|
||||||
|
return
|
||||||
|
case "q":
|
||||||
|
return
|
||||||
|
case "help":
|
||||||
|
fmt.Println("use invite <player name> to invite a player\nchat or / to send a message to the lobby\nq or quit to leave the game")
|
||||||
|
case "h":
|
||||||
|
fmt.Println("use invite <player name> to invite a player\nchat or / to send a message to the lobby\nq or quit to leave the game")
|
||||||
|
default:
|
||||||
|
fmt.Println("use invite <player name> to invite a player\nchat or / to send a message to the lobby\nq or quit to leave the game")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,4 +9,5 @@ func main() {
|
||||||
fmt.Println("Starting sshpong server!")
|
fmt.Println("Starting sshpong server!")
|
||||||
|
|
||||||
netwrk.Listen()
|
netwrk.Listen()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
153
internal/netwrk/client.go
Normal file
153
internal/netwrk/client.go
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
package netwrk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LobbyPlayerStatus struct {
|
||||||
|
Username string
|
||||||
|
Status string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Interrupter struct {
|
||||||
|
MessageType string
|
||||||
|
Message string
|
||||||
|
ReplyChan chan string
|
||||||
|
}
|
||||||
|
|
||||||
|
var username string
|
||||||
|
var lobby chan LobbyPlayerStatus
|
||||||
|
var interruptChan chan Interrupter
|
||||||
|
|
||||||
|
func ConnectToLobby(playerUsername string, messageOutputChan chan *LobbyMessage, lobbyMessageChan chan LobbyPlayerStatus, interruptChannel chan Interrupter) {
|
||||||
|
username = playerUsername
|
||||||
|
lobby = lobbyMessageChan
|
||||||
|
interruptChan = interruptChannel
|
||||||
|
|
||||||
|
conn, err := net.Dial("tcp", "127.0.0.1:12345")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Sorry, failed to connect to server...")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loginMsg, err := proto.Marshal(&LobbyMessage{Type: "name", Content: username})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Sorry bro but your username is wack AF...")
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = conn.Write(loginMsg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Sorry, could not communicate with server...")
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Starting client loop")
|
||||||
|
messageInputChan := make(chan *LobbyMessage)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
messageBytes := make([]byte, 1024)
|
||||||
|
|
||||||
|
n, err := conn.Read(messageBytes)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Sorry, failed to read message from server...", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
message := &LobbyMessage{}
|
||||||
|
|
||||||
|
err = proto.Unmarshal(messageBytes[:n], message)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Sorry, the server sent something weird back...")
|
||||||
|
}
|
||||||
|
|
||||||
|
messageInputChan <- message
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case msg := <-messageInputChan:
|
||||||
|
if isDone, gameID := handleLobbyMessage(conn, msg); isDone {
|
||||||
|
if gameID != "" {
|
||||||
|
interruptChan <- Interrupter{
|
||||||
|
MessageType: "game",
|
||||||
|
Message: gameID,
|
||||||
|
ReplyChan: make(chan string),
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case msg := <-messageOutputChan:
|
||||||
|
fmt.Println("Sending message out", msg)
|
||||||
|
err := SendMessageToServer(conn, msg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error!", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLobbyMessage(serverConn net.Conn, message *LobbyMessage) (bool, string) {
|
||||||
|
switch message.Type {
|
||||||
|
case "text":
|
||||||
|
fmt.Println(message.Content)
|
||||||
|
return false, ""
|
||||||
|
case "error":
|
||||||
|
fmt.Println("Error:", message.Content)
|
||||||
|
return false, ""
|
||||||
|
case "invite":
|
||||||
|
fmt.Println("GOT INVITE!")
|
||||||
|
replyChan := make(chan string)
|
||||||
|
interruptChan <- Interrupter{
|
||||||
|
MessageType: "invite",
|
||||||
|
Message: fmt.Sprintf("Invite from player %s\nAccept: Y Decline: N", message.Content),
|
||||||
|
ReplyChan: replyChan,
|
||||||
|
}
|
||||||
|
input := <-replyChan
|
||||||
|
if strings.ToLower(input) == "yes" || strings.ToLower(input) == "y" {
|
||||||
|
SendMessageToServer(serverConn, &LobbyMessage{Type: "accept_game", Content: username})
|
||||||
|
SendMessageToServer(serverConn, &LobbyMessage{Type: "quit", Content: username})
|
||||||
|
return true, message.Content
|
||||||
|
} else {
|
||||||
|
SendMessageToServer(serverConn, &LobbyMessage{Type: "decline_game", Content: username})
|
||||||
|
}
|
||||||
|
return false, ""
|
||||||
|
case "accept":
|
||||||
|
fmt.Println(message.Content, "accepted your invite. Game starting...")
|
||||||
|
SendMessageToServer(serverConn, &LobbyMessage{Type: "quit", Content: username})
|
||||||
|
return true, message.Content
|
||||||
|
case "decline_game":
|
||||||
|
fmt.Println("Sorry,", message.Content, "declined your game invite...")
|
||||||
|
return false, ""
|
||||||
|
case "connect":
|
||||||
|
lobby <- LobbyPlayerStatus{Username: message.Content, Status: "connected"}
|
||||||
|
fmt.Println(message.Content, "connected!")
|
||||||
|
return false, ""
|
||||||
|
case "disconnect":
|
||||||
|
lobby <- LobbyPlayerStatus{Username: message.Content, Status: "disconnected"}
|
||||||
|
fmt.Println(message.Content, "disconnected!")
|
||||||
|
return false, ""
|
||||||
|
case "pong":
|
||||||
|
log.Println("PoNg!")
|
||||||
|
return false, ""
|
||||||
|
default:
|
||||||
|
log.Println("Got message", message)
|
||||||
|
}
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendMessageToServer(connection net.Conn, message *LobbyMessage) error {
|
||||||
|
bytes, err := proto.Marshal(message)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error marshalling message. Your protobuf is wack yo.")
|
||||||
|
}
|
||||||
|
_, err = connection.Write(bytes)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error writing to client connection")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -2,9 +2,9 @@ package netwrk
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
|
||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
@ -14,29 +14,45 @@ func handleLobbyConnection(conn net.Conn) {
|
||||||
|
|
||||||
messageBytes := make([]byte, 4096)
|
messageBytes := make([]byte, 4096)
|
||||||
|
|
||||||
for {
|
recvMessageChan := make(chan *LobbyMessage)
|
||||||
n, err := conn.Read(messageBytes)
|
go func() {
|
||||||
if err != nil {
|
for {
|
||||||
log.Printf("Error reading message %v", err)
|
fmt.Println("READING!")
|
||||||
return
|
n, err := conn.Read(messageBytes)
|
||||||
}
|
if err == io.EOF {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("READ something!")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error reading message %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if isDone, err := handleLobbyMessage(conn, messageBytes[:n]); err != nil || isDone {
|
message := LobbyMessage{}
|
||||||
return
|
|
||||||
|
err = proto.Unmarshal(messageBytes[:n], &message)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Invalid message received from client")
|
||||||
|
}
|
||||||
|
recvMessageChan <- &message
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
|
||||||
|
select {
|
||||||
|
case msg := <-recvMessageChan:
|
||||||
|
if isDone, err := handleClientLobbyMessage(conn, msg); err != nil || isDone {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("Handled message")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a bool of whether the player has disconnected from the lobby and an error
|
// Returns a bool of whether the player has disconnected from the lobby and an error
|
||||||
func handleLobbyMessage(playerConnection net.Conn, bytes []byte) (bool, error) {
|
func handleClientLobbyMessage(playerConnection net.Conn, message *LobbyMessage) (bool, error) {
|
||||||
|
|
||||||
message := LobbyMessage{}
|
|
||||||
|
|
||||||
err := proto.Unmarshal(bytes, &message)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("Invalid message received from client")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch message.Type {
|
switch message.Type {
|
||||||
case "name":
|
case "name":
|
||||||
_, ok := clientPool.clients[message.Content]
|
_, ok := clientPool.clients[message.Content]
|
||||||
|
@ -57,10 +73,13 @@ func handleLobbyMessage(playerConnection net.Conn, bytes []byte) (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Println("Broadcasting new player", message.Content)
|
||||||
|
|
||||||
broadcastToLobby(&LobbyMessage{PlayerId: "", Type: "connect", Content: playerID})
|
broadcastToLobby(&LobbyMessage{PlayerId: "", Type: "connect", Content: playerID})
|
||||||
|
|
||||||
return false, SendMessageToClient(playerConnection, &LobbyMessage{PlayerId: playerID, Type: "name", Content: playerID})
|
return false, SendMessageToClient(playerConnection, &LobbyMessage{PlayerId: playerID, Type: "name", Content: playerID})
|
||||||
case "invite_player":
|
case "invite":
|
||||||
|
log.Println("Got invite for player:", message.Content)
|
||||||
invitee, ok := clientPool.clients[message.Content]
|
invitee, ok := clientPool.clients[message.Content]
|
||||||
if !ok {
|
if !ok {
|
||||||
SendMessageToClient(playerConnection, &LobbyMessage{Type: "text", Content: "Sorry, that player is not available..."})
|
SendMessageToClient(playerConnection, &LobbyMessage{Type: "text", Content: "Sorry, that player is not available..."})
|
||||||
|
@ -77,9 +96,12 @@ func handleLobbyMessage(playerConnection net.Conn, bytes []byte) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
|
case "chat":
|
||||||
|
broadcastToLobby(&LobbyMessage{PlayerId: message.PlayerId, Type: "text", Content: message.Content})
|
||||||
|
return false, nil
|
||||||
case "decline_game":
|
case "decline_game":
|
||||||
inviter := clientPool.clients[message.Content]
|
inviter := clientPool.clients[message.Content]
|
||||||
SendMessageToClient(inviter.conn, &LobbyMessage{Type: "decline_game", Content: ""})
|
SendMessageToClient(inviter.conn, &LobbyMessage{Type: "decline_game", Content: message.PlayerId})
|
||||||
return false, nil
|
return false, nil
|
||||||
case "quit":
|
case "quit":
|
||||||
delete(clientPool.clients, message.PlayerId)
|
delete(clientPool.clients, message.PlayerId)
|
||||||
|
@ -103,11 +125,15 @@ func SendMessageToClient(connection net.Conn, message *LobbyMessage) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error writing to client connection")
|
return fmt.Errorf("Error writing to client connection")
|
||||||
}
|
}
|
||||||
|
fmt.Println("Sent message to client")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func broadcastToLobby(message *LobbyMessage) {
|
func broadcastToLobby(message *LobbyMessage) {
|
||||||
for _, player := range clientPool.clients {
|
for _, player := range clientPool.clients {
|
||||||
SendMessageToClient(player.conn, message)
|
err := SendMessageToClient(player.conn, message)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error broadcasting to clients...", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ func Listen() {
|
||||||
clients: map[string]Client{},
|
clients: map[string]Client{},
|
||||||
}
|
}
|
||||||
|
|
||||||
listener, err := net.Listen("tcp", ":12345")
|
listener, err := net.Listen("tcp", "127.0.0.1:12345")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ func Listen() {
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
conn, err := listener.Accept()
|
conn, err := listener.Accept()
|
||||||
|
log.Println("got a connection!")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
continue
|
continue
|
||||||
|
@ -56,20 +57,18 @@ func Listen() {
|
||||||
games: map[string]GameClients{},
|
games: map[string]GameClients{},
|
||||||
}
|
}
|
||||||
|
|
||||||
gameListener, err := net.Listen("tcp", ":42069")
|
gameListener, err := net.Listen("tcp", "127.0.0.1:42069")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer gameListener.Close()
|
defer gameListener.Close()
|
||||||
go func() {
|
for {
|
||||||
for {
|
conn, err := gameListener.Accept()
|
||||||
conn, err := gameListener.Accept()
|
if err != nil {
|
||||||
if err != nil {
|
log.Println(err)
|
||||||
log.Println(err)
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
handleGameConnection(conn)
|
|
||||||
}
|
}
|
||||||
}()
|
handleGameConnection(conn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user