package server import ( "io" "sync" logging "git.loafle.net/commons/logging-go" ) type ClientRWCHandler struct { ReadwriteHandler ReadWriteHandler ReadChan chan<- []byte WriteChan <-chan []byte DisconnectedChan chan<- struct{} ReconnectedChan <-chan *Conn ClientStopChan <-chan struct{} ClientStopWg *sync.WaitGroup } func (crwch *ClientRWCHandler) HandleConnection(conn *Conn) { defer func() { if nil != conn { conn.Close() } logging.Logger().Infof("disconnected") crwch.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 { crwch.DisconnectedChan <- struct{}{} newConn := <-crwch.ReconnectedChan if nil == newConn { return } conn = newConn } else { return } } go connReadHandler(crwch.ReadwriteHandler, conn, stopChan, readerDoneChan, crwch.ReadChan) go connWriteHandler(crwch.ReadwriteHandler, conn, stopChan, writerDoneChan, crwch.WriteChan) select { case err = <-readerDoneChan: close(stopChan) <-writerDoneChan case err = <-writerDoneChan: close(stopChan) <-readerDoneChan case <-crwch.ClientStopChan: close(stopChan) <-readerDoneChan <-writerDoneChan return } } }