github.com/psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/parameters/parameters.go (about)

     1  /*
     2   * Copyright (c) 2018, Psiphon Inc.
     3   * All rights reserved.
     4   *
     5   * This program is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  /*
    21  Package parameters implements dynamic, concurrency-safe parameters that
    22  determine Psiphon client and server behaviors.
    23  
    24  Parameters include network timeouts, probabilities for actions, lists of
    25  protocols, etc. Parameters are initialized with reasonable defaults. New
    26  values may be applied, allowing the client or server to customize its
    27  parameters from both a config file and tactics data. Sane minimum values are
    28  enforced.
    29  
    30  Parameters may be read and updated concurrently. The read mechanism offers a
    31  snapshot so that related parameters, such as two Ints representing a range; or
    32  a more complex series of related parameters; may be read in an atomic and
    33  consistent way. For example:
    34  
    35  	p := params.Get()
    36  	min := p.Int("Min")
    37  	max := p.Int("Max")
    38  	p = nil
    39  
    40  For long-running operations, it is recommended to set any pointer to the
    41  snapshot to nil to allow garbage collection of old snaphots in cases where the
    42  parameters change.
    43  
    44  In general, parameters should be read as close to the point of use as possible
    45  to ensure that dynamic changes to the parameter values take effect.
    46  
    47  For duration parameters, time.ParseDuration-compatible string values are
    48  supported when applying new values. This allows specifying durations as, for
    49  example, "100ms" or "24h".
    50  
    51  Values read from the parameters are not deep copies and must be treated as
    52  read-only.
    53  */
    54  package parameters
    55  
    56  import (
    57  	"encoding/json"
    58  	"net/http"
    59  	"reflect"
    60  	"sync/atomic"
    61  	"time"
    62  
    63  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
    64  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
    65  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
    66  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
    67  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
    68  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/transforms"
    69  	"golang.org/x/net/bpf"
    70  )
    71  
    72  const (
    73  	NetworkLatencyMultiplier                         = "NetworkLatencyMultiplier"
    74  	NetworkLatencyMultiplierMin                      = "NetworkLatencyMultiplierMin"
    75  	NetworkLatencyMultiplierMax                      = "NetworkLatencyMultiplierMax"
    76  	NetworkLatencyMultiplierLambda                   = "NetworkLatencyMultiplierLambda"
    77  	TacticsWaitPeriod                                = "TacticsWaitPeriod"
    78  	TacticsRetryPeriod                               = "TacticsRetryPeriod"
    79  	TacticsRetryPeriodJitter                         = "TacticsRetryPeriodJitter"
    80  	TacticsTimeout                                   = "TacticsTimeout"
    81  	ConnectionWorkerPoolSize                         = "ConnectionWorkerPoolSize"
    82  	TunnelPoolSize                                   = "TunnelPoolSize"
    83  	TunnelConnectTimeout                             = "TunnelConnectTimeout"
    84  	EstablishTunnelTimeout                           = "EstablishTunnelTimeout"
    85  	EstablishTunnelWorkTime                          = "EstablishTunnelWorkTime"
    86  	EstablishTunnelPausePeriod                       = "EstablishTunnelPausePeriod"
    87  	EstablishTunnelPausePeriodJitter                 = "EstablishTunnelPausePeriodJitter"
    88  	EstablishTunnelServerAffinityGracePeriod         = "EstablishTunnelServerAffinityGracePeriod"
    89  	StaggerConnectionWorkersPeriod                   = "StaggerConnectionWorkersPeriod"
    90  	StaggerConnectionWorkersJitter                   = "StaggerConnectionWorkersJitter"
    91  	LimitIntensiveConnectionWorkers                  = "LimitIntensiveConnectionWorkers"
    92  	UpstreamProxyErrorMinWaitDuration                = "UpstreamProxyErrorMinWaitDuration"
    93  	UpstreamProxyErrorMaxWaitDuration                = "UpstreamProxyErrorMaxWaitDuration"
    94  	IgnoreHandshakeStatsRegexps                      = "IgnoreHandshakeStatsRegexps"
    95  	PrioritizeTunnelProtocolsProbability             = "PrioritizeTunnelProtocolsProbability"
    96  	PrioritizeTunnelProtocols                        = "PrioritizeTunnelProtocols"
    97  	PrioritizeTunnelProtocolsCandidateCount          = "PrioritizeTunnelProtocolsCandidateCount"
    98  	InitialLimitTunnelProtocolsProbability           = "InitialLimitTunnelProtocolsProbability"
    99  	InitialLimitTunnelProtocols                      = "InitialLimitTunnelProtocols"
   100  	InitialLimitTunnelProtocolsCandidateCount        = "InitialLimitTunnelProtocolsCandidateCount"
   101  	LimitTunnelProtocolsProbability                  = "LimitTunnelProtocolsProbability"
   102  	LimitTunnelProtocols                             = "LimitTunnelProtocols"
   103  	LimitTunnelDialPortNumbersProbability            = "LimitTunnelDialPortNumbersProbability"
   104  	LimitTunnelDialPortNumbers                       = "LimitTunnelDialPortNumbers"
   105  	LimitTLSProfilesProbability                      = "LimitTLSProfilesProbability"
   106  	LimitTLSProfiles                                 = "LimitTLSProfiles"
   107  	UseOnlyCustomTLSProfiles                         = "UseOnlyCustomTLSProfiles"
   108  	CustomTLSProfiles                                = "CustomTLSProfiles"
   109  	SelectRandomizedTLSProfileProbability            = "SelectRandomizedTLSProfileProbability"
   110  	NoDefaultTLSSessionIDProbability                 = "NoDefaultTLSSessionIDProbability"
   111  	DisableFrontingProviderTLSProfiles               = "DisableFrontingProviderTLSProfiles"
   112  	LimitQUICVersionsProbability                     = "LimitQUICVersionsProbability"
   113  	LimitQUICVersions                                = "LimitQUICVersions"
   114  	DisableFrontingProviderQUICVersions              = "DisableFrontingProviderQUICVersions"
   115  	QUICDisableClientPathMTUDiscoveryProbability     = "QUICDisableClientPathMTUDiscoveryProbability"
   116  	FragmentorProbability                            = "FragmentorProbability"
   117  	FragmentorLimitProtocols                         = "FragmentorLimitProtocols"
   118  	FragmentorMinTotalBytes                          = "FragmentorMinTotalBytes"
   119  	FragmentorMaxTotalBytes                          = "FragmentorMaxTotalBytes"
   120  	FragmentorMinWriteBytes                          = "FragmentorMinWriteBytes"
   121  	FragmentorMaxWriteBytes                          = "FragmentorMaxWriteBytes"
   122  	FragmentorMinDelay                               = "FragmentorMinDelay"
   123  	FragmentorMaxDelay                               = "FragmentorMaxDelay"
   124  	FragmentorDownstreamProbability                  = "FragmentorDownstreamProbability"
   125  	FragmentorDownstreamLimitProtocols               = "FragmentorDownstreamLimitProtocols"
   126  	FragmentorDownstreamMinTotalBytes                = "FragmentorDownstreamMinTotalBytes"
   127  	FragmentorDownstreamMaxTotalBytes                = "FragmentorDownstreamMaxTotalBytes"
   128  	FragmentorDownstreamMinWriteBytes                = "FragmentorDownstreamMinWriteBytes"
   129  	FragmentorDownstreamMaxWriteBytes                = "FragmentorDownstreamMaxWriteBytes"
   130  	FragmentorDownstreamMinDelay                     = "FragmentorDownstreamMinDelay"
   131  	FragmentorDownstreamMaxDelay                     = "FragmentorDownstreamMaxDelay"
   132  	ObfuscatedSSHMinPadding                          = "ObfuscatedSSHMinPadding"
   133  	ObfuscatedSSHMaxPadding                          = "ObfuscatedSSHMaxPadding"
   134  	TunnelOperateShutdownTimeout                     = "TunnelOperateShutdownTimeout"
   135  	TunnelPortForwardDialTimeout                     = "TunnelPortForwardDialTimeout"
   136  	PacketTunnelReadTimeout                          = "PacketTunnelReadTimeout"
   137  	TunnelRateLimits                                 = "TunnelRateLimits"
   138  	AdditionalCustomHeaders                          = "AdditionalCustomHeaders"
   139  	SpeedTestPaddingMinBytes                         = "SpeedTestPaddingMinBytes"
   140  	SpeedTestPaddingMaxBytes                         = "SpeedTestPaddingMaxBytes"
   141  	SpeedTestMaxSampleCount                          = "SpeedTestMaxSampleCount"
   142  	SSHKeepAliveSpeedTestSampleProbability           = "SSHKeepAliveSpeedTestSampleProbability"
   143  	SSHKeepAlivePaddingMinBytes                      = "SSHKeepAlivePaddingMinBytes"
   144  	SSHKeepAlivePaddingMaxBytes                      = "SSHKeepAlivePaddingMaxBytes"
   145  	SSHKeepAlivePeriodMin                            = "SSHKeepAlivePeriodMin"
   146  	SSHKeepAlivePeriodMax                            = "SSHKeepAlivePeriodMax"
   147  	SSHKeepAlivePeriodicTimeout                      = "SSHKeepAlivePeriodicTimeout"
   148  	SSHKeepAlivePeriodicInactivePeriod               = "SSHKeepAlivePeriodicInactivePeriod"
   149  	SSHKeepAliveProbeTimeout                         = "SSHKeepAliveProbeTimeout"
   150  	SSHKeepAliveProbeInactivePeriod                  = "SSHKeepAliveProbeInactivePeriod"
   151  	SSHKeepAliveNetworkConnectivityPollingPeriod     = "SSHKeepAliveNetworkConnectivityPollingPeriod"
   152  	SSHKeepAliveResetOnFailureProbability            = "SSHKeepAliveResetOnFailureProbability"
   153  	HTTPProxyOriginServerTimeout                     = "HTTPProxyOriginServerTimeout"
   154  	HTTPProxyMaxIdleConnectionsPerHost               = "HTTPProxyMaxIdleConnectionsPerHost"
   155  	FetchRemoteServerListTimeout                     = "FetchRemoteServerListTimeout"
   156  	FetchRemoteServerListRetryPeriod                 = "FetchRemoteServerListRetryPeriod"
   157  	FetchRemoteServerListStalePeriod                 = "FetchRemoteServerListStalePeriod"
   158  	RemoteServerListSignaturePublicKey               = "RemoteServerListSignaturePublicKey"
   159  	RemoteServerListURLs                             = "RemoteServerListURLs"
   160  	ObfuscatedServerListRootURLs                     = "ObfuscatedServerListRootURLs"
   161  	PsiphonAPIRequestTimeout                         = "PsiphonAPIRequestTimeout"
   162  	PsiphonAPIStatusRequestPeriodMin                 = "PsiphonAPIStatusRequestPeriodMin"
   163  	PsiphonAPIStatusRequestPeriodMax                 = "PsiphonAPIStatusRequestPeriodMax"
   164  	PsiphonAPIStatusRequestShortPeriodMin            = "PsiphonAPIStatusRequestShortPeriodMin"
   165  	PsiphonAPIStatusRequestShortPeriodMax            = "PsiphonAPIStatusRequestShortPeriodMax"
   166  	PsiphonAPIStatusRequestPaddingMinBytes           = "PsiphonAPIStatusRequestPaddingMinBytes"
   167  	PsiphonAPIStatusRequestPaddingMaxBytes           = "PsiphonAPIStatusRequestPaddingMaxBytes"
   168  	PsiphonAPIPersistentStatsMaxCount                = "PsiphonAPIPersistentStatsMaxCount"
   169  	PsiphonAPIConnectedRequestPeriod                 = "PsiphonAPIConnectedRequestPeriod"
   170  	PsiphonAPIConnectedRequestRetryPeriod            = "PsiphonAPIConnectedRequestRetryPeriod"
   171  	FetchSplitTunnelRoutesTimeout                    = "FetchSplitTunnelRoutesTimeout"
   172  	SplitTunnelRoutesURLFormat                       = "SplitTunnelRoutesURLFormat"
   173  	SplitTunnelRoutesSignaturePublicKey              = "SplitTunnelRoutesSignaturePublicKey"
   174  	SplitTunnelDNSServer                             = "SplitTunnelDNSServer"
   175  	SplitTunnelClassificationTTL                     = "SplitTunnelClassificationTTL"
   176  	SplitTunnelClassificationMaxEntries              = "SplitTunnelClassificationMaxEntries"
   177  	FetchUpgradeTimeout                              = "FetchUpgradeTimeout"
   178  	FetchUpgradeRetryPeriod                          = "FetchUpgradeRetryPeriod"
   179  	FetchUpgradeStalePeriod                          = "FetchUpgradeStalePeriod"
   180  	UpgradeDownloadURLs                              = "UpgradeDownloadURLs"
   181  	UpgradeDownloadClientVersionHeader               = "UpgradeDownloadClientVersionHeader"
   182  	TotalBytesTransferredNoticePeriod                = "TotalBytesTransferredNoticePeriod"
   183  	TotalBytesTransferredEmitMemoryMetrics           = "TotalBytesTransferredEmitMemoryMetrics"
   184  	MeekDialDomainsOnly                              = "MeekDialDomainsOnly"
   185  	MeekLimitBufferSizes                             = "MeekLimitBufferSizes"
   186  	MeekCookieMaxPadding                             = "MeekCookieMaxPadding"
   187  	MeekFullReceiveBufferLength                      = "MeekFullReceiveBufferLength"
   188  	MeekReadPayloadChunkLength                       = "MeekReadPayloadChunkLength"
   189  	MeekLimitedFullReceiveBufferLength               = "MeekLimitedFullReceiveBufferLength"
   190  	MeekLimitedReadPayloadChunkLength                = "MeekLimitedReadPayloadChunkLength"
   191  	MeekMinPollInterval                              = "MeekMinPollInterval"
   192  	MeekMinPollIntervalJitter                        = "MeekMinPollIntervalJitter"
   193  	MeekMaxPollInterval                              = "MeekMaxPollInterval"
   194  	MeekMaxPollIntervalJitter                        = "MeekMaxPollIntervalJitter"
   195  	MeekPollIntervalMultiplier                       = "MeekPollIntervalMultiplier"
   196  	MeekPollIntervalJitter                           = "MeekPollIntervalJitter"
   197  	MeekApplyPollIntervalMultiplierProbability       = "MeekApplyPollIntervalMultiplierProbability"
   198  	MeekRoundTripRetryDeadline                       = "MeekRoundTripRetryDeadline"
   199  	MeekRoundTripRetryMinDelay                       = "MeekRoundTripRetryMinDelay"
   200  	MeekRoundTripRetryMaxDelay                       = "MeekRoundTripRetryMaxDelay"
   201  	MeekRoundTripRetryMultiplier                     = "MeekRoundTripRetryMultiplier"
   202  	MeekRoundTripTimeout                             = "MeekRoundTripTimeout"
   203  	MeekTrafficShapingProbability                    = "MeekTrafficShapingProbability"
   204  	MeekTrafficShapingLimitProtocols                 = "MeekTrafficShapingLimitProtocols"
   205  	MeekMinTLSPadding                                = "MeekMinTLSPadding"
   206  	MeekMaxTLSPadding                                = "MeekMaxTLSPadding"
   207  	MeekMinLimitRequestPayloadLength                 = "MeekMinLimitRequestPayloadLength"
   208  	MeekMaxLimitRequestPayloadLength                 = "MeekMaxLimitRequestPayloadLength"
   209  	MeekRedialTLSProbability                         = "MeekRedialTLSProbability"
   210  	MeekAlternateCookieNameProbability               = "MeekAlternateCookieNameProbability"
   211  	MeekAlternateContentTypeProbability              = "MeekAlternateContentTypeProbability"
   212  	TransformHostNameProbability                     = "TransformHostNameProbability"
   213  	PickUserAgentProbability                         = "PickUserAgentProbability"
   214  	LivenessTestMinUpstreamBytes                     = "LivenessTestMinUpstreamBytes"
   215  	LivenessTestMaxUpstreamBytes                     = "LivenessTestMaxUpstreamBytes"
   216  	LivenessTestMinDownstreamBytes                   = "LivenessTestMinDownstreamBytes"
   217  	LivenessTestMaxDownstreamBytes                   = "LivenessTestMaxDownstreamBytes"
   218  	ReplayCandidateCount                             = "ReplayCandidateCount"
   219  	ReplayDialParametersTTL                          = "ReplayDialParametersTTL"
   220  	ReplayTargetUpstreamBytes                        = "ReplayTargetUpstreamBytes"
   221  	ReplayTargetDownstreamBytes                      = "ReplayTargetDownstreamBytes"
   222  	ReplayTargetTunnelDuration                       = "ReplayTargetTunnelDuration"
   223  	ReplayLaterRoundMoveToFrontProbability           = "ReplayLaterRoundMoveToFrontProbability"
   224  	ReplayRetainFailedProbability                    = "ReplayRetainFailedProbability"
   225  	ReplayBPF                                        = "ReplayBPF"
   226  	ReplaySSH                                        = "ReplaySSH"
   227  	ReplayObfuscatorPadding                          = "ReplayObfuscatorPadding"
   228  	ReplayFragmentor                                 = "ReplayFragmentor"
   229  	ReplayTLSProfile                                 = "ReplayTLSProfile"
   230  	ReplayRandomizedTLSProfile                       = "ReplayRandomizedTLSProfile"
   231  	ReplayFronting                                   = "ReplayFronting"
   232  	ReplayHostname                                   = "ReplayHostname"
   233  	ReplayQUICVersion                                = "ReplayQUICVersion"
   234  	ReplayObfuscatedQUIC                             = "ReplayObfuscatedQUIC"
   235  	ReplayConjureRegistration                        = "ReplayConjureRegistration"
   236  	ReplayConjureTransport                           = "ReplayConjureTransport"
   237  	ReplayLivenessTest                               = "ReplayLivenessTest"
   238  	ReplayUserAgent                                  = "ReplayUserAgent"
   239  	ReplayAPIRequestPadding                          = "ReplayAPIRequestPadding"
   240  	ReplayHoldOffTunnel                              = "ReplayHoldOffTunnel"
   241  	ReplayResolveParameters                          = "ReplayResolveParameters"
   242  	APIRequestUpstreamPaddingMinBytes                = "APIRequestUpstreamPaddingMinBytes"
   243  	APIRequestUpstreamPaddingMaxBytes                = "APIRequestUpstreamPaddingMaxBytes"
   244  	APIRequestDownstreamPaddingMinBytes              = "APIRequestDownstreamPaddingMinBytes"
   245  	APIRequestDownstreamPaddingMaxBytes              = "APIRequestDownstreamPaddingMaxBytes"
   246  	PersistentStatsMaxStoreRecords                   = "PersistentStatsMaxStoreRecords"
   247  	PersistentStatsMaxSendBytes                      = "PersistentStatsMaxSendBytes"
   248  	RecordRemoteServerListPersistentStatsProbability = "RecordRemoteServerListPersistentStatsProbability"
   249  	RecordFailedTunnelPersistentStatsProbability     = "RecordFailedTunnelPersistentStatsProbability"
   250  	ServerEntryMinimumAgeForPruning                  = "ServerEntryMinimumAgeForPruning"
   251  	ApplicationParametersProbability                 = "ApplicationParametersProbability"
   252  	ApplicationParameters                            = "ApplicationParameters"
   253  	BPFServerTCPProgram                              = "BPFServerTCPProgram"
   254  	BPFServerTCPProbability                          = "BPFServerTCPProbability"
   255  	BPFClientTCPProgram                              = "BPFClientTCPProgram"
   256  	BPFClientTCPProbability                          = "BPFClientTCPProbability"
   257  	ServerPacketManipulationSpecs                    = "ServerPacketManipulationSpecs"
   258  	ServerProtocolPacketManipulations                = "ServerProtocolPacketManipulations"
   259  	ServerPacketManipulationProbability              = "ServerPacketManipulationProbability"
   260  	FeedbackUploadURLs                               = "FeedbackUploadURLs"
   261  	FeedbackEncryptionPublicKey                      = "FeedbackEncryptionPublicKey"
   262  	FeedbackTacticsWaitPeriod                        = "FeedbackTacticsWaitPeriod"
   263  	FeedbackUploadMaxAttempts                        = "FeedbackUploadMaxAttempts"
   264  	FeedbackUploadRetryMinDelaySeconds               = "FeedbackUploadRetryMinDelaySeconds"
   265  	FeedbackUploadRetryMaxDelaySeconds               = "FeedbackUploadRetryMaxDelaySeconds"
   266  	FeedbackUploadTimeoutSeconds                     = "FeedbackUploadTimeoutSeconds"
   267  	ServerReplayPacketManipulation                   = "ServerReplayPacketManipulation"
   268  	ServerReplayFragmentor                           = "ServerReplayFragmentor"
   269  	ServerReplayUnknownGeoIP                         = "ServerReplayUnknownGeoIP"
   270  	ServerReplayTTL                                  = "ServerReplayTTL"
   271  	ServerReplayTargetWaitDuration                   = "ServerReplayTargetWaitDuration"
   272  	ServerReplayTargetTunnelDuration                 = "ServerReplayTargetTunnelDuration"
   273  	ServerReplayTargetUpstreamBytes                  = "ServerReplayTargetUpstreamBytes"
   274  	ServerReplayTargetDownstreamBytes                = "ServerReplayTargetDownstreamBytes"
   275  	ServerReplayFailedCountThreshold                 = "ServerReplayFailedCountThreshold"
   276  	ServerBurstUpstreamDeadline                      = "ServerBurstUpstreamDeadline"
   277  	ServerBurstUpstreamTargetBytes                   = "ServerBurstUpstreamTargetBytes"
   278  	ServerBurstDownstreamDeadline                    = "ServerBurstDownstreamDeadline"
   279  	ServerBurstDownstreamTargetBytes                 = "ServerBurstDownstreamTargetBytes"
   280  	ClientBurstUpstreamDeadline                      = "ClientBurstUpstreamDeadline"
   281  	ClientBurstUpstreamTargetBytes                   = "ClientBurstUpstreamTargetBytes"
   282  	ClientBurstDownstreamDeadline                    = "ClientBurstDownstreamDeadline"
   283  	ClientBurstDownstreamTargetBytes                 = "ClientBurstDownstreamTargetBytes"
   284  	ConjureCachedRegistrationTTL                     = "ConjureCachedRegistrationTTL"
   285  	ConjureAPIRegistrarURL                           = "ConjureAPIRegistrarURL"
   286  	ConjureAPIRegistrarBidirectionalURL              = "ConjureAPIRegistrarBidirectionalURL"
   287  	ConjureAPIRegistrarFrontingSpecs                 = "ConjureAPIRegistrarFrontingSpecs"
   288  	ConjureAPIRegistrarMinDelay                      = "ConjureAPIRegistrarMinDelay"
   289  	ConjureAPIRegistrarMaxDelay                      = "ConjureAPIRegistrarMaxDelay"
   290  	ConjureDecoyRegistrarProbability                 = "ConjureDecoyRegistrarProbability"
   291  	ConjureDecoyRegistrarWidth                       = "ConjureDecoyRegistrarWidth"
   292  	ConjureDecoyRegistrarMinDelay                    = "ConjureDecoyRegistrarMinDelay"
   293  	ConjureDecoyRegistrarMaxDelay                    = "ConjureDecoyRegistrarMaxDelay"
   294  	ConjureTransportObfs4Probability                 = "ConjureTransportObfs4Probability"
   295  	CustomHostNameRegexes                            = "CustomHostNameRegexes"
   296  	CustomHostNameProbability                        = "CustomHostNameProbability"
   297  	CustomHostNameLimitProtocols                     = "CustomHostNameLimitProtocols"
   298  	HoldOffTunnelMinDuration                         = "HoldOffTunnelMinDuration"
   299  	HoldOffTunnelMaxDuration                         = "HoldOffTunnelMaxDuration"
   300  	HoldOffTunnelProtocols                           = "HoldOffTunnelProtocols"
   301  	HoldOffTunnelFrontingProviderIDs                 = "HoldOffTunnelFrontingProviderIDs"
   302  	HoldOffTunnelProbability                         = "HoldOffTunnelProbability"
   303  	RestrictFrontingProviderIDs                      = "RestrictFrontingProviderIDs"
   304  	RestrictFrontingProviderIDsServerProbability     = "RestrictFrontingProviderIDsServerProbability"
   305  	RestrictFrontingProviderIDsClientProbability     = "RestrictFrontingProviderIDsClientProbability"
   306  	UpstreamProxyAllowAllServerEntrySources          = "UpstreamProxyAllowAllServerEntrySources"
   307  	DestinationBytesMetricsASN                       = "DestinationBytesMetricsASN"
   308  	DNSResolverAttemptsPerServer                     = "DNSResolverAttemptsPerServer"
   309  	DNSResolverAttemptsPerPreferredServer            = "DNSResolverAttemptsPerPreferredServer"
   310  	DNSResolverRequestTimeout                        = "DNSResolverRequestTimeout"
   311  	DNSResolverAwaitTimeout                          = "DNSResolverAwaitTimeout"
   312  	DNSResolverPreresolvedIPAddressCIDRs             = "DNSResolverPreresolvedIPAddressCIDRs"
   313  	DNSResolverPreresolvedIPAddressProbability       = "DNSResolverPreresolvedIPAddressProbability"
   314  	DNSResolverAlternateServers                      = "DNSResolverAlternateServers"
   315  	DNSResolverPreferredAlternateServers             = "DNSResolverPreferredAlternateServers"
   316  	DNSResolverPreferAlternateServerProbability      = "DNSResolverPreferAlternateServerProbability"
   317  	DNSResolverProtocolTransformSpecs                = "DNSResolverProtocolTransformSpecs"
   318  	DNSResolverProtocolTransformScopedSpecNames      = "DNSResolverProtocolTransformScopedSpecNames"
   319  	DNSResolverProtocolTransformProbability          = "DNSResolverProtocolTransformProbability"
   320  	DNSResolverIncludeEDNS0Probability               = "DNSResolverIncludeEDNS0Probability"
   321  	DNSResolverCacheExtensionInitialTTL              = "DNSResolverCacheExtensionInitialTTL"
   322  	DNSResolverCacheExtensionVerifiedTTL             = "DNSResolverCacheExtensionVerifiedTTL"
   323  )
   324  
   325  const (
   326  	useNetworkLatencyMultiplier = 1
   327  	serverSideOnly              = 2
   328  )
   329  
   330  // defaultParameters specifies the type, default value, and minimum value for
   331  // all dynamically configurable client and server parameters.
   332  //
   333  // Do not change the names or types of existing values, as that can break
   334  // client logic or cause parameters to not be applied.
   335  //
   336  // Minimum values are a fail-safe for cases where lower values would break the
   337  // client logic. For example, setting a ConnectionWorkerPoolSize of 0 would
   338  // make the client never connect.
   339  var defaultParameters = map[string]struct {
   340  	value   interface{}
   341  	minimum interface{}
   342  	flags   int32
   343  }{
   344  	// NetworkLatencyMultiplier defaults to 0, meaning off. But when set, it
   345  	// must be a multiplier >= 1.
   346  
   347  	NetworkLatencyMultiplier:       {value: 0.0, minimum: 1.0},
   348  	NetworkLatencyMultiplierMin:    {value: 1.0, minimum: 1.0},
   349  	NetworkLatencyMultiplierMax:    {value: 3.0, minimum: 1.0},
   350  	NetworkLatencyMultiplierLambda: {value: 2.0, minimum: 0.001},
   351  
   352  	TacticsWaitPeriod:        {value: 10 * time.Second, minimum: 0 * time.Second, flags: useNetworkLatencyMultiplier},
   353  	TacticsRetryPeriod:       {value: 5 * time.Second, minimum: 1 * time.Millisecond},
   354  	TacticsRetryPeriodJitter: {value: 0.3, minimum: 0.0},
   355  	TacticsTimeout:           {value: 2 * time.Minute, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   356  
   357  	ConnectionWorkerPoolSize:                 {value: 10, minimum: 1},
   358  	TunnelPoolSize:                           {value: 1, minimum: 1},
   359  	TunnelConnectTimeout:                     {value: 20 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   360  	EstablishTunnelTimeout:                   {value: 300 * time.Second, minimum: time.Duration(0)},
   361  	EstablishTunnelWorkTime:                  {value: 60 * time.Second, minimum: 1 * time.Second},
   362  	EstablishTunnelPausePeriod:               {value: 5 * time.Second, minimum: 1 * time.Millisecond},
   363  	EstablishTunnelPausePeriodJitter:         {value: 0.1, minimum: 0.0},
   364  	EstablishTunnelServerAffinityGracePeriod: {value: 1 * time.Second, minimum: time.Duration(0), flags: useNetworkLatencyMultiplier},
   365  	StaggerConnectionWorkersPeriod:           {value: time.Duration(0), minimum: time.Duration(0)},
   366  	StaggerConnectionWorkersJitter:           {value: 0.1, minimum: 0.0},
   367  	LimitIntensiveConnectionWorkers:          {value: 0, minimum: 0},
   368  	UpstreamProxyErrorMinWaitDuration:        {value: 10 * time.Second, minimum: time.Duration(0)},
   369  	UpstreamProxyErrorMaxWaitDuration:        {value: 30 * time.Second, minimum: time.Duration(0)},
   370  	IgnoreHandshakeStatsRegexps:              {value: false},
   371  	TunnelOperateShutdownTimeout:             {value: 1 * time.Second, minimum: 1 * time.Millisecond, flags: useNetworkLatencyMultiplier},
   372  	TunnelPortForwardDialTimeout:             {value: 10 * time.Second, minimum: 1 * time.Millisecond, flags: useNetworkLatencyMultiplier},
   373  	PacketTunnelReadTimeout:                  {value: 10 * time.Second, minimum: 1 * time.Millisecond, flags: useNetworkLatencyMultiplier},
   374  	TunnelRateLimits:                         {value: common.RateLimits{}},
   375  
   376  	// PrioritizeTunnelProtocols parameters are obsoleted by InitialLimitTunnelProtocols.
   377  	// TODO: remove once no longer required for older clients.
   378  	PrioritizeTunnelProtocolsProbability:    {value: 1.0, minimum: 0.0},
   379  	PrioritizeTunnelProtocols:               {value: protocol.TunnelProtocols{}},
   380  	PrioritizeTunnelProtocolsCandidateCount: {value: 10, minimum: 0},
   381  
   382  	InitialLimitTunnelProtocolsProbability:    {value: 1.0, minimum: 0.0},
   383  	InitialLimitTunnelProtocols:               {value: protocol.TunnelProtocols{}},
   384  	InitialLimitTunnelProtocolsCandidateCount: {value: 0, minimum: 0},
   385  
   386  	LimitTunnelProtocolsProbability: {value: 1.0, minimum: 0.0},
   387  	LimitTunnelProtocols:            {value: protocol.TunnelProtocols{}},
   388  
   389  	LimitTunnelDialPortNumbersProbability: {value: 1.0, minimum: 0.0},
   390  	LimitTunnelDialPortNumbers:            {value: TunnelProtocolPortLists{}},
   391  
   392  	LimitTLSProfilesProbability:           {value: 1.0, minimum: 0.0},
   393  	LimitTLSProfiles:                      {value: protocol.TLSProfiles{}},
   394  	UseOnlyCustomTLSProfiles:              {value: false},
   395  	CustomTLSProfiles:                     {value: protocol.CustomTLSProfiles{}},
   396  	SelectRandomizedTLSProfileProbability: {value: 0.25, minimum: 0.0},
   397  	NoDefaultTLSSessionIDProbability:      {value: 0.5, minimum: 0.0},
   398  	DisableFrontingProviderTLSProfiles:    {value: protocol.LabeledTLSProfiles{}},
   399  
   400  	LimitQUICVersionsProbability:                 {value: 1.0, minimum: 0.0},
   401  	LimitQUICVersions:                            {value: protocol.QUICVersions{}},
   402  	DisableFrontingProviderQUICVersions:          {value: protocol.LabeledQUICVersions{}},
   403  	QUICDisableClientPathMTUDiscoveryProbability: {value: 0.0, minimum: 0.0},
   404  
   405  	FragmentorProbability:              {value: 0.5, minimum: 0.0},
   406  	FragmentorLimitProtocols:           {value: protocol.TunnelProtocols{}},
   407  	FragmentorMinTotalBytes:            {value: 0, minimum: 0},
   408  	FragmentorMaxTotalBytes:            {value: 0, minimum: 0},
   409  	FragmentorMinWriteBytes:            {value: 1, minimum: 1},
   410  	FragmentorMaxWriteBytes:            {value: 1500, minimum: 1},
   411  	FragmentorMinDelay:                 {value: time.Duration(0), minimum: time.Duration(0)},
   412  	FragmentorMaxDelay:                 {value: 10 * time.Millisecond, minimum: time.Duration(0)},
   413  	FragmentorDownstreamProbability:    {value: 0.5, minimum: 0.0, flags: serverSideOnly},
   414  	FragmentorDownstreamLimitProtocols: {value: protocol.TunnelProtocols{}, flags: serverSideOnly},
   415  	FragmentorDownstreamMinTotalBytes:  {value: 0, minimum: 0, flags: serverSideOnly},
   416  	FragmentorDownstreamMaxTotalBytes:  {value: 0, minimum: 0, flags: serverSideOnly},
   417  	FragmentorDownstreamMinWriteBytes:  {value: 1, minimum: 1, flags: serverSideOnly},
   418  	FragmentorDownstreamMaxWriteBytes:  {value: 1500, minimum: 1, flags: serverSideOnly},
   419  	FragmentorDownstreamMinDelay:       {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
   420  	FragmentorDownstreamMaxDelay:       {value: 10 * time.Millisecond, minimum: time.Duration(0), flags: serverSideOnly},
   421  
   422  	// The Psiphon server will reject obfuscated SSH seed messages with
   423  	// padding greater than OBFUSCATE_MAX_PADDING.
   424  	// obfuscator.NewClientObfuscator will ignore invalid min/max padding
   425  	// configurations.
   426  
   427  	ObfuscatedSSHMinPadding: {value: 0, minimum: 0},
   428  	ObfuscatedSSHMaxPadding: {value: obfuscator.OBFUSCATE_MAX_PADDING, minimum: 0},
   429  
   430  	AdditionalCustomHeaders: {value: make(http.Header)},
   431  
   432  	// Speed test and SSH keep alive padding is intended to frustrate
   433  	// fingerprinting and should not exceed ~1 IP packet size.
   434  	//
   435  	// Currently, each serialized speed test sample, populated with real
   436  	// values, is approximately 100 bytes. All SpeedTestMaxSampleCount samples
   437  	// are loaded into memory are sent as API inputs.
   438  
   439  	SpeedTestPaddingMinBytes: {value: 0, minimum: 0},
   440  	SpeedTestPaddingMaxBytes: {value: 256, minimum: 0},
   441  	SpeedTestMaxSampleCount:  {value: 25, minimum: 1},
   442  
   443  	// The Psiphon server times out inactive tunnels after 5 minutes, so this
   444  	// is a soft max for SSHKeepAlivePeriodMax.
   445  
   446  	SSHKeepAliveSpeedTestSampleProbability:       {value: 0.5, minimum: 0.0},
   447  	SSHKeepAlivePaddingMinBytes:                  {value: 0, minimum: 0},
   448  	SSHKeepAlivePaddingMaxBytes:                  {value: 256, minimum: 0},
   449  	SSHKeepAlivePeriodMin:                        {value: 1 * time.Minute, minimum: 1 * time.Second},
   450  	SSHKeepAlivePeriodMax:                        {value: 2 * time.Minute, minimum: 1 * time.Second},
   451  	SSHKeepAlivePeriodicTimeout:                  {value: 30 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   452  	SSHKeepAlivePeriodicInactivePeriod:           {value: 10 * time.Second, minimum: 1 * time.Second},
   453  	SSHKeepAliveProbeTimeout:                     {value: 5 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   454  	SSHKeepAliveProbeInactivePeriod:              {value: 10 * time.Second, minimum: 1 * time.Second},
   455  	SSHKeepAliveNetworkConnectivityPollingPeriod: {value: 500 * time.Millisecond, minimum: 1 * time.Millisecond},
   456  	SSHKeepAliveResetOnFailureProbability:        {value: 0.0, minimum: 0.0},
   457  
   458  	HTTPProxyOriginServerTimeout:       {value: 15 * time.Second, minimum: time.Duration(0), flags: useNetworkLatencyMultiplier},
   459  	HTTPProxyMaxIdleConnectionsPerHost: {value: 50, minimum: 0},
   460  
   461  	FetchRemoteServerListTimeout:       {value: 30 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   462  	FetchRemoteServerListRetryPeriod:   {value: 30 * time.Second, minimum: 1 * time.Millisecond},
   463  	FetchRemoteServerListStalePeriod:   {value: 6 * time.Hour, minimum: 1 * time.Hour},
   464  	RemoteServerListSignaturePublicKey: {value: ""},
   465  	RemoteServerListURLs:               {value: TransferURLs{}},
   466  	ObfuscatedServerListRootURLs:       {value: TransferURLs{}},
   467  
   468  	PsiphonAPIRequestTimeout: {value: 20 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   469  
   470  	PsiphonAPIStatusRequestPeriodMin:      {value: 5 * time.Minute, minimum: 1 * time.Second},
   471  	PsiphonAPIStatusRequestPeriodMax:      {value: 10 * time.Minute, minimum: 1 * time.Second},
   472  	PsiphonAPIStatusRequestShortPeriodMin: {value: 5 * time.Second, minimum: 1 * time.Second},
   473  	PsiphonAPIStatusRequestShortPeriodMax: {value: 10 * time.Second, minimum: 1 * time.Second},
   474  	// PsiphonAPIPersistentStatsMaxCount parameter is obsoleted by PersistentStatsMaxSendBytes.
   475  	// TODO: remove once no longer required for older clients.
   476  	PsiphonAPIPersistentStatsMaxCount: {value: 100, minimum: 1},
   477  	// PsiphonAPIStatusRequestPadding parameters are obsoleted by APIRequestUp/DownstreamPadding.
   478  	// TODO: remove once no longer required for older clients.
   479  	PsiphonAPIStatusRequestPaddingMinBytes: {value: 0, minimum: 0},
   480  	PsiphonAPIStatusRequestPaddingMaxBytes: {value: 256, minimum: 0},
   481  
   482  	PsiphonAPIConnectedRequestRetryPeriod: {value: 5 * time.Second, minimum: 1 * time.Millisecond},
   483  
   484  	// FetchSplitTunnelRoutesTimeout, SplitTunnelRoutesURLFormat,
   485  	// SplitTunnelRoutesSignaturePublicKey and SplitTunnelDNSServer are obsoleted
   486  	// by the server-assisted split tunnel implementation.
   487  	// TODO: remove once no longer required for older clients.
   488  	FetchSplitTunnelRoutesTimeout:       {value: 60 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   489  	SplitTunnelRoutesURLFormat:          {value: ""},
   490  	SplitTunnelRoutesSignaturePublicKey: {value: ""},
   491  	SplitTunnelDNSServer:                {value: ""},
   492  
   493  	SplitTunnelClassificationTTL:        {value: 24 * time.Hour, minimum: 0 * time.Second},
   494  	SplitTunnelClassificationMaxEntries: {value: 65536, minimum: 0},
   495  
   496  	FetchUpgradeTimeout:                {value: 60 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   497  	FetchUpgradeRetryPeriod:            {value: 30 * time.Second, minimum: 1 * time.Millisecond},
   498  	FetchUpgradeStalePeriod:            {value: 6 * time.Hour, minimum: 1 * time.Hour},
   499  	UpgradeDownloadURLs:                {value: TransferURLs{}},
   500  	UpgradeDownloadClientVersionHeader: {value: ""},
   501  
   502  	TotalBytesTransferredNoticePeriod:      {value: 5 * time.Minute, minimum: 1 * time.Second},
   503  	TotalBytesTransferredEmitMemoryMetrics: {value: true},
   504  
   505  	// The meek server times out inactive sessions after 45 seconds, so this
   506  	// is a soft max for MeekMaxPollInterval,  MeekRoundTripTimeout, and
   507  	// MeekRoundTripRetryDeadline.
   508  	//
   509  	// MeekCookieMaxPadding cannot exceed common.OBFUSCATE_SEED_LENGTH.
   510  	//
   511  	// MeekMinTLSPadding/MeekMaxTLSPadding are subject to TLS server limitations.
   512  	//
   513  	// MeekMinLimitRequestPayloadLength/MeekMaxLimitRequestPayloadLength
   514  	// cannot exceed server.MEEK_MAX_REQUEST_PAYLOAD_LENGTH.
   515  
   516  	MeekDialDomainsOnly:                        {value: false},
   517  	MeekLimitBufferSizes:                       {value: false},
   518  	MeekCookieMaxPadding:                       {value: 256, minimum: 0},
   519  	MeekFullReceiveBufferLength:                {value: 4194304, minimum: 1024},
   520  	MeekReadPayloadChunkLength:                 {value: 65536, minimum: 1024},
   521  	MeekLimitedFullReceiveBufferLength:         {value: 131072, minimum: 1024},
   522  	MeekLimitedReadPayloadChunkLength:          {value: 4096, minimum: 1024},
   523  	MeekMinPollInterval:                        {value: 100 * time.Millisecond, minimum: 1 * time.Millisecond},
   524  	MeekMinPollIntervalJitter:                  {value: 0.3, minimum: 0.0},
   525  	MeekMaxPollInterval:                        {value: 5 * time.Second, minimum: 1 * time.Millisecond},
   526  	MeekMaxPollIntervalJitter:                  {value: 0.1, minimum: 0.0},
   527  	MeekPollIntervalMultiplier:                 {value: 1.5, minimum: 0.0},
   528  	MeekPollIntervalJitter:                     {value: 0.1, minimum: 0.0},
   529  	MeekApplyPollIntervalMultiplierProbability: {value: 0.5},
   530  	MeekRoundTripRetryDeadline:                 {value: 5 * time.Second, minimum: 1 * time.Millisecond, flags: useNetworkLatencyMultiplier},
   531  	MeekRoundTripRetryMinDelay:                 {value: 50 * time.Millisecond, minimum: time.Duration(0)},
   532  	MeekRoundTripRetryMaxDelay:                 {value: 1 * time.Second, minimum: time.Duration(0)},
   533  	MeekRoundTripRetryMultiplier:               {value: 2.0, minimum: 0.0},
   534  	MeekRoundTripTimeout:                       {value: 20 * time.Second, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   535  	MeekTrafficShapingProbability:              {value: 1.0, minimum: 0.0},
   536  	MeekTrafficShapingLimitProtocols:           {value: protocol.TunnelProtocols{}},
   537  	MeekMinTLSPadding:                          {value: 0, minimum: 0},
   538  	MeekMaxTLSPadding:                          {value: 0, minimum: 0},
   539  	MeekMinLimitRequestPayloadLength:           {value: 65536, minimum: 1},
   540  	MeekMaxLimitRequestPayloadLength:           {value: 65536, minimum: 1},
   541  	MeekRedialTLSProbability:                   {value: 0.0, minimum: 0.0},
   542  	MeekAlternateCookieNameProbability:         {value: 0.5, minimum: 0.0},
   543  	MeekAlternateContentTypeProbability:        {value: 0.5, minimum: 0.0},
   544  
   545  	TransformHostNameProbability: {value: 0.5, minimum: 0.0},
   546  	PickUserAgentProbability:     {value: 0.5, minimum: 0.0},
   547  
   548  	LivenessTestMinUpstreamBytes:   {value: 0, minimum: 0},
   549  	LivenessTestMaxUpstreamBytes:   {value: 0, minimum: 0},
   550  	LivenessTestMinDownstreamBytes: {value: 0, minimum: 0},
   551  	LivenessTestMaxDownstreamBytes: {value: 0, minimum: 0},
   552  
   553  	ReplayCandidateCount:                   {value: 10, minimum: -1},
   554  	ReplayDialParametersTTL:                {value: 24 * time.Hour, minimum: time.Duration(0)},
   555  	ReplayTargetUpstreamBytes:              {value: 0, minimum: 0},
   556  	ReplayTargetDownstreamBytes:            {value: 0, minimum: 0},
   557  	ReplayTargetTunnelDuration:             {value: 1 * time.Second, minimum: time.Duration(0)},
   558  	ReplayLaterRoundMoveToFrontProbability: {value: 0.0, minimum: 0.0},
   559  	ReplayRetainFailedProbability:          {value: 0.5, minimum: 0.0},
   560  	ReplayBPF:                              {value: true},
   561  	ReplaySSH:                              {value: true},
   562  	ReplayObfuscatorPadding:                {value: true},
   563  	ReplayFragmentor:                       {value: true},
   564  	ReplayTLSProfile:                       {value: true},
   565  	ReplayRandomizedTLSProfile:             {value: true},
   566  	ReplayFronting:                         {value: true},
   567  	ReplayHostname:                         {value: true},
   568  	ReplayQUICVersion:                      {value: true},
   569  	ReplayObfuscatedQUIC:                   {value: true},
   570  	ReplayConjureRegistration:              {value: true},
   571  	ReplayConjureTransport:                 {value: true},
   572  	ReplayLivenessTest:                     {value: true},
   573  	ReplayUserAgent:                        {value: true},
   574  	ReplayAPIRequestPadding:                {value: true},
   575  	ReplayHoldOffTunnel:                    {value: true},
   576  	ReplayResolveParameters:                {value: true},
   577  
   578  	APIRequestUpstreamPaddingMinBytes:   {value: 0, minimum: 0},
   579  	APIRequestUpstreamPaddingMaxBytes:   {value: 1024, minimum: 0},
   580  	APIRequestDownstreamPaddingMinBytes: {value: 0, minimum: 0},
   581  	APIRequestDownstreamPaddingMaxBytes: {value: 1024, minimum: 0},
   582  
   583  	PersistentStatsMaxStoreRecords:                   {value: 200, minimum: 1},
   584  	PersistentStatsMaxSendBytes:                      {value: 65536, minimum: 1},
   585  	RecordRemoteServerListPersistentStatsProbability: {value: 1.0, minimum: 0.0},
   586  	RecordFailedTunnelPersistentStatsProbability:     {value: 0.0, minimum: 0.0},
   587  
   588  	ServerEntryMinimumAgeForPruning: {value: 7 * 24 * time.Hour, minimum: 24 * time.Hour},
   589  
   590  	ApplicationParametersProbability: {value: 1.0, minimum: 0.0},
   591  	ApplicationParameters:            {value: KeyValues{}},
   592  
   593  	BPFServerTCPProgram:     {value: (*BPFProgramSpec)(nil), flags: serverSideOnly},
   594  	BPFServerTCPProbability: {value: 0.5, minimum: 0.0, flags: serverSideOnly},
   595  	BPFClientTCPProgram:     {value: (*BPFProgramSpec)(nil)},
   596  	BPFClientTCPProbability: {value: 0.5, minimum: 0.0},
   597  
   598  	ServerPacketManipulationSpecs:       {value: PacketManipulationSpecs{}, flags: serverSideOnly},
   599  	ServerProtocolPacketManipulations:   {value: make(ProtocolPacketManipulations), flags: serverSideOnly},
   600  	ServerPacketManipulationProbability: {value: 0.5, minimum: 0.0, flags: serverSideOnly},
   601  
   602  	FeedbackUploadURLs:          {value: TransferURLs{}},
   603  	FeedbackEncryptionPublicKey: {value: ""},
   604  	FeedbackTacticsWaitPeriod:   {value: 5 * time.Second, minimum: 0 * time.Second, flags: useNetworkLatencyMultiplier},
   605  	FeedbackUploadMaxAttempts:   {value: 5, minimum: 0},
   606  	// TODO: rename -- remove "Seconds" suffix
   607  	FeedbackUploadRetryMinDelaySeconds: {value: 1 * time.Minute, minimum: time.Duration(0), flags: useNetworkLatencyMultiplier},
   608  	FeedbackUploadRetryMaxDelaySeconds: {value: 5 * time.Minute, minimum: 1 * time.Second, flags: useNetworkLatencyMultiplier},
   609  	FeedbackUploadTimeoutSeconds:       {value: 30 * time.Second, minimum: 0 * time.Second, flags: useNetworkLatencyMultiplier},
   610  
   611  	ServerReplayPacketManipulation:    {value: true, flags: serverSideOnly},
   612  	ServerReplayFragmentor:            {value: true, flags: serverSideOnly},
   613  	ServerReplayUnknownGeoIP:          {value: false, flags: serverSideOnly},
   614  	ServerReplayTTL:                   {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
   615  	ServerReplayTargetWaitDuration:    {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
   616  	ServerReplayTargetTunnelDuration:  {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
   617  	ServerReplayTargetUpstreamBytes:   {value: 0, minimum: 0, flags: serverSideOnly},
   618  	ServerReplayTargetDownstreamBytes: {value: 0, minimum: 0, flags: serverSideOnly},
   619  	ServerReplayFailedCountThreshold:  {value: 0, minimum: 0, flags: serverSideOnly},
   620  
   621  	ServerBurstUpstreamTargetBytes:   {value: 0, minimum: 0, flags: serverSideOnly},
   622  	ServerBurstUpstreamDeadline:      {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
   623  	ServerBurstDownstreamTargetBytes: {value: 0, minimum: 0, flags: serverSideOnly},
   624  	ServerBurstDownstreamDeadline:    {value: time.Duration(0), minimum: time.Duration(0), flags: serverSideOnly},
   625  	ClientBurstUpstreamTargetBytes:   {value: 0, minimum: 0},
   626  	ClientBurstUpstreamDeadline:      {value: time.Duration(0), minimum: time.Duration(0)},
   627  	ClientBurstDownstreamTargetBytes: {value: 0, minimum: 0},
   628  	ClientBurstDownstreamDeadline:    {value: time.Duration(0), minimum: time.Duration(0)},
   629  
   630  	ConjureCachedRegistrationTTL: {value: time.Duration(0), minimum: time.Duration(0)},
   631  	// ConjureAPIRegistrarURL parameter is obsoleted by ConjureAPIRegistrarBidirectionalURL.
   632  	// TODO: remove once no longer required for older clients.
   633  	ConjureAPIRegistrarURL:              {value: ""},
   634  	ConjureAPIRegistrarBidirectionalURL: {value: ""},
   635  	ConjureAPIRegistrarFrontingSpecs:    {value: FrontingSpecs{}},
   636  	ConjureAPIRegistrarMinDelay:         {value: time.Duration(0), minimum: time.Duration(0)},
   637  	ConjureAPIRegistrarMaxDelay:         {value: time.Duration(0), minimum: time.Duration(0)},
   638  	ConjureDecoyRegistrarProbability:    {value: 0.0, minimum: 0.0},
   639  	ConjureDecoyRegistrarWidth:          {value: 5, minimum: 0},
   640  	ConjureDecoyRegistrarMinDelay:       {value: time.Duration(0), minimum: time.Duration(0)},
   641  	ConjureDecoyRegistrarMaxDelay:       {value: time.Duration(0), minimum: time.Duration(0)},
   642  
   643  	ConjureTransportObfs4Probability: {value: 0.0, minimum: 0.0},
   644  
   645  	CustomHostNameRegexes:        {value: RegexStrings{}},
   646  	CustomHostNameProbability:    {value: 0.0, minimum: 0.0},
   647  	CustomHostNameLimitProtocols: {value: protocol.TunnelProtocols{}},
   648  
   649  	HoldOffTunnelMinDuration:         {value: time.Duration(0), minimum: time.Duration(0)},
   650  	HoldOffTunnelMaxDuration:         {value: time.Duration(0), minimum: time.Duration(0)},
   651  	HoldOffTunnelProtocols:           {value: protocol.TunnelProtocols{}},
   652  	HoldOffTunnelFrontingProviderIDs: {value: []string{}},
   653  	HoldOffTunnelProbability:         {value: 0.0, minimum: 0.0},
   654  
   655  	RestrictFrontingProviderIDs:                  {value: []string{}},
   656  	RestrictFrontingProviderIDsServerProbability: {value: 0.0, minimum: 0.0, flags: serverSideOnly},
   657  	RestrictFrontingProviderIDsClientProbability: {value: 0.0, minimum: 0.0},
   658  
   659  	UpstreamProxyAllowAllServerEntrySources: {value: false},
   660  
   661  	DestinationBytesMetricsASN: {value: "", flags: serverSideOnly},
   662  
   663  	DNSResolverAttemptsPerServer:                {value: 2, minimum: 1},
   664  	DNSResolverAttemptsPerPreferredServer:       {value: 1, minimum: 1},
   665  	DNSResolverRequestTimeout:                   {value: 5 * time.Second, minimum: 100 * time.Millisecond, flags: useNetworkLatencyMultiplier},
   666  	DNSResolverAwaitTimeout:                     {value: 10 * time.Millisecond, minimum: 1 * time.Millisecond, flags: useNetworkLatencyMultiplier},
   667  	DNSResolverPreresolvedIPAddressCIDRs:        {value: LabeledCIDRs{}},
   668  	DNSResolverPreresolvedIPAddressProbability:  {value: 0.0, minimum: 0.0},
   669  	DNSResolverAlternateServers:                 {value: []string{}},
   670  	DNSResolverPreferredAlternateServers:        {value: []string{}},
   671  	DNSResolverPreferAlternateServerProbability: {value: 0.0, minimum: 0.0},
   672  	DNSResolverProtocolTransformSpecs:           {value: transforms.Specs{}},
   673  	DNSResolverProtocolTransformScopedSpecNames: {value: transforms.ScopedSpecNames{}},
   674  	DNSResolverProtocolTransformProbability:     {value: 0.0, minimum: 0.0},
   675  	DNSResolverIncludeEDNS0Probability:          {value: 0.0, minimum: 0.0},
   676  	DNSResolverCacheExtensionInitialTTL:         {value: time.Duration(0), minimum: time.Duration(0)},
   677  	DNSResolverCacheExtensionVerifiedTTL:        {value: time.Duration(0), minimum: time.Duration(0)},
   678  }
   679  
   680  // IsServerSideOnly indicates if the parameter specified by name is used
   681  // server-side only.
   682  func IsServerSideOnly(name string) bool {
   683  	defaultParameter, ok := defaultParameters[name]
   684  	return ok && (defaultParameter.flags&serverSideOnly) != 0
   685  }
   686  
   687  // Parameters is a set of parameters. To use the parameters, call Get. To
   688  // apply new values to the parameters, call Set.
   689  type Parameters struct {
   690  	getValueLogger func(error)
   691  	snapshot       atomic.Value
   692  }
   693  
   694  // NewParameters initializes a new Parameters with the default parameter
   695  // values.
   696  //
   697  // getValueLogger is optional, and is used to report runtime errors with
   698  // getValue; see comment in getValue.
   699  func NewParameters(
   700  	getValueLogger func(error)) (*Parameters, error) {
   701  
   702  	parameters := &Parameters{
   703  		getValueLogger: getValueLogger,
   704  	}
   705  
   706  	_, err := parameters.Set("", false)
   707  	if err != nil {
   708  		return nil, errors.Trace(err)
   709  	}
   710  
   711  	return parameters, nil
   712  }
   713  
   714  func makeDefaultParameters() (map[string]interface{}, error) {
   715  
   716  	parameters := make(map[string]interface{})
   717  
   718  	for name, defaults := range defaultParameters {
   719  
   720  		if defaults.value == nil {
   721  			return nil, errors.Tracef("default parameter missing value: %s", name)
   722  		}
   723  
   724  		if defaults.minimum != nil &&
   725  			reflect.TypeOf(defaults.value) != reflect.TypeOf(defaults.minimum) {
   726  
   727  			return nil, errors.Tracef("default parameter value and minimum type mismatch: %s", name)
   728  		}
   729  
   730  		_, isDuration := defaults.value.(time.Duration)
   731  		if defaults.flags&useNetworkLatencyMultiplier != 0 && !isDuration {
   732  			return nil, errors.Tracef("default non-duration parameter uses multipler: %s", name)
   733  		}
   734  
   735  		parameters[name] = defaults.value
   736  	}
   737  
   738  	return parameters, nil
   739  }
   740  
   741  // Set replaces the current parameters. First, a set of parameters are
   742  // initialized using the default values. Then, each applyParameters is applied
   743  // in turn, with the later instances having precedence.
   744  //
   745  // When skipOnError is true, unknown or invalid parameters in any
   746  // applyParameters are skipped instead of aborting with an error.
   747  //
   748  // For protocol.TunnelProtocols and protocol.TLSProfiles type values, when
   749  // skipOnError is true the values are filtered instead of validated, so
   750  // only known tunnel protocols and TLS profiles are retained.
   751  //
   752  // When an error is returned, the previous parameters remain completely
   753  // unmodified.
   754  //
   755  // For use in logging, Set returns a count of the number of parameters applied
   756  // from each applyParameters.
   757  func (p *Parameters) Set(
   758  	tag string, skipOnError bool, applyParameters ...map[string]interface{}) ([]int, error) {
   759  
   760  	makeTypedValue := func(templateValue, value interface{}) (interface{}, error) {
   761  
   762  		// Accept strings such as "1h" for duration parameters.
   763  
   764  		switch templateValue.(type) {
   765  		case time.Duration:
   766  			if s, ok := value.(string); ok {
   767  				if d, err := time.ParseDuration(s); err == nil {
   768  					value = d
   769  				}
   770  			}
   771  		}
   772  
   773  		// A JSON remarshal resolves cases where applyParameters is a
   774  		// result of unmarshal-into-interface, in which case non-scalar
   775  		// values will not have the expected types; see:
   776  		// https://golang.org/pkg/encoding/json/#Unmarshal. This remarshal
   777  		// also results in a deep copy.
   778  
   779  		marshaledValue, err := json.Marshal(value)
   780  		if err != nil {
   781  			return nil, errors.Trace(err)
   782  		}
   783  
   784  		newValuePtr := reflect.New(reflect.TypeOf(templateValue))
   785  
   786  		err = json.Unmarshal(marshaledValue, newValuePtr.Interface())
   787  		if err != nil {
   788  			return nil, errors.Trace(err)
   789  		}
   790  
   791  		return newValuePtr.Elem().Interface(), nil
   792  	}
   793  
   794  	getAppliedValue := func(
   795  		name string,
   796  		parameters map[string]interface{},
   797  		applyParameters []map[string]interface{}) (interface{}, error) {
   798  
   799  		templateValue := parameters[name]
   800  		if templateValue == nil {
   801  			return nil, errors.Tracef("unknown parameter: %s", name)
   802  		}
   803  
   804  		value := templateValue
   805  		for i := len(applyParameters) - 1; i >= 0; i-- {
   806  			if v := applyParameters[i][name]; v != nil {
   807  				value = v
   808  				break
   809  			}
   810  		}
   811  
   812  		return makeTypedValue(templateValue, value)
   813  	}
   814  
   815  	var counts []int
   816  
   817  	parameters, err := makeDefaultParameters()
   818  	if err != nil {
   819  		return nil, errors.Trace(err)
   820  	}
   821  
   822  	// Special case: TLSProfiles/LabeledTLSProfiles may reference
   823  	// CustomTLSProfiles names. Inspect the CustomTLSProfiles parameter and
   824  	// extract its names. Do not call Get().CustomTLSProfilesNames() as
   825  	// CustomTLSProfiles may not yet be validated.
   826  
   827  	customTLSProfilesValue, err := getAppliedValue(
   828  		CustomTLSProfiles, parameters, applyParameters)
   829  	if err != nil {
   830  		return nil, errors.Trace(err)
   831  	}
   832  	customTLSProfiles, _ := customTLSProfilesValue.(protocol.CustomTLSProfiles)
   833  	customTLSProfileNames := make([]string, len(customTLSProfiles))
   834  	for i, profile := range customTLSProfiles {
   835  		customTLSProfileNames[i] = profile.Name
   836  	}
   837  
   838  	// Special case: PacketManipulations will reference PacketManipulationSpecs.
   839  
   840  	serverPacketManipulationSpecsValue, err := getAppliedValue(
   841  		ServerPacketManipulationSpecs, parameters, applyParameters)
   842  	if err != nil {
   843  		return nil, errors.Trace(err)
   844  	}
   845  	serverPacketManipulationSpecs, _ :=
   846  		serverPacketManipulationSpecsValue.(PacketManipulationSpecs)
   847  
   848  	// Special case: ProtocolTransformScopedSpecNames will reference
   849  	// ProtocolTransformSpecs.
   850  
   851  	dnsResolverProtocolTransformSpecsValue, err := getAppliedValue(
   852  		DNSResolverProtocolTransformSpecs, parameters, applyParameters)
   853  	if err != nil {
   854  		return nil, errors.Trace(err)
   855  	}
   856  	dnsResolverProtocolTransformSpecs, _ :=
   857  		dnsResolverProtocolTransformSpecsValue.(transforms.Specs)
   858  
   859  	for i := 0; i < len(applyParameters); i++ {
   860  
   861  		count := 0
   862  
   863  		for name, value := range applyParameters[i] {
   864  
   865  			templateValue, ok := parameters[name]
   866  			if !ok {
   867  				if skipOnError {
   868  					continue
   869  				}
   870  				return nil, errors.Tracef("unknown parameter: %s", name)
   871  			}
   872  
   873  			newValue, err := makeTypedValue(templateValue, value)
   874  			if err != nil {
   875  				if skipOnError {
   876  					continue
   877  				}
   878  				return nil, errors.Tracef(
   879  					"unmarshal parameter %s failed: %v", name, err)
   880  			}
   881  
   882  			// Perform type-specific validation for some cases.
   883  
   884  			// TODO: require RemoteServerListSignaturePublicKey when
   885  			// RemoteServerListURLs is set?
   886  
   887  			switch v := newValue.(type) {
   888  			case TransferURLs:
   889  				err := v.DecodeAndValidate()
   890  				if err != nil {
   891  					if skipOnError {
   892  						continue
   893  					}
   894  					return nil, errors.Trace(err)
   895  				}
   896  			case protocol.TunnelProtocols:
   897  				if skipOnError {
   898  					newValue = v.PruneInvalid()
   899  				} else {
   900  					err := v.Validate()
   901  					if err != nil {
   902  						return nil, errors.Trace(err)
   903  					}
   904  				}
   905  			case protocol.TLSProfiles:
   906  				if skipOnError {
   907  					newValue = v.PruneInvalid(customTLSProfileNames)
   908  				} else {
   909  					err := v.Validate(customTLSProfileNames)
   910  					if err != nil {
   911  						return nil, errors.Trace(err)
   912  					}
   913  				}
   914  			case protocol.LabeledTLSProfiles:
   915  				if skipOnError {
   916  					newValue = v.PruneInvalid(customTLSProfileNames)
   917  				} else {
   918  					err := v.Validate(customTLSProfileNames)
   919  					if err != nil {
   920  						return nil, errors.Trace(err)
   921  					}
   922  				}
   923  			case protocol.QUICVersions:
   924  				if skipOnError {
   925  					newValue = v.PruneInvalid()
   926  				} else {
   927  					err := v.Validate()
   928  					if err != nil {
   929  						return nil, errors.Trace(err)
   930  					}
   931  				}
   932  			case protocol.LabeledQUICVersions:
   933  				if skipOnError {
   934  					newValue = v.PruneInvalid()
   935  				} else {
   936  					err := v.Validate()
   937  					if err != nil {
   938  						return nil, errors.Trace(err)
   939  					}
   940  				}
   941  			case protocol.CustomTLSProfiles:
   942  				err := v.Validate()
   943  				if err != nil {
   944  					if skipOnError {
   945  						continue
   946  					}
   947  					return nil, errors.Trace(err)
   948  				}
   949  			case KeyValues:
   950  				err := v.Validate()
   951  				if err != nil {
   952  					if skipOnError {
   953  						continue
   954  					}
   955  					return nil, errors.Trace(err)
   956  				}
   957  			case *BPFProgramSpec:
   958  				if v != nil {
   959  					err := v.Validate()
   960  					if err != nil {
   961  						if skipOnError {
   962  							continue
   963  						}
   964  						return nil, errors.Trace(err)
   965  					}
   966  				}
   967  			case PacketManipulationSpecs:
   968  				err := v.Validate()
   969  				if err != nil {
   970  					if skipOnError {
   971  						continue
   972  					}
   973  					return nil, errors.Trace(err)
   974  				}
   975  			case ProtocolPacketManipulations:
   976  
   977  				var packetManipulationSpecs PacketManipulationSpecs
   978  				if name == ServerProtocolPacketManipulations {
   979  					packetManipulationSpecs = serverPacketManipulationSpecs
   980  				}
   981  
   982  				err := v.Validate(packetManipulationSpecs)
   983  				if err != nil {
   984  					if skipOnError {
   985  						continue
   986  					}
   987  					return nil, errors.Trace(err)
   988  				}
   989  			case RegexStrings:
   990  				err := v.Validate()
   991  				if err != nil {
   992  					if skipOnError {
   993  						continue
   994  					}
   995  					return nil, errors.Trace(err)
   996  				}
   997  			case FrontingSpecs:
   998  				err := v.Validate()
   999  				if err != nil {
  1000  					if skipOnError {
  1001  						continue
  1002  					}
  1003  					return nil, errors.Trace(err)
  1004  				}
  1005  			case TunnelProtocolPortLists:
  1006  				err := v.Validate()
  1007  				if err != nil {
  1008  					if skipOnError {
  1009  						continue
  1010  					}
  1011  					return nil, errors.Trace(err)
  1012  				}
  1013  			case LabeledCIDRs:
  1014  				err := v.Validate()
  1015  				if err != nil {
  1016  					if skipOnError {
  1017  						continue
  1018  					}
  1019  					return nil, errors.Trace(err)
  1020  				}
  1021  			case transforms.Specs:
  1022  				err := v.Validate()
  1023  				if err != nil {
  1024  					if skipOnError {
  1025  						continue
  1026  					}
  1027  					return nil, errors.Trace(err)
  1028  				}
  1029  			case transforms.ScopedSpecNames:
  1030  
  1031  				var specs transforms.Specs
  1032  				if name == DNSResolverProtocolTransformScopedSpecNames {
  1033  					specs = dnsResolverProtocolTransformSpecs
  1034  				}
  1035  
  1036  				err := v.Validate(specs)
  1037  				if err != nil {
  1038  					if skipOnError {
  1039  						continue
  1040  					}
  1041  					return nil, errors.Trace(err)
  1042  				}
  1043  			}
  1044  
  1045  			// Enforce any minimums. Assumes defaultParameters[name]
  1046  			// exists.
  1047  			if defaultParameters[name].minimum != nil {
  1048  				valid := true
  1049  				switch v := newValue.(type) {
  1050  				case int:
  1051  					m, ok := defaultParameters[name].minimum.(int)
  1052  					if !ok || v < m {
  1053  						valid = false
  1054  					}
  1055  				case float64:
  1056  					m, ok := defaultParameters[name].minimum.(float64)
  1057  					if !ok || v < m {
  1058  						valid = false
  1059  					}
  1060  				case time.Duration:
  1061  					m, ok := defaultParameters[name].minimum.(time.Duration)
  1062  					if !ok || v < m {
  1063  						valid = false
  1064  					}
  1065  				default:
  1066  					if skipOnError {
  1067  						continue
  1068  					}
  1069  					return nil, errors.Tracef("unexpected parameter with minimum: %s", name)
  1070  				}
  1071  				if !valid {
  1072  					if skipOnError {
  1073  						continue
  1074  					}
  1075  					return nil, errors.Tracef("parameter below minimum: %s", name)
  1076  				}
  1077  			}
  1078  
  1079  			parameters[name] = newValue
  1080  
  1081  			count++
  1082  		}
  1083  
  1084  		counts = append(counts, count)
  1085  	}
  1086  
  1087  	snapshot := &parametersSnapshot{
  1088  		getValueLogger: p.getValueLogger,
  1089  		tag:            tag,
  1090  		parameters:     parameters,
  1091  	}
  1092  
  1093  	p.snapshot.Store(snapshot)
  1094  
  1095  	return counts, nil
  1096  }
  1097  
  1098  // Get returns the current parameters.
  1099  //
  1100  // Values read from the current parameters are not deep copies and must be
  1101  // treated read-only.
  1102  //
  1103  // The returned ParametersAccessor may be used to read multiple related values
  1104  // atomically and consistently while the current set of values in Parameters
  1105  // may change concurrently.
  1106  //
  1107  // Get does not perform any heap allocations and is intended for repeated,
  1108  // direct, low-overhead invocations.
  1109  func (p *Parameters) Get() ParametersAccessor {
  1110  	return ParametersAccessor{
  1111  		snapshot: p.snapshot.Load().(*parametersSnapshot)}
  1112  }
  1113  
  1114  // GetCustom returns the current parameters while also setting customizations
  1115  // for this instance.
  1116  //
  1117  // The properties of Get also apply to GetCustom: must be read-only; atomic
  1118  // and consisent view; no heap allocations.
  1119  //
  1120  // Customizations include:
  1121  //
  1122  //   - customNetworkLatencyMultiplier, which overrides NetworkLatencyMultiplier
  1123  //     for this instance only.
  1124  func (p *Parameters) GetCustom(
  1125  	customNetworkLatencyMultiplier float64) ParametersAccessor {
  1126  
  1127  	return ParametersAccessor{
  1128  		snapshot:                       p.snapshot.Load().(*parametersSnapshot),
  1129  		customNetworkLatencyMultiplier: customNetworkLatencyMultiplier,
  1130  	}
  1131  }
  1132  
  1133  // parametersSnapshot is an atomic snapshot of the parameter values.
  1134  // Parameters.Get will return a snapshot which may be used to read multiple
  1135  // related values atomically and consistently while the current snapshot in
  1136  // Parameters may change concurrently.
  1137  type parametersSnapshot struct {
  1138  	getValueLogger func(error)
  1139  	tag            string
  1140  	parameters     map[string]interface{}
  1141  }
  1142  
  1143  // getValue sets target to the value of the named parameter.
  1144  //
  1145  // It is an error if the name is not found, target is not a pointer, or the
  1146  // type of target points to does not match the value.
  1147  //
  1148  // Any of these conditions would be a bug in the caller. getValue does not
  1149  // panic in these cases as clients are deployed as a library in various apps
  1150  // and the failure of Psiphon may not be a failure for the app process.
  1151  //
  1152  // Instead, errors are logged to the getValueLogger and getValue leaves the
  1153  // target unset, which will result in the caller getting and using a zero
  1154  // value of the requested type.
  1155  func (p *parametersSnapshot) getValue(name string, target interface{}) {
  1156  
  1157  	value, ok := p.parameters[name]
  1158  	if !ok {
  1159  		if p.getValueLogger != nil {
  1160  			p.getValueLogger(errors.Tracef(
  1161  				"value %s not found", name))
  1162  		}
  1163  		return
  1164  	}
  1165  
  1166  	valueType := reflect.TypeOf(value)
  1167  
  1168  	if reflect.PtrTo(valueType) != reflect.TypeOf(target) {
  1169  		if p.getValueLogger != nil {
  1170  			p.getValueLogger(errors.Tracef(
  1171  				"value %s has unexpected type %s", name, valueType.Name()))
  1172  		}
  1173  		return
  1174  	}
  1175  
  1176  	// Note: there is no deep copy of parameter values; the returned value may
  1177  	// share memory with the original and should not be modified.
  1178  
  1179  	targetValue := reflect.ValueOf(target)
  1180  
  1181  	if targetValue.Kind() != reflect.Ptr {
  1182  		p.getValueLogger(errors.Tracef(
  1183  			"target for value %s is not pointer", name))
  1184  		return
  1185  	}
  1186  
  1187  	targetValue.Elem().Set(reflect.ValueOf(value))
  1188  }
  1189  
  1190  // ParametersAccessor provides consistent, atomic access to  parameter values.
  1191  // Any customizations are applied transparently.
  1192  type ParametersAccessor struct {
  1193  	snapshot                       *parametersSnapshot
  1194  	customNetworkLatencyMultiplier float64
  1195  }
  1196  
  1197  // MakeNilParametersAccessor produces a stub ParametersAccessor which returns
  1198  // true for IsNil. This may be used where a ParametersAccessor value is
  1199  // required, but Parameters.Get may not succeed. In contexts where
  1200  // MakeNilParametersAccessor may be used, calls to ParametersAccessor must
  1201  // first check IsNil before calling accessor functions.
  1202  func MakeNilParametersAccessor() ParametersAccessor {
  1203  	return ParametersAccessor{}
  1204  }
  1205  
  1206  // IsNil indicates that this ParametersAccessor is a stub and its accessor
  1207  // functions may not be called. A ParametersAccessor produced by
  1208  // Parameters.Get will never return true for IsNil and IsNil guards are not
  1209  // required for ParametersAccessors known to be produced by Parameters.Get.
  1210  func (p ParametersAccessor) IsNil() bool {
  1211  	return p.snapshot == nil
  1212  }
  1213  
  1214  // Close clears internal references to large memory objects, allowing them to
  1215  // be garbage collected. Call Close when done using a ParametersAccessor,
  1216  // where memory footprint is a concern, and where the ParametersAccessor is
  1217  // not immediately going out of scope. After Close is called, all other
  1218  // ParametersAccessor functions will panic if called.
  1219  func (p ParametersAccessor) Close() {
  1220  	p.snapshot = nil
  1221  }
  1222  
  1223  // Tag returns the tag associated with these parameters.
  1224  func (p ParametersAccessor) Tag() string {
  1225  	return p.snapshot.tag
  1226  }
  1227  
  1228  // String returns a string parameter value.
  1229  func (p ParametersAccessor) String(name string) string {
  1230  	value := ""
  1231  	p.snapshot.getValue(name, &value)
  1232  	return value
  1233  }
  1234  
  1235  func (p ParametersAccessor) Strings(name string) []string {
  1236  	value := []string{}
  1237  	p.snapshot.getValue(name, &value)
  1238  	return value
  1239  }
  1240  
  1241  // Int returns an int parameter value.
  1242  func (p ParametersAccessor) Int(name string) int {
  1243  	value := int(0)
  1244  	p.snapshot.getValue(name, &value)
  1245  	return value
  1246  }
  1247  
  1248  // Bool returns a bool parameter value.
  1249  func (p ParametersAccessor) Bool(name string) bool {
  1250  	value := false
  1251  	p.snapshot.getValue(name, &value)
  1252  	return value
  1253  }
  1254  
  1255  // Float returns a float64 parameter value.
  1256  func (p ParametersAccessor) Float(name string) float64 {
  1257  	value := float64(0.0)
  1258  	p.snapshot.getValue(name, &value)
  1259  	return value
  1260  }
  1261  
  1262  // WeightedCoinFlip returns the result of prng.FlipWeightedCoin using the
  1263  // specified float parameter as the probability input.
  1264  func (p ParametersAccessor) WeightedCoinFlip(name string) bool {
  1265  	var value float64
  1266  	p.snapshot.getValue(name, &value)
  1267  	return prng.FlipWeightedCoin(value)
  1268  }
  1269  
  1270  // Duration returns a time.Duration parameter value. When the duration
  1271  // parameter has the useNetworkLatencyMultiplier flag, the
  1272  // NetworkLatencyMultiplier is applied to the returned value.
  1273  func (p ParametersAccessor) Duration(name string) time.Duration {
  1274  	value := time.Duration(0)
  1275  	p.snapshot.getValue(name, &value)
  1276  
  1277  	defaultParameter, ok := defaultParameters[name]
  1278  	if value > 0 && ok && defaultParameter.flags&useNetworkLatencyMultiplier != 0 {
  1279  
  1280  		multiplier := float64(0.0)
  1281  
  1282  		if p.customNetworkLatencyMultiplier != 0.0 {
  1283  			multiplier = p.customNetworkLatencyMultiplier
  1284  		} else {
  1285  			p.snapshot.getValue(NetworkLatencyMultiplier, &multiplier)
  1286  		}
  1287  
  1288  		if multiplier > 0.0 {
  1289  			value = time.Duration(float64(value) * multiplier)
  1290  		}
  1291  
  1292  	}
  1293  
  1294  	return value
  1295  }
  1296  
  1297  // TunnelProtocols returns a protocol.TunnelProtocols parameter value.
  1298  // If there is a corresponding Probability value, a weighted coin flip
  1299  // will be performed and, depending on the result, the value or the
  1300  // parameter default will be returned.
  1301  func (p ParametersAccessor) TunnelProtocols(name string) protocol.TunnelProtocols {
  1302  
  1303  	probabilityName := name + "Probability"
  1304  	_, ok := p.snapshot.parameters[probabilityName]
  1305  	if ok {
  1306  		probabilityValue := float64(1.0)
  1307  		p.snapshot.getValue(probabilityName, &probabilityValue)
  1308  		if !prng.FlipWeightedCoin(probabilityValue) {
  1309  			defaultParameter, ok := defaultParameters[name]
  1310  			if ok {
  1311  				defaultValue, ok := defaultParameter.value.(protocol.TunnelProtocols)
  1312  				if ok {
  1313  					value := make(protocol.TunnelProtocols, len(defaultValue))
  1314  					copy(value, defaultValue)
  1315  					return value
  1316  				}
  1317  			}
  1318  		}
  1319  	}
  1320  
  1321  	value := protocol.TunnelProtocols{}
  1322  	p.snapshot.getValue(name, &value)
  1323  	return value
  1324  }
  1325  
  1326  // TLSProfiles returns a protocol.TLSProfiles parameter value.
  1327  // If there is a corresponding Probability value, a weighted coin flip
  1328  // will be performed and, depending on the result, the value or the
  1329  // parameter default will be returned.
  1330  func (p ParametersAccessor) TLSProfiles(name string) protocol.TLSProfiles {
  1331  
  1332  	probabilityName := name + "Probability"
  1333  	_, ok := p.snapshot.parameters[probabilityName]
  1334  	if ok {
  1335  		probabilityValue := float64(1.0)
  1336  		p.snapshot.getValue(probabilityName, &probabilityValue)
  1337  		if !prng.FlipWeightedCoin(probabilityValue) {
  1338  			defaultParameter, ok := defaultParameters[name]
  1339  			if ok {
  1340  				defaultValue, ok := defaultParameter.value.(protocol.TLSProfiles)
  1341  				if ok {
  1342  					value := make(protocol.TLSProfiles, len(defaultValue))
  1343  					copy(value, defaultValue)
  1344  					return value
  1345  				}
  1346  			}
  1347  		}
  1348  	}
  1349  
  1350  	value := protocol.TLSProfiles{}
  1351  	p.snapshot.getValue(name, &value)
  1352  	return value
  1353  }
  1354  
  1355  // LabeledTLSProfiles returns a protocol.TLSProfiles parameter value
  1356  // corresponding to the specified labeled set and label value. The return
  1357  // value is nil when no set is found.
  1358  func (p ParametersAccessor) LabeledTLSProfiles(name, label string) protocol.TLSProfiles {
  1359  	var value protocol.LabeledTLSProfiles
  1360  	p.snapshot.getValue(name, &value)
  1361  	return value[label]
  1362  }
  1363  
  1364  // QUICVersions returns a protocol.QUICVersions parameter value.
  1365  // If there is a corresponding Probability value, a weighted coin flip
  1366  // will be performed and, depending on the result, the value or the
  1367  // parameter default will be returned.
  1368  func (p ParametersAccessor) QUICVersions(name string) protocol.QUICVersions {
  1369  
  1370  	probabilityName := name + "Probability"
  1371  	_, ok := p.snapshot.parameters[probabilityName]
  1372  	if ok {
  1373  		probabilityValue := float64(1.0)
  1374  		p.snapshot.getValue(probabilityName, &probabilityValue)
  1375  		if !prng.FlipWeightedCoin(probabilityValue) {
  1376  			defaultParameter, ok := defaultParameters[name]
  1377  			if ok {
  1378  				defaultValue, ok := defaultParameter.value.(protocol.QUICVersions)
  1379  				if ok {
  1380  					value := make(protocol.QUICVersions, len(defaultValue))
  1381  					copy(value, defaultValue)
  1382  					return value
  1383  				}
  1384  			}
  1385  		}
  1386  	}
  1387  
  1388  	value := protocol.QUICVersions{}
  1389  	p.snapshot.getValue(name, &value)
  1390  	return value
  1391  }
  1392  
  1393  // LabeledQUICVersions returns a protocol.QUICVersions parameter value
  1394  // corresponding to the specified labeled set and label value. The return
  1395  // value is nil when no set is found.
  1396  func (p ParametersAccessor) LabeledQUICVersions(name, label string) protocol.QUICVersions {
  1397  	value := protocol.LabeledQUICVersions{}
  1398  	p.snapshot.getValue(name, &value)
  1399  	return value[label]
  1400  }
  1401  
  1402  // TransferURLs returns a TransferURLs parameter value.
  1403  func (p ParametersAccessor) TransferURLs(name string) TransferURLs {
  1404  	value := TransferURLs{}
  1405  	p.snapshot.getValue(name, &value)
  1406  	return value
  1407  }
  1408  
  1409  // RateLimits returns a common.RateLimits parameter value.
  1410  func (p ParametersAccessor) RateLimits(name string) common.RateLimits {
  1411  	value := common.RateLimits{}
  1412  	p.snapshot.getValue(name, &value)
  1413  	return value
  1414  }
  1415  
  1416  // HTTPHeaders returns an http.Header parameter value.
  1417  func (p ParametersAccessor) HTTPHeaders(name string) http.Header {
  1418  	value := make(http.Header)
  1419  	p.snapshot.getValue(name, &value)
  1420  	return value
  1421  }
  1422  
  1423  // CustomTLSProfileNames returns the CustomTLSProfile.Name fields for
  1424  // each profile in the CustomTLSProfiles parameter value.
  1425  func (p ParametersAccessor) CustomTLSProfileNames() []string {
  1426  	value := protocol.CustomTLSProfiles{}
  1427  	p.snapshot.getValue(CustomTLSProfiles, &value)
  1428  	names := make([]string, len(value))
  1429  	for i := 0; i < len(value); i++ {
  1430  		names[i] = value[i].Name
  1431  	}
  1432  	return names
  1433  }
  1434  
  1435  // CustomTLSProfile returns the CustomTLSProfile fields with the specified
  1436  // Name field if it exists in the CustomTLSProfiles parameter value.
  1437  // Returns nil if not found.
  1438  func (p ParametersAccessor) CustomTLSProfile(name string) *protocol.CustomTLSProfile {
  1439  	value := protocol.CustomTLSProfiles{}
  1440  	p.snapshot.getValue(CustomTLSProfiles, &value)
  1441  
  1442  	// Note: linear lookup -- assumes a short list
  1443  
  1444  	for i := 0; i < len(value); i++ {
  1445  		if value[i].Name == name {
  1446  			return value[i]
  1447  		}
  1448  	}
  1449  	return nil
  1450  }
  1451  
  1452  // KeyValues returns a KeyValues parameter value.
  1453  func (p ParametersAccessor) KeyValues(name string) KeyValues {
  1454  	value := KeyValues{}
  1455  	p.snapshot.getValue(name, &value)
  1456  	return value
  1457  }
  1458  
  1459  // BPFProgram returns an assembled BPF program corresponding to a
  1460  // BPFProgramSpec parameter value. Returns nil in the case of any empty
  1461  // program.
  1462  func (p ParametersAccessor) BPFProgram(name string) (bool, string, []bpf.RawInstruction) {
  1463  	var value *BPFProgramSpec
  1464  	p.snapshot.getValue(name, &value)
  1465  	if value == nil {
  1466  		return false, "", nil
  1467  	}
  1468  	// Validation checks that Assemble is successful.
  1469  	rawInstructions, _ := value.Assemble()
  1470  	return true, value.Name, rawInstructions
  1471  }
  1472  
  1473  // PacketManipulationSpecs returns a PacketManipulationSpecs parameter value.
  1474  func (p ParametersAccessor) PacketManipulationSpecs(name string) PacketManipulationSpecs {
  1475  	value := PacketManipulationSpecs{}
  1476  	p.snapshot.getValue(name, &value)
  1477  	return value
  1478  }
  1479  
  1480  // ProtocolPacketManipulations returns a ProtocolPacketManipulations parameter value.
  1481  func (p ParametersAccessor) ProtocolPacketManipulations(name string) ProtocolPacketManipulations {
  1482  	value := make(ProtocolPacketManipulations)
  1483  	p.snapshot.getValue(name, &value)
  1484  	return value
  1485  }
  1486  
  1487  // RegexStrings returns a RegexStrings parameter value.
  1488  func (p ParametersAccessor) RegexStrings(name string) RegexStrings {
  1489  	value := RegexStrings{}
  1490  	p.snapshot.getValue(name, &value)
  1491  	return value
  1492  }
  1493  
  1494  // FrontingSpecs returns a FrontingSpecs parameter value.
  1495  func (p ParametersAccessor) FrontingSpecs(name string) FrontingSpecs {
  1496  	value := FrontingSpecs{}
  1497  	p.snapshot.getValue(name, &value)
  1498  	return value
  1499  }
  1500  
  1501  // TunnelProtocolPortLists returns a TunnelProtocolPortLists parameter value.
  1502  func (p ParametersAccessor) TunnelProtocolPortLists(name string) TunnelProtocolPortLists {
  1503  
  1504  	probabilityName := name + "Probability"
  1505  	_, ok := p.snapshot.parameters[probabilityName]
  1506  	if ok {
  1507  		probabilityValue := float64(1.0)
  1508  		p.snapshot.getValue(probabilityName, &probabilityValue)
  1509  		if !prng.FlipWeightedCoin(probabilityValue) {
  1510  			defaultParameter, ok := defaultParameters[name]
  1511  			if ok {
  1512  				defaultValue, ok := defaultParameter.value.(TunnelProtocolPortLists)
  1513  				if ok {
  1514  					value := make(TunnelProtocolPortLists)
  1515  					for tunnelProtocol, portLists := range defaultValue {
  1516  						value[tunnelProtocol] = portLists
  1517  					}
  1518  					return value
  1519  				}
  1520  			}
  1521  		}
  1522  	}
  1523  
  1524  	value := make(TunnelProtocolPortLists)
  1525  	p.snapshot.getValue(name, &value)
  1526  	return value
  1527  }
  1528  
  1529  // LabeledCIDRs returns a CIDR string list parameter value corresponding to
  1530  // the specified labeled set and label value. The return value is nil when no
  1531  // set is found.
  1532  func (p ParametersAccessor) LabeledCIDRs(name, label string) []string {
  1533  	value := LabeledCIDRs{}
  1534  	p.snapshot.getValue(name, &value)
  1535  	return value[label]
  1536  }
  1537  
  1538  // ProtocolTransformSpecs returns a transforms.Specs parameter value.
  1539  func (p ParametersAccessor) ProtocolTransformSpecs(name string) transforms.Specs {
  1540  	value := transforms.Specs{}
  1541  	p.snapshot.getValue(name, &value)
  1542  	return value
  1543  }
  1544  
  1545  // ProtocolTransformScopedSpecNames returns a transforms.ScopedSpecNames
  1546  // parameter value.
  1547  func (p ParametersAccessor) ProtocolTransformScopedSpecNames(name string) transforms.ScopedSpecNames {
  1548  	value := transforms.ScopedSpecNames{}
  1549  	p.snapshot.getValue(name, &value)
  1550  	return value
  1551  }