| OLD | NEW |
| 1 #!/usr/bin/python2.4 | 1 #!/usr/bin/python2.4 |
| 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """A bare-bones and non-compliant XMPP server. | 6 """A bare-bones and non-compliant XMPP server. |
| 7 | 7 |
| 8 Just enough of the protocol is implemented to get it to work with | 8 Just enough of the protocol is implemented to get it to work with |
| 9 Chrome's sync notification system. | 9 Chrome's sync notification system. |
| 10 """ | 10 """ |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 The XMPP server starts accepting connections on the given address | 481 The XMPP server starts accepting connections on the given address |
| 482 and spawns off XmppConnection objects for each one. | 482 and spawns off XmppConnection objects for each one. |
| 483 | 483 |
| 484 Use like so: | 484 Use like so: |
| 485 | 485 |
| 486 socket_map = {} | 486 socket_map = {} |
| 487 xmpp_server = xmppserver.XmppServer(socket_map, ('127.0.0.1', 5222)) | 487 xmpp_server = xmppserver.XmppServer(socket_map, ('127.0.0.1', 5222)) |
| 488 asyncore.loop(30.0, False, socket_map) | 488 asyncore.loop(30.0, False, socket_map) |
| 489 """ | 489 """ |
| 490 | 490 |
| 491 # Used when sending a notification. |
| 492 _NOTIFICATION_STANZA = ParseXml( |
| 493 '<message>' |
| 494 ' <push xmlns="google:push">' |
| 495 ' <data/>' |
| 496 ' </push>' |
| 497 '</message>') |
| 498 |
| 491 def __init__(self, socket_map, addr): | 499 def __init__(self, socket_map, addr): |
| 492 asyncore.dispatcher.__init__(self, None, socket_map) | 500 asyncore.dispatcher.__init__(self, None, socket_map) |
| 493 self.create_socket(socket.AF_INET, socket.SOCK_STREAM) | 501 self.create_socket(socket.AF_INET, socket.SOCK_STREAM) |
| 494 self.set_reuse_addr() | 502 self.set_reuse_addr() |
| 495 self.bind(addr) | 503 self.bind(addr) |
| 496 self.listen(5) | 504 self.listen(5) |
| 497 self._socket_map = socket_map | 505 self._socket_map = socket_map |
| 498 self._connections = set() | 506 self._connections = set() |
| 499 self._handshake_done_connections = set() | 507 self._handshake_done_connections = set() |
| 508 self._notifications_enabled = True |
| 500 | 509 |
| 501 def handle_accept(self): | 510 def handle_accept(self): |
| 502 (sock, addr) = self.accept() | 511 (sock, addr) = self.accept() |
| 503 xmpp_connection = XmppConnection(sock, self._socket_map, self, addr) | 512 xmpp_connection = XmppConnection(sock, self._socket_map, self, addr) |
| 504 self._connections.add(xmpp_connection) | 513 self._connections.add(xmpp_connection) |
| 514 # Return the new XmppConnection for testing. |
| 515 return xmpp_connection |
| 505 | 516 |
| 506 def close(self): | 517 def close(self): |
| 507 # A copy is necessary since calling close on each connection | 518 # A copy is necessary since calling close on each connection |
| 508 # removes it from self._connections. | 519 # removes it from self._connections. |
| 509 for connection in self._connections.copy(): | 520 for connection in self._connections.copy(): |
| 510 connection.close() | 521 connection.close() |
| 511 asyncore.dispatcher.close(self) | 522 asyncore.dispatcher.close(self) |
| 512 | 523 |
| 524 def EnableNotifications(self): |
| 525 self._notifications_enabled = True |
| 526 |
| 527 def DisableNotifications(self): |
| 528 self._notifications_enabled = False |
| 529 |
| 530 def MakeNotification(self, channel, data): |
| 531 """Makes a notification from the given channel and encoded data. |
| 532 |
| 533 Args: |
| 534 channel: The channel on which to send the notification. |
| 535 data: The notification payload. |
| 536 """ |
| 537 notification_stanza = CloneXml(self._NOTIFICATION_STANZA) |
| 538 push_element = notification_stanza.getElementsByTagName('push')[0] |
| 539 push_element.setAttribute('channel', channel) |
| 540 data_element = push_element.getElementsByTagName('data')[0] |
| 541 encoded_data = base64.b64encode(data) |
| 542 data_text = notification_stanza.parentNode.createTextNode(encoded_data) |
| 543 data_element.appendChild(data_text) |
| 544 return notification_stanza |
| 545 |
| 546 def SendNotification(self, channel, data): |
| 547 """Sends a notification to all connections. |
| 548 |
| 549 Args: |
| 550 channel: The channel on which to send the notification. |
| 551 data: The notification payload. |
| 552 """ |
| 553 notification_stanza = self.MakeNotification(channel, data) |
| 554 self.ForwardNotification(None, notification_stanza) |
| 555 notification_stanza.unlink() |
| 556 |
| 513 # XmppConnection delegate methods. | 557 # XmppConnection delegate methods. |
| 514 def OnXmppHandshakeDone(self, xmpp_connection): | 558 def OnXmppHandshakeDone(self, xmpp_connection): |
| 515 self._handshake_done_connections.add(xmpp_connection) | 559 self._handshake_done_connections.add(xmpp_connection) |
| 516 | 560 |
| 517 def OnXmppConnectionClosed(self, xmpp_connection): | 561 def OnXmppConnectionClosed(self, xmpp_connection): |
| 518 self._connections.discard(xmpp_connection) | 562 self._connections.discard(xmpp_connection) |
| 519 self._handshake_done_connections.discard(xmpp_connection) | 563 self._handshake_done_connections.discard(xmpp_connection) |
| 520 | 564 |
| 521 def ForwardNotification(self, unused_xmpp_connection, notification_stanza): | 565 def ForwardNotification(self, unused_xmpp_connection, notification_stanza): |
| 522 for connection in self._handshake_done_connections: | 566 if self._notifications_enabled: |
| 523 print 'Sending notification to %s' % connection | 567 for connection in self._handshake_done_connections: |
| 524 connection.ForwardNotification(notification_stanza) | 568 print 'Sending notification to %s' % connection |
| 569 connection.ForwardNotification(notification_stanza) |
| 570 else: |
| 571 print 'Notifications disabled; dropping notification' |
| OLD | NEW |