commit f74b68a36be462737b8e07e47b7287d341dd8687
parent 6f59b78e2f686dd95a96076ed7444c18ec810ba9
Author: mdnrz <mehdeenoroozi@gmail.com>
Date: Tue, 8 Apr 2025 01:07:04 +0330
add README.md and rename module
Diffstat:
| M | .gitignore | | | 2 | +- |
| A | LICENSE | | | 19 | +++++++++++++++++++ |
| A | README.md | | | 5 | +++++ |
| M | go.mod | | | 2 | +- |
| A | gotel.go | | | 112 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| D | hello.go | | | 112 | ------------------------------------------------------------------------------- |
6 files changed, 138 insertions(+), 114 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1 +1 @@
-hello
+gotel
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,19 @@
+Copyright 2025 Mehdi Noroozi <mehdeenoroozi@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
@@ -0,0 +1,5 @@
+# GoTel
+
+Simple telnet multi-user chat program.
+
+My attempt at learning golang.
diff --git a/go.mod b/go.mod
@@ -1,3 +1,3 @@
-module hello
+module gotel
go 1.24.0
diff --git a/gotel.go b/gotel.go
@@ -0,0 +1,112 @@
+package main
+
+import (
+ "log"
+ "net"
+ "time"
+ "strings"
+)
+
+type msgType int
+
+const (
+ msgConnect msgType = iota + 1
+ msgLogin
+ msgText
+ msgQuit
+)
+
+type Client struct {
+ UserName string
+ Request msgType
+ Strike int
+ Banned bool
+ BannedAt time.Time
+ Conn net.Conn
+ Text string
+}
+
+const Port = "6969"
+
+func addClient(conn net.Conn, Client_q chan Client) {
+ loginPrompt := "Who are you?\n> "
+ _, err := conn.Write([]byte(loginPrompt))
+ if err != nil {
+ log.Printf("[ERROR] Could not send login prompt to user %s: %s\n",
+ conn.RemoteAddr().String(), err)
+ }
+ readBuf := make([]byte, 512)
+ for {
+ n, err := conn.Read(readBuf)
+ if err != nil {
+ log.Printf("Could not read message from client %s: %s\n", conn.RemoteAddr().String(), err)
+ conn.Close()
+ return
+ }
+ Client_q <- Client {
+ Request: msgText,
+ Conn: conn,
+ Text: string(readBuf[:n]),
+ }
+ }
+}
+
+func server(Client_q chan Client) {
+ clientsOnline := make(map[string]Client)
+ clientsOffline := make(map[string]Client)
+ for {
+ client := <-Client_q
+ keyString := client.Conn.RemoteAddr().String();
+ switch client.Request {
+ case msgConnect:
+ log.Printf("Got login request from %s\n", keyString);
+ clientsOffline[keyString] = client;
+ case msgText:
+ clientOffline, ok := clientsOffline[keyString];
+ if ok {
+ clientOffline.UserName = strings.TrimRight(client.Text, "\r\n");
+ log.Printf("logging in %s\n", clientOffline.UserName);
+ clientsOnline[keyString] = clientOffline;
+ delete(clientsOffline, keyString);
+ _, err := clientsOnline[keyString].Conn.Write([]byte("Welcome " + clientsOnline[keyString].UserName + "\n\n"));
+ if err != nil {
+ log.Printf("Could not send message to client %s\n", clientsOnline[keyString].UserName)
+ }
+ break;
+ }
+ author, _ := clientsOnline[keyString];
+ author.Text = client.Text;
+ for _, value := range clientsOnline {
+ if value.Conn == author.Conn {
+ continue
+ }
+ _, err := value.Conn.Write([]byte(author.UserName + ": " + author.Text))
+ if err != nil {
+ log.Printf("Could not send message to client %s\n", value.UserName)
+ }
+ }
+ }
+ }
+}
+
+func main() {
+ ln, err := net.Listen("tcp", ":"+Port)
+ if err != nil {
+ log.Fatalf("Could not listen to port %s: %s\n", Port, err)
+ }
+ Client_q := make(chan Client)
+ go server(Client_q)
+ for {
+ conn, err := ln.Accept()
+ if err != nil {
+ log.Printf("Could not accept the connection: %s\n", err)
+ continue
+ }
+ log.Printf("Accepted connection from %s", conn.RemoteAddr())
+ Client_q <- Client {
+ Request: msgConnect,
+ Conn: conn,
+ }
+ go addClient(conn, Client_q)
+ }
+}
diff --git a/hello.go b/hello.go
@@ -1,112 +0,0 @@
-package main
-
-import (
- "log"
- "net"
- "time"
- "strings"
-)
-
-type msgType int
-
-const (
- msgConnect msgType = iota + 1
- msgLogin
- msgText
- msgQuit
-)
-
-type Client struct {
- UserName string
- Request msgType
- Strike int
- Banned bool
- BannedAt time.Time
- Conn net.Conn
- Text string
-}
-
-const Port = "6969"
-
-func client(conn net.Conn, Client_q chan Client) {
- loginPrompt := "Who are you?\n> "
- _, err := conn.Write([]byte(loginPrompt))
- if err != nil {
- log.Printf("[ERROR] Could not send login prompt to user %s: %s\n",
- conn.RemoteAddr().String(), err)
- }
- readBuf := make([]byte, 512)
- for {
- n, err := conn.Read(readBuf)
- if err != nil {
- log.Printf("Could not read message from client %s: %s\n", conn.RemoteAddr().String(), err)
- conn.Close()
- return
- }
- Client_q <- Client {
- Request: msgText,
- Conn: conn,
- Text: string(readBuf[:n]),
- }
- }
-}
-
-func server(Client_q chan Client) {
- clientsOnline := make(map[string]Client)
- clientsOffline := make(map[string]Client)
- for {
- client := <-Client_q
- keyString := client.Conn.RemoteAddr().String();
- switch client.Request {
- case msgConnect:
- log.Printf("Got login request from %s\n", keyString);
- clientsOffline[keyString] = client;
- case msgText:
- clientOffline, ok := clientsOffline[keyString];
- if ok {
- clientOffline.UserName = strings.TrimRight(client.Text, "\r\n");
- log.Printf("logging in %s\n", clientOffline.UserName);
- clientsOnline[keyString] = clientOffline;
- delete(clientsOffline, keyString);
- _, err := clientsOnline[keyString].Conn.Write([]byte("Welcome " + clientsOnline[keyString].UserName + "\n\n"));
- if err != nil {
- log.Printf("Could not send message to client %s\n", clientsOnline[keyString].UserName)
- }
- break;
- }
- author, _ := clientsOnline[keyString];
- author.Text = client.Text;
- for _, value := range clientsOnline {
- if value.Conn == author.Conn {
- continue
- }
- _, err := value.Conn.Write([]byte(author.UserName + ": " + author.Text))
- if err != nil {
- log.Printf("Could not send message to client %s\n", value.UserName)
- }
- }
- }
- }
-}
-
-func main() {
- ln, err := net.Listen("tcp", ":"+Port)
- if err != nil {
- log.Fatalf("Could not listen to port %s: %s\n", Port, err)
- }
- Client_q := make(chan Client)
- go server(Client_q)
- for {
- conn, err := ln.Accept()
- if err != nil {
- log.Printf("Could not accept the connection: %s\n", err)
- continue
- }
- log.Printf("Accepted connection from %s", conn.RemoteAddr())
- Client_q <- Client {
- Request: msgConnect,
- Conn: conn,
- }
- go client(conn, Client_q)
- }
-}