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!")
|
||||
|
||||
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 (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
@ -14,29 +14,45 @@ func handleLobbyConnection(conn net.Conn) {
|
|||
|
||||
messageBytes := make([]byte, 4096)
|
||||
|
||||
for {
|
||||
n, err := conn.Read(messageBytes)
|
||||
if err != nil {
|
||||
log.Printf("Error reading message %v", err)
|
||||
return
|
||||
}
|
||||
recvMessageChan := make(chan *LobbyMessage)
|
||||
go func() {
|
||||
for {
|
||||
fmt.Println("READING!")
|
||||
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 {
|
||||
return
|
||||
message := LobbyMessage{}
|
||||
|
||||
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
|
||||
func handleLobbyMessage(playerConnection net.Conn, bytes []byte) (bool, error) {
|
||||
|
||||
message := LobbyMessage{}
|
||||
|
||||
err := proto.Unmarshal(bytes, &message)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Invalid message received from client")
|
||||
}
|
||||
|
||||
func handleClientLobbyMessage(playerConnection net.Conn, message *LobbyMessage) (bool, error) {
|
||||
switch message.Type {
|
||||
case "name":
|
||||
_, 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})
|
||||
|
||||
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]
|
||||
if !ok {
|
||||
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
|
||||
case "chat":
|
||||
broadcastToLobby(&LobbyMessage{PlayerId: message.PlayerId, Type: "text", Content: message.Content})
|
||||
return false, nil
|
||||
case "decline_game":
|
||||
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
|
||||
case "quit":
|
||||
delete(clientPool.clients, message.PlayerId)
|
||||
|
@ -103,11 +125,15 @@ func SendMessageToClient(connection net.Conn, message *LobbyMessage) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("Error writing to client connection")
|
||||
}
|
||||
fmt.Println("Sent message to client")
|
||||
return nil
|
||||
}
|
||||
|
||||
func broadcastToLobby(message *LobbyMessage) {
|
||||
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{},
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", ":12345")
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:12345")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ func Listen() {
|
|||
go func() {
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
log.Println("got a connection!")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
|
@ -56,20 +57,18 @@ func Listen() {
|
|||
games: map[string]GameClients{},
|
||||
}
|
||||
|
||||
gameListener, err := net.Listen("tcp", ":42069")
|
||||
gameListener, err := net.Listen("tcp", "127.0.0.1:42069")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
defer gameListener.Close()
|
||||
go func() {
|
||||
for {
|
||||
conn, err := gameListener.Accept()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
handleGameConnection(conn)
|
||||
for {
|
||||
conn, err := gameListener.Accept()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
}()
|
||||
handleGameConnection(conn)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user