2018-04-05 15:15:29 +00:00
|
|
|
package socket
|
2018-04-04 13:28:35 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
logging "git.loafle.net/commons/logging-go"
|
|
|
|
)
|
|
|
|
|
2018-04-04 13:50:34 +00:00
|
|
|
type ClientReadWriter struct {
|
2018-04-04 13:28:35 +00:00
|
|
|
ReadwriteHandler ReadWriteHandler
|
|
|
|
ReadChan chan<- []byte
|
|
|
|
WriteChan <-chan []byte
|
|
|
|
DisconnectedChan chan<- struct{}
|
2018-04-04 16:51:34 +00:00
|
|
|
ReconnectedChan <-chan Conn
|
2018-04-04 13:28:35 +00:00
|
|
|
ClientStopChan <-chan struct{}
|
|
|
|
ClientStopWg *sync.WaitGroup
|
|
|
|
}
|
|
|
|
|
2018-04-04 16:51:34 +00:00
|
|
|
func (crw *ClientReadWriter) HandleConnection(conn Conn) {
|
2018-04-04 13:28:35 +00:00
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if nil != conn {
|
|
|
|
conn.Close()
|
|
|
|
}
|
|
|
|
logging.Logger().Infof("disconnected")
|
2018-04-04 13:50:34 +00:00
|
|
|
crw.ClientStopWg.Done()
|
2018-04-04 13:28:35 +00:00
|
|
|
}()
|
|
|
|
|
|
|
|
logging.Logger().Infof("connected")
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
|
|
|
for {
|
|
|
|
if nil != err {
|
2018-04-04 14:21:40 +00:00
|
|
|
if IsUnexpectedCloseError(err) || io.EOF == err || io.ErrUnexpectedEOF == err {
|
2018-04-04 13:50:34 +00:00
|
|
|
crw.DisconnectedChan <- struct{}{}
|
|
|
|
newConn := <-crw.ReconnectedChan
|
2018-04-04 13:28:35 +00:00
|
|
|
if nil == newConn {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
conn = newConn
|
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-04 14:21:40 +00:00
|
|
|
stopChan := make(chan struct{})
|
|
|
|
|
|
|
|
readerDoneChan := make(chan error)
|
|
|
|
writerDoneChan := make(chan error)
|
|
|
|
|
2018-04-04 13:50:34 +00:00
|
|
|
go connReadHandler(crw.ReadwriteHandler, conn, stopChan, readerDoneChan, crw.ReadChan)
|
|
|
|
go connWriteHandler(crw.ReadwriteHandler, conn, stopChan, writerDoneChan, crw.WriteChan)
|
2018-04-04 13:28:35 +00:00
|
|
|
|
|
|
|
select {
|
|
|
|
case err = <-readerDoneChan:
|
|
|
|
close(stopChan)
|
|
|
|
<-writerDoneChan
|
|
|
|
case err = <-writerDoneChan:
|
|
|
|
close(stopChan)
|
|
|
|
<-readerDoneChan
|
2018-04-04 13:50:34 +00:00
|
|
|
case <-crw.ClientStopChan:
|
2018-04-04 13:28:35 +00:00
|
|
|
close(stopChan)
|
|
|
|
<-readerDoneChan
|
|
|
|
<-writerDoneChan
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|