From adf22b588f83caf74ce0c1f546ea6bb8a1f8c63b Mon Sep 17 00:00:00 2001 From: raul Date: Mon, 1 Apr 2024 12:28:22 +0200 Subject: [PATCH] Finish chat functionality and prepare for release --- cmd/root.go | 18 +++++------- cmd/server.go | 78 +++++++++++++++++++++++++++++++++++---------------- main.go | 2 +- 3 files changed, 62 insertions(+), 36 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index b856ca3..b501093 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,7 +1,7 @@ /* Copyright © 2024 Raul - */ + package cmd import ( @@ -10,18 +10,16 @@ import ( "github.com/spf13/cobra" ) - - // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "mini-chat", - Short: "A brief description of your application", - Long: `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: + Short: "Minimalistic chat server built using Go", + Long: `mini-chat was originally designed to be used as a standalone server +users could connect to using netcat, but it can be also used with the binary +client -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, +Examples: + ./mini-chat server --port 8080`, // Uncomment the following line if your bare application // has an action associated with it: // Run: func(cmd *cobra.Command, args []string) { }, @@ -47,5 +45,3 @@ func init() { // when this action is called directly. rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") } - - diff --git a/cmd/server.go b/cmd/server.go index b76c154..72da336 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -1,31 +1,29 @@ /* Copyright © 2024 Raul */ + package cmd import ( "bufio" "fmt" - //"log" + "github.com/spf13/cobra" "net" "strings" "time" - - //"os" - - "github.com/spf13/cobra" ) // serverCmd represents the server command var serverCmd = &cobra.Command{ Use: "server", - Short: "A brief description of your command", - Long: `A longer description that spans multiple lines and likely contains examples -and usage of using your command. For example: + Short: "Main chat server", + Long: `You can connect to this server by running the following command from +a client: + nc $SERVER_IP $PORT -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, +Assuming your IP is 192.168.0.30 and the server port is left on default the +command would be as follows: + nc 192.168.0.30 1302`, Run: func(cmd *cobra.Command, args []string) { server(cmd) }, @@ -46,6 +44,13 @@ func init() { serverCmd.Flags().String("port", "1302", "Port to listen on") } +var receiverIsStarted bool = false + +type chatter struct { + Username string + IP string +} + func server(cmd *cobra.Command) { var lport string port, _ := cmd.Flags().GetString("port") @@ -58,42 +63,66 @@ func server(cmd *cobra.Command) { ln, err := net.Listen("tcp", ":"+lport) cobra.CheckErr(err) fmt.Printf("Listening on port %v...\n", lport) - messageChan := make(chan string) + masterChannel := make(chan string, 20) + + slaveChannel := make(chan string, 20) + go masterReceiver(slaveChannel, masterChannel) // TODO: get channels properly working - //receivingChannel := make(chan string) - //sendingChannelº := make(chan string) + // receivingChannel := make(chan string) + // sendingChannel := make(chan string) for { conn, err := ln.Accept() cobra.CheckErr(err) - go handleConn(conn, messageChan) + numOfClients++ + go handleConn(conn, slaveChannel, masterChannel) } } -type chatter struct { - Username string - IP string +var numOfClients int = 0 + +func masterReceiver(slaveChannel chan<- string, masterChannel <-chan string) { + for { + message := <-masterChannel + for i := 0; i < numOfClients; i++ { + slaveChannel <- message + } + } } -func handleConn(conn net.Conn, ch chan string) { +// func receiver(conn net.Conn, ch chan string) { +// fmt.Println("THE RECEIVER HAS BEEN STARTED, YOU CAN ONLY SEE THIS MESSAGE ONCE") +// receiverIsStarted = false +// for { +// select { +// case otherMessage := <-ch: +// conn.Write([]byte(otherMessage)) +// default: +// } +// } +// } + +func handleConn(conn net.Conn, slaveChannel <-chan string, masterChannel chan<- string) { defer conn.Close() - var otherMessage string + //var otherMessage string go func() { for { - otherMessage = <-ch - conn.Write([]byte(otherMessage)) + //select { + message := <-slaveChannel + conn.Write([]byte(message)) } }() IP := getIP(conn) t := time.Now() - date := fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()) + date := fmt.Sprintf("%d-%02d-%02d | %02d:%02d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()) final_message_connect := fmt.Sprintf("[%v] Received connection from %v!\n", date, IP) fmt.Print(final_message_connect) conn.Write([]byte("What's your name?\nName: ")) name, err := bufio.NewReader(conn).ReadString('\n') if err != nil { + numOfClients-- return } var NewUser = new(chatter) @@ -103,11 +132,12 @@ func handleConn(conn net.Conn, ch chan string) { message, err := bufio.NewReader(conn).ReadString('\n') if err != nil { fmt.Printf(NewUser.Username + " disconnected!\n") + numOfClients-- return } finalMessage := fmt.Sprint("{" + NewUser.IP + "} " + NewUser.Username + ": " + message) fmt.Print(finalMessage) - ch <- finalMessage + masterChannel <- finalMessage //conn.Write([]byte(message)) } } diff --git a/main.go b/main.go index f109379..8970d54 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,7 @@ /* Copyright © 2024 Raul - */ + package main import "mini-chat/cmd"