From 2571936a48bae72c0080dacfd2fe28803c26c55c Mon Sep 17 00:00:00 2001
From: raul
Date: Wed, 8 May 2024 08:34:07 +0200
Subject: [PATCH 01/25] Add shorthand parameters
---
cmd/client.go | 4 ++--
cmd/server.go | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/cmd/client.go b/cmd/client.go
index 0a52479..fba8423 100644
--- a/cmd/client.go
+++ b/cmd/client.go
@@ -41,8 +41,8 @@ func init() {
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// clientCmd.PersistentFlags().String("foo", "", "A help for foo")
- clientCmd.PersistentFlags().String("ip", "", "Server IP to connect to")
- clientCmd.PersistentFlags().String("port", "1302", "Server port to connect to")
+ clientCmd.PersistentFlags().StringP("ip", "i", "", "Server IP to connect to")
+ clientCmd.PersistentFlags().StringP("port", "p", "1302", "Server port to connect to")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
diff --git a/cmd/server.go b/cmd/server.go
index 2b13d0a..7e2903a 100644
--- a/cmd/server.go
+++ b/cmd/server.go
@@ -36,8 +36,8 @@ func init() {
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// serverCmd.PersistentFlags().String("foo", "", "A help for foo")
- serverCmd.PersistentFlags().String("port", "1302", "port to use for listening")
- serverCmd.PersistentFlags().String("history", "", "File to store and recover chat history from")
+ serverCmd.PersistentFlags().StringP("port", "p", "1302", "port to use for listening")
+ serverCmd.PersistentFlags().StringP("history", "r", "", "File to store and recover chat history from")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
--
2.30.2
From b6e133c60873c5ec41b6ebaf28e98043ac36cd58 Mon Sep 17 00:00:00 2001
From: raul
Date: Fri, 10 May 2024 07:58:12 +0200
Subject: [PATCH 02/25] Clean up Cobra files
---
cmd/client.go | 11 -----------
cmd/root.go | 15 ---------------
cmd/server.go | 11 -----------
3 files changed, 37 deletions(-)
diff --git a/cmd/client.go b/cmd/client.go
index fba8423..6f658e1 100644
--- a/cmd/client.go
+++ b/cmd/client.go
@@ -10,7 +10,6 @@ import (
"os"
)
-// clientCmd represents the client command
var clientCmd = &cobra.Command{
Use: "client",
Short: "Client interface for mini-chat",
@@ -35,18 +34,8 @@ Example:
func init() {
rootCmd.AddCommand(clientCmd)
-
- // Here you will define your flags and configuration settings.
-
- // Cobra supports Persistent Flags which will work for this command
- // and all subcommands, e.g.:
- // clientCmd.PersistentFlags().String("foo", "", "A help for foo")
clientCmd.PersistentFlags().StringP("ip", "i", "", "Server IP to connect to")
clientCmd.PersistentFlags().StringP("port", "p", "1302", "Server port to connect to")
-
- // Cobra supports local flags which will only run when this command
- // is called directly, e.g.:
- // clientCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
func setClientParameters(cmd *cobra.Command) error {
diff --git a/cmd/root.go b/cmd/root.go
index 57577e0..3557b46 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -9,19 +9,13 @@ import (
"os"
)
-// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "mini-chat",
Short: "Application for hosting and joining a simple chat server",
Long: `Application for hosting and joining a simple chat server`,
- // Uncomment the following line if your bare application
- // has an action associated with it:
- // Run: func(cmd *cobra.Command, args []string) { },
}
-// Execute adds all child commands to the root command and sets flags appropriately.
-// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
@@ -30,13 +24,4 @@ func Execute() {
}
func init() {
- // Here you will define your flags and configuration settings.
- // Cobra supports persistent flags, which, if defined here,
- // will be global for your application.
-
- // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.chat-tests.yaml)")
-
- // Cobra also supports local flags, which will only run
- // 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 7e2903a..918bf04 100644
--- a/cmd/server.go
+++ b/cmd/server.go
@@ -9,7 +9,6 @@ import (
"log"
)
-// serverCmd represents the server command
var serverCmd = &cobra.Command{
Use: "server",
Short: "Tiny chat server",
@@ -30,18 +29,8 @@ Example:
func init() {
rootCmd.AddCommand(serverCmd)
-
- // Here you will define your flags and configuration settings.
-
- // Cobra supports Persistent Flags which will work for this command
- // and all subcommands, e.g.:
- // serverCmd.PersistentFlags().String("foo", "", "A help for foo")
serverCmd.PersistentFlags().StringP("port", "p", "1302", "port to use for listening")
serverCmd.PersistentFlags().StringP("history", "r", "", "File to store and recover chat history from")
-
- // Cobra supports local flags which will only run when this command
- // is called directly, e.g.:
- // serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
func setServerParameters(cmd *cobra.Command) error {
--
2.30.2
From a615cb91944c2a216daa7b1f15bd59ead09a9175 Mon Sep 17 00:00:00 2001
From: raul
Date: Fri, 10 May 2024 09:50:26 +0200
Subject: [PATCH 03/25] Fix windows version being unable to take input
---
cmd/clientFunc.go | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index f8d2de8..770233f 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -7,13 +7,15 @@ package cmd
import (
"bufio"
"fmt"
- "github.com/jroimartin/gocui"
- "github.com/nsf/termbox-go"
"log"
"net"
"os"
+ "runtime"
"strings"
"time"
+
+ "github.com/jroimartin/gocui"
+ "github.com/nsf/termbox-go"
)
type Message struct {
@@ -92,13 +94,29 @@ func receiveMessage(conn net.Conn) (s string, err error) {
return finalMessage, nil
}
-func sendName(conn net.Conn) {
- message, err := bufio.NewReader(os.Stdin).ReadString('\n')
+func scanLine() (line string, err error) {
+ switch runtime.GOOS {
+ case "linux":
+ message, err := bufio.NewReader(os.Stdin).ReadString('\n')
+ if err != nil {
+ return "", err
+ }
+ line = message
+ case "windows":
+ message, err := bufio.NewReader(os.Stdin).ReadString('\r')
+ if err != nil {
+ return "", err
+ }
+ line = message
+ }
+ return line, nil
+}
+func sendName(conn net.Conn) {
+ message, err := scanLine()
if err != nil {
log.Fatalf("Error occurred sending message to server: %v\n", err)
}
-
Profile.Username = strings.TrimRight(message, "\n")
if _, err := conn.Write([]byte(message)); err != nil {
--
2.30.2
From 8cb40303dc17a908b50b0ba6d61a48d561554203 Mon Sep 17 00:00:00 2001
From: raul
Date: Mon, 13 May 2024 12:02:03 +0200
Subject: [PATCH 04/25] Add password parameter
---
cmd/server.go | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/cmd/server.go b/cmd/server.go
index 918bf04..10b4bd1 100644
--- a/cmd/server.go
+++ b/cmd/server.go
@@ -31,6 +31,7 @@ func init() {
rootCmd.AddCommand(serverCmd)
serverCmd.PersistentFlags().StringP("port", "p", "1302", "port to use for listening")
serverCmd.PersistentFlags().StringP("history", "r", "", "File to store and recover chat history from")
+ serverCmd.PersistentFlags().String("password", "", "Password for accessing the chat server")
}
func setServerParameters(cmd *cobra.Command) error {
@@ -49,5 +50,12 @@ func setServerParameters(cmd *cobra.Command) error {
logLocation = parameterHistory
isLogging = true
}
+ parPassword, err := cmd.Flags().GetString("password")
+ if err != nil {
+ return err
+ }
+ if parPassword != "" {
+ password = parPassword
+ }
return nil
}
--
2.30.2
From 99923c64b1c8d3f4f0a4bb058be058b7d24c3705 Mon Sep 17 00:00:00 2001
From: raul
Date: Mon, 13 May 2024 12:02:21 +0200
Subject: [PATCH 05/25] Handle passwords serverside
---
cmd/serverFunc.go | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go
index 97d9a10..f55b37e 100644
--- a/cmd/serverFunc.go
+++ b/cmd/serverFunc.go
@@ -15,6 +15,7 @@ import (
var (
listenPort string = "1302"
+ password string = ""
isLogging bool = false
logLocation string
listenerList []chan string
@@ -92,9 +93,31 @@ func populateChat(conn net.Conn) {
}
+func getPasswd(conn net.Conn) error {
+ conn.Write([]byte("Password: "))
+ userPassNewline, err := bufio.NewReader(conn).ReadString('\n')
+ userPass := strings.TrimRight(userPassNewline, "\n")
+ if err != nil {
+ e := fmt.Errorf("Node %v didn't respond to password prompt!\n", getIP(conn))
+ return e
+ }
+ if userPass != password {
+ e := fmt.Errorf("Node %v attempted connecting with an incorrect password!\n", getIP(conn))
+ return e
+ }
+ return nil
+}
+
func handleConn(conn net.Conn, chatChan chan string) {
defer conn.Close()
+ if password != "" {
+ if err := getPasswd(conn); err != nil {
+ log.Print(err)
+ return
+ }
+ }
+
go receiveMessageServer(conn, chatChan)
//////////////////////////////////
--
2.30.2
From 015e1bb65f9dfbf0103006b04623a938595dfae7 Mon Sep 17 00:00:00 2001
From: raul
Date: Mon, 13 May 2024 12:02:32 +0200
Subject: [PATCH 06/25] Handle passwords clientside
---
cmd/clientFunc.go | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index 770233f..8e50de0 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -7,6 +7,7 @@ package cmd
import (
"bufio"
"fmt"
+ "io"
"log"
"net"
"os"
@@ -53,7 +54,28 @@ func Client() {
log.Fatalf("Error occurred reading from server while requesting name: %v\n", err)
}
fmt.Print(nameRequest)
- sendName(conn)
+ test := make([]byte, 2048)
+ copy(test, "Password: ")
+
+ if nameRequest == string(test) {
+ pass, err := scanLine()
+ if err != nil {
+ log.Fatal(err)
+ }
+ conn.Write([]byte(pass))
+
+ nameRequest, err := receiveMessage(conn)
+ if err != nil {
+ if err != io.EOF {
+ log.Fatalf("Error occurred reading from server while requesting name: %v\n", err)
+ }
+ os.Exit(1)
+ }
+ fmt.Print(nameRequest)
+ sendName(conn)
+ } else {
+ sendName(conn)
+ }
GUI()
}
--
2.30.2
From 940d1287ec58bbadf7480a3c9de0441ae49190ce Mon Sep 17 00:00:00 2001
From: raul
Date: Mon, 13 May 2024 12:04:20 +0200
Subject: [PATCH 07/25] Stop showing errors on client Ctrl+C
---
cmd/clientFunc.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index 8e50de0..91fa534 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -97,7 +97,7 @@ func listenMessages(g *gocui.Gui) {
g.Close()
} else {
g.Close()
- log.Fatalf("Error occurred reading from server: %v\n", err)
+ os.Exit(1)
}
}
--
2.30.2
From e0f9c63a54d7a8a4a89483d3cc3202fb637a8bca Mon Sep 17 00:00:00 2001
From: raul
Date: Mon, 13 May 2024 13:04:45 +0200
Subject: [PATCH 08/25] Reduce latency time for synchronization
---
cmd/clientFunc.go | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index 91fa534..1da0934 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -84,7 +84,7 @@ func Client() {
////////////////////////////////////////////////////
func listenMessages(g *gocui.Gui) {
- time.Sleep(time.Millisecond * 250)
+ time.Sleep(time.Millisecond * 50)
chatbox, err := g.View("chatbox")
if err != nil {
log.Panicln(err)
@@ -92,7 +92,7 @@ func listenMessages(g *gocui.Gui) {
for {
messageFromServer, err := receiveMessage(data.Server)
if err != nil {
- // Avoid triggering an error if client quits the client
+ // What the hell is this
if err == gocui.ErrQuit {
g.Close()
} else {
@@ -254,6 +254,7 @@ func layout(g *gocui.Gui) error {
if err != gocui.ErrUnknownView {
return err
}
+
chatbox.Autoscroll = true
chatbox.Title = "Chat Box (Find source at https://git.bulgariu.xyz/raul/mini-chat!)"
}
--
2.30.2
From cc3f4fbcd60e72dc6b567c5d5b2118e5408a9cc2 Mon Sep 17 00:00:00 2001
From: raul
Date: Mon, 13 May 2024 13:08:37 +0200
Subject: [PATCH 09/25] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index c622535..d1c7166 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Tiny IRC-like chat server written in Go
## Usage examples
### Starting the server:
-./mini-chat server --port 1337 --history chat.log
+./mini-chat server --port 1337 --history chat.log --password verysecurepassword
### Connecting to the server:
./mini-chat client --ip 192.168.0.100 --port 1337
--
2.30.2
From fde175401e898f97dab62d1f4ef775605371ffdf Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 08:19:39 +0200
Subject: [PATCH 10/25] Update .gitignore
---
.gitignore | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.gitignore b/.gitignore
index 97ea58f..7368b61 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,8 @@
*.so
*.dylib
dist/
+server.crt
+server.key
# Test binary, built with `go test -c`
*.test
--
2.30.2
From e3b681e90490188be61ab1e7045668d40ec80375 Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 09:06:24 +0200
Subject: [PATCH 11/25] Add gen-cert.sh
---
cmd/gen-cert.sh | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100755 cmd/gen-cert.sh
diff --git a/cmd/gen-cert.sh b/cmd/gen-cert.sh
new file mode 100755
index 0000000..d5b25f2
--- /dev/null
+++ b/cmd/gen-cert.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+SSLCOMMAND=$(which openssl)
+
+echo "[+] Generating server.key..."
+$SSLCOMMAND genrsa -out server.key 2048
+
+echo "[+] Generating server.crt..."
+$SSLCOMMAND req -new -x509 -sha256 -key server.key -out server.crt -days 3650 -subj "/C=ES/ST=Valencia/L=Valencia/O=mini-chat /OU=mini-chat/CN=mini-chat"
+
+echo "[+] Success!"
--
2.30.2
From 0f33d13d6a9157ff5e5ea8324a7157c7964441b8 Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 09:06:45 +0200
Subject: [PATCH 12/25] Implement serverside TLS
---
cmd/serverFunc.go | 49 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go
index f55b37e..3759b94 100644
--- a/cmd/serverFunc.go
+++ b/cmd/serverFunc.go
@@ -6,10 +6,13 @@ package cmd
import (
"bufio"
+ "crypto/tls"
+ _ "embed"
"fmt"
"log"
"net"
"os"
+ "os/exec"
"strings"
)
@@ -19,8 +22,12 @@ var (
isLogging bool = false
logLocation string
listenerList []chan string
+ servInsecure bool
)
+//go:embed gen-cert.sh
+var script string
+
type User struct {
Username string
IP string
@@ -32,8 +39,46 @@ func (u User) CreateUser(usr string, ip string) User {
return u
}
-func Server() {
+func createCerts() {
+ fmt.Println("[-] Certificates don't exist! Creating them...")
+ c := exec.Command("bash")
+ c.Stdin = strings.NewReader(script)
+ b, err := c.Output()
+ if err != nil {
+ log.Fatalf("Error occurred creating certificates: %v\n", err)
+ }
+ fmt.Print(string(b))
+}
+
+func startInsecureServer() (net.Listener, error) {
ln, err := net.Listen("tcp", ":"+listenPort)
+ return ln, err
+}
+
+func startSecureServer() (net.Listener, error) {
+
+}
+
+func Server() {
+ var ln net.Listener
+ var err error
+ if servInsecure == true {
+ ln, err = startInsecureServer()
+ } else {
+ ln, err = startSecureServer()
+ }
+ cer, err := tls.LoadX509KeyPair("server.crt", "server.key")
+ if os.IsNotExist(err) {
+ createCerts()
+ cer, err = tls.LoadX509KeyPair("server.crt", "server.key")
+ }
+ if err != nil {
+ log.Fatalf("Error happened loading certificates: %v\n", err)
+ }
+ config := &tls.Config{Certificates: []tls.Certificate{cer}}
+
+ ln, err := tls.Listen("tcp", ":"+listenPort, config)
+
if err != nil {
log.Fatalf("Error happened trying to listen on port: %v\n", err)
}
@@ -44,7 +89,7 @@ func Server() {
if err != nil {
log.Fatalf("Error happened trying to accept connection: %v\n", err)
}
- chatChan := make(chan string, 10)
+ chatChan := make(chan string, 30)
listenerList = append(listenerList, chatChan)
go handleConn(conn, chatChan)
}
--
2.30.2
From 51b0dd5258a7cf0a3e3e532dbbe957c900613b52 Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 09:07:00 +0200
Subject: [PATCH 13/25] Implement clientside TLS
---
cmd/clientFunc.go | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index 1da0934..73d67f2 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -6,6 +6,7 @@ package cmd
import (
"bufio"
+ "crypto/tls"
"fmt"
"io"
"log"
@@ -42,7 +43,11 @@ var (
)
func Client() {
- conn, err := net.Dial("tcp", serverIP+":"+serverPort)
+ //conn, err := net.Dial("tcp", serverIP+":"+serverPort)
+ conf := &tls.Config{
+ InsecureSkipVerify: true,
+ }
+ conn, err := tls.Dial("tcp", serverIP+":"+serverPort, conf)
if err != nil {
log.Fatalf("Error occurred trying to connect to server: %v\n", err)
}
--
2.30.2
From afafb126637b4d2647a07ec0adb93fe12ca10a3b Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 09:11:22 +0200
Subject: [PATCH 14/25] Implement choosing TLS/plaintext for server
---
cmd/server.go | 5 +++++
cmd/serverFunc.go | 24 ++++++++++++------------
2 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/cmd/server.go b/cmd/server.go
index 10b4bd1..a83c38b 100644
--- a/cmd/server.go
+++ b/cmd/server.go
@@ -32,6 +32,7 @@ func init() {
serverCmd.PersistentFlags().StringP("port", "p", "1302", "port to use for listening")
serverCmd.PersistentFlags().StringP("history", "r", "", "File to store and recover chat history from")
serverCmd.PersistentFlags().String("password", "", "Password for accessing the chat server")
+ serverCmd.Flags().Bool("insecure", false, "[UNSAFE] Do not use TLS encryption")
}
func setServerParameters(cmd *cobra.Command) error {
@@ -57,5 +58,9 @@ func setServerParameters(cmd *cobra.Command) error {
if parPassword != "" {
password = parPassword
}
+ insecure, err := cmd.Flags().GetBool("insecure")
+ if insecure == true {
+ servInsecure = true
+ }
return nil
}
diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go
index 3759b94..447b60c 100644
--- a/cmd/serverFunc.go
+++ b/cmd/serverFunc.go
@@ -56,17 +56,6 @@ func startInsecureServer() (net.Listener, error) {
}
func startSecureServer() (net.Listener, error) {
-
-}
-
-func Server() {
- var ln net.Listener
- var err error
- if servInsecure == true {
- ln, err = startInsecureServer()
- } else {
- ln, err = startSecureServer()
- }
cer, err := tls.LoadX509KeyPair("server.crt", "server.key")
if os.IsNotExist(err) {
createCerts()
@@ -76,8 +65,19 @@ func Server() {
log.Fatalf("Error happened loading certificates: %v\n", err)
}
config := &tls.Config{Certificates: []tls.Certificate{cer}}
-
ln, err := tls.Listen("tcp", ":"+listenPort, config)
+ return ln, err
+}
+
+func Server() {
+ var ln net.Listener
+ var err error
+ if servInsecure == true {
+ fmt.Println("[WARNING] Starting unencrypted server!")
+ ln, err = startInsecureServer()
+ } else {
+ ln, err = startSecureServer()
+ }
if err != nil {
log.Fatalf("Error happened trying to listen on port: %v\n", err)
--
2.30.2
From 7493af68fcb3aa189612dcdc1266cfa14a9944ed Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 09:26:45 +0200
Subject: [PATCH 15/25] Implement choosing TLS/plaintext for client
---
cmd/client.go | 6 ++++++
cmd/clientFunc.go | 28 +++++++++++++++++++++++-----
2 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/cmd/client.go b/cmd/client.go
index 6f658e1..78a63f3 100644
--- a/cmd/client.go
+++ b/cmd/client.go
@@ -36,6 +36,7 @@ func init() {
rootCmd.AddCommand(clientCmd)
clientCmd.PersistentFlags().StringP("ip", "i", "", "Server IP to connect to")
clientCmd.PersistentFlags().StringP("port", "p", "1302", "Server port to connect to")
+ clientCmd.Flags().Bool("insecure", false, "[UNSAFE] Do not use TLS encryption")
}
func setClientParameters(cmd *cobra.Command) error {
@@ -57,5 +58,10 @@ func setClientParameters(cmd *cobra.Command) error {
}
serverIP = parameterIP
+ insecure, err := cmd.Flags().GetBool("insecure")
+ if insecure == true {
+ clientInsecure = true
+ }
+
return nil
}
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index 73d67f2..e74ecf3 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -37,17 +37,35 @@ func (m Message) toSend() {
}
var (
- serverPort string = "1302"
- serverIP string
- data Message
+ serverPort string = "1302"
+ serverIP string
+ data Message
+ clientInsecure bool
)
-func Client() {
- //conn, err := net.Dial("tcp", serverIP+":"+serverPort)
+func startSecureConnection() (net.Conn, error) {
conf := &tls.Config{
InsecureSkipVerify: true,
}
conn, err := tls.Dial("tcp", serverIP+":"+serverPort, conf)
+ return conn, err
+}
+
+func startInsecureConnection() (net.Conn, error) {
+ conn, err := net.Dial("tcp", serverIP+":"+serverPort)
+ return conn, err
+}
+
+func Client() {
+ var conn net.Conn
+ var err error
+ if clientInsecure == true {
+ fmt.Println("WARNING: Starting unencrypted connection!")
+ conn, err = startInsecureConnection()
+ } else {
+ conn, err = startSecureConnection()
+ }
+
if err != nil {
log.Fatalf("Error occurred trying to connect to server: %v\n", err)
}
--
2.30.2
From 872523700b5964e7fa0a98070a2e9ac1d350bbe1 Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 09:27:23 +0200
Subject: [PATCH 16/25] Minor formatting changes
---
cmd/server.go | 3 +++
cmd/serverFunc.go | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/cmd/server.go b/cmd/server.go
index a83c38b..a2a4ffb 100644
--- a/cmd/server.go
+++ b/cmd/server.go
@@ -43,6 +43,7 @@ func setServerParameters(cmd *cobra.Command) error {
if parameterPort != "" {
listenPort = parameterPort
}
+
parameterHistory, err := cmd.Flags().GetString("history")
if err != nil {
return err
@@ -51,6 +52,7 @@ func setServerParameters(cmd *cobra.Command) error {
logLocation = parameterHistory
isLogging = true
}
+
parPassword, err := cmd.Flags().GetString("password")
if err != nil {
return err
@@ -58,6 +60,7 @@ func setServerParameters(cmd *cobra.Command) error {
if parPassword != "" {
password = parPassword
}
+
insecure, err := cmd.Flags().GetBool("insecure")
if insecure == true {
servInsecure = true
diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go
index 447b60c..75c569b 100644
--- a/cmd/serverFunc.go
+++ b/cmd/serverFunc.go
@@ -73,7 +73,7 @@ func Server() {
var ln net.Listener
var err error
if servInsecure == true {
- fmt.Println("[WARNING] Starting unencrypted server!")
+ fmt.Println("WARNING: Starting unencrypted server!")
ln, err = startInsecureServer()
} else {
ln, err = startSecureServer()
--
2.30.2
From 6d15f303b7378d5a129d6dde00f6a70f509d5427 Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 09:58:09 +0200
Subject: [PATCH 17/25] Fix extra newlines being appended by populateChat() on
TLS based servers
For some reason, writing to a conn variable on a TLS connection
appends newlines by default, so new users will have their chat box
populated if the server is using --history/-r with messages that have
unnecessary newlines
---
cmd/serverFunc.go | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go
index 75c569b..44857a8 100644
--- a/cmd/serverFunc.go
+++ b/cmd/serverFunc.go
@@ -132,10 +132,18 @@ func populateChat(conn net.Conn) {
}
defer file.Close()
scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- conn.Write([]byte(fmt.Sprintln(scanner.Text())))
+ // For WHATEVER reason, writing to a TLS-based conn here appends newlines by default,
+ // so we have to split it off here to avoid ending up with chat logs full of
+ // unnecessary newlines
+ if servInsecure == true {
+ for scanner.Scan() {
+ conn.Write([]byte(fmt.Sprintln(scanner.Text())))
+ }
+ } else {
+ for scanner.Scan() {
+ conn.Write([]byte(fmt.Sprint(scanner.Text())))
+ }
}
-
}
func getPasswd(conn net.Conn) error {
--
2.30.2
From e7aada9a2a30a632bd8ac1dfbcc8525bc9056aa1 Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 10:05:02 +0200
Subject: [PATCH 18/25] Update README.md
---
README.md | 35 ++++++++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index d1c7166..028c3e6 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,34 @@ Tiny IRC-like chat server written in Go
-## Usage examples
-### Starting the server:
-./mini-chat server --port 1337 --history chat.log --password verysecurepassword
+## Commands
+### Client
+```
+Example:
+ ./mini-chat client --ip 192.168.0.100 --port 1337
-### Connecting to the server:
-./mini-chat client --ip 192.168.0.100 --port 1337
+Usage:
+ mini-chat client [flags]
+
+Flags:
+ -h, --help help for client
+ --insecure [UNSAFE] Do not use TLS encryption
+ -i, --ip string Server IP to connect to
+ -p, --port string Server port to connect to (default "1302")
+```
+
+### Server
+```
+Example:
+ ./mini-chat server --port 1337
+
+Usage:
+ mini-chat server [flags]
+
+Flags:
+ -h, --help help for server
+ -r, --history string File to store and recover chat history from
+ --insecure [UNSAFE] Do not use TLS encryption
+ --password string Password for accessing the chat server
+ -p, --port string port to use for listening (default "1302")
+```
--
2.30.2
From 5bb37a53feb7430e2e3966c195455924a3059125 Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 15:30:16 +0200
Subject: [PATCH 19/25] Add date formatting to messages
I also went ahead and removed adding the user's IP to each one of its
messages to retain the user's privacy and security.
---
cmd/serverFunc.go | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/cmd/serverFunc.go b/cmd/serverFunc.go
index 44857a8..74b679e 100644
--- a/cmd/serverFunc.go
+++ b/cmd/serverFunc.go
@@ -14,6 +14,7 @@ import (
"os"
"os/exec"
"strings"
+ "time"
)
var (
@@ -69,6 +70,12 @@ func startSecureServer() (net.Listener, error) {
return ln, err
}
+func getTime() string {
+ t := time.Now()
+ currentTime := fmt.Sprintf("%d-%02d-%02d | %02d:%02d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
+ return currentTime
+}
+
func Server() {
var ln net.Listener
var err error
@@ -188,8 +195,8 @@ func handleConn(conn net.Conn, chatChan chan string) {
newUserTemplate := new(User)
newUser := newUserTemplate.CreateUser(userName, userIP)
- joinMessage := fmt.Sprintf("%v has joined the chat!", newUser.Username)
- fmt.Println(joinMessage)
+ joinMessage := fmt.Sprintf("[%v] %v has joined the chat!", getTime(), newUser.Username)
+ fmt.Println(joinMessage + " [" + newUser.IP + "]")
addToLog(fmt.Sprintln(joinMessage))
//conn.Write([]byte(joinMessage))
sendMessage(joinMessage)
@@ -198,8 +205,8 @@ func handleConn(conn net.Conn, chatChan chan string) {
for {
message, err := getUserInput(conn)
if err != nil {
- quitMessage := fmt.Sprintf("%v has disconnected!", newUser.Username)
- fmt.Println(quitMessage)
+ quitMessage := fmt.Sprintf("[%v] %v has disconnected!", getTime(), newUser.Username)
+ fmt.Println(quitMessage + " [" + newUser.IP + "]")
addToLog(fmt.Sprintln(quitMessage))
sendMessage(quitMessage)
//removeFromList(chatChan)
@@ -208,7 +215,7 @@ func handleConn(conn net.Conn, chatChan chan string) {
// }
return
}
- finalMessage := fmt.Sprintf("[%v] %v: %v", newUser.IP, newUser.Username, strings.TrimRight(message, "\n"))
+ finalMessage := fmt.Sprintf("[%v] %v: %v", getTime(), newUser.Username, strings.TrimRight(message, "\n"))
fm := fmt.Sprintf("%v\n", finalMessage)
fmt.Print(fm)
addToLog(fm)
--
2.30.2
From a21199a6e0448b9783edac40cedebfd63da78df7 Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 15:31:55 +0200
Subject: [PATCH 20/25] Optimize client RAM memory usage
The receiveMessage() function would regularly keep casting strings based
on a 2048 byte array, this didn't seemingly pose a problem until I
noticed the RAM usage go through the roof when the client had to be
populated with the chat history of a lengthy chat log by the server. To
fix this I am now creating a second array using the number of bytes
being returned by the Read() method and copying the 2048 byte array's
contents into it, setting the former array to nil afterwards.
---
cmd/clientFunc.go | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index e74ecf3..abdc46f 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -72,12 +72,12 @@ func Client() {
defer conn.Close()
data.Server = conn
- nameRequest, err := receiveMessage(conn)
+ nameRequest, b, err := receiveMessage(conn)
if err != nil {
log.Fatalf("Error occurred reading from server while requesting name: %v\n", err)
}
fmt.Print(nameRequest)
- test := make([]byte, 2048)
+ test := make([]byte, b)
copy(test, "Password: ")
if nameRequest == string(test) {
@@ -87,7 +87,7 @@ func Client() {
}
conn.Write([]byte(pass))
- nameRequest, err := receiveMessage(conn)
+ nameRequest, _, err := receiveMessage(conn)
if err != nil {
if err != io.EOF {
log.Fatalf("Error occurred reading from server while requesting name: %v\n", err)
@@ -113,7 +113,7 @@ func listenMessages(g *gocui.Gui) {
log.Panicln(err)
}
for {
- messageFromServer, err := receiveMessage(data.Server)
+ messageFromServer, _, err := receiveMessage(data.Server)
if err != nil {
// What the hell is this
if err == gocui.ErrQuit {
@@ -130,13 +130,20 @@ func listenMessages(g *gocui.Gui) {
}
}
-func receiveMessage(conn net.Conn) (s string, err error) {
+func receiveMessage(conn net.Conn) (s string, b int, err error) {
serverMessage := make([]byte, 2048)
- if _, err := conn.Read(serverMessage); err != nil {
- return "", err
+ n, err := conn.Read(serverMessage)
+ if err != nil {
+ return "", 0, err
}
- finalMessage := string(serverMessage)
- return finalMessage, nil
+
+ serverMessageReduced := make([]byte, n)
+ copy(serverMessageReduced, serverMessage)
+
+ finalMessage := string(serverMessageReduced)
+ serverMessage = nil
+
+ return finalMessage, n, nil
}
func scanLine() (line string, err error) {
--
2.30.2
From 93c76f42424280db23ea07fddc92370c64ccbe34 Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 15:42:03 +0200
Subject: [PATCH 21/25] Add chatbox text wrapping
How the hell did I manage to forget about this?
---
cmd/clientFunc.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index abdc46f..1e3c6de 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -287,6 +287,7 @@ func layout(g *gocui.Gui) error {
chatbox.Autoscroll = true
chatbox.Title = "Chat Box (Find source at https://git.bulgariu.xyz/raul/mini-chat!)"
+ chatbox.Wrap = true
}
// if button, err := g.SetView("button", maxX/2+32, maxY-4, maxX-28, maxY-2); err != nil {
--
2.30.2
From b2f9ff501674c38621092ab3d9efeefbec6f9c8f Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 15:59:23 +0200
Subject: [PATCH 22/25] Small tweaks
---
README.md | 4 ++--
cmd/clientFunc.go | 2 +-
cmd/server.go | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index 028c3e6..a4086da 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ Flags:
### Server
```
Example:
- ./mini-chat server --port 1337
+ ./mini-chat server --port 1337 --history chat.log --password coolh4x0r1337
Usage:
mini-chat server [flags]
@@ -35,5 +35,5 @@ Flags:
-r, --history string File to store and recover chat history from
--insecure [UNSAFE] Do not use TLS encryption
--password string Password for accessing the chat server
- -p, --port string port to use for listening (default "1302")
+ -p, --port string Port to use for listening (default "1302")
```
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index 1e3c6de..b1b6518 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -131,7 +131,7 @@ func listenMessages(g *gocui.Gui) {
}
func receiveMessage(conn net.Conn) (s string, b int, err error) {
- serverMessage := make([]byte, 2048)
+ serverMessage := make([]byte, 1536)
n, err := conn.Read(serverMessage)
if err != nil {
return "", 0, err
diff --git a/cmd/server.go b/cmd/server.go
index a2a4ffb..c7b0142 100644
--- a/cmd/server.go
+++ b/cmd/server.go
@@ -16,7 +16,7 @@ var serverCmd = &cobra.Command{
using a proper interface this time, not using netcat.
Example:
- ./mini-chat server --port 1337`,
+ ./mini-chat server --port 1337 --history chat.log --password coolh4x0r1337`,
Run: func(cmd *cobra.Command, args []string) {
if err := setServerParameters(cmd); err != nil {
@@ -29,7 +29,7 @@ Example:
func init() {
rootCmd.AddCommand(serverCmd)
- serverCmd.PersistentFlags().StringP("port", "p", "1302", "port to use for listening")
+ serverCmd.PersistentFlags().StringP("port", "p", "1302", "Port to use for listening")
serverCmd.PersistentFlags().StringP("history", "r", "", "File to store and recover chat history from")
serverCmd.PersistentFlags().String("password", "", "Password for accessing the chat server")
serverCmd.Flags().Bool("insecure", false, "[UNSAFE] Do not use TLS encryption")
--
2.30.2
From c7a34a7d9391fcdd229209e65533858446eb832d Mon Sep 17 00:00:00 2001
From: raul
Date: Tue, 14 May 2024 16:31:36 +0200
Subject: [PATCH 23/25] Add option to render client UI in pure ASCII
---
README.md | 1 +
cmd/client.go | 5 +++++
cmd/clientFunc.go | 4 ++++
3 files changed, 10 insertions(+)
diff --git a/README.md b/README.md
index a4086da..b7d6f61 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@ Usage:
mini-chat client [flags]
Flags:
+ -a, --ascii Render UI in pure ASCII, might help with rendering issues
-h, --help help for client
--insecure [UNSAFE] Do not use TLS encryption
-i, --ip string Server IP to connect to
diff --git a/cmd/client.go b/cmd/client.go
index 78a63f3..cf8507d 100644
--- a/cmd/client.go
+++ b/cmd/client.go
@@ -37,6 +37,7 @@ func init() {
clientCmd.PersistentFlags().StringP("ip", "i", "", "Server IP to connect to")
clientCmd.PersistentFlags().StringP("port", "p", "1302", "Server port to connect to")
clientCmd.Flags().Bool("insecure", false, "[UNSAFE] Do not use TLS encryption")
+ clientCmd.Flags().BoolP("ascii", "a", false, "Render UI in pure ASCII, might help with rendering issues")
}
func setClientParameters(cmd *cobra.Command) error {
@@ -63,5 +64,9 @@ func setClientParameters(cmd *cobra.Command) error {
clientInsecure = true
}
+ ascii, err := cmd.Flags().GetBool("ascii")
+ if ascii == true {
+ useASCII = true
+ }
return nil
}
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index b1b6518..2f6090b 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -41,6 +41,7 @@ var (
serverIP string
data Message
clientInsecure bool
+ useASCII bool
)
func startSecureConnection() (net.Conn, error) {
@@ -185,6 +186,9 @@ func GUI() {
g.SetManagerFunc(layout)
g.Mouse = true
g.Cursor = true
+ if useASCII == true {
+ g.ASCII = true
+ }
initKeybindings(g)
go listenMessages(g)
--
2.30.2
From ff801f81d025611bf6de06437bc077a8d52a02f1 Mon Sep 17 00:00:00 2001
From: raul
Date: Thu, 16 May 2024 08:10:19 +0200
Subject: [PATCH 24/25] Final tweaks
---
cmd/client.go | 3 +++
cmd/clientFunc.go | 9 ++-------
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/cmd/client.go b/cmd/client.go
index cf8507d..5ae7199 100644
--- a/cmd/client.go
+++ b/cmd/client.go
@@ -65,6 +65,9 @@ func setClientParameters(cmd *cobra.Command) error {
}
ascii, err := cmd.Flags().GetBool("ascii")
+ if err != nil {
+ return err
+ }
if ascii == true {
useASCII = true
}
diff --git a/cmd/clientFunc.go b/cmd/clientFunc.go
index 2f6090b..85ef25e 100644
--- a/cmd/clientFunc.go
+++ b/cmd/clientFunc.go
@@ -116,13 +116,8 @@ func listenMessages(g *gocui.Gui) {
for {
messageFromServer, _, err := receiveMessage(data.Server)
if err != nil {
- // What the hell is this
- if err == gocui.ErrQuit {
- g.Close()
- } else {
- g.Close()
- os.Exit(1)
- }
+ g.Close()
+ os.Exit(0)
}
formattedMessage := strings.TrimRight(messageFromServer, "\n")
--
2.30.2
From c837e78c7ce40131e2ccf43c5ced2db8793da1a4 Mon Sep 17 00:00:00 2001
From: raul
Date: Fri, 17 May 2024 07:59:04 +0200
Subject: [PATCH 25/25] Remove workflow file
The damn runner keeps making too many POST requests per minute to my
Gitea instance and flooding the entire access.log file, I'm gonna keep
using Goreleaser for easy binary releases but CI/CD unfortunately has to
go away
---
.gitea/workflows/go-audit.yaml | 25 -------------------------
1 file changed, 25 deletions(-)
delete mode 100644 .gitea/workflows/go-audit.yaml
diff --git a/.gitea/workflows/go-audit.yaml b/.gitea/workflows/go-audit.yaml
deleted file mode 100644
index 70c5e4b..0000000
--- a/.gitea/workflows/go-audit.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
-name: Go audit
-run-name: ${{ gitea.actor }} pulled to main! 🚀
-on:
- pull_request:
- branches: [main]
-jobs:
- audit:
- runs-on: ubuntu-latest
- steps:
-
- - uses: actions/checkout@v2
-
- - name: Set up Go
- uses: actions/setup-go@v2
- with:
- go-version: '>=1.22.0'
-
- - name: Verify dependencies
- run: go mod verify
-
- - name: Build
- run: go build -v ./...
-
- - name: Run go vet
- run: go vet ./...
--
2.30.2