-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.go
127 lines (110 loc) · 2.47 KB
/
server.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
package main
import (
"bufio"
"crypto/rand"
"encoding/hex"
"log"
"net"
"strconv"
"strings"
)
// NewServer creates a new server listening on port
func NewServer(port string) {
log.Print("Making a new server")
sock, err := net.Listen("tcp", ":"+port)
if err != nil {
log.Fatal("Error creating socket:", err)
}
defer sock.Close()
inChan := make(chan connMsg)
go handleSocket(inChan, sock)
handleMessages(inChan)
}
type connMsg struct {
conn net.Conn
id string
text string
}
func handleMessages(message chan connMsg) {
buffer := EmptyBuffer()
for msg := range message {
line := msg.text
a1, line := getAddress(line)
line = strings.TrimPrefix(line, ",")
a2, cmd := getAddress(line)
log.Printf("a1: %d", a1)
log.Printf("a2: %d", a2)
log.Printf("cmd: %s", cmd)
if cmd == "q" {
return
} else if cmd == "Q" {
return
} else if strings.HasPrefix(cmd, "e") {
filename := strings.TrimPrefix(cmd, "e ")
buffer = BufferFromFile(filename)
} else if cmd == "p" {
say(msg.conn, buffer.GetLine())
} else {
log.Printf("Unknown command from conn(%s): %s", msg.id, msg.text)
}
}
}
// getAddress parses a digit from the from of a line.
// It returns the digit, and the rest of the line.
// It returns -1 if no digit was found.
func getAddress(line string) (int, string) {
offset := len(line)
for {
digit, err := strconv.Atoi(line[0:offset])
if err == nil {
return digit, line[offset:]
}
offset--
if offset == 0 {
return -1, line
}
}
}
func handleSocket(inChan chan connMsg, sock net.Listener) {
for {
conn, err := sock.Accept()
if err != nil {
log.Fatal("Error accepting connectiong:", err)
}
defer conn.Close()
go handleConnection(inChan, conn)
}
}
func handleConnection(inChan chan connMsg, conn net.Conn) {
id := newID()
rd := bufio.NewReader(conn)
log.Print("New connection, id: " + id)
for {
line, err := rd.ReadString('\n')
if err != nil {
if err.Error() == "EOF" {
log.Printf("Connection (%s) closed", id)
} else {
log.Print("Error while reading from connection:")
log.Print(" " + err.Error())
}
return
}
cmd := strings.TrimSpace(line)
if cmd != "" {
inChan <- connMsg{conn, id, cmd}
}
}
}
func newID() string {
rb := make([]byte, 4)
_, err := rand.Read(rb)
if err != nil {
log.Fatal("Error generating ID: " + err.Error())
}
return hex.EncodeToString(rb)
}
func say(conn net.Conn, line string) {
conn.Write([]byte(line + "\n"))
log.Printf("Printing line [%s]", line)
}