コード例 #1
0
ファイル: bootContext.go プロジェクト: noscripter/deblocus
func (ctx *bootContext) startServer() {
	defer func() {
		sigChan <- Bye
	}()
	var (
		conn *net.TCPConn
		ln   *net.TCPListener
		err  error
	)

	server := NewServer(ctx.cman)
	addr := ctx.cman.ListenAddr(SR_SERVER)

	ln, err = net.ListenTCP("tcp", addr)
	fatalError(err)
	defer ln.Close()

	ctx.register(server, ln)
	log.Infoln(versionString())
	log.Infoln("Server is listening on", addr)

	for {
		conn, err = ln.AcceptTCP()
		if err == nil {
			go server.TunnelServe(conn)
		} else {
			SafeClose(conn)
		}
	}
}
コード例 #2
0
ファイル: service.go プロジェクト: voxadam/cascades-sockets
// Accept connections and spawn a goroutine to serve each one.  Stop listening
// if anything is received on the service's channel.
func (self *Service) Serve(listener *net.TCPListener) {
	defer self.waitGroup.Done()
	for {
		select {
		case <-self.done:
			log.Println("Stopping listening on", listener.Addr())
			listener.Close()
			return
		default:
		}

		listener.SetDeadline(time.Now().Add(1e9))
		conn, err := listener.AcceptTCP()
		if err != nil {
			if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
				continue
			}
			log.Println(err)
		}

		log.Println(conn.RemoteAddr(), "connected")

		connection := NewConnection(conn, make(chan []byte))
		self.dataMap[connection.Id] = connection
		self.waitGroup.Add(1)
		go self.serve(connection)
	}
}
コード例 #3
0
ファイル: server.go プロジェクト: andradeandrey/go-ipfs
// serveTCP starts a TCP listener for the server.
// Each request is handled in a separate goroutine.
func (srv *Server) serveTCP(l *net.TCPListener) error {
	defer l.Close()

	if srv.NotifyStartedFunc != nil {
		srv.NotifyStartedFunc()
	}

	handler := srv.Handler
	if handler == nil {
		handler = DefaultServeMux
	}
	rtimeout := srv.getReadTimeout()
	// deadline is not used here
	for {
		rw, e := l.AcceptTCP()
		if e != nil {
			continue
		}
		m, e := srv.readTCP(rw, rtimeout)
		select {
		case <-srv.stopTCP:
			return nil
		default:
		}
		if e != nil {
			continue
		}
		srv.wgTCP.Add(1)
		go srv.serve(rw.RemoteAddr(), handler, m, nil, nil, rw)
	}
	panic("dns: not reached")
}
コード例 #4
0
ファイル: local_server.go プロジェクト: yinqiwen/gsnova
func startLocalProxyServer(proxy ProxyConfig) (*net.TCPListener, error) {
	tcpaddr, err := net.ResolveTCPAddr("tcp", proxy.Local)
	if nil != err {
		log.Fatalf("[ERROR]Local server address:%s error:%v", proxy.Local, err)
		return nil, err
	}
	var lp *net.TCPListener
	lp, err = net.ListenTCP("tcp", tcpaddr)
	if nil != err {
		log.Fatalf("Can NOT listen on address:%s", proxy.Local)
		return nil, err
	}
	log.Printf("Listen on address %s", proxy.Local)
	go func() {
		for proxyServerRunning {
			conn, err := lp.AcceptTCP()
			if nil != err {
				continue
			}
			go serveProxyConn(conn, proxy)
		}
		lp.Close()
	}()
	return lp, nil
}
コード例 #5
0
ファイル: server.go プロジェクト: Alienero/IamServer
func (r *SrsServer) Serve() error {
	// too many open files will thows a panic.
	addr, err := net.ResolveTCPAddr("tcp", r.addr)
	if err != nil {
		glog.Errorf("resolve listen address failed, err=%v", err)
		return fmt.Errorf("resolve listen address failed, err=%v", err)
	}

	var listener *net.TCPListener
	listener, err = net.ListenTCP("tcp", addr)
	if err != nil {
		glog.Errorf("listen failed, err=%v", err)
		return fmt.Errorf("listen failed, err=%v", err)
	}
	defer listener.Close()
	for {
		glog.Info("listener ready to accept client")
		conn, err := listener.AcceptTCP()
		if err != nil {
			glog.Errorf("accept client failed, err=%v", err)
			return fmt.Errorf("accept client failed, err=%v", err)
		}
		glog.Info("TCP Connected")

		go r.serve(conn)
	}
}
コード例 #6
0
ファイル: sync.go プロジェクト: Cepave/lvs-metrics
// serve accepts connections from the given TCP listener and dispatches each
// connection to the RPC server. Connections are only accepted from localhost
// and the seesaw node that we are configured to peer with.
func (s *syncServer) serve(l *net.TCPListener) error {
	defer l.Close()

	s.server = rpc.NewServer()
	s.server.Register(&SeesawSync{s})

	for {
		c, err := l.AcceptTCP()
		if err != nil {
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				time.Sleep(100 * time.Millisecond)
				continue
			}
			return err
		}
		raddr := c.RemoteAddr().String()
		host, _, err := net.SplitHostPort(raddr)
		if err != nil {
			log.Errorf("Failed to parse remote address %q: %v", raddr, err)
			c.Close()
			continue
		}
		rip := net.ParseIP(host)
		if rip == nil || (!rip.IsLoopback() && !rip.Equal(s.engine.config.Peer.IPv4Addr) && !rip.Equal(s.engine.config.Peer.IPv6Addr)) {
			log.Warningf("Rejecting connection from non-peer (%s)...", rip)
			c.Close()
			continue
		}
		log.Infof("Sync connection established from %s", rip)
		go s.server.ServeConn(c)
	}
}
コード例 #7
0
ファイル: service.go プロジェクト: gitter-badger/siberite
func (self *Service) Serve(listener *net.TCPListener) {
	defer self.wg.Done()

	log.Println("initializing...")
	var err error
	self.repo, err = repository.Initialize(self.dataDir)
	log.Println("data directory: ", self.dataDir)
	if err != nil {
		log.Fatal(err)
	}

	for {
		select {
		case <-self.ch:
			log.Println("stopping listening on", listener.Addr())
			listener.Close()
			return
		default:
		}
		listener.SetDeadline(time.Now().Add(1e9))
		conn, err := listener.AcceptTCP()
		if nil != err {
			if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
				continue
			}
			log.Println(err)
		}
		self.wg.Add(1)
		go self.HandleConnection(conn)
	}
}
コード例 #8
0
ファイル: oauth.go プロジェクト: vokal/googauth
func tokenFromWeb(g_config *oauth.Config) *oauth.Token {
	ch := make(chan string)
	randState := fmt.Sprintf("st%d", time.Now())

	var listener *net.TCPListener

	go serveCallback(listener, randState, ch)
	defer listener.Close()

	g_config.RedirectURL = "http://localhost:8080/callback"
	authUrl := g_config.AuthCodeURL(randState)
	go openUrl(authUrl)
	log.Printf("Authorize this app at: %s", authUrl)
	code := <-ch
	log.Printf("Got code: %s", code)

	t := &oauth.Transport{
		Config:    g_config,
		Transport: condDebugTransport(http.DefaultTransport),
	}
	_, err := t.Exchange(code)
	if err != nil {
		log.Fatalf("Token exchange error: %v", err)
	}
	return t.Token
}
コード例 #9
0
ファイル: server.go プロジェクト: larixsource/atto
func (s *Server) loop(listener *net.TCPListener) {
	defer s.waitGroup.Done()
	log.Printf("[DEBUG] waiting for connections...")
	for {
		select {
		case <-s.ch:
			log.Printf("[DEBUG] stopping listening on %s", listener.Addr())
			_ = listener.Close()
			return
		default:
		}
		_ = listener.SetDeadline(time.Now().Add(s.Deadline))
		conn, err := listener.AcceptTCP()
		if nil != err {
			if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
				continue
			}
			log.Printf("[ERROR] error on loop: %s", err)
		}
		log.Printf("[DEBUG] connected to %s", conn.RemoteAddr())
		c := &connection{
			conn:          conn,
			protocol:      s.protocolCtor(conn),
			waitGroup:     s.waitGroup,
			deadline:      s.Deadline,
			readBuffSize:  s.ReadBuffSize,
			writeBuffSize: s.WriteBuffSize,
		}
		s.waitGroup.Add(1)
		go c.handle(s.ch)
	}
}
コード例 #10
0
ファイル: server.go プロジェクト: whiskerman/gotcp
// Start starts service
func (s *Server) Start(listener *net.TCPListener, acceptTimeout time.Duration) {
	s.waitGroup.Add(1)
	defer func() {
		listener.Close()
		s.waitGroup.Done()
	}()

	for {
		select {
		case <-s.exitChan:
			return

		default:
		}

		listener.SetDeadline(time.Now().Add(acceptTimeout))

		conn, err := listener.AcceptTCP()

		if e, ok := err.(net.Error); ok && e.Timeout() {
			continue
			// This was a timeout
		} else if err != nil {
			l4g.Info("listener accepttcp continue and found a error: %v", err)
			return
			// This was an error, but not a timeout
		}

		go newConn(conn, s).Do()
	}
}
コード例 #11
0
ファイル: server.go プロジェクト: ningye/gotcp
func (this *Server) Start(listener *net.TCPListener) {
	log.Printf("Start listen on %v", listener.Addr())
	this.waitGroup.Add(1)
	defer func() {
		listener.Close()
		this.waitGroup.Done()
	}()

	for {
		select {
		case <-this.exitCh:
			log.Printf("Stop listen on %v", listener.Addr())
			return
		default:
		}

		listener.SetDeadline(time.Now().Add(this.acceptTimeout))
		conn, err := listener.AcceptTCP()
		if err != nil {
			if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
				// log.Printf("Accept timeout: %v", opErr)
				continue
			}
			log.Printf("Accept error: %v", err)
			continue
		}

		log.Printf("Accept: %v", conn.RemoteAddr())
		go this.handleClientConn(conn)
	}
}
コード例 #12
0
ファイル: bootContext.go プロジェクト: noscripter/deblocus
func (ctx *bootContext) startClient() {
	defer func() {
		sigChan <- Bye
	}()
	var (
		conn *net.TCPConn
		ln   *net.TCPListener
		err  error
	)

	client := NewClient(ctx.cman)
	addr := ctx.cman.ListenAddr(SR_CLIENT)

	ln, err = net.ListenTCP("tcp", addr)
	fatalError(err)
	defer ln.Close()

	ctx.register(client, ln)
	log.Infoln(versionString())
	log.Infoln("Proxy(SOCKS5/HTTP) is listening on", addr)

	// connect to server
	go client.StartTun(true)

	for {
		conn, err = ln.AcceptTCP()
		if err == nil {
			go client.ClientServe(conn)
		} else {
			SafeClose(conn)
		}
	}
}
コード例 #13
0
ファイル: 15_free_ports.go プロジェクト: gyuho/learn
// FreePorts returns maximum n tcp ports available to use.
func FreePorts(n int, matchFunc func(int) bool) (ports []int, err error) {
	if n > 50000 {
		return nil, fmt.Errorf("too many ports requested (%d)", n)
	}
	for len(ports) < n {
		var addr *net.TCPAddr
		addr, err = net.ResolveTCPAddr("tcp", "localhost:0")
		if err != nil {
			break
		}
		var l *net.TCPListener
		l, err = net.ListenTCP("tcp", addr)
		if err != nil {
			break
		}
		port := l.Addr().(*net.TCPAddr).Port
		l.Close()

		if matchFunc == nil {
			ports = append(ports, port)
			continue
		}
		if matchFunc(port) {
			ports = append(ports, port)
		}
	}
	return
}
コード例 #14
0
ファイル: server.go プロジェクト: ciaos/gotcp
// Start starts service
func (s *Server) Start(listener *net.TCPListener, acceptTimeout time.Duration) {
	s.waitGroup.Add(1)
	defer func() {
		listener.Close()
		s.waitGroup.Done()
	}()

	for {
		select {
		case <-s.exitChan:
			return

		default:
		}

		listener.SetDeadline(time.Now().Add(acceptTimeout))

		conn, err := listener.AcceptTCP()
		if err != nil {
			continue
		}

		go newConn(conn, s).Do()
	}
}
コード例 #15
0
ファイル: tcp_server.go プロジェクト: Leon2012/libnet
func (s *TcpServer) accept(lis *net.TCPListener) {
	defer lis.Close()
	defer s.waitGroup.Done()
	for {
		select {
		case <-s.ch: //stop goroutine
			//log.Println("close tcp listener")
			return
		default:
			//log.Println("close 11111 .....")
		}
		var trans Transport = nil
		conn, err := lis.AcceptTCP()
		if nil != err {
			if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
				//log.Println("Stop accepting connections")
				continue
			}
			log.Println(err)
		}
		conn.SetLinger(-1)
		trans = NewTCPTransport(conn, s.rTimeout, s.wTimeout)
		s.connections[trans.Id()] = trans
		if s.transHandler != nil {
			s.transHandler.OnConnect(trans)
		}
		s.waitGroup.Add(1)
		go s.run(trans)
	}
}
コード例 #16
0
ファイル: server.go プロジェクト: GisKook/gobed
// Start starts service
func (s *Server) Start(listener *net.TCPListener, acceptTimeout time.Duration) {
	s.waitGroup.Add(1)
	defer func() {
		listener.Close()
		s.waitGroup.Done()
	}()

	var index uint32
	index = 0
	for {
		select {
		case <-s.exitChan:
			return

		default:
		}

		listener.SetDeadline(time.Now().Add(acceptTimeout))

		conn, err := listener.AcceptTCP()
		if err != nil {
			continue
		}

		myconn := newConn(conn, s, index)
		s.mqhub.conns[index] = myconn
		index += 1

		go myconn.Do()
	}
}
コード例 #17
0
//TODO timeout connection and try
func (l *Link) startConnTCP(s string, m bool, o *Link, t rocproto.Packet_Section) {

	var listener *net.TCPListener

	log.Println("Starting connection on ", s)
	tcpAddr, err := net.ResolveTCPAddr("tcp", s)
	misc.CheckError(err, "resolving address in linker.go/startConn", true)
	for {
		if m {
			log.Println("Listening on", tcpAddr.String())
			listener, err = net.ListenTCP("tcp", tcpAddr)
			misc.CheckError(err, "listening in linker.go/startConn", true)
			log.Println("Looking for a client...")
			l.conn, err = listener.AcceptTCP()
			misc.CheckError(err, "Accepting client in linker.go/startCnn", true)
			log.Print("Connection acepted")
			listener.Close()
		} else {
			log.Print("Dialing...")
			l.conn, err = net.DialTCP("tcp", nil, tcpAddr)
			misc.CheckError(err, "Dialing adresse in linker.go/startConn", true)
		}
		l.handleConn(o, t)
		log.Println("Closing connection")
		listener.Close()
		l.conn.Close()
		l.conn = nil
	}
}
コード例 #18
0
ファイル: tcp_consumer.go プロジェクト: elodina/gonzo
func (tc *Consumer) closeListener(listener *net.TCPListener) {
	<-tc.close
	err := listener.Close()
	if err != nil {
		log.Warning("%s", err)
	}
	close(tc.closed)
}
コード例 #19
0
func (svr *Server) handler(listener *net.TCPListener) {
	defer listener.Close()
	for {
		conn, err := listener.Accept()
		if err != nil {
			time.Sleep(1 * time.Second)
			svr.StartServer()
			return
		}

		go svr.handleClient(conn)
	}
}
コード例 #20
0
ファイル: tcp.go プロジェクト: ducktsmt/v2ray-core
func (server *Server) acceptConnections(listener *net.TCPListener) {
	server.accepting = true
	defer listener.Close()
	for server.accepting {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Printf("Failed accept TCP connection: %v", err)
			continue
		}

		go server.handleConnection(conn)
	}
}
コード例 #21
0
ファイル: server.go プロジェクト: silverjava/dns
// serveTCP starts a TCP listener for the server.
// Each request is handled in a seperate goroutine.
func (srv *Server) serveTCP(l *net.TCPListener) error {
	defer l.Close()
	handler := srv.Handler
	if handler == nil {
		handler = DefaultServeMux
	}
forever:
	for {
		rw, e := l.AcceptTCP()
		if e != nil {
			// don't bail out, but wait for a new request
			continue
		}
		if srv.ReadTimeout != 0 {
			rw.SetReadDeadline(time.Now().Add(srv.ReadTimeout))
		}
		if srv.WriteTimeout != 0 {
			rw.SetWriteDeadline(time.Now().Add(srv.WriteTimeout))
		}
		l := make([]byte, 2)
		n, err := rw.Read(l)
		if err != nil || n != 2 {
			continue
		}
		length, _ := unpackUint16(l, 0)
		if length == 0 {
			continue
		}
		m := make([]byte, int(length))
		n, err = rw.Read(m[:int(length)])
		if err != nil || n == 0 {
			continue
		}
		i := n
		for i < int(length) {
			j, err := rw.Read(m[i:int(length)])
			if err != nil {
				continue forever
			}
			i += j
		}
		n = i
		d, err := newConn(rw, nil, rw.RemoteAddr(), m, handler, srv.TsigSecret)
		if err != nil {
			continue
		}
		go d.serve()
	}
	panic("dns: not reached")
}
コード例 #22
0
ファイル: server.go プロジェクト: andradeandrey/godns
func (srv *Server) ServeTCP(l *net.TCPListener) os.Error {
	defer l.Close()
	handler := srv.Handler
	if handler == nil {
		handler = DefaultServeMux
	}
forever:
	for {
		rw, e := l.AcceptTCP()
		if e != nil {
			return e
		}
		if srv.ReadTimeout != 0 {
			rw.SetReadTimeout(srv.ReadTimeout)
		}
		if srv.WriteTimeout != 0 {
			rw.SetWriteTimeout(srv.WriteTimeout)
		}
		l := make([]byte, 2)
		n, err := rw.Read(l)
		if err != nil || n != 2 {
			continue
		}
		length, _ := unpackUint16(l, 0)
		if length == 0 {
			continue
		}
		m := make([]byte, int(length))
		n, err = rw.Read(m[:int(length)])
		if err != nil {
			continue
		}
		i := n
		for i < int(length) {
			j, err := rw.Read(m[i:int(length)])
			if err != nil {
				continue forever
			}
			i += j
		}
		n = i
		d, err := newConn(rw, nil, rw.RemoteAddr(), m, handler)
		if err != nil {
			continue
		}
		go d.serve()
	}
	panic("not reached")
}
コード例 #23
0
ファイル: server.go プロジェクト: mconintet/kiwi
func (srv *Server) serve(ln *net.TCPListener) error {
	defer ln.Close()

	for {
		if cn, err := ln.Accept(); err != nil {
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				continue
			} else {
				return err
			}
		} else {
			conn := newConn(srv, cn)
			srv.ConnPool.Add(conn)
			go conn.serve()
		}
	}
}
コード例 #24
0
ファイル: sockopt_linux.go プロジェクト: osrg/gobgp
func SetTcpMD5SigSockopts(l *net.TCPListener, address string, key string) error {
	t, _ := buildTcpMD5Sig(address, key)
	fi, err := l.File()
	defer fi.Close()
	if err != nil {
		return err
	}
	if l, err := net.FileListener(fi); err == nil {
		defer l.Close()
	}
	b := *(*[unsafe.Sizeof(t)]byte)(unsafe.Pointer(&t))
	if err := syscall.SetsockoptString(int(fi.Fd()),
		syscall.IPPROTO_TCP, TCP_MD5SIG,
		string(b[:])); err != nil {
		return err
	}
	return nil
}
コード例 #25
0
ファイル: sockopt_linux.go プロジェクト: jojimt/netplugin
func SetTcpMD5SigSockopts(l *net.TCPListener, address string, key string) error {
	t, _ := buildTcpMD5Sig(address, key)
	fi, err := l.File()
	defer fi.Close()
	if err != nil {
		return err
	}
	if l, err := net.FileListener(fi); err == nil {
		defer l.Close()
	}
	_, _, e := syscall.Syscall6(syscall.SYS_SETSOCKOPT, fi.Fd(),
		uintptr(syscall.IPPROTO_TCP), uintptr(TCP_MD5SIG),
		uintptr(unsafe.Pointer(&t)), unsafe.Sizeof(t), 0)
	if e > 0 {
		return e
	}
	return nil
}
コード例 #26
0
func listenTCP(host, port string) (err error) {
	var listener *net.TCPListener
	// Automatically assign open port
	address, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(host, port))
	if err != nil {
		log.WithField("error", err).Fatal("Unable to resolve tcp address")
		return
	}
	listener, err = net.ListenTCP("tcp", address)
	if err != nil {
		log.WithField("error", err).Fatal("Unable to bind to tcp on localhost")
		return
	}
	log.WithField("address", listener.Addr()).Info("Listening")
	defer listener.Close()
	serve(listener)
	return
}
コード例 #27
0
ファイル: server.go プロジェクト: jackwanger/chatserver
func (this *Server) Start(listener *net.TCPListener) {
	log.Printf("Start listen on %v\r\n", listener.Addr())
	this.waitGroup.Add(1)
	defer func() {
		listener.Close()
		this.waitGroup.Done()
	}()

	// 防止恶意连接
	go this.dealSpamConn()

	// report记录,定时发送邮件
	go report.Work()

	for {
		select {
		case <-this.exitCh:
			log.Printf("Stop listen on %v\r\n", listener.Addr())
			return
		default:
		}

		listener.SetDeadline(time.Now().Add(this.acceptTimeout))
		conn, err := listener.AcceptTCP()

		if err != nil {
			if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
				// log.Printf("Accept timeout: %v\r\n", opErr)
				continue
			}
			report.AddCount(report.TryConnect, 1)
			log.Printf("Accept error: %v\r\n", err)
			continue
		}

		report.AddCount(report.SuccessConnect, 1)

		// 连接后等待登陆验证
		handlers.ConnMapLoginStatus.Set(conn, time.Now())
		log.Printf("Accept: %v\r\n", conn.RemoteAddr())

		go this.handleClientConn(conn)
	}
}
コード例 #28
0
ファイル: server.go プロジェクト: houcy/push
func (this *Server) Run(listener *net.TCPListener) {
	defer func() {
		listener.Close()
	}()

	//go this.dealSpamConn()
	log.Infof("Starting comet server on: %s", listener.Addr().String())
	if err := storage.Instance.AddComet(this.Name); err != nil {
		log.Errorf("failed to add comet to Redis: %s", err.Error())
	}

	// keep the data of this node not expired on redis
	this.startRefreshRoutine()
	this.startWorkers()

	for {
		select {
		case <-this.ctrl:
			log.Infof("ask me to quit")
			this.stopWorkers()
			this.stopRefreshRoutine()
			return
		default:
		}

		listener.SetDeadline(time.Now().Add(this.acceptTimeout * time.Second))
		conn, err := listener.AcceptTCP()
		if err != nil {
			if e, ok := err.(*net.OpError); ok && e.Timeout() {
				continue
			}
			log.Errorf("accept failed: %v\n", err)
			continue
		}
		/*
			// first packet must sent by client in specified seconds
			if err = conn.SetReadDeadline(time.Now().Add(20)); err != nil {
				glog.Errorf("conn.SetReadDeadLine() error(%v)", err)
				conn.Close()
				continue
			}*/
		go this.handleConnection(conn)
	}
}
コード例 #29
0
ファイル: server.go プロジェクト: kaelliu/Miscellaneous
func (srv *Server) Serve(listener *net.TCPListener) error {
	defer listener.Close()

	for {
		conn, err := listener.Accept()
		fmt.Println("accept :", conn.RemoteAddr())
		if err != nil {
			return err
		}

		serveConn, err := srv.newConn(conn)
		if err != nil {
			continue
		}
		go serveConn.ServeConn()
	}

	panic("not reached")
}
コード例 #30
0
ファイル: service.go プロジェクト: simia-tech/iris
// Accepts inbound connections till the service is terminated. For each one it
// starts a new handler and hands the socket over.
func (r *Relay) acceptor(listener *net.TCPListener) {
	// Accept connections until termination request
	var errc chan error
	for errc == nil {
		select {
		case errc = <-r.quit:
			break
		case client := <-r.done:
			// A client terminated, remove from active list
			delete(r.clients, client)
			if err := client.report(); err != nil {
				log.Printf("relay: closing client error: %v.", err)
			}
		default:
			// Accept an incoming connection but without blocking for too long
			listener.SetDeadline(time.Now().Add(acceptPollRate))
			if sock, err := listener.Accept(); err == nil {
				if rel, err := r.acceptRelay(sock); err != nil {
					log.Printf("relay: accept failed: %v.", err)
				} else {
					r.clients[rel] = struct{}{}
				}
			} else if !err.(net.Error).Timeout() {
				log.Printf("relay: accept failed: %v, terminating.", err)
			}
		}
	}
	// In case of failure, wait for termination request
	if errc == nil {
		errc = <-r.quit
	}
	// Forcefully close all active client connections
	for rel, _ := range r.clients {
		rel.drop()
		<-r.done
	}
	for rel, _ := range r.clients {
		rel.report()
	}
	// Clean up and report
	errc <- listener.Close()
}