26 """ |
26 """ |
27 Class representing a peer connection. |
27 Class representing a peer connection. |
28 |
28 |
29 @signal readyForUse() emitted when the connection is ready for use |
29 @signal readyForUse() emitted when the connection is ready for use |
30 @signal newMessage(user, message) emitted after a new message has |
30 @signal newMessage(user, message) emitted after a new message has |
31 arrived (string, string) |
31 arrived (string, string) |
32 @signal getParticipants() emitted after a get participants message has arrived |
32 @signal getParticipants() emitted after a get participants message has |
33 @signal participants(participants) emitted after the list of participants has |
33 arrived |
34 arrived (list of strings of "host:port") |
34 @signal participants(participants) emitted after the list of participants |
|
35 has arrived (list of strings of "host:port") |
35 """ |
36 """ |
36 WaitingForGreeting = 0 |
37 WaitingForGreeting = 0 |
37 ReadingGreeting = 1 |
38 ReadingGreeting = 1 |
38 ReadyForUse = 2 |
39 ReadyForUse = 2 |
39 |
40 |
161 |
162 |
162 if self.__state == Connection.ReadingGreeting: |
163 if self.__state == Connection.ReadingGreeting: |
163 if not self.__hasEnoughData(): |
164 if not self.__hasEnoughData(): |
164 return |
165 return |
165 |
166 |
166 self.__buffer = QByteArray(self.read(self.__numBytesForCurrentDataType)) |
167 self.__buffer = QByteArray( |
|
168 self.read(self.__numBytesForCurrentDataType)) |
167 if self.__buffer.size() != self.__numBytesForCurrentDataType: |
169 if self.__buffer.size() != self.__numBytesForCurrentDataType: |
168 self.abort() |
170 self.abort() |
169 return |
171 return |
170 |
172 |
171 try: |
173 try: |
172 user, serverPort = str(self.__buffer, encoding="utf-8").split(":") |
174 user, serverPort = \ |
|
175 str(self.__buffer, encoding="utf-8").split(":") |
173 except ValueError: |
176 except ValueError: |
174 self.abort() |
177 self.abort() |
175 return |
178 return |
176 self.__serverPort = int(serverPort) |
179 self.__serverPort = int(serverPort) |
177 |
180 |
193 user, |
196 user, |
194 hostInfo.hostName(), |
197 hostInfo.hostName(), |
195 ) |
198 ) |
196 Preferences.syncPreferences() |
199 Preferences.syncPreferences() |
197 if bannedName in Preferences.getCooperation("BannedUsers"): |
200 if bannedName in Preferences.getCooperation("BannedUsers"): |
198 self.rejected.emit( |
201 self.rejected.emit(self.trUtf8( |
199 self.trUtf8("* Connection attempted by banned user '{0}'.")\ |
202 "* Connection attempted by banned user '{0}'.") |
200 .format(bannedName)) |
203 .format(bannedName)) |
201 self.abort() |
204 self.abort() |
202 return |
205 return |
203 |
206 |
204 if self.__serverPort != self.peerPort() and \ |
207 if self.__serverPort != self.peerPort() and \ |
205 not Preferences.getCooperation("AutoAcceptConnections"): |
208 not Preferences.getCooperation("AutoAcceptConnections"): |
216 return |
219 return |
217 |
220 |
218 if self.__client is not None: |
221 if self.__client is not None: |
219 chatWidget = self.__client.chatWidget() |
222 chatWidget = self.__client.chatWidget() |
220 if chatWidget is not None and not chatWidget.isVisible(): |
223 if chatWidget is not None and not chatWidget.isVisible(): |
221 e5App().getObject("UserInterface").activateCooperationViewer() |
224 e5App().getObject( |
|
225 "UserInterface").activateCooperationViewer() |
222 |
226 |
223 if not self.__isGreetingMessageSent: |
227 if not self.__isGreetingMessageSent: |
224 self.__sendGreetingMessage() |
228 self.__sendGreetingMessage() |
225 |
229 |
226 self.__pingTimer.start() |
230 self.__pingTimer.start() |
244 """ |
248 """ |
245 if self.__pongTime.elapsed() > PongTimeout: |
249 if self.__pongTime.elapsed() > PongTimeout: |
246 self.abort() |
250 self.abort() |
247 return |
251 return |
248 |
252 |
249 self.write("{0}{1}1{1}p".format(Connection.ProtocolPing, SeparatorToken)) |
253 self.write("{0}{1}1{1}p".format( |
|
254 Connection.ProtocolPing, SeparatorToken)) |
250 |
255 |
251 def __sendGreetingMessage(self): |
256 def __sendGreetingMessage(self): |
252 """ |
257 """ |
253 Private slot to send a greeting message. |
258 Private slot to send a greeting message. |
254 """ |
259 """ |
255 greeting = QByteArray(self.__greetingMessage.encode("utf-8")) |
260 greeting = QByteArray(self.__greetingMessage.encode("utf-8")) |
256 data = QByteArray("{0}{1}{2}{1}".format( |
261 data = QByteArray("{0}{1}{2}{1}".format( |
257 Connection.ProtocolGreeting, SeparatorToken, greeting.size())) + greeting |
262 Connection.ProtocolGreeting, SeparatorToken, greeting.size())) + \ |
|
263 greeting |
258 if self.write(data) == data.size(): |
264 if self.write(data) == data.size(): |
259 self.__isGreetingMessageSent = True |
265 self.__isGreetingMessageSent = True |
260 |
266 |
261 def __readDataIntoBuffer(self, maxSize=MaxBufferSize): |
267 def __readDataIntoBuffer(self, maxSize=MaxBufferSize): |
262 """ |
268 """ |
329 self.__currentDataType = Connection.Undefined |
335 self.__currentDataType = Connection.Undefined |
330 self.abort() |
336 self.abort() |
331 return False |
337 return False |
332 |
338 |
333 self.__buffer.clear() |
339 self.__buffer.clear() |
334 self.__numBytesForCurrentDataType = self.__dataLengthForCurrentDataType() |
340 self.__numBytesForCurrentDataType = \ |
|
341 self.__dataLengthForCurrentDataType() |
335 return True |
342 return True |
336 |
343 |
337 def __hasEnoughData(self): |
344 def __hasEnoughData(self): |
338 """ |
345 """ |
339 Private method to check, if enough data is available. |
346 Private method to check, if enough data is available. |
343 if self.__transferTimerId: |
350 if self.__transferTimerId: |
344 self.killTimer(self.__transferTimerId) |
351 self.killTimer(self.__transferTimerId) |
345 self.__transferTimerId = 0 |
352 self.__transferTimerId = 0 |
346 |
353 |
347 if self.__numBytesForCurrentDataType <= 0: |
354 if self.__numBytesForCurrentDataType <= 0: |
348 self.__numBytesForCurrentDataType = self.__dataLengthForCurrentDataType() |
355 self.__numBytesForCurrentDataType = \ |
|
356 self.__dataLengthForCurrentDataType() |
349 |
357 |
350 if self.bytesAvailable() < self.__numBytesForCurrentDataType or \ |
358 if self.bytesAvailable() < self.__numBytesForCurrentDataType or \ |
351 self.__numBytesForCurrentDataType <= 0: |
359 self.__numBytesForCurrentDataType <= 0: |
352 self.__transferTimerId = self.startTimer(TransferTimeout) |
360 self.__transferTimerId = self.startTimer(TransferTimeout) |
353 return False |
361 return False |
356 |
364 |
357 def __processData(self): |
365 def __processData(self): |
358 """ |
366 """ |
359 Private method to process the received data. |
367 Private method to process the received data. |
360 """ |
368 """ |
361 self.__buffer = QByteArray(self.read(self.__numBytesForCurrentDataType)) |
369 self.__buffer = QByteArray( |
|
370 self.read(self.__numBytesForCurrentDataType)) |
362 if self.__buffer.size() != self.__numBytesForCurrentDataType: |
371 if self.__buffer.size() != self.__numBytesForCurrentDataType: |
363 self.abort() |
372 self.abort() |
364 return |
373 return |
365 |
374 |
366 if self.__currentDataType == Connection.PlainText: |
375 if self.__currentDataType == Connection.PlainText: |
367 self.newMessage.emit(self.__username, str(self.__buffer, encoding="utf-8")) |
376 self.newMessage.emit( |
|
377 self.__username, str(self.__buffer, encoding="utf-8")) |
368 elif self.__currentDataType == Connection.Ping: |
378 elif self.__currentDataType == Connection.Ping: |
369 self.write("{0}{1}1{1}p".format(Connection.ProtocolPong, SeparatorToken)) |
379 self.write("{0}{1}1{1}p".format( |
|
380 Connection.ProtocolPong, SeparatorToken)) |
370 elif self.__currentDataType == Connection.Pong: |
381 elif self.__currentDataType == Connection.Pong: |
371 self.__pongTime.restart() |
382 self.__pongTime.restart() |
372 elif self.__currentDataType == Connection.GetParticipants: |
383 elif self.__currentDataType == Connection.GetParticipants: |
373 self.getParticipants.emit() |
384 self.getParticipants.emit() |
374 elif self.__currentDataType == Connection.Participants: |
385 elif self.__currentDataType == Connection.Participants: |
377 participantsList = [] |
388 participantsList = [] |
378 else: |
389 else: |
379 participantsList = msg.split(SeparatorToken) |
390 participantsList = msg.split(SeparatorToken) |
380 self.participants.emit(participantsList[:]) |
391 self.participants.emit(participantsList[:]) |
381 elif self.__currentDataType == Connection.Editor: |
392 elif self.__currentDataType == Connection.Editor: |
382 hash, fn, msg = str(self.__buffer, encoding="utf-8").split(SeparatorToken) |
393 hash, fn, msg = \ |
|
394 str(self.__buffer, encoding="utf-8").split(SeparatorToken) |
383 self.editorCommand.emit(hash, fn, msg) |
395 self.editorCommand.emit(hash, fn, msg) |
384 |
396 |
385 self.__currentDataType = Connection.Undefined |
397 self.__currentDataType = Connection.Undefined |
386 self.__numBytesForCurrentDataType = 0 |
398 self.__numBytesForCurrentDataType = 0 |
387 self.__buffer.clear() |
399 self.__buffer.clear() |
389 def sendGetParticipants(self): |
401 def sendGetParticipants(self): |
390 """ |
402 """ |
391 Public method to request a list of participants. |
403 Public method to request a list of participants. |
392 """ |
404 """ |
393 self.write( |
405 self.write( |
394 "{0}{1}1{1}l".format(Connection.ProtocolGetParticipants, SeparatorToken) |
406 "{0}{1}1{1}l".format( |
|
407 Connection.ProtocolGetParticipants, SeparatorToken) |
395 ) |
408 ) |
396 |
409 |
397 def sendParticipants(self, participants): |
410 def sendParticipants(self, participants): |
398 """ |
411 """ |
399 Public method to send the list of participants. |
412 Public method to send the list of participants. |
400 |
413 |
401 @param participants list of participants (list of strings of "host:port") |
414 @param participants list of participants (list of strings of |
|
415 "host:port") |
402 """ |
416 """ |
403 if participants: |
417 if participants: |
404 message = SeparatorToken.join(participants) |
418 message = SeparatorToken.join(participants) |
405 else: |
419 else: |
406 message = "<empty>" |
420 message = "<empty>" |
428 """ |
442 """ |
429 Private slot to handle the connection being dropped. |
443 Private slot to handle the connection being dropped. |
430 """ |
444 """ |
431 self.__pingTimer.stop() |
445 self.__pingTimer.stop() |
432 if self.__state == Connection.WaitingForGreeting: |
446 if self.__state == Connection.WaitingForGreeting: |
433 self.rejected.emit(self.trUtf8("* Connection to {0}:{1} refused.").format( |
447 self.rejected.emit(self.trUtf8( |
|
448 "* Connection to {0}:{1} refused.").format( |
434 self.peerName(), self.peerPort())) |
449 self.peerName(), self.peerPort())) |