diff --git a/internal/imap/server_test.go b/internal/imap/server_test.go
deleted file mode 100644
index 1653cbd2..00000000
--- a/internal/imap/server_test.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// ProtonMail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with ProtonMail Bridge. If not, see .
-
-package imap
-
-import (
- "fmt"
- "testing"
-
- "github.com/ProtonMail/proton-bridge/internal/bridge"
- "github.com/ProtonMail/proton-bridge/internal/config/useragent"
- "github.com/ProtonMail/proton-bridge/internal/serverutil/mocks"
- imapserver "github.com/emersion/go-imap/server"
-
- "github.com/stretchr/testify/require"
-)
-
-func TestIMAPServerTurnOffAndOnAgain(t *testing.T) {
- r := require.New(t)
- ts := mocks.NewTestServer(12345)
-
- server := imapserver.New(nil)
- server.Addr = fmt.Sprintf("%v:%v", bridge.Host, ts.WantPort)
-
- s := &imapServer{
- panicHandler: ts.PanicHandler,
- server: server,
- port: ts.WantPort,
- eventListener: ts.EventListener,
- userAgent: useragent.New(),
- }
- s.isRunning.Store(false)
-
- r.True(ts.IsPortFree())
-
- go s.ListenAndServe()
- ts.RunServerTests(r)
-}
diff --git a/internal/serverutil/mocks/server.go b/internal/serverutil/mocks/server.go
deleted file mode 100644
index 8e60c33c..00000000
--- a/internal/serverutil/mocks/server.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// ProtonMail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with ProtonMail Bridge. If not, see .
-
-package mocks
-
-import (
- "fmt"
- "net/http"
- "sync/atomic"
- "time"
-
- "github.com/ProtonMail/proton-bridge/internal/events"
- "github.com/ProtonMail/proton-bridge/pkg/listener"
- "github.com/ProtonMail/proton-bridge/pkg/ports"
- "github.com/sirupsen/logrus"
- "github.com/stretchr/testify/require"
-)
-
-type DummyPanicHandler struct{}
-
-func (ph *DummyPanicHandler) HandlePanic() {}
-
-type TestServer struct {
- PanicHandler *DummyPanicHandler
- WantPort int
- EventListener listener.Listener
-
- isRunning atomic.Value
- srv *http.Server
-}
-
-func NewTestServer(port int) *TestServer {
- s := &TestServer{
- PanicHandler: &DummyPanicHandler{},
- EventListener: listener.New(),
- WantPort: ports.FindFreePortFrom(port),
- }
- s.isRunning.Store(false)
- return s
-}
-
-func (s *TestServer) IsPortFree() bool {
- return true
-}
-
-func (s *TestServer) IsPortOccupied() bool {
- return true
-}
-
-func (s *TestServer) Emit(event string, try, iEvt int) int {
- // Emit has separate go routine so it is needed to wait here to
- // prevent event race condition.
- time.Sleep(100 * time.Millisecond)
- iEvt++
- s.EventListener.Emit(event, fmt.Sprintf("%d:%d", try, iEvt))
- return iEvt
-}
-
-func (s *TestServer) HandlePanic() {}
-func (s *TestServer) DisconnectUser(string) {}
-func (s *TestServer) Port() int { return s.WantPort }
-func (s *TestServer) IsRunning() bool { return s.isRunning.Load().(bool) }
-
-func (s *TestServer) ListenRetryAndServe(retries int, retryAfter time.Duration) {
- if s.isRunning.Load().(bool) {
- return
- }
- s.isRunning.Store(true)
-
- // There can be delay when starting server
- time.Sleep(200 * time.Millisecond)
-
- s.srv = &http.Server{
- Addr: fmt.Sprintf("127.0.0.1:%d", s.WantPort),
- }
-
- err := s.srv.ListenAndServe()
- if err != nil {
- s.isRunning.Store(false)
- if retries > 0 {
- time.Sleep(retryAfter)
- s.ListenRetryAndServe(retries-1, retryAfter)
- }
- }
-
- if s.IsRunning() {
- logrus.Error("Not serving but isRunning is true")
- s.isRunning.Store(false)
- }
-}
-
-func (s *TestServer) Close() {
- if !s.isRunning.Load().(bool) {
- return
- }
- s.isRunning.Store(false)
-
- // There can be delay when stopping server
- time.Sleep(200 * time.Millisecond)
- if err := s.srv.Close(); err != nil {
- logrus.WithError(err).Error("Closing dummy server")
- }
-}
-
-func (s *TestServer) RunServerTests(r *require.Assertions) {
- // NOTE About choosing tick durations:
- // In order to avoid ticks to synchronise and cause occasional race
- // condition we choose the tick duration around 100ms but not exactly
- // to have large common multiple.
- r.Eventually(s.IsPortOccupied, 5*time.Second, 97*time.Millisecond)
-
- // There was an issue where second time we were not able to restore server.
- for try := 0; try < 3; try++ {
- i := s.Emit(events.InternetOffEvent, try, 0)
- r.Eventually(s.IsPortFree, 10*time.Second, 99*time.Millisecond, "signal off try %d : %d", try, i)
-
- i = s.Emit(events.InternetOnEvent, try, i)
- i = s.Emit(events.InternetOffEvent, try, i)
- i = s.Emit(events.InternetOffEvent, try, i)
- i = s.Emit(events.InternetOffEvent, try, i)
- i = s.Emit(events.InternetOffEvent, try, i)
- i = s.Emit(events.InternetOnEvent, try, i)
- i = s.Emit(events.InternetOnEvent, try, i)
- i = s.Emit(events.InternetOffEvent, try, i)
- // Wait a bit longer if needed to process all events
- r.Eventually(s.IsPortFree, 20*time.Second, 101*time.Millisecond, "again signal off number %d : %d", try, i)
-
- i = s.Emit(events.InternetOnEvent, try, i)
- r.Eventually(s.IsPortOccupied, 10*time.Second, 103*time.Millisecond, "signal on number %d : %d", try, i)
-
- i = s.Emit(events.InternetOffEvent, try, i)
- i = s.Emit(events.InternetOnEvent, try, i)
- i = s.Emit(events.InternetOnEvent, try, i)
- r.Eventually(s.IsPortOccupied, 10*time.Second, 107*time.Millisecond, "again signal on number %d : %d", try, i)
- }
-}
diff --git a/internal/serverutil/server.go b/internal/serverutil/server.go
index 6542194e..a9865036 100644
--- a/internal/serverutil/server.go
+++ b/internal/serverutil/server.go
@@ -22,18 +22,12 @@ import (
"github.com/ProtonMail/proton-bridge/internal/events"
"github.com/ProtonMail/proton-bridge/pkg/listener"
- "github.com/ProtonMail/proton-bridge/pkg/ports"
- "github.com/sirupsen/logrus"
)
// Server which can handle disconnected users and lost internet connection.
type Server interface {
- HandlePanic()
DisconnectUser(string)
ListenRetryAndServe(int, time.Duration)
- Close()
- Port() int
- IsRunning() bool
}
func monitorDisconnectedUsers(s Server, l listener.Listener) {
@@ -44,87 +38,10 @@ func monitorDisconnectedUsers(s Server, l listener.Listener) {
}
}
-func redirectInternetEventsToOneChannel(l listener.Listener) (isInternetOn chan bool) {
- on := make(chan string)
- l.Add(events.InternetOnEvent, on)
- off := make(chan string)
- l.Add(events.InternetOffEvent, off)
-
- // Redirect two channels into one. When select was used the algorithm
- // first read all on channels and then read all off channels.
- isInternetOn = make(chan bool, 20)
- go func() {
- for {
- logrus.WithField("try", <-on).Trace("Internet ON")
- isInternetOn <- true
- }
- }()
-
- go func() {
- for {
- logrus.WithField("try", <-off).Trace("Internet OFF")
- isInternetOn <- false
- }
- }()
- return
-}
-
-const (
- recheckPortAfter = 50 * time.Millisecond
- stopPortChecksAfter = 15 * time.Second
- retryListenerAfter = 5 * time.Second
-)
-
-func monitorInternetConnection(s Server, l listener.Listener) {
- isInternetOn := redirectInternetEventsToOneChannel(l)
- for {
- var expectedIsPortFree bool
- if <-isInternetOn {
- if s.IsRunning() {
- continue
- }
- go func() {
- defer s.HandlePanic()
- // We had issues on Mac that from time to time something
- // blocked our port for a bit after we closed IMAP server
- // due to connection issues.
- // Restart always helped, so we do retry to not bother user.
- s.ListenRetryAndServe(10, retryListenerAfter)
- }()
- expectedIsPortFree = false
- } else {
- if !s.IsRunning() {
- continue
- }
- s.Close()
- expectedIsPortFree = true
- }
- start := time.Now()
- for {
- isPortFree := ports.IsPortFree(s.Port())
- logrus.
- WithField("port", s.Port()).
- WithField("isFree", isPortFree).
- WithField("wantToBeFree", expectedIsPortFree).
- Trace("Check port")
- if isPortFree == expectedIsPortFree {
- break
- }
- // Safety stop if something went wrong.
- if time.Since(start) > stopPortChecksAfter {
- logrus.WithField("expectedIsPortFree", expectedIsPortFree).Warn("Server start/stop check timeouted")
- break
- }
- time.Sleep(recheckPortAfter)
- }
- }
-}
-
// ListenAndServe starts the server and keeps it on based on internet
// availability. It also monitors and disconnect users if requested.
func ListenAndServe(s Server, l listener.Listener) {
go monitorDisconnectedUsers(s, l)
- go monitorInternetConnection(s, l)
// When starting the Bridge, we don't want to retry to notify user
// quickly about the issue. Very probably retry will not help anyway.
diff --git a/internal/serverutil/server_test.go b/internal/serverutil/server_test.go
deleted file mode 100644
index fa04a06f..00000000
--- a/internal/serverutil/server_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// ProtonMail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with ProtonMail Bridge. If not, see .
-
-package serverutil
-
-import (
- "testing"
-
- "github.com/ProtonMail/proton-bridge/internal/serverutil/mocks"
- "github.com/stretchr/testify/require"
-)
-
-func TestServerTurnOffAndOnAgain(t *testing.T) {
- r := require.New(t)
- s := mocks.NewTestServer(12321)
-
- r.True(s.IsPortFree())
-
- go ListenAndServe(s, s.EventListener)
- s.RunServerTests(r)
-}
diff --git a/internal/smtp/server_test.go b/internal/smtp/server_test.go
deleted file mode 100644
index 3342d21c..00000000
--- a/internal/smtp/server_test.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2021 Proton Technologies AG
-//
-// This file is part of ProtonMail Bridge.
-//
-// ProtonMail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// ProtonMail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with ProtonMail Bridge. If not, see .
-
-package smtp
-
-import (
- "testing"
-
- "github.com/ProtonMail/proton-bridge/internal/serverutil/mocks"
-
- "github.com/stretchr/testify/require"
-)
-
-func TestSMTPServerTurnOffAndOnAgain(t *testing.T) {
- r := require.New(t)
- ts := mocks.NewTestServer(12342)
-
- s := &Server{
- panicHandler: ts.PanicHandler,
- port: ts.WantPort,
- eventListener: ts.EventListener,
- }
- s.isRunning.Store(false)
-
- r.True(ts.IsPortFree())
-
- go s.ListenAndServe()
- ts.RunServerTests(r)
-}
diff --git a/test/context/users.go b/test/context/users.go
index cea3601e..ee8d2db5 100644
--- a/test/context/users.go
+++ b/test/context/users.go
@@ -63,7 +63,7 @@ func (ctx *TestContext) LoginUser(username string, password, mailboxPassword []b
}
// FinishLogin prevents authentication if not necessary.
-func (ctx *TestContext) FinishLogin(client pmapi.Client, mailboxPassword string) error {
+func (ctx *TestContext) FinishLogin(client pmapi.Client, mailboxPassword []byte) error {
user, err := ctx.users.FinishLogin(client, client.GetCurrentAuth(), mailboxPassword)
if err != nil {
return errors.Wrap(err, "failed to finish login")
diff --git a/test/liveapi/persistent_clients.go b/test/liveapi/persistent_clients.go
index 265db81a..404d76b2 100644
--- a/test/liveapi/persistent_clients.go
+++ b/test/liveapi/persistent_clients.go
@@ -23,9 +23,9 @@ import (
"math/rand"
"os"
+ "github.com/ProtonMail/go-srp"
"github.com/ProtonMail/proton-bridge/internal/constants"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
- "github.com/ProtonMail/proton-bridge/pkg/srp"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)