[Telepathy-commits] [telepathy-python/master] add file-transfer.py to examples
Guillaume Desmottes
guillaume.desmottes at collabora.co.uk
Thu Dec 4 06:00:19 PST 2008
---
examples/file-transfer.py | 207 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 207 insertions(+), 0 deletions(-)
create mode 100644 examples/file-transfer.py
diff --git a/examples/file-transfer.py b/examples/file-transfer.py
new file mode 100644
index 0000000..8d053c3
--- /dev/null
+++ b/examples/file-transfer.py
@@ -0,0 +1,207 @@
+import dbus.glib
+import sys
+import dbus
+import gobject
+import socket
+import os
+import sys
+
+from dbus import PROPERTIES_IFACE
+from telepathy.client import (Connection, Channel)
+from telepathy.interfaces import (CONN_INTERFACE, CONNECTION_INTERFACE_REQUESTS, CHANNEL)
+from telepathy.constants import (CONNECTION_HANDLE_TYPE_CONTACT, CONNECTION_STATUS_CONNECTING, CONNECTION_STATUS_CONNECTED,
+ CONNECTION_STATUS_DISCONNECTED, SOCKET_ADDRESS_TYPE_UNIX, SOCKET_ACCESS_CONTROL_LOCALHOST)
+
+from account import connection_from_file
+
+loop = None
+
+# FIXME: use constants from tp-python
+CHANNEL_TYPE_FILE_TRANSFER = 'org.freedesktop.Telepathy.Channel.Type.FileTransfer.DRAFT'
+
+FT_STATE_NONE = 0
+FT_STATE_NOT_OFFERED = 1
+FT_STATE_ACCEPTED = 2
+FT_STATE_LOCAL_PENDING = 3
+FT_STATE_REMOTE_PENDING = 4
+FT_STATE_OPEN = 5
+FT_STATE_COMPLETED = 6
+FT_STATE_CANCELLED = 7
+
+ft_states = ['none', 'not offered', 'accepted', 'local pending', 'remote pending', 'open', 'completed', 'cancelled']
+
+class FTClient:
+ def __init__(self, account_file):
+ self.conn = connection_from_file(account_file)
+
+ self.conn[CONN_INTERFACE].connect_to_signal('StatusChanged',
+ self.status_changed_cb)
+ # hack
+ self.conn._valid_interfaces.add(CONNECTION_INTERFACE_REQUESTS)
+ self.conn[CONNECTION_INTERFACE_REQUESTS].connect_to_signal('NewChannels',
+ self.new_channels_cb)
+
+ def run(self):
+ self.conn[CONN_INTERFACE].Connect()
+
+ loop = gobject.MainLoop()
+ try:
+ loop.run()
+ finally:
+ try:
+ self.conn[CONN_INTERFACE].Disconnect()
+ except:
+ pass
+
+ def status_changed_cb(self, state, reason):
+ if state == CONNECTION_STATUS_CONNECTING:
+ print 'connecting'
+ elif state == CONNECTION_STATUS_CONNECTED:
+ print 'connected'
+ self.connected_cb()
+ elif state == CONNECTION_STATUS_DISCONNECTED:
+ print 'disconnected'
+ loop.quit()
+
+ def connected_cb(self):
+ self.self_handle = self.conn[CONN_INTERFACE].GetSelfHandle()
+ self.self_id = self.conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT,
+ [self.self_handle])[0]
+ print "I am %s" % self.self_id
+
+ if not self.is_ft_present():
+ print "FileTransfer is not implemented on this ConnectionManager"
+ sys.exit(1)
+
+ def is_ft_present(self):
+ # check if we can request FT channels
+ properties = self.conn[PROPERTIES_IFACE].GetAll(CONNECTION_INTERFACE_REQUESTS)
+ classes = properties['RequestableChannelClasses']
+ for fixed_prop, allowed_prop in classes:
+ if fixed_prop[CHANNEL + '.ChannelType'] == CHANNEL_TYPE_FILE_TRANSFER:
+ return True
+
+ return False
+
+ def new_channels_cb(self, channels):
+ for path, props in channels:
+ if props[CHANNEL + '.ChannelType'] == CHANNEL_TYPE_FILE_TRANSFER:
+ print "new FileTransfer channel"
+ self.ft_channel = Channel(self.conn.service_name, path)
+
+ self.ft_channel[CHANNEL_TYPE_FILE_TRANSFER].connect_to_signal('FileTransferStateChanged',
+ self.ft_state_changed_cb)
+ self.got_ft_channel()
+
+ self.file_name = props[CHANNEL_TYPE_FILE_TRANSFER + '.Filename']
+ self.file_size = props[CHANNEL_TYPE_FILE_TRANSFER + '.Size']
+
+ def ft_state_changed_cb(self, state, reason):
+ print "file transfer is now in state %s" % ft_states[state]
+
+class FTReceiverClient(FTClient):
+ def connected_cb(self):
+ FTClient.connected_cb(self)
+
+ print "waiting for file transfer offer"
+
+ def got_ft_channel(self):
+ print "accept FT"
+ self.sock_addr = self.ft_channel[CHANNEL_TYPE_FILE_TRANSFER].AcceptFile(
+ SOCKET_ADDRESS_TYPE_UNIX, SOCKET_ACCESS_CONTROL_LOCALHOST, "", 0)
+
+ def ft_state_changed_cb(self, state, reason):
+ FTClient.ft_state_changed_cb(self, state, reason)
+
+ if state == FT_STATE_OPEN:
+ # receive file
+ s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ s.connect(self.sock_addr)
+
+ path = self.create_output_path()
+ out = file(path, 'w')
+ read = 0
+ while read < self.file_size:
+ data = s.recv(self.file_size - read)
+ read += len(data)
+ out.write(data)
+
+ print "received file: %s" % path
+
+ def create_output_path(self):
+ for i in range(30):
+ if i == 0:
+ name = self.file_name
+ else:
+ name = "%s.%d" % (self.file_name, i)
+
+ path = os.path.join('/tmp', name)
+ if not os.path.exists(path):
+ return path
+
+class FTSenderClient(FTClient):
+ def __init__(self, account_file, contact, filename):
+ FTClient.__init__(self, account_file)
+
+ self.contact = contact
+ self.file_to_offer = filename
+
+ def connected_cb(self):
+ FTClient.connected_cb(self)
+
+ handle = self.conn.RequestHandles(CONNECTION_HANDLE_TYPE_CONTACT, [self.contact])[0]
+
+ file_name = os.path.basename(self.file_to_offer)
+ info = os.stat(self.file_to_offer)
+ size = info.st_size
+
+ # Request FT channel
+ self.conn[CONNECTION_INTERFACE_REQUESTS].CreateChannel({
+ CHANNEL + '.ChannelType': CHANNEL_TYPE_FILE_TRANSFER,
+ CHANNEL + '.TargetHandleType': CONNECTION_HANDLE_TYPE_CONTACT,
+ CHANNEL + '.TargetHandle': handle,
+ CHANNEL_TYPE_FILE_TRANSFER + '.ContentType': 'application/octet-stream',
+ CHANNEL_TYPE_FILE_TRANSFER + '.Filename': file_name,
+ CHANNEL_TYPE_FILE_TRANSFER + '.Size': size,
+ CHANNEL_TYPE_FILE_TRANSFER + '.Description': "I'm testing file transfer using Telepathy",
+ CHANNEL_TYPE_FILE_TRANSFER + '.InitialOffset': 0})
+
+ def got_ft_channel(self):
+ print "Offer %s to %s" % (self.file_to_offer, self.contact)
+ self.sock_addr = self.ft_channel[CHANNEL_TYPE_FILE_TRANSFER].OfferFile(SOCKET_ADDRESS_TYPE_UNIX,
+ SOCKET_ACCESS_CONTROL_LOCALHOST, "")
+
+ def ft_state_changed_cb(self, state, reason):
+ FTClient.ft_state_changed_cb(self, state, reason)
+
+ if state == FT_STATE_OPEN:
+ # receive file
+ s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ s.connect(self.sock_addr)
+
+ s.send(file(self.file_to_offer).read())
+
+def usage():
+ print "Usage:\n" \
+ "Send [file] to [contact]:\n" \
+ "\tpython %s [account-file] [contact] [file]\n" \
+ "Accept a file transfer from a contact:\n" \
+ "\tpython %s [account-file]\n" \
+ % (sys.argv[0], sys.argv[0])
+
+if __name__ == '__main__':
+ args = sys.argv[1:]
+
+ if len(args) == 3:
+ account_file = args[0]
+ contact = args[1]
+ filename = args[2]
+ client = FTSenderClient(account_file, contact, filename)
+ elif len(args) == 1:
+ account_file = args[0]
+ client = FTReceiverClient(account_file)
+ else:
+ usage()
+ sys.exit(0)
+
+ client.run()
--
1.5.6.5
More information about the Telepathy-commits
mailing list