|
Client - File Transfer
|
Printable Version
|
File transfer
Though not technically a part of the MSN Messenger protocol, a file transfer protocol called "MSNFTP" is included in the official client. This protocol is unrelated to "FTP", or any other file transfer protocol.
Overview
Several very similar terms are used in MSNFTP, which can make it very confusing to read this page. The "sender" and "receiver" is the computer which sends and receives the file, respectively. The "server" and "client" is the computer which initiates and receives the TCP connection, respectively. A messages is "transmitted" (so as not to confuse "sending a message" with "sending the file").
During the invitation stage, the messenger clients will agree on which computer should be the server and which the client, which computer should be sender and which the receiver, what the file to be transferred is called, and an authentication cookie for the session. The sender is usually the server, but may ask the receiver to serve.
Once the client has connected to the server, MSNFTP begins with the two computers exchanging lines of text much like in an NS or SB conversation. In this initial stage, the computers negotiate a protocol, the receiver gives its passport and the authentication cookie, and the sender replies with the size of the file. Then, the sender sends the file in fixed-length blocks of binary data. The receiver can cancel the transfer at any time.
Establishing the connection
During the invitation stage, the computers agreed on either one or two IP addresses and ports the client should connect to. If only one IP address and port was given, the client should connect to that address and port, while the server should listen for connections on the port. If two addresses and ports were given, the server should listen for connections on both ports, while the client should simultaneously attempt to connect to the primary and secondary IP addresses and ports. As soon as one connection has been established, both computers should stop attempting to connect on the other port.
Binary data
This section discusses binary data, how to transmit and receive it. If you're already familiar with binary, you can safely ignore this section.
Ultimately, all computer information is just a series of 1s and 0s. A byte is a series of eight 1s and 0s, so a byte can be in any one of 256 (2^8) different states. In a text-based protocol like MSN Messenger, bytes are interpreted as characters of information according to some standard - usually ASCII. In a binary protocol, bytes are interpreted as something else - numbers between 0 and 255, shades of grey between black and white, reasons for a program crashing, etc.
It's most popular to interpret bytes of data as numbers, often in base 16 ("hexadecimal") instead of base 10 ("decimal"). To make this page easier to read, I'll use decimal, but hexadecimal numbers are used a lot in computing - for example, in plaintext message colour codes. Some programmers like to write things in hexadecimal because (once you get used to it) it's much easier to convert between hexadecimal and binary in your head.
You should consult your language's documentation about how it handles binary data. One important thing to check is that many programming languages (e.g. C and Visual Basic) use the same data type to represent a byte that they use to represent a character, but don't treat bytes and characters the same way - for example, the character '0' is not the same as the number 0. In Visual Basic, for example, you have to do asc(0) to get the ASCII character equivalent to the number 0, and val('0') to get the numerical value of the ASCII character 0.
Protocol - text section
The text section resembles the authentication step of logging into a notification server, except that there are no transaction IDs, and if either side transmits an invalid command, the other side should just close the connection without transmitting an error message.
First, the receiver transmits a VER command with the versions of the MSNFTP protocol it supports as parameters. The official client only supports MSNFTP . The sender replies with a VER command containing the chosen protocol.
Then, the receiver transmits a USR command with the username as the first parameter and authentication cookie as the second. The sender replies with a FIL command with the size of the file in bytes as the only parameter. The official client uses this instead of the size given during the invitation stage.
The receiver transmits a TFR command to indicate that it is ready to receive. At this point, the sender switches to binary for the rest of the session.
At some point after that, the receiver must transmit BYE with a single numeric parameter indicating the result of the file transfer. The following values are allowed:
- 2147942405
- Failure: receiver is out of disk space
- 2164261682
- Failure: receiver cancelled the transfer
- 2164261683
- Failure: sender has cancelled the transfer
- 2164261694
- Failure: connection is blocked
- 16777987
- Success
- 16777989
- Success
As a special case, CCL should be sent with no parameter instead of BYE 2164261682 . In practice, only BYE 16777989 and CCL have ever been observed, and the official client's support for other codes is shabby at best.
Once the sender has finished sending, it should wait for the receiver to transmit a BYE command. If the sender does not receive a BYE quickly enough (within about 1 minute in the official client), it will transmit an invitation command in the switchboard session with "Invitation-Command: CANCEL" and "Cancel-Code: FTTIMEOUT". The sender may close the connection at any time after it has finished sending.
Protocol - binary section
An MSNFTP block consists of a header and a body. The header specifies whether the file has been completely sent, and (if not) the number of bytes that will be sent in the body of this block. The body contains the specified number of bytes from the file.
The header is three bytes long. If the file has not been completely transmitted, the first byte of the header will be 0, and the second two bytes of the header will specify the length of the body - the length is equal to the value of the second byte plus 256 times the value of the third byte. So, for example, if the number of bytes in the body is 2045 (the default length in the official client), the value of second byte would be 253 and the value of the third byte would be 7 (253 + 7*256 = 2045). the specified number of bytes follow in the body. Once the file has been completely transmitted, a final block is sent in which the first byte of the header is 1, the second two bytes are 0, and the body is empty.
For example, if you wanted to transmit a 13-byte long file containing the string "Hello, world!", the steps you might go through are:
- Generate the first block.
- There are 13 bytes left to transmit. Therefore, the value of the header's first byte is 0.
- The file is less than 2045 bytes long, so only one block needs to be sent, for which the length needs to be calculated.
13 bytes divided by 256 is 0, remainder 13. Therefore the value of the header's second byte is 13 and the value of the header's third byte is 0.
- The 13 bytes of the file go in the body of this block.
- The first block reads: 0, 13, 0, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33
- Transmit the first block.
- Check whether the receiver has transmitted a
BYE or CCL message. If so, close the socket.
- Generate the second block.
- There are 0 bytes left to transmit, so this is the last block.
- The second block reads: 1, 0, 0
- Transmit the second block
- The file is now complete.
- Wait up to a minute for the receiver to transmit
BYE or CCL , then close the connection
Example sessions
Here is an example of a successful transfer (note that italics represent binary data):
<o> Incoming Connection on Port: 6891
<<< VER MYPROTO MSNFTP
>>> VER MSNFTP
<<< USR myname@msn.com 93301
>>> FIL 13
<<< TFR
>>> 0, 13, 0, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33
>>> 1, 0, 0
<<< BYE 16777989
And here is a failed negotiation:
<o> Incoming Connection on Port: 6891
<<< VER MYPROTO
<o> Disconnect
File Transfers in older MSN protocol
The file transfer between 3rd party MSN clients and official
Microsoft's MSN client uses MSNP2P protocol for file
transfer. The file transfer takes place through SB
connection established for chat, i.e. there is no separate TCP
connection for file transfer as discribed above in MSNFT protocol. The
typical process can be enumerated in following steps -
- When client wants to transfer file, it sends message to
receiver with
Content-Type set to application/x-msnmsgrp2p
Content-Type is followed by P2P-Dest
header.
- A
P2P-Dest header is followed by 48 bytes
which contains following information in sequence (we are only
interested in Channel SessionID, Offset, Total Data Size, and Message
Size for the purpose of File Transfer).
- Channel SessionID - 4 bytes
- ID - 4 bytes
- Offset - 8 bytes
- Total Data Size - 8 bytes
- Message Size - 4 bytes
- Flags - 4 bytes
- Acknowledgement ID - 4 bytes
- Acknowledgement UID - 4 bytes
- Acknowledgement Size - 8 bytes
- The above 48 bytes header ends with message
INVITE
MSNMSGR <email>@hotmail.com MSNSLP/1.0
- This is followed by few more headers like
To ,
From indicating the sender and receiver of the
file.
- Then there is 2nd
Content-Type header where
type is set to application/x-msnmsgr-sessionreqbody
- Followed by this is a header
EUF-GUID whose
value indicates whether the invitation is for a file transfer or a
buddy icon transfer. In case of file transfer EUF-GUID is
set to {5D3E02AB-6190-11D3-BBBB-00C04F795683}
- Then is
SessionID header. When the actual
file data is transfered, the Channel Session ID of that
message, in the 48 bytes P2P header is set to this SessionID
value. So the current SessionID header is an indication
to receiver that when it receives MSNP2P message with Channel
Session ID set to this, the data section contains file-data. This
typically looks like -
SessionID: 1189641425 \r\n
- The
AppID indicates the type of file transfer
viz, whethere it's buddy icon/image or a file transfer. In case of file
transfer AppID is set to 2 like -
AppID: 2 \r\n
- Then follows the
Context part. Context's
value is base64 encoded 250 bytes string which contains name of file
and filesize etc information.
A typical MSNP2P file transfer invitation message looks as
follows -
>>> MSG 6 D 1348\r\n
MIME-Version: 1.0\r\n
Content-Type: application/x-msnmsgrp2p\r\n
P2P-Dest: some_body@hotmail.com\r\n
\r\n
\000\000\000\000-\037\216#\000\000\000\000\000
\000\000\000\271\004\000\000\000\000\000\000
\262\004\000\000\000\000\000\000.\371\234\020\000\000
\000\000\000\000\000\000\000\000\000\000INVITE MSNMSGR
some_body@hotmail.com MSNSLP/1.0\r\n
To: <msnmsgr:some_body @hotmail.com>\r\n
From: <msnmsgr:this_buddy@hotmail.com>\r\n
Via: MSNSLP/1.0/TLP
;branch={7E873D59-824B-5084-3544-90B83C8D3C40}\r\n
CSeq: 0\r\n
Call-ID: {9C468B3E-4BEA-1C6E-9E6D-1BE9455F8147}\r\n
Max-Forwards: 0\r\n
Content-Type: application/x-msnmsgr-sessionreqbody\r\n
Content-Length: 865\r\n
\r\n
EUF-GUID: {5D3E02AB-6190-11D3-BBBB-00C04F795683}\r\n
SessionID: 1189641425\r\n
Context: PgIAAAIAAAAsAQAAAAAAAAAAAAB0AGUAcwB0ADEAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n
When the file is actually sent, that time sender sets the Channel
SessionID field in 48 bytes MSNP2P header as equal
to the SessionID negotiated above in INVITE
message. i.e. in above example it will be 1189641425
The receiver responds with MSNP2P message indicating
acceptance of invitation, which typically looks like -
<<< MSG some_body@hotmail.com
Somebody 487\r\n
MIME-Version: 1.0\r\n
Content-Type: application/x-msnmsgrp2p\r\n
P2P-Dest: this_buddy@hotmail.com\r\n
\r\n
\000\000\000\000\016\212\235\020\000\000\000\000\000\000\000
\000T\001\000\000\000\000\000\000T\001\000\000\000\000\000\000
\205\360\203%\000\000\000\000\000\000\000\000\000\000\000\000
MSNSLP/1.0 200 OK\r\n
To: <msnmsgr:this_buddy@hotmail.com>\r\n
From: <msnmsgr:some_body@hotmail.com>\r\n
Via: MSNSLP/1.0/TLP
;branch={7E873D59-824B-5084-3544-90B83C8D3C40}\r\n
CSeq: 1\r\n
Call-ID: {9C468B3E-4BEA-1C6E-9E6D-1BE9455F8147}\r\n
Max-Forwards: 0\r\n
Content-Type: application/x-msnmsgr-sessionreqbody\r\n
Content-Length: 26\r\n
\r\n
SessionID: 1189641425\r\n
\r\n
\000\000\000
A typical file transfer message with actual file data inside
it looks like -
>>> MSG 8 D 446\r\n
MIME-Version: 1.0\r\n
Content-Type: application/x-msnmsgrp2p\r\n
P2P-Dest: some_body@hotmail.com\r\n
\r\n
\321|\350F.\037\216#\000\000\000\000\000\000\000\000,\001\000\000\000\000\000\000
\001\000\0000\000\000\0013\302\334\177\000\000\000\000\000\000\000\000\000\000\000\000
This is test msg for MSN FT 0\n
This is test msg for MSN FT 1\n
This is test msg for MSN FT 2\n
This is test msg for MSN FT 3\n
This is test msg for MSN FT 4\n
This is test msg for MSN FT 5\n
This is test msg for MSN FT 6\n
This is test msg for MSN FT 7\n
This is test msg for MSN FT 8\n
This is test msg for MSN FT 9\n
\000\000\000\000
Please note that any MSNP2P message first contains the 48
bytes MSNP2P headers before start of any data. So in above case the
actual file data starts with This is test msg for MSN FT
and
previous to that is the 48 bytes header as mentioned above. When the
file is huge and cannot be transfered in one packet, it is sent
partially through multiple MSNP2P messages. In that case, the Message
Size field indicates the total number of bytes from file in this
message, and Total Data Size field indicates the total size of
file being transfered. So receiver comes to know end of
file transfer by examining these fields from 48 bytes P2P header
(Typically Offset+ Message Size = Total Data Size
indicates that file transfer is complete).
(This section on File Transfer in Older MSN Protocol was
researched and submitted by Medha Atre medhaATgs-labDOTcom).
|