package server import ( "io" "sync" logging "git.loafle.net/commons/logging-go" ) type ClientReadWriter struct { ReadwriteHandler ReadWriteHandler ReadChan chan<- []byte WriteChan <-chan []byte DisconnectedChan chan<- struct{} ReconnectedChan <-chan *Conn ClientStopChan <-chan struct{} ClientStopWg *sync.WaitGroup } func (crw *ClientReadWriter) HandleConnection(conn *Conn) { defer func() { if nil != conn { conn.Close() } logging.Logger().Infof("disconnected") crw.ClientStopWg.Done() }() logging.Logger().Infof("connected") stopChan := make(chan struct{}) readerDoneChan := make(chan error) writerDoneChan := make(chan error) var err error for { if nil != err { if io.EOF == err || io.ErrUnexpectedEOF == err { crw.DisconnectedChan <- struct{}{} newConn := <-crw.ReconnectedChan if nil == newConn { return } conn = newConn } else { return } } go connReadHandler(crw.ReadwriteHandler, conn, stopChan, readerDoneChan, crw.ReadChan) go connWriteHandler(crw.ReadwriteHandler, conn, stopChan, writerDoneChan, crw.WriteChan) select { case err = <-readerDoneChan: close(stopChan) <-writerDoneChan case err = <-writerDoneChan: close(stopChan) <-readerDoneChan case <-crw.ClientStopChan: close(stopChan) <-readerDoneChan <-writerDoneChan return } } }