2
0
mirror of https://github.com/soheilhy/cmux.git synced 2024-11-10 03:31:52 +08:00

add cmux.Close() function

This commit is contained in:
Abhilash Gnan 2019-06-14 21:47:40 +02:00 committed by Soheil Hassas Yeganeh
parent 8a8ea3c539
commit e13d1cbf02

41
cmux.go
View File

@ -93,6 +93,8 @@ type CMux interface {
// Serve starts multiplexing the listener. Serve blocks and perhaps // Serve starts multiplexing the listener. Serve blocks and perhaps
// should be invoked concurrently within a go routine. // should be invoked concurrently within a go routine.
Serve() error Serve() error
// Closes cmux server and stops accepting any connections on listener
Close()
// HandleError registers an error handler that handles listener errors. // HandleError registers an error handler that handles listener errors.
HandleError(ErrorHandler) HandleError(ErrorHandler)
// sets a timeout for the read of matchers // sets a timeout for the read of matchers
@ -111,6 +113,7 @@ type cMux struct {
donec chan struct{} donec chan struct{}
sls []matchersListener sls []matchersListener
readTimeout time.Duration readTimeout time.Duration
mu sync.Mutex
} }
func matchersToMatchWriters(matchers []Matcher) []MatchWriter { func matchersToMatchWriters(matchers []Matcher) []MatchWriter {
@ -146,7 +149,7 @@ func (m *cMux) Serve() error {
var wg sync.WaitGroup var wg sync.WaitGroup
defer func() { defer func() {
close(m.donec) m.closeDoneChanLocked()
wg.Wait() wg.Wait()
for _, sl := range m.sls { for _, sl := range m.sls {
@ -161,6 +164,11 @@ func (m *cMux) Serve() error {
for { for {
c, err := m.root.Accept() c, err := m.root.Accept()
if err != nil { if err != nil {
select {
case <-m.getDoneChan():
// cmux was closed with cmux.Close()
return nil
}
if !m.handleErr(err) { if !m.handleErr(err) {
return err return err
} }
@ -189,7 +197,7 @@ func (m *cMux) serve(c net.Conn, donec <-chan struct{}, wg *sync.WaitGroup) {
} }
select { select {
case sl.l.connc <- muc: case sl.l.connc <- muc:
case <-donec: case <-m.getDoneChan():
_ = c.Close() _ = c.Close()
} }
return return
@ -204,6 +212,35 @@ func (m *cMux) serve(c net.Conn, donec <-chan struct{}, wg *sync.WaitGroup) {
} }
} }
func (m *cMux) Close() {
m.mu.Lock()
defer m.mu.Unlock()
m.closeDoneChanLocked()
}
func (m *cMux) getDoneChan() chan struct{} {
m.mu.Lock()
defer m.mu.Unlock()
return m.getDoneChanLocked()
}
func (m *cMux) getDoneChanLocked() chan struct{} {
if m.donec == nil {
m.donec = make(chan struct{})
}
return m.donec
}
func (m *cMux) closeDoneChanLocked() {
ch := m.getDoneChanLocked()
select {
case <-ch:
// Already closed. Don't close again
default:
close(ch)
}
}
func (m *cMux) HandleError(h ErrorHandler) { func (m *cMux) HandleError(h ErrorHandler) {
m.errh = h m.errh = h
} }