| /* |
| * |
| * Copyright 2019 gRPC authors. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package grpclb |
| |
| import ( |
| "net" |
| "sync" |
| ) |
| |
| type tempError struct{} |
| |
| func (*tempError) Error() string { |
| return "grpclb test temporary error" |
| } |
| func (*tempError) Temporary() bool { |
| return true |
| } |
| |
| type restartableListener struct { |
| net.Listener |
| addr string |
| |
| mu sync.Mutex |
| closed bool |
| conns []net.Conn |
| } |
| |
| func newRestartableListener(l net.Listener) *restartableListener { |
| return &restartableListener{ |
| Listener: l, |
| addr: l.Addr().String(), |
| } |
| } |
| |
| func (l *restartableListener) Accept() (conn net.Conn, err error) { |
| conn, err = l.Listener.Accept() |
| if err == nil { |
| l.mu.Lock() |
| if l.closed { |
| conn.Close() |
| l.mu.Unlock() |
| return nil, &tempError{} |
| } |
| l.conns = append(l.conns, conn) |
| l.mu.Unlock() |
| } |
| return |
| } |
| |
| func (l *restartableListener) Close() error { |
| return l.Listener.Close() |
| } |
| |
| func (l *restartableListener) stopPreviousConns() { |
| l.mu.Lock() |
| l.closed = true |
| tmp := l.conns |
| l.conns = nil |
| l.mu.Unlock() |
| for _, conn := range tmp { |
| conn.Close() |
| } |
| } |
| |
| func (l *restartableListener) restart() { |
| l.mu.Lock() |
| l.closed = false |
| l.mu.Unlock() |
| } |