-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmessage_handler.go
182 lines (163 loc) · 5.38 KB
/
message_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// message_handler.go
// Package main handles reading and processing messages from the server.
package main
import (
"bufio"
"encoding/hex"
"fmt"
"net"
"strings"
tea "github.com/charmbracelet/bubbletea"
)
// readMessages continuously reads messages from the server and processes them.
func readMessages(conn net.Conn, hashedSecret []byte, messageChan chan<- tea.Msg) {
reader := bufio.NewReader(conn)
var inMultiLineResponse bool = false
var multiLineBuffer []string
for {
message, err := reader.ReadString('\n')
if err != nil {
messageChan <- disconnectMsg{}
return
}
message = strings.TrimRight(message, "\r\n")
if message == "" {
continue
}
// Handle being registered as operator
if message == "REGISTERED as operator" {
messageChan <- operatorMsg{content: "You are registered as the server operator."}
continue
}
// Handle being kicked
if message == "KICKED You have been kicked by the operator" {
messageChan <- kickedMsg{}
return
}
// Handle being banned
if message == "BANNED You have been banned by the operator" {
messageChan <- bannedMsg{}
return
}
// Detect the start of a multi-line response
if message == "BEGIN_RESPONSE" {
inMultiLineResponse = true
multiLineBuffer = []string{}
continue // Skip printing the marker
}
// Detect the end of a multi-line response
if message == "END_RESPONSE" {
inMultiLineResponse = false
messageChan <- serverMsg{content: strings.Join(multiLineBuffer, "\n")}
continue // Skip printing the marker
}
if inMultiLineResponse {
multiLineBuffer = append(multiLineBuffer, message)
continue
}
// Handle incoming messages from other clients
if strings.HasPrefix(message, "MESSAGE from") || strings.HasPrefix(message, "BROADCAST from") {
parts := strings.SplitN(message, ": ", 2)
if len(parts) != 2 {
messageChan <- serverMsg{content: "Invalid message format. Ignoring."}
continue
}
senderInfo := parts[0]
encryptedData := parts[1]
// Extract sender ID
var senderID string
isBroadcast := false
if strings.HasPrefix(senderInfo, "MESSAGE from") {
senderID = strings.TrimPrefix(senderInfo, "MESSAGE from ")
} else if strings.HasPrefix(senderInfo, "BROADCAST from") {
senderID = strings.TrimPrefix(senderInfo, "BROADCAST from ")
isBroadcast = true
}
if isBroadcast {
if strings.Contains(encryptedData, "|") {
// Encrypted data format: key_hex|ciphertext_hex
dataParts := strings.SplitN(encryptedData, "|", 2)
if len(dataParts) != 2 {
messageChan <- serverMsg{content: fmt.Sprintf("Invalid broadcast message format from %s. Ignoring.", senderID)}
continue
}
keyHex := dataParts[0]
ciphertextHex := dataParts[1]
// Decode hex strings
key, err := hex.DecodeString(keyHex)
if err != nil {
messageChan <- serverMsg{content: fmt.Sprintf("Error decoding key from broadcast from %s: %v", senderID, err)}
continue
}
ciphertext, err := hex.DecodeString(ciphertextHex)
if err != nil {
messageChan <- serverMsg{content: fmt.Sprintf("Error decoding ciphertext from broadcast from %s: %v", senderID, err)}
continue
}
// Decrypt the message using XOR cipher
if len(key) != len(ciphertext) {
messageChan <- serverMsg{content: fmt.Sprintf("Key and ciphertext lengths do not match in broadcast from %s.", senderID)}
continue
}
plaintext := encryptXOR(ciphertext, key)
messageChan <- incomingMessage{
senderID: senderID,
content: string(plaintext),
isBroadcast: true,
}
} else {
// Decrypt broadcast message using AES
ciphertext, err := hex.DecodeString(encryptedData)
if err != nil {
messageChan <- serverMsg{content: fmt.Sprintf("Error decoding broadcast from %s: %v", senderID, err)}
continue
}
plaintext, err := decryptAES(hashedSecret, ciphertext)
if err != nil {
messageChan <- serverMsg{content: fmt.Sprintf("Error decrypting broadcast from %s: %v", senderID, err)}
continue
}
messageChan <- incomingMessage{
senderID: senderID,
content: string(plaintext),
isBroadcast: true,
}
}
} else {
// Encrypted data format: key_hex|ciphertext_hex
dataParts := strings.SplitN(encryptedData, "|", 2)
if len(dataParts) != 2 {
messageChan <- serverMsg{content: fmt.Sprintf("Invalid message format from %s. Ignoring.", senderID)}
continue
}
keyHex := dataParts[0]
ciphertextHex := dataParts[1]
// Decode hex strings
key, err := hex.DecodeString(keyHex)
if err != nil {
messageChan <- serverMsg{content: fmt.Sprintf("Error decoding key from %s: %v", senderID, err)}
continue
}
ciphertext, err := hex.DecodeString(ciphertextHex)
if err != nil {
messageChan <- serverMsg{content: fmt.Sprintf("Error decoding ciphertext from %s: %v", senderID, err)}
continue
}
// Decrypt the message using XOR cipher
if len(key) != len(ciphertext) {
messageChan <- serverMsg{content: fmt.Sprintf("Key and ciphertext lengths do not match from %s.", senderID)}
continue
}
plaintext := encryptXOR(ciphertext, key)
messageChan <- incomingMessage{
senderID: senderID,
content: string(plaintext),
isBroadcast: false,
}
}
} else {
// Handle other server messages
messageChan <- serverMsg{content: message}
}
}
}