config.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Copyright (c) 2015, 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. package psiphon
  20. import (
  21. "encoding/json"
  22. "errors"
  23. "os"
  24. "time"
  25. )
  26. // TODO: allow all params to be configured
  27. const (
  28. VERSION = "0.0.9"
  29. DATA_STORE_FILENAME = "psiphon.db"
  30. CONNECTION_WORKER_POOL_SIZE = 10
  31. TUNNEL_POOL_SIZE = 1
  32. TUNNEL_CONNECT_TIMEOUT = 15 * time.Second
  33. TUNNEL_READ_TIMEOUT = 0 * time.Second
  34. TUNNEL_WRITE_TIMEOUT = 5 * time.Second
  35. TUNNEL_OPERATE_SHUTDOWN_TIMEOUT = 2 * time.Second
  36. TUNNEL_SSH_KEEP_ALIVE_PAYLOAD_MAX_BYTES = 256
  37. TUNNEL_SSH_KEEP_ALIVE_PERIOD_MIN = 60 * time.Second
  38. TUNNEL_SSH_KEEP_ALIVE_PERIOD_MAX = 120 * time.Second
  39. ESTABLISH_TUNNEL_TIMEOUT_SECONDS = 300
  40. ESTABLISH_TUNNEL_WORK_TIME_SECONDS = 60 * time.Second
  41. ESTABLISH_TUNNEL_PAUSE_PERIOD = 5 * time.Second
  42. PORT_FORWARD_FAILURE_THRESHOLD = 10
  43. HTTP_PROXY_ORIGIN_SERVER_TIMEOUT = 15 * time.Second
  44. HTTP_PROXY_MAX_IDLE_CONNECTIONS_PER_HOST = 50
  45. FETCH_REMOTE_SERVER_LIST_TIMEOUT = 10 * time.Second
  46. FETCH_REMOTE_SERVER_LIST_RETRY_PERIOD = 5 * time.Second
  47. FETCH_REMOTE_SERVER_LIST_STALE_PERIOD = 6 * time.Hour
  48. PSIPHON_API_CLIENT_SESSION_ID_LENGTH = 16
  49. PSIPHON_API_SERVER_TIMEOUT = 20 * time.Second
  50. PSIPHON_API_STATUS_REQUEST_PERIOD_MIN = 5 * time.Minute
  51. PSIPHON_API_STATUS_REQUEST_PERIOD_MAX = 10 * time.Minute
  52. PSIPHON_API_STATUS_REQUEST_PADDING_MAX_BYTES = 256
  53. PSIPHON_API_CONNECTED_REQUEST_PERIOD = 24 * time.Hour
  54. PSIPHON_API_CONNECTED_REQUEST_RETRY_PERIOD = 5 * time.Second
  55. FETCH_ROUTES_TIMEOUT = 10 * time.Second
  56. )
  57. // To distinguish omitted timeout params from explicit 0 value timeout
  58. // params, these params are int pointers. nil means no param was supplied
  59. // so use the default; a non-nil pointer to 0 means no timeout.
  60. type Config struct {
  61. LogFilename string
  62. DataStoreDirectory string
  63. DataStoreTempDirectory string
  64. PropagationChannelId string
  65. SponsorId string
  66. RemoteServerListUrl string
  67. RemoteServerListSignaturePublicKey string
  68. ClientVersion string
  69. ClientPlatform string
  70. TunnelWholeDevice int
  71. EgressRegion string
  72. TunnelProtocol string
  73. EstablishTunnelTimeoutSeconds *int
  74. LocalSocksProxyPort int
  75. LocalHttpProxyPort int
  76. ConnectionWorkerPoolSize int
  77. TunnelPoolSize int
  78. PortForwardFailureThreshold int
  79. UpstreamHttpProxyAddress string
  80. NetworkConnectivityChecker NetworkConnectivityChecker
  81. DeviceBinder DeviceBinder
  82. DnsServerGetter DnsServerGetter
  83. TargetServerEntry string
  84. DisableApi bool
  85. DisableRemoteServerListFetcher bool
  86. SplitTunnelRoutesUrlFormat string
  87. SplitTunnelRoutesSignaturePublicKey string
  88. SplitTunnelDnsServer string
  89. }
  90. // LoadConfig parses and validates a JSON format Psiphon config JSON
  91. // string and returns a Config struct populated with config values.
  92. func LoadConfig(configJson []byte) (*Config, error) {
  93. var config Config
  94. err := json.Unmarshal(configJson, &config)
  95. if err != nil {
  96. return nil, ContextError(err)
  97. }
  98. // These fields are required; the rest are optional
  99. if config.PropagationChannelId == "" {
  100. return nil, ContextError(
  101. errors.New("propagation channel ID is missing from the configuration file"))
  102. }
  103. if config.SponsorId == "" {
  104. return nil, ContextError(
  105. errors.New("sponsor ID is missing from the configuration file"))
  106. }
  107. if config.DataStoreDirectory == "" {
  108. config.DataStoreDirectory, err = os.Getwd()
  109. if err != nil {
  110. return nil, ContextError(err)
  111. }
  112. }
  113. if config.ClientVersion == "" {
  114. config.ClientVersion = "0"
  115. }
  116. if config.TunnelProtocol != "" {
  117. if !Contains(SupportedTunnelProtocols, config.TunnelProtocol) {
  118. return nil, ContextError(
  119. errors.New("invalid tunnel protocol"))
  120. }
  121. }
  122. if config.EstablishTunnelTimeoutSeconds == nil {
  123. defaultEstablishTunnelTimeoutSeconds := ESTABLISH_TUNNEL_TIMEOUT_SECONDS
  124. config.EstablishTunnelTimeoutSeconds = &defaultEstablishTunnelTimeoutSeconds
  125. }
  126. if config.ConnectionWorkerPoolSize == 0 {
  127. config.ConnectionWorkerPoolSize = CONNECTION_WORKER_POOL_SIZE
  128. }
  129. if config.TunnelPoolSize == 0 {
  130. config.TunnelPoolSize = TUNNEL_POOL_SIZE
  131. }
  132. if config.PortForwardFailureThreshold == 0 {
  133. config.PortForwardFailureThreshold = PORT_FORWARD_FAILURE_THRESHOLD
  134. }
  135. if config.NetworkConnectivityChecker != nil {
  136. return nil, ContextError(errors.New("NetworkConnectivityChecker interface must be set at runtime"))
  137. }
  138. if config.DeviceBinder != nil {
  139. return nil, ContextError(errors.New("DeviceBinder interface must be set at runtime"))
  140. }
  141. if config.DnsServerGetter != nil {
  142. return nil, ContextError(errors.New("DnsServerGetter interface must be set at runtime"))
  143. }
  144. return &config, nil
  145. }