Browse Source

Fix manager reconnection bug in server. Add ClientTracker persistence.

wip
Maurizio Porrato 9 years ago
parent
commit
05894bb136
6 changed files with 63 additions and 57 deletions
  1. 1
    0
      .gitignore
  2. 29
    2
      frn/clienttracker.py
  3. 21
    46
      frn/manager/remote.py
  4. 7
    6
      frn/protocol/manager.py
  5. 4
    3
      frn/protocol/server.py
  6. 1
    0
      server.py

+ 1
- 0
.gitignore View File

@@ -5,3 +5,4 @@ servers.conf
5 5
 recordings/*
6 6
 sounds/*
7 7
 *.sqlite3
8
+*.shelve

+ 29
- 2
frn/clienttracker.py View File

@@ -3,12 +3,13 @@
3 3
 # Copyright 2010 Maurizio Porrato <maurizio.porrato@gmail.com>
4 4
 # See LICENSE.txt for copyright info
5 5
 
6
+import shelve
6 7
 from twisted.python import log
7 8
 
8 9
 
9 10
 class ClientTracker(object):
10 11
 
11
-    def __init__(self, cbClient, cbNet, cbMute, cbBlock, cbAdmin):
12
+    def __init__(self, filename, cbClient, cbNet, cbMute, cbBlock, cbAdmin):
12 13
         self._clientData = {}
13 14
         self._net = {}
14 15
         self._mute = {}
@@ -19,6 +20,24 @@ class ClientTracker(object):
19 20
         self.cbMute = cbMute
20 21
         self.cbBlock = cbBlock
21 22
         self.cbAdmin = cbAdmin
23
+        self.filename = filename
24
+        self.load()
25
+
26
+    def load(self, filename=None):
27
+        s = shelve.open(filename or self.filename)
28
+        try:
29
+            self._mute = s['mute']
30
+            self._block = s['block']
31
+            self._admin = s['admin']
32
+        except KeyError: pass
33
+        s.close()
34
+
35
+    def save(self, filename=None):
36
+        s = shelve.open(filename or self.filename)
37
+        s['mute'] = self._mute
38
+        s['block'] = self._block
39
+        s['admin'] = self._admin
40
+        s.close()
22 41
 
23 42
     def getClient(self, clientId):
24 43
         return self._clientData[clientId].user
@@ -76,7 +95,7 @@ class ClientTracker(object):
76 95
             if clientId in self._mute:
77 96
                 client.user.M = 1
78 97
                 a = self._mute[clientId].AI
79
-                self._mute[clientId].update(client.user.dict())
98
+                self._mute[clientId].update(**client.user.dict())
80 99
                 self._mute[clientId].AI = a
81 100
             else:
82 101
                 client.user.M = 0
@@ -85,6 +104,7 @@ class ClientTracker(object):
85 104
             if client.user.EA in self._admin:
86 105
                 client.role = "ADMIN"
87 106
                 self._admin[client.user.EA].update(client.user.dict())
107
+            self.save()
88 108
             if len(nc) == 1:
89 109
                 self.cbNet(self.getNetworkList())
90 110
             self.cbClient(net, self.getClientList(net))
@@ -101,6 +121,7 @@ class ClientTracker(object):
101 121
             if not self._net[net]:
102 122
                 del self._net[net]
103 123
                 self.cbNet(self.getNetworkList())
124
+            self.save()
104 125
             self.cbClient(net, self.getClientList(net))
105 126
 
106 127
     def setStatus(self, clientId, status):
@@ -114,6 +135,7 @@ class ClientTracker(object):
114 135
         if clientId not in self._mute:
115 136
             self._mute[clientId] = self.getClient(clientId).copy(AI=admin.ON)
116 137
             self._clientData[clientId].user.M = 1
138
+            self.save()
117 139
             net = self.getClient(clientId).NT
118 140
             self.cbClient(net, self.getClientList(net))
119 141
             self.cbMute(self.getMuteList())
@@ -125,6 +147,7 @@ class ClientTracker(object):
125 147
                 self._clientData[clientId].user.M = 0
126 148
                 net = self._clientData[clientId].user.NT
127 149
                 self.cbClient(net, self.getClientList(net))
150
+            self.save()
128 151
             self.cbMute(self.getMuteList())
129 152
 
130 153
     def block(self, admin, clientId):
@@ -132,21 +155,25 @@ class ClientTracker(object):
132 155
             self._block[clientId] = self.getClient(clientId).copy(AI=admin.ON)
133 156
             if clientId in self._clientData:
134 157
                 net = self._clientData[clientId].user.NT
158
+            self.save()
135 159
             self.cbBlock(self.getBlockList())
136 160
 
137 161
     def unBlock(self, clientId):
138 162
         if clientId in self._block:
139 163
             del self._block[clientId]
164
+            self.save()
140 165
             self.cbBlock(self.getBlockList())
141 166
 
142 167
     def admin(self, clientId):
143 168
         if clientId not in self._admin:
144 169
             self._admin[clientId] = self.getClient(clientId).copy()
170
+            self.save()
145 171
             self.cbAdmin(self.getAdminList())
146 172
 
147 173
     def unAdmin(self, clientId):
148 174
         if clientId in self._admin:
149 175
             del self._admin[clientId]
176
+            self.save()
150 177
             self.cbAdmin(self.getAdminList())
151 178
 
152 179
 

+ 21
- 46
frn/manager/remote.py View File

@@ -12,45 +12,28 @@ from frn.protocol.manager import FRNManagerClient, FRNManagerClientFactory
12 12
 
13 13
 class CustomManagerClientFactory(FRNManagerClientFactory):
14 14
 
15
-    def __init__(self, user, onConnect, onDisconnect):
15
+    def __init__(self, user):
16 16
         self.user = user
17
-        self.onConnect = onConnect
18
-        self.onDisconnect = onDisconnect
19 17
         self.authResult = False
20 18
         self.client = None
21
-        self.managerReady = Deferred()
22
-        self.client = None
19
+        self.authDone = False
20
+        self.deferred = Deferred()
21
+
22
+    def managerConnected(self, connection):
23
+        def authReply(auth):
24
+            self.authResult = auth
25
+            self.authDone = (auth['al'] == '0')
26
+            if self.authDone:
27
+                self.deferred.callback(auth)
28
+        connection.sendServerLogin(self.user).addCallback(authReply)
29
+
30
+    def managerDisconnected(self, connection):
31
+        pass
23 32
 
24
-    def clientConnectionFailed(self, connector, reason):
25
-        self.authResult = False
26
-        self.client = None
27
-        self.managerReady = Deferred()
28
-        self.onDisconnect(self.protocol)
29
-        FRNManagerClientFactory.clientConnectionFailed(
30
-            self, connector, reason)
31
-        self.managerConnection.addCallback(self.connectionReady)
32
-
33
-    def clientConnectionLost(self, connector, reason):
34
-        self.authResult = False
35
-        self.client = None
36
-        self.managerReady = Deferred()
37
-        self.onDisconnect(self.protocol)
38
-        FRNManagerClientFactory.clientConnectionLost(
39
-            self, connector, reason)
40
-        self.managerConnection.addCallback(self.connectionReady)
41
-
42
-    def connectionReady(self, client):
43
-        def authDone(res):
44
-            log.msg("Auth: %s" % str(res))
45
-            if res['al'] == '0':
46
-                self.authResult = res
47
-                self.onConnect(client)
48
-                self.managerReady.callback(res)
49
-            else:
50
-                client.transport.loseConnection()
51
-            return res
52
-        self.client = client
53
-        self.client.sendServerLogin(self.user).addCallback(authDone)
33
+    def buildProtocol(self, addr):
34
+        p = FRNManagerClientFactory.buildProtocol(self, addr)
35
+        self.client = p
36
+        return p
54 37
 
55 38
 
56 39
 class RemoteManager(object):
@@ -63,21 +46,13 @@ class RemoteManager(object):
63 46
         self.port = port
64 47
         self.factory = None
65 48
 
66
-    def onManagerConnect(self, protocol):
67
-        pass
68
-
69
-    def onManagerDisconnect(self, protocol):
70
-        pass
71
-
72 49
     def doConnect(self):
73 50
         self.reactor.connectTCP(self.server, self.port, self.factory)
74
-        self.factory.managerConnection.addCallback(self.factory.connectionReady)
75
-        return self.factory.managerReady
76 51
 
77 52
     def serverLogin(self, user):
78
-        self.factory = CustomManagerClientFactory(
79
-            user, self.onManagerConnect, self.onManagerDisconnect)
80
-        return self.doConnect()
53
+        self.factory = CustomManagerClientFactory(user)
54
+        self.doConnect()
55
+        return self.factory.deferred
81 56
 
82 57
     def serverLogout(self, user):
83 58
         if self.factory.client is not None:

+ 7
- 6
frn/protocol/manager.py View File

@@ -20,9 +20,7 @@ class FRNManagerClient(LineOnlyReceiver):
20 20
     def connectionMade(self):
21 21
         log.msg("Connected to manager [%s]" % self.transport.getPeer().host)
22 22
         self.notifications = []
23
-        if not self.factory.managerConnection.called: # FIXME: Why???
24
-            log.msg("Firing manager connection callback!")
25
-            self.factory.managerConnection.callback(self)
23
+        self.factory.managerConnected(self)
26 24
 
27 25
     def connectionLost(self, reason):
28 26
         log.msg("Manager disconnected")
@@ -31,7 +29,7 @@ class FRNManagerClient(LineOnlyReceiver):
31 29
         except: pass
32 30
         for d in self.notifications:
33 31
             d.errback(reason)
34
-        self.factory.managerConnection = Deferred()
32
+        self.factory.managerDisconnected(self)
35 33
 
36 34
     def notifyFinish(self):
37 35
         self.notifications.append(Deferred())
@@ -102,8 +100,11 @@ class FRNManagerClientFactory(ReconnectingClientFactory):
102 100
 
103 101
     protocol = FRNManagerClient
104 102
 
105
-    def startFactory(self):
106
-        self.managerConnection = Deferred()
103
+    def managerConnected(self, connection):
104
+        pass
105
+
106
+    def managerDisconnected(self, connection):
107
+        pass
107 108
 
108 109
 
109 110
 class FRNManagerServer(LineOnlyReceiver):

+ 4
- 3
frn/protocol/server.py View File

@@ -110,9 +110,9 @@ class FRNServer(BufferingLineReceiver, TimeoutMixin):
110 110
         def authReturned(result):
111 111
             self.role, clientId = result
112 112
             log.msg("AUTH result: %s %s" % (self.role, clientId))
113
+            self.user = FRNUser(**body)
114
+            self.user.ID = clientId
113 115
             if self.role == 'OK':
114
-                self.user = FRNUser(**body)
115
-                self.user.ID = clientId
116 116
                 if self.user.EA == self.factory.serverAuth.OW:
117 117
                     self.role = 'OWNER'
118 118
                 elif self.factory.tracker.isAdmin(self.user.EA):
@@ -272,12 +272,13 @@ class FRNServerFactory(ServerFactory):
272 272
 
273 273
     protocol = FRNServer
274 274
 
275
-    def __init__(self, manager, serverAuth):
275
+    def __init__(self, trackerfile, manager, serverAuth):
276 276
         self.manager = manager
277 277
         self.serverAuth = serverAuth
278 278
         self.talking = None
279 279
         self.officialNets = []
280 280
         self.tracker = ClientTracker(
281
+            trackerfile,
281 282
             self.sendClientList, self.sendNetworkList,
282 283
             self.sendMuteList, self.sendBlockList,
283 284
             self.sendAdminList)

+ 1
- 0
server.py View File

@@ -43,6 +43,7 @@ if __name__ == '__main__':
43 43
         password = acfg.get(account_name, 'password')
44 44
 
45 45
         reactor.listenTCP(10024, FRNServerFactory(
46
+            pjoin(basedir, 'tracker.shelve'),
46 47
     #        DatabaseUserStore(
47 48
     #            ConnectionPool("sqlite3", "frn_users.sqlite3",
48 49
     #                check_same_thread=False)),

Loading…
Cancel
Save