Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/connection listener #777

Merged
merged 2 commits into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions client/android/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ func (c *Client) PeersList() *PeerInfoArray {
return &PeerInfoArray{items: peerInfos}
}

// AddConnectionListener add new network connection listener
func (c *Client) AddConnectionListener(listener ConnectionListener) {
c.recorder.AddConnectionListener(listener)
// SetConnectionListener set the network connection listener
func (c *Client) SetConnectionListener(listener ConnectionListener) {
c.recorder.SetConnectionListener(listener)
}

// RemoveConnectionListener remove connection listener
func (c *Client) RemoveConnectionListener(listener ConnectionListener) {
c.recorder.RemoveConnectionListener(listener)
func (c *Client) RemoveConnectionListener() {
c.recorder.RemoveConnectionListener()
}
67 changes: 34 additions & 33 deletions client/internal/peer/notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,31 @@ const (
type notifier struct {
serverStateLock sync.Mutex
listenersLock sync.Mutex
listeners map[Listener]struct{}
listener Listener
currentServerState bool
currentClientState bool
lastNotification int
}

func newNotifier() *notifier {
return &notifier{
listeners: make(map[Listener]struct{}),
}
return &notifier{}
}

func (n *notifier) addListener(listener Listener) {
func (n *notifier) setListener(listener Listener) {
n.listenersLock.Lock()
defer n.listenersLock.Unlock()

n.serverStateLock.Lock()
go n.notifyListener(listener, n.lastNotification)
n.notifyListener(listener, n.lastNotification)
n.serverStateLock.Unlock()
n.listeners[listener] = struct{}{}

n.listener = listener
}

func (n *notifier) removeListener(listener Listener) {
func (n *notifier) removeListener() {
n.listenersLock.Lock()
defer n.listenersLock.Unlock()
delete(n.listeners, listener)
n.listener = nil
}

func (n *notifier) updateServerStates(mgmState bool, signalState bool) {
Expand All @@ -64,57 +63,59 @@ func (n *notifier) updateServerStates(mgmState bool, signalState bool) {
}

n.lastNotification = n.calculateState(newState, n.currentClientState)
go n.notifyAll(n.lastNotification)
n.notify(n.lastNotification)
}

func (n *notifier) clientStart() {
n.serverStateLock.Lock()
defer n.serverStateLock.Unlock()
n.currentClientState = true
n.lastNotification = n.calculateState(n.currentServerState, true)
go n.notifyAll(n.lastNotification)
n.notify(n.lastNotification)
}

func (n *notifier) clientStop() {
n.serverStateLock.Lock()
defer n.serverStateLock.Unlock()
n.currentClientState = false
n.lastNotification = n.calculateState(n.currentServerState, false)
go n.notifyAll(n.lastNotification)
n.notify(n.lastNotification)
}

func (n *notifier) clientTearDown() {
n.serverStateLock.Lock()
defer n.serverStateLock.Unlock()
n.currentClientState = false
n.lastNotification = stateDisconnecting
go n.notifyAll(n.lastNotification)
n.notify(n.lastNotification)
}

func (n *notifier) isServerStateChanged(newState bool) bool {
return n.currentServerState != newState
}

func (n *notifier) notifyAll(state int) {
func (n *notifier) notify(state int) {
n.listenersLock.Lock()
defer n.listenersLock.Unlock()

for l := range n.listeners {
n.notifyListener(l, state)
if n.listener == nil {
return
}
n.notifyListener(n.listener, state)
}

func (n *notifier) notifyListener(l Listener, state int) {
switch state {
case stateDisconnected:
l.OnDisconnected()
case stateConnected:
l.OnConnected()
case stateConnecting:
l.OnConnecting()
case stateDisconnecting:
l.OnDisconnecting()
}
go func() {
switch state {
case stateDisconnected:
l.OnDisconnected()
case stateConnected:
l.OnConnected()
case stateConnecting:
l.OnConnecting()
case stateDisconnecting:
l.OnDisconnecting()
}
}()
}

func (n *notifier) calculateState(serverState bool, clientState bool) int {
Expand All @@ -132,17 +133,17 @@ func (n *notifier) calculateState(serverState bool, clientState bool) int {
func (n *notifier) peerListChanged(numOfPeers int) {
n.listenersLock.Lock()
defer n.listenersLock.Unlock()

for l := range n.listeners {
l.OnPeersListChanged(numOfPeers)
if n.listener == nil {
return
}
n.listener.OnPeersListChanged(numOfPeers)
}

func (n *notifier) localAddressChanged(fqdn, address string) {
n.listenersLock.Lock()
defer n.listenersLock.Unlock()

for l := range n.listeners {
l.OnAddressChanged(fqdn, address)
if n.listener == nil {
return
}
n.listener.OnAddressChanged(fqdn, address)
}
66 changes: 66 additions & 0 deletions client/internal/peer/notifier_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,48 @@
package peer

import (
"sync"
"testing"
)

type mocListener struct {
lastState int
wg sync.WaitGroup
peers int
}

func (l *mocListener) OnConnected() {
l.lastState = stateConnected
l.wg.Done()
}
func (l *mocListener) OnDisconnected() {
l.lastState = stateDisconnected
l.wg.Done()
}
func (l *mocListener) OnConnecting() {
l.lastState = stateConnecting
l.wg.Done()
}
func (l *mocListener) OnDisconnecting() {
l.lastState = stateDisconnecting
l.wg.Done()
}

func (l *mocListener) OnAddressChanged(host, addr string) {

}
func (l *mocListener) OnPeersListChanged(size int) {
l.peers = size
}

func (l *mocListener) setWaiter() {
l.wg.Add(1)
}

func (l *mocListener) wait() {
l.wg.Wait()
}

func Test_notifier_serverState(t *testing.T) {

type scenario struct {
Expand All @@ -30,3 +69,30 @@ func Test_notifier_serverState(t *testing.T) {
})
}
}

func Test_notifier_SetListener(t *testing.T) {
listener := &mocListener{}
listener.setWaiter()

n := newNotifier()
n.lastNotification = stateConnecting
n.setListener(listener)
listener.wait()
if listener.lastState != n.lastNotification {
t.Errorf("invalid state: %d, expected: %d", listener.lastState, n.lastNotification)
}
}

func Test_notifier_RemoveListener(t *testing.T) {
listener := &mocListener{}
listener.setWaiter()
n := newNotifier()
n.lastNotification = stateConnecting
n.setListener(listener)
n.removeListener()
n.peerListChanged(1)

if listener.peers != 0 {
t.Errorf("invalid state: %d", listener.peers)
}
}
12 changes: 6 additions & 6 deletions client/internal/peer/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,14 +293,14 @@ func (d *Status) ClientTeardown() {
d.notifier.clientTearDown()
}

// AddConnectionListener add a listener to the notifier
func (d *Status) AddConnectionListener(listener Listener) {
d.notifier.addListener(listener)
// SetConnectionListener set a listener to the notifier
func (d *Status) SetConnectionListener(listener Listener) {
d.notifier.setListener(listener)
}

// RemoveConnectionListener remove a listener from the notifier
func (d *Status) RemoveConnectionListener(listener Listener) {
d.notifier.removeListener(listener)
// RemoveConnectionListener remove the listener from the notifier
func (d *Status) RemoveConnectionListener() {
d.notifier.removeListener()
}

func (d *Status) onConnectionChanged() {
Expand Down