|
@@ -10,7 +10,6 @@ import (
|
10
|
10
|
"crypto/tls"
|
11
|
11
|
"encoding/hex"
|
12
|
12
|
"errors"
|
13
|
|
- "fmt"
|
14
|
13
|
"io"
|
15
|
14
|
"net"
|
16
|
15
|
"strings"
|
|
@@ -26,12 +25,16 @@ var (
|
26
|
25
|
|
27
|
26
|
// Socket represents an IRC socket.
|
28
|
27
|
type Socket struct {
|
29
|
|
- Closed bool
|
30
|
28
|
conn net.Conn
|
31
|
29
|
reader *bufio.Reader
|
32
|
30
|
|
33
|
31
|
MaxSendQBytes uint64
|
34
|
|
- FinalData string // what to send when we die
|
|
32
|
+
|
|
33
|
+ closed bool
|
|
34
|
+ closedMutex sync.Mutex
|
|
35
|
+
|
|
36
|
+ finalData string // what to send when we die
|
|
37
|
+ finalDataMutex sync.Mutex
|
35
|
38
|
|
36
|
39
|
lineToSendExists chan bool
|
37
|
40
|
linesToSend []string
|
|
@@ -50,10 +53,12 @@ func NewSocket(conn net.Conn, maxSendQBytes uint64) Socket {
|
50
|
53
|
|
51
|
54
|
// Close stops a Socket from being able to send/receive any more data.
|
52
|
55
|
func (socket *Socket) Close() {
|
53
|
|
- if socket.Closed {
|
|
56
|
+ socket.closedMutex.Lock()
|
|
57
|
+ defer socket.closedMutex.Unlock()
|
|
58
|
+ if socket.closed {
|
54
|
59
|
return
|
55
|
60
|
}
|
56
|
|
- socket.Closed = true
|
|
61
|
+ socket.closed = true
|
57
|
62
|
|
58
|
63
|
// force close loop to happen if it hasn't already
|
59
|
64
|
go socket.timedFillLineToSendExists(200 * time.Millisecond)
|
|
@@ -88,7 +93,7 @@ func (socket *Socket) CertFP() (string, error) {
|
88
|
93
|
|
89
|
94
|
// Read returns a single IRC line from a Socket.
|
90
|
95
|
func (socket *Socket) Read() (string, error) {
|
91
|
|
- if socket.Closed {
|
|
96
|
+ if socket.IsClosed() {
|
92
|
97
|
return "", io.EOF
|
93
|
98
|
}
|
94
|
99
|
|
|
@@ -113,7 +118,7 @@ func (socket *Socket) Read() (string, error) {
|
113
|
118
|
|
114
|
119
|
// Write sends the given string out of Socket.
|
115
|
120
|
func (socket *Socket) Write(data string) error {
|
116
|
|
- if socket.Closed {
|
|
121
|
+ if socket.IsClosed() {
|
117
|
122
|
return io.EOF
|
118
|
123
|
}
|
119
|
124
|
|
|
@@ -121,9 +126,7 @@ func (socket *Socket) Write(data string) error {
|
121
|
126
|
socket.linesToSend = append(socket.linesToSend, data)
|
122
|
127
|
socket.linesToSendMutex.Unlock()
|
123
|
128
|
|
124
|
|
- if !socket.Closed {
|
125
|
|
- go socket.timedFillLineToSendExists(15 * time.Second)
|
126
|
|
- }
|
|
129
|
+ go socket.timedFillLineToSendExists(15 * time.Second)
|
127
|
130
|
|
128
|
131
|
return nil
|
129
|
132
|
}
|
|
@@ -138,9 +141,22 @@ func (socket *Socket) timedFillLineToSendExists(duration time.Duration) {
|
138
|
141
|
}
|
139
|
142
|
}
|
140
|
143
|
|
|
144
|
+// SetFinalData sets the final data to send when the SocketWriter closes.
|
|
145
|
+func (socket *Socket) SetFinalData(data string) {
|
|
146
|
+ socket.finalDataMutex.Lock()
|
|
147
|
+ socket.finalData = data
|
|
148
|
+ socket.finalDataMutex.Unlock()
|
|
149
|
+}
|
|
150
|
+
|
|
151
|
+// IsClosed returns whether the socket is closed.
|
|
152
|
+func (socket *Socket) IsClosed() bool {
|
|
153
|
+ socket.closedMutex.Lock()
|
|
154
|
+ defer socket.closedMutex.Unlock()
|
|
155
|
+ return socket.closed
|
|
156
|
+}
|
|
157
|
+
|
141
|
158
|
// RunSocketWriter starts writing messages to the outgoing socket.
|
142
|
159
|
func (socket *Socket) RunSocketWriter() {
|
143
|
|
- var errOut bool
|
144
|
160
|
for {
|
145
|
161
|
// wait for new lines
|
146
|
162
|
select {
|
|
@@ -148,7 +164,7 @@ func (socket *Socket) RunSocketWriter() {
|
148
|
164
|
socket.linesToSendMutex.Lock()
|
149
|
165
|
|
150
|
166
|
// check if we're closed
|
151
|
|
- if socket.Closed {
|
|
167
|
+ if socket.IsClosed() {
|
152
|
168
|
socket.linesToSendMutex.Unlock()
|
153
|
169
|
break
|
154
|
170
|
}
|
|
@@ -169,7 +185,7 @@ func (socket *Socket) RunSocketWriter() {
|
169
|
185
|
}
|
170
|
186
|
}
|
171
|
187
|
if socket.MaxSendQBytes < sendQBytes {
|
172
|
|
- socket.FinalData = "\r\nERROR :SendQ Exceeded\r\n"
|
|
188
|
+ socket.SetFinalData("\r\nERROR :SendQ Exceeded\r\n")
|
173
|
189
|
socket.linesToSendMutex.Unlock()
|
174
|
190
|
break
|
175
|
191
|
}
|
|
@@ -184,24 +200,30 @@ func (socket *Socket) RunSocketWriter() {
|
184
|
200
|
if 0 < len(data) {
|
185
|
201
|
_, err := socket.conn.Write([]byte(data))
|
186
|
202
|
if err != nil {
|
187
|
|
- errOut = true
|
188
|
|
- fmt.Println(err.Error())
|
189
|
203
|
break
|
190
|
204
|
}
|
191
|
205
|
}
|
192
|
206
|
}
|
193
|
|
- if errOut || socket.Closed {
|
|
207
|
+ if socket.IsClosed() {
|
194
|
208
|
// error out or we've been closed
|
195
|
209
|
break
|
196
|
210
|
}
|
197
|
211
|
}
|
198
|
|
- if !socket.Closed {
|
199
|
|
- socket.Closed = true
|
|
212
|
+ // force closure of socket
|
|
213
|
+ socket.closedMutex.Lock()
|
|
214
|
+ if !socket.closed {
|
|
215
|
+ socket.closed = true
|
200
|
216
|
}
|
|
217
|
+ socket.closedMutex.Unlock()
|
|
218
|
+
|
201
|
219
|
// write error lines
|
202
|
|
- if 0 < len(socket.FinalData) {
|
203
|
|
- socket.conn.Write([]byte(socket.FinalData))
|
|
220
|
+ socket.finalDataMutex.Lock()
|
|
221
|
+ if 0 < len(socket.finalData) {
|
|
222
|
+ socket.conn.Write([]byte(socket.finalData))
|
204
|
223
|
}
|
|
224
|
+ socket.finalDataMutex.Unlock()
|
|
225
|
+
|
|
226
|
+ // close the connection
|
205
|
227
|
socket.conn.Close()
|
206
|
228
|
|
207
|
229
|
// empty the lineToSendExists channel
|