// Copyright 2015 The etcd 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 main import ( "errors" "net" "time" ) // stoppableListener sets TCP keep-alive timeouts on accepted // connections and waits on stopc message type stoppableListener struct { *net.TCPListener stopc <-chan struct{} } func newStoppableListener(addr string, stopc <-chan struct{}) (*stoppableListener, error) { ln, err := net.Listen("tcp", addr) if err != nil { return nil, err } return &stoppableListener{ln.(*net.TCPListener), stopc}, nil } func (ln stoppableListener) Accept() (c net.Conn, err error) { connc := make(chan *net.TCPConn, 1) errc := make(chan error, 1) go func() { tc, err := ln.AcceptTCP() if err != nil { errc <- err return } connc <- tc }() select { case <-ln.stopc: return nil, errors.New("server stopped") case err := <-errc: return nil, err case tc := <-connc: tc.SetKeepAlive(true) tc.SetKeepAlivePeriod(3 * time.Minute) return tc, nil } }