Skip to content

Commit 1b414f4

Browse files
authored
[CONFIG] Add configurable broadcast and chat ports (#22)
* Ports added * Bugs fixed * chat_test updated(goroutine safe operation)
1 parent 590ecde commit 1b414f4

8 files changed

Lines changed: 97 additions & 33 deletions

File tree

cmd/root.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66

77
tea "github.com/charmbracelet/bubbletea"
88
"github.com/huseynovvusal/goch/internal/chat"
9-
"github.com/huseynovvusal/goch/internal/config"
9+
"github.com/huseynovvusal/goch/internal/db"
1010
"github.com/huseynovvusal/goch/internal/discovery"
1111
"github.com/huseynovvusal/goch/internal/tui"
1212
"github.com/spf13/cobra"
@@ -19,10 +19,18 @@ var rootCmd = &cobra.Command{
1919
over a local area network (LAN). It supports multiple users, private messaging, and
2020
various customization options.`,
2121
Run: func(cmd *cobra.Command, args []string) {
22-
go discovery.ListenForPresence(config.BROADCAST_PORT)
22+
cfg := db.Config{BroadCastPort: db.DefaultBroadcastPort, ChatPort: db.DefaultChatPort}
23+
store := db.NewConfigStore()
24+
if store.Exists() {
25+
if loadedCfg, err := store.Load(); err == nil {
26+
cfg = loadedCfg.WithDefaults()
27+
}
28+
}
29+
30+
go discovery.ListenForPresence(cfg.BroadCastPort)
2331

2432
chatMessages := make(chan chat.NetworkMessage)
25-
go chat.ListenForChatMessages(chatMessages)
33+
go chat.ListenForChatMessages(chatMessages, cfg.ChatPort)
2634

2735
p := tea.NewProgram(tui.NewMainModel(chatMessages), tea.WithAltScreen())
2836
mainModel, err := p.Run()

internal/chat/chat.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"net"
77
"time"
88

9-
"github.com/huseynovvusal/goch/internal/config"
109
"github.com/huseynovvusal/goch/internal/discovery"
1110
)
1211

@@ -16,10 +15,10 @@ type NetworkMessage struct {
1615
Timestamp time.Time `json:"timestamp"`
1716
}
1817

19-
func SendChatMessage(content string, to discovery.NetworkUser, from discovery.NetworkUser) error {
18+
func SendChatMessage(content string, to discovery.NetworkUser, from discovery.NetworkUser, chatPort int) error {
2019
addr := &net.UDPAddr{
2120
IP: net.ParseIP(to.IP),
22-
Port: config.CHAT_PORT,
21+
Port: chatPort,
2322
}
2423
conn, err := net.DialUDP("udp", nil, addr)
2524
if err != nil {
@@ -42,10 +41,10 @@ func SendChatMessage(content string, to discovery.NetworkUser, from discovery.Ne
4241
return err
4342
}
4443

45-
func ListenForChatMessages(messages chan<- NetworkMessage) {
44+
func ListenForChatMessages(messages chan<- NetworkMessage, chatPort int) {
4645
addr := net.UDPAddr{
4746
IP: net.IPv4zero,
48-
Port: config.CHAT_PORT,
47+
Port: chatPort,
4948
}
5049
conn, err := net.ListenUDP("udp", &addr)
5150
if err != nil {

internal/chat/chat_test.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
package chat
1+
package chat_test
22

33
import (
44
"encoding/json"
55
"net"
66
"testing"
77
"time"
88

9-
"github.com/huseynovvusal/goch/internal/config"
9+
"github.com/huseynovvusal/goch/internal/chat"
10+
"github.com/huseynovvusal/goch/internal/db"
1011
"github.com/huseynovvusal/goch/internal/discovery"
1112
)
1213

@@ -16,7 +17,7 @@ func TestSendChatMessage(t *testing.T) {
1617
// and verify that the content and sender information are correct.
1718
addr := &net.UDPAddr{
1819
IP: net.ParseIP("127.0.0.1"),
19-
Port: config.CHAT_PORT,
20+
Port: db.DefaultChatPort,
2021
}
2122

2223
conn, err := net.ListenUDP("udp", addr)
@@ -29,12 +30,19 @@ func TestSendChatMessage(t *testing.T) {
2930
to := discovery.NetworkUser{IP: "127.0.0.1", Name: "Receiver"}
3031
content := "Hello, World!"
3132

33+
errCh := make(chan error, 1)
3234
go func() {
33-
err := SendChatMessage(content, to, from)
35+
errCh <- chat.SendChatMessage(content, to, from, db.DefaultChatPort)
36+
}()
37+
38+
select {
39+
case err := <-errCh:
3440
if err != nil {
3541
t.Fatalf("Failed to send chat message: %v", err)
3642
}
37-
}()
43+
case <-time.After(2 * time.Second):
44+
t.Fatalf("Timed out sending chat message")
45+
}
3846

3947
buf := make([]byte, 1024)
4048
if err := conn.SetReadDeadline(time.Now().Add(2 * time.Second)); err != nil { // Don't wait forever
@@ -45,7 +53,7 @@ func TestSendChatMessage(t *testing.T) {
4553
t.Fatalf("Failed to read sent message: %v", err)
4654
}
4755

48-
var received NetworkMessage
56+
var received chat.NetworkMessage
4957
err = json.Unmarshal(buf[:n], &received)
5058
if err != nil {
5159
t.Fatalf("Failed to unmarshal received data: %v", err)
@@ -57,13 +65,13 @@ func TestSendChatMessage(t *testing.T) {
5765
}
5866

5967
func TestListenForChatMessages(t *testing.T) {
60-
messages := make(chan NetworkMessage, 1)
68+
messages := make(chan chat.NetworkMessage, 1)
6169

62-
go ListenForChatMessages(messages)
70+
go chat.ListenForChatMessages(messages, db.DefaultChatPort)
6371

6472
srvrAddr := &net.UDPAddr{
6573
IP: net.ParseIP("127.0.0.1"),
66-
Port: config.CHAT_PORT,
74+
Port: db.DefaultChatPort,
6775
}
6876

6977
conn, err := net.DialUDP("udp", nil, srvrAddr)
@@ -72,7 +80,7 @@ func TestListenForChatMessages(t *testing.T) {
7280
}
7381
defer conn.Close()
7482

75-
testMessage := NetworkMessage{
83+
testMessage := chat.NetworkMessage{
7684
Content: "Test Message",
7785
From: discovery.NetworkUser{IP: "127.0.0.1", Name: "Sender"},
7886
Timestamp: time.Now(),

internal/config/config.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package config
22

33
var (
4-
BROADCAST_PORT = 8787
5-
CHAT_PORT = 8989
64
BROADCAST_INTERVAL = 5 // in seconds
75
USER_TIMEOUT = 15 // in seconds
86
DISCOVERY_BUFFER_SIZE = 1024

internal/db/config_store.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,27 @@ import (
77
)
88

99
type Config struct {
10-
Username string `json:"username"`
11-
Bio string `json:"bio"`
12-
Port string `json:"port"`
10+
Username string `json:"username"`
11+
Bio string `json:"bio"`
12+
Port string `json:"port"`
13+
BroadCastPort int `json:"broadcast_port"`
14+
ChatPort int `json:"chat_port"`
15+
}
16+
17+
const (
18+
DefaultBroadcastPort = 8787
19+
DefaultChatPort = 8989
20+
)
21+
22+
func (c Config) WithDefaults() Config {
23+
if c.BroadCastPort == 0 {
24+
c.BroadCastPort = DefaultBroadcastPort
25+
}
26+
if c.ChatPort == 0 {
27+
c.ChatPort = DefaultChatPort
28+
}
29+
30+
return c
1331
}
1432

1533
type ConfigStore struct{}

internal/tui/helpers.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
)
99

1010
func initForm(m *Model, theme *huh.Theme) *huh.Form {
11+
portStr := strconv.Itoa(m.broadcastPort)
12+
chatPortStr := strconv.Itoa(m.chatPort)
1113
return huh.NewForm(
1214
huh.NewGroup(
1315
huh.NewInput().
@@ -40,6 +42,26 @@ func initForm(m *Model, theme *huh.Theme) *huh.Form {
4042
}
4143
return nil
4244
}),
45+
huh.NewInput().
46+
Key("broadcast_port").
47+
Title("Broadcast Port").
48+
Value(&portStr).
49+
Validate(func(s string) error {
50+
if _, err := strconv.Atoi(s); err != nil {
51+
return errors.New("must be an integer")
52+
}
53+
return nil
54+
}),
55+
huh.NewInput().
56+
Key("chat_port").
57+
Title("Chat Port").
58+
Value(&chatPortStr).
59+
Validate(func(s string) error {
60+
if _, err := strconv.Atoi(s); err != nil {
61+
return errors.New("must be an integer")
62+
}
63+
return nil
64+
}),
4365
),
4466
).WithTheme(theme)
4567
}

internal/tui/model.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ type Model struct {
2525
state state
2626

2727
// Onboarding
28-
form *huh.Form
29-
username string
30-
bio string
31-
port string
28+
form *huh.Form
29+
username string
30+
bio string
31+
port string
32+
broadcastPort int
33+
chatPort int
3234

3335
// Hub
3436
onlineUsers []discovery.NetworkUser
@@ -67,15 +69,20 @@ func NewMainModel(chatMessagesChan chan chat.NetworkMessage) Model {
6769
username: "",
6870
bio: "",
6971
port: "7070",
72+
broadcastPort: db.DefaultBroadcastPort,
73+
chatPort: db.DefaultChatPort,
7074
}
7175

7276
store := db.NewConfigStore()
7377
if store.Exists() {
7478
m.state = stateHub
7579
if cfg, err := store.Load(); err == nil {
80+
cfg = cfg.WithDefaults()
7681
m.username = cfg.Username
7782
m.bio = cfg.Bio
7883
m.port = cfg.Port
84+
m.broadcastPort = cfg.BroadCastPort
85+
m.chatPort = cfg.ChatPort
7986
}
8087
// addDummyData(&m)
8188
} else {
@@ -94,7 +101,7 @@ func (m Model) Init() tea.Cmd {
94101
if m.state == stateOnboarding {
95102
cmds = append(cmds, m.form.Init())
96103
} else if m.state == stateHub {
97-
go discovery.BroadcastPresence(m.username, config.BROADCAST_PORT)
104+
go discovery.BroadcastPresence(m.username, m.broadcastPort)
98105
cmds = append(cmds, tea.Tick(time.Duration(config.ONLINE_USERS_REFRESH_INTERVAL)*time.Second, func(t time.Time) tea.Msg {
99106
users := discovery.GetOnlineUsers()
100107
return UpdateUsersMsg(users)

internal/tui/update.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,20 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
4646
m.username = m.form.GetString("username")
4747
m.bio = m.form.GetString("bio")
4848
m.port = m.form.GetString("port")
49+
m.broadcastPort = m.form.GetInt("broadcast_port")
50+
m.chatPort = m.form.GetInt("chat_port")
4951

5052
store := db.NewConfigStore()
5153
_ = store.Save(db.Config{
52-
Username: m.username,
53-
Bio: m.bio,
54-
Port: m.port,
54+
Username: m.username,
55+
Bio: m.bio,
56+
Port: m.port,
57+
BroadCastPort: m.broadcastPort,
58+
ChatPort: m.chatPort,
5559
})
5660

5761
if pastState == stateOnboarding {
58-
go discovery.BroadcastPresence(m.username, config.BROADCAST_PORT)
62+
go discovery.BroadcastPresence(m.username, m.broadcastPort)
5963

6064
return m, tea.Batch(cmd, tea.Tick(time.Duration(config.ONLINE_USERS_REFRESH_INTERVAL)*time.Second, func(t time.Time) tea.Msg {
6165
users := discovery.GetOnlineUsers()
@@ -140,7 +144,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
140144
if messageContent != "" {
141145
toUser := m.onlineUsers[m.selectedUserIndex]
142146
fromUser := discovery.GetSelfUser()
143-
_ = chat.SendChatMessage(messageContent, toUser, fromUser)
147+
_ = chat.SendChatMessage(messageContent, toUser, fromUser, m.chatPort)
144148

145149
message := chat.NetworkMessage{
146150
Content: messageContent,

0 commit comments

Comments
 (0)