1
# -*- coding: utf-8 -*-
3
# pymsn - a python client library for Msn
5
# Copyright (C) 2007 Ali Sabil <asabil@gmail.com>
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 2 of the License, or
10
# (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, write to the Free Software
19
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
from pymsn.msnp2p.transport.switchboard import *
22
from pymsn.msnp2p.transport.TLP import MessageBlob
28
__all__ = ['P2PTransportManager']
30
logger = logging.getLogger('msnp2p:transport')
33
class P2PTransportManager(gobject.GObject):
35
"blob-received" : (gobject.SIGNAL_RUN_FIRST,
39
"blob-sent" : (gobject.SIGNAL_RUN_FIRST,
44
def __init__(self, client):
45
gobject.GObject.__init__(self)
48
switchboard_manager = self._client._switchboard_manager
49
switchboard_manager.register_handler(SwitchboardP2PTransport, self)
50
self._default_transport = \
51
lambda transport_mgr, peer : \
52
SwitchboardP2PTransport(client, (peer,), transport_mgr)
53
self._transports = set()
54
self._transport_signals = {}
55
self._signaling_blobs = {} # blob_id => blob
56
self._data_blobs = {} # session_id => blob
58
def _register_transport(self, transport):
59
assert transport not in self._transports, "Trying to register transport twice"
60
self._transports.add(transport)
62
signals.append(transport.connect("chunk-received", self._on_chunk_received))
63
signals.append(transport.connect("chunk-sent", self._on_chunk_sent))
64
self._transport_signals[transport] = signals
66
def _unregister_transport(self, transport):
67
self._transports.discard(transport)
68
signals = self._transport_signals[transport]
69
for signal in signals:
70
transport.disconnect(signal)
71
del self._transport_signals[transport]
73
def _get_transport(self, peer):
74
for transport in self._transports:
75
if transport.peer == peer:
77
return self._default_transport(self, peer)
79
def _on_chunk_received(self, transport, chunk):
80
session_id = chunk.header.session_id
81
blob_id = chunk.header.blob_id
83
if session_id == 0: # signaling blob
84
if blob_id in self._signaling_blobs:
85
blob = self._signaling_blobs[blob_id]
87
# create an in-memory blob
88
blob = MessageBlob(chunk.application_id, "",
89
chunk.header.blob_size,
90
session_id, chunk.header.blob_id)
91
self._signaling_blobs[blob_id] = blob
93
if session_id in self._data_blobs:
94
blob = self._data_blobs[session_id]
95
if blob.transferred == 0:
96
blob.id = chunk.header.blob_id
98
# create an in-memory blob
99
blob = MessageBlob(chunk.application_id, "",
100
chunk.header.blob_size,
101
session_id, chunk.header.blob_id)
102
self._data_blobs[session_id] = blob
104
blob.append_chunk(chunk)
105
if blob.is_complete():
107
self.emit("blob-received", blob)
109
del self._signaling_blobs[blob_id]
111
del self._data_blobs[session_id]
113
def _on_chunk_sent(self, transport, chunk):
116
def _on_blob_sent(self, transport, blob):
117
self.emit("blob-sent", blob)
119
def send(self, peer, blob):
120
transport = self._get_transport(peer)
121
transport.send(blob, (self._on_blob_sent, transport, blob))
123
def register_writable_blob(self, blob):
124
if blob.session_id in self._data_blobs:
125
logger.warning("registering already registered blob "\
126
"with session_id=" + str(session_id))
128
self._data_blobs[blob.session_id] = blob
130
gobject.type_register(P2PTransportManager)