func (server *Server) ListenAndServe(updateConfig func(func(*ServerConfig) error)) error { fs := &fronted.Server{ Addr: server.Addr, HostFn: server.HostFn, ReadTimeout: server.ReadTimeout, WriteTimeout: server.WriteTimeout, CertContext: server.CertContext, AllowNonGlobalDestinations: server.AllowNonGlobalDestinations, } if server.AllowedCountries != nil { server.geoCache, _ = lru.New(1000000) } if server.AllowedPorts != nil || server.AllowedCountries != nil { fs.Allow = func(req *http.Request, destAddr string) error { if server.AllowedPorts != nil { err := server.checkForDisallowedPort(destAddr) if err != nil { return err } } if server.AllowedCountries != nil { err := server.checkForDisallowedCountry(req) if err != nil { return err } } return nil } } if server.cfg.Unencrypted { log.Debug("Running in unencrypted mode") fs.CertContext = nil } // Add callbacks to track bytes given fs.OnBytesReceived = func(ip string, destAddr string, req *http.Request, bytes int64) { onBytesGiven(destAddr, req, bytes) statserver.OnBytesReceived(ip, bytes) } fs.OnBytesSent = func(ip string, destAddr string, req *http.Request, bytes int64) { onBytesGiven(destAddr, req, bytes) statserver.OnBytesSent(ip, bytes) } l, err := fs.Listen() if err != nil { return fmt.Errorf("Unable to listen at %s: %s", server.Addr, err) } go server.register(updateConfig) return fs.Serve(l) }
// withStats wraps a connection with stat tracking logic, recording traffic // under the Conn's RemoteAddr. func withStats(conn net.Conn, err error) (net.Conn, error) { if err != nil { return conn, err } remoteAddr := conn.RemoteAddr().String() ip, _, err := net.SplitHostPort(remoteAddr) if err != nil { log.Debugf("Unable to split host and port for %v, skipping byte counting: %v", remoteAddr, err) return conn, nil } return &bytecounting.Conn{ Orig: conn, OnRead: func(bytes int64) { onBytesGotten(bytes) statserver.OnBytesReceived(ip, bytes) }, OnWrite: func(bytes int64) { onBytesGotten(bytes) statserver.OnBytesSent(ip, bytes) }, }, nil }