Receiving Files

9.2.1. Handling The New Channel

An incoming file transfer channel will be heralded using the same mechanism as other incoming channels (e.g. text channels — see Section 6.2 ― Incoming Channels). The channel type of the new channel will be org.freedesktop.Telepathy.Channel.Type.FileTransfer.

If this particular Connection is being handled by Mission Control, it is important to let only the dispatched Handler handle the channel — see Section 4.1 ― Telepathy Clients for more information.

As well as common channel properties (e.g. InitiatorHandle, InitiatorID, TargetHandle, TargetID, etc.), there will be properties specific to file transfers that contain the metadata for the file, summarised in Table 9-1. The client should display this information to the user when asking whether or not to accept the file.

If the user declines to receive the file, simply closing the channel will cancel the transfer.

9.2.2. Accepting The File

Before calling AcceptFile, the client should first connect the FileTransferStateChanged signal.

AcceptFile takes as its arguments the type of socket we wish to use to transfer the file from the Connection Manager to the client. Different Connection Managers and different OS platforms might support different socket options. The property AvailableSocketTypes lists the supported socket types and their access modes. This property would have been passed in as one of the channel properties to NewChannels.

AcceptFile also takes a requested initial file offset (for continuations, if a partial transfer was deemed to occur) — or use 0 for the whole file. Note that this is a requested offset, and depending on the protocol and sending client, may not be honoured. Clients must check InitialOffset property once the channel is open.

Calling AcceptFile will return the address of a socket opened by the Connection Manager and put the channel into the Accepted state (File_Transfer_State_Accepted). However, you should not attempt to open the socket yourself until the channel enters the Open state (File_Transfer_State_Open).

The socket address returned by AcceptFile and ProvideFile is a socket shared between the client and the Connection Manager. It is not the address of the socket between you and the remote client.

The file itself is transferred by the Connection Manager using the most appropriate mechanism to reach the remote host, be it a peer-to-peer socket, SOCKS5 proxy, using ICE or in-band via the server. A Telepathy client doesn't have to be concerned with the mechanism.

AcceptFile returns a variant type that depends on the type of socket that is being set up. Decoding this type is discussed in Section 9.1 ― Sending Files.

9.2.3. Transferring the File

When FileTransferStateChanged reports the state of Open (File_Transfer_State_Open), you should connect to the socket returned by AcceptFile.

You must check the value of the property InitialOffset to determine what offset to seek to in the target file. You cannot assume that the requested offset will be honoured.

Transferring the file may take some time, so you should not spin in a read loop from the Connection Manager's socket. Instead register the socket's file descriptor with your mainloop implementation to copy data into the target when it arrives.

Sockets, File Descriptors and Mainloops

Most mainloop implementations provide a way to register your own file descriptors into the mainloop's select() call. This allows your program to reenter the mainloop and receive a callback when there is new data to be read from the socket.

With GLib, you can use GIOChannel (g_io_channel_unix_new).

The end of the file transfer will be indicated by the FileTransferStateChanged signal reporting the state Completed (File_Transfer_State_Completed). When this state is reached, the socket, channel and destination file can all be closed. Equally the Cancelled state (File_Transfer_State_Cancelled) state will be emitted when the remote end cancels the transfer.