-
Notifications
You must be signed in to change notification settings - Fork 0
/
handleconnection.go
83 lines (74 loc) · 2.47 KB
/
handleconnection.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
package netchan
import (
"encoding/gob"
"io"
"log"
"net"
// "time"
)
// handleConnection manages a single client connection.
// It receives and sends messages using the send and receive channels.
// In case of disconnection, it notifies through the clientDisconnectNotifyChan.
// The function uses goroutines to concurrently handle incoming and outgoing messages.
func handleConnection(conn net.Conn, send chan Message, receive chan Message, clientDisconnectNotifyChan chan string) {
// This deferred function notifies about the client disconnection and closes the connection.
defer func() {
conn.Close()
//then close connection
clientDisconnectNotifyChan <- conn.RemoteAddr().String()
//first send address to clientDisconnectNotifyChan to clean it from address book
//NOTE: defer func() goes reverse direction!
}()
// Channel to collect any errors that occur during connection handling.
decodeErrorChannel := make(chan error, 1000)
// Creating a new decoder and encoder for the connection.
decoder := gob.NewDecoder(conn)
encoder := gob.NewEncoder(conn)
// Goroutine for receiving messages.
go func() {
for {
var msg Message
err := decoder.Decode(&msg)
if err != nil {
if err == io.EOF {
// Connection closed by the other end.
log.Printf("Error: remote connection closed. (%s)", err)
decodeErrorChannel <- err
return
} else {
// Send error to decodeErrorChannel and log it.
decodeErrorChannel <- err
log.Printf("Error while decoding: %s", err)
return
}
}
// Update the message with the sender's address and send it to the receive channel.
msg.From = conn.RemoteAddr().String()
receive <- msg
}
}()
// Main loop for handling sending messages and connection errors.
for {
select {
case message, ok := <-send:
// Check if the send channel is closed.
if !ok {
log.Println("Exiting due to SEND channel closed.")
return
}
// Attempt to encode and send the message.
sendingErr := encoder.Encode(message)
if sendingErr != nil {
// Re-queue the message on failure and log the error.
send <- message
log.Printf("Re-queue sending data as sending failed with error: %s\n", sendingErr)
return
}
// Logging the sent message is disabled to reduce verbosity.
case decodeError := <-decodeErrorChannel:
// Log any network error received and exit the loop.
log.Printf("Netchan handle connection worker exited due to decode error: %s\n", decodeError)
return
}
}
}