-
Notifications
You must be signed in to change notification settings - Fork 0
/
loginserver.py
248 lines (222 loc) · 8.05 KB
/
loginserver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
from pandac.PandaModules import QueuedConnectionManager, QueuedConnectionListener
from pandac.PandaModules import QueuedConnectionReader, ConnectionWriter
from pandac.PandaModules import PointerToConnection, NetAddress
from direct.distributed.PyDatagram import PyDatagram
from direct.distributed.PyDatagramIterator import PyDatagramIterator
from pandac.PandaModules import NetDatagram
from direct.task.Task import Task
from direct.showbase.ShowBase import ShowBase
from db import ClientDataBase
import rencode
from pandac.PandaModules import loadPrcFileData
loadPrcFileData("",
"""
window-type none
"""
)
class Client:
def __init__(self, name, connection):
self.name = name
self.connection = connection
print 'Client connected: ', name, 'From: ', connection.getAddress()
class Server:
def __init__(self, name, connection):
self.name = name
self.connection = connection
self.state = 'starting'
print 'Server connected: ', name, 'From: ', connection.getAddress()
class Chat:
def __init__(self, name, connection):
self.name = name
self.private = False
self.connection = connection
print 'Chat Server connected: ', name, 'From: ', connection.getAddress()
# Login server Core.
class LoginServer(ShowBase):
def __init__(self, port, backlog = 1000, compress = False):
ShowBase.__init__(self)
self.compress = compress
self.cManager = QueuedConnectionManager()
self.cListener = QueuedConnectionListener(self.cManager, 0)
self.cReader = QueuedConnectionReader(self.cManager, 0)
self.cWriter = ConnectionWriter(self.cManager,0)
self.clientdb = ClientDataBase()
if not self.clientdb.connected:
self.clientdb = None
print 'Login Server failed to start...'
else:
# This is for pre-login
self.tempConnections = []
# This is for authed clients
self.activeClients = []
# This is for authed servers
self.activeServers = []
# This is for authed chat servers
self.activeChats = []
self.connect(port, backlog)
self.startPolling()
self.taskMgr.doMethodLater(0.5, self.lobbyLoop, 'Lobby Loop')
print 'Login Server operating...'
def connect(self, port, backlog = 1000):
# Bind to our socket
tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog)
self.cListener.addConnection(tcpSocket)
def startPolling(self):
self.taskMgr.add(self.tskListenerPolling, "serverListenTask", -40)
self.taskMgr.add(self.tskDisconnectPolling, "serverDisconnectTask", -39)
def tskListenerPolling(self, task):
if self.cListener.newConnectionAvailable():
rendezvous = PointerToConnection()
netAddress = NetAddress()
newConnection = PointerToConnection()
if self.cListener.getNewConnection(rendezvous, netAddress, newConnection):
newConnection = newConnection.p()
self.tempConnections.append(newConnection)
self.cReader.addConnection(newConnection)
return Task.cont
def tskDisconnectPolling(self, task):
while self.cManager.resetConnectionAvailable() == True:
connPointer = PointerToConnection()
self.cManager.getResetConnection(connPointer)
connection = connPointer.p()
# Remove the connection
self.cReader.removeConnection(connection)
# Check for if it was a client
for client in self.activeClients:
if client.connection == connection:
print 'removing client'
self.activeClients.remove(client)
break
# then check servers
for server in self.activeServers:
if server.connection == connection:
self.activeServers.remove(server)
break
# then check servers
for chat in self.activeChats:
if chat.connection == connection:
self.activeChats.remove(chat)
break
return Task.cont
def processData(self, netDatagram):
myIterator = PyDatagramIterator(netDatagram)
return self.decode(myIterator.getString())
def encode(self, data, compress = False):
# encode(and possibly compress) the data with rencode
return rencode.dumps(data, compress)
def decode(self, data):
# decode(and possibly decompress) the data with rencode
return rencode.loads(data)
def sendData(self, data, con):
myPyDatagram = PyDatagram()
myPyDatagram.addString(self.encode(data, self.compress))
self.cWriter.send(myPyDatagram, con)
# This will check and do the logins.
def auth(self, datagram):
# If in login state.
con = datagram.getConnection()
package = self.processData(datagram)
if len(package) == 2:
if package[0] == 'create':
success, result = self.clientdb.addClient(package[1][0], package[1][1])
if success:
self.sendData(('createSuccess', result), con)
else:
self.sendData(('createFailed', result), con)
return False
if package[0] == 'client':
userFound = False
for client in self.activeClients:
if client.name == package[1][0]:
userFound = True
self.sendData(('loginFailed', 'logged'), con)
break
if not userFound:
valid, result = self.clientdb.validateClient(package[1][0], package[1][1])
if valid:
self.activeClients.append(Client(package[1][0], con))
self.sendData(('loginValid', result), con)
return True
else:
self.sendData(('loginFailed', result), con)
return False
# if server add it to the list of current active servers
if package[0] == 'server':
self.activeServers.append(Server(package[1], con))
return True
# if server add it to the list of current active servers
if package[0] == 'chat':
self.activeChats.append(Chat(package[1], con))
return True
def getData(self):
data = []
while self.cReader.dataAvailable():
datagram = NetDatagram()
if self.cReader.getData(datagram):
if datagram.getConnection() in self.tempConnections:
if self.auth(datagram):
self.tempConnections.remove(datagram.getConnection())
continue
# Check if the data recieved is from a valid client.
for client in self.activeClients:
if datagram.getConnection() == client.connection:
data.append(('client', self.processData(datagram), client))
break
# Check if the data recieved is from a valid server.
for server in self.activeServers:
if datagram.getConnection() == server.connection:
data.append(('server', self.processData(datagram), server))
break
# Check if the data recieved is from a valid chat.
for chat in self.activeChats:
if datagram.getConnection() == chat.connection:
data.append(('chat', self.processData(datagram), chat))
break
return data
# handles new joining clients and updates all clients of chats and readystatus of players
def lobbyLoop(self, task):
# if in lobby state
temp = self.getData()
if temp != []:
for package in temp:
# handle client incoming packages here
if package[0] == 'client':
# This is where packages will come after clients connect to the server
# will be things like requesting available servers and chat servers
if package[1] == 'server_query':
for server in self.activeServers:
if server.state == 'lobby':
self.sendData(
('server', (server.name, str(server.connection.getAddress()))),
package[2].connection)
self.sendData(
('final', 'No more servers'),
package[2].connection)
# handle server incoming packages here
elif package[0] == 'server':
# auth
# game state change
if len(package[1]) == 2:
if package[1][0] == 'auth':
clientAuth = False
print 'Attempting Authentication on: ', package[1][1]
for client in self.activeClients:
if client.name == package[1][1]:
clientAuth = True
break
if clientAuth:
self.sendData(('auth', client.name), package[2].connection)
else:
self.sendData(('fail', package[1][1]), package[2].connection)
elif package[1][0] == 'state':
package[2].state = package[1][1]
# handle chat server incoming packages here
elif package[0] == 'chat':
print 'Authorized chat server sent package'
# handle packages from the chat servers
# like making public/private
# authing clients
return task.again
print 'STARTING LOGIN SERVER'
loginServer = LoginServer(9098, compress = True)
loginServer.run()