services.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * Copyright (c) 2016, 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 server
  20. import (
  21. "os"
  22. "os/signal"
  23. "sync"
  24. log "github.com/Psiphon-Inc/logrus"
  25. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon"
  26. )
  27. func RunServices(encodedConfig []byte) error {
  28. config, err := LoadConfig(encodedConfig)
  29. if err != nil {
  30. log.Error("RunServices failed: %s", err)
  31. return psiphon.ContextError(err)
  32. }
  33. // TODO: init logging
  34. waitGroup := new(sync.WaitGroup)
  35. shutdownBroadcast := make(chan struct{})
  36. errors := make(chan error)
  37. // TODO: optional services (e.g., run SSH only)
  38. waitGroup.Add(1)
  39. go func() {
  40. defer waitGroup.Done()
  41. err := RunWebServer(config, shutdownBroadcast)
  42. select {
  43. case errors <- err:
  44. default:
  45. }
  46. }()
  47. waitGroup.Add(1)
  48. go func() {
  49. defer waitGroup.Done()
  50. err := RunSSHServer(config, shutdownBroadcast)
  51. select {
  52. case errors <- err:
  53. default:
  54. }
  55. }()
  56. // An OS signal triggers an orderly shutdown
  57. systemStopSignal := make(chan os.Signal, 1)
  58. signal.Notify(systemStopSignal, os.Interrupt, os.Kill)
  59. err = nil
  60. select {
  61. case <-systemStopSignal:
  62. log.Info("RunServices shutdown by system")
  63. case err = <-errors:
  64. log.Error("RunServices failed: %s", err)
  65. }
  66. close(shutdownBroadcast)
  67. waitGroup.Wait()
  68. return err
  69. }