config.go 5.9 KB

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