MSN P2P data reprinted

Source: Internet
Author: User
Tags emit

Find a reprinted copy of the MSN P2P protocol. Save it. There is another URL that is invalid.

/*
Msnp2p. cpp-MSN P2P protocol

Copyright (c) 2003 by Olivier goffart <ogoffart@tiscalinet.be>

**************************************** *********************************
**
* This program is free software; you can redistribute it and/or modify *
* It under the terms of the GNU General Public License as published *
* The Free Software Foundation; either version 2 of the license, or *
* (At your option) any later version .*
**
**************************************** *********************************
*/

# Include "msnp2p. H"

# Include <stdlib. h>

// QT
# Include <qregexp. h>
# Include <qfile. h>

// KDE
# Include <kdebug. h>
# Include <kmdcodec. h>
# Include <ktempfile. h>
# Include <krun. h>
# Include <klocale. h>
# Include <kglobal. h>
# Include <kdeversion. h>
# Include <kstandarddirs. h>

Msnp2p: msnp2p (qobject * parent, const char * name)
: Qobject (parent, name)
{
M_file = 0l;
M_sfile = 0l;
M_msgidentifier = 0;
M_sessionid = 0;
M_totaldatasize = 0;
M_offset = 0;
}

Msnp2p ::~ Msnp2p ()
{
Delete m_file;
Delete m_sfile;
}

Void msnp2p: slotreadmessage (const qbytearray & MSG)
{
Qstring messageheader = qcstring (msg. Data (), (msg. Find ('\ 0') =-1 )? MSG. Size (): MSG. Find ('\ 0 '));

Qregexp rx ("Content-Type: [A-Za-z0-9 $! */\-] *) ");
Rx. Search (messageheader );
Qstring type = Rx. CAP (1 );

If (type = "application/x-msnmsgrp2p ")
{< br> // get the starting position of the 48-bytes bunary header
unsigned int startbinheader = 0;
bool justcr = false;
while (startbinheader {< br> If (MSG. data () [startbinheader] = '\ R')
startbinheader ++;
If (MSG. data () [startbinheader] = '\ n')
{< br> If (justcr) break;
else justcr = true;
}< br> else justcr = false;
startbinheader ++;
}< br> startbinheader ++;
If (! Justcr | startbinheader + 48> MSG. Size () return; // No binary header, or not long enough, todo: Error Handling

// read some interesting field from the binary header
unsigned int datamessagesize = (INT) (unsigned char) (MSG. data () [startbinheader + 24]) + (INT) (unsigned char) MSG. data () [startbinheader + 25]) * 256;
unsigned int totalsize = (INT) (unsigned char) (MSG. data () [startbinheader + 16]) + (INT) (unsigned char) MSG. data () [startbinheader + 17]) * 256 + (INT) (unsigned char) MSG. data () [startbinheader + 18]) * 256*256 + (INT) (unsigned char) MSG. data () [startbinheader + 19]) * 256*256*256;
unsigned int dataoffset = (INT) (unsigned char) (MSG. data () [startbinheader + 8]) + (INT) (unsigned char) MSG. data () [startbinheader + 9]) * 256 + (INT) (unsigned char) MSG. data () [startbinheader + 10]) * 256*256 + (INT) (unsigned char) MSG. data () [startbinheader + 11]) * 256*256*256;

If (datamessagesize = 0)
{
Kddebug (14140) <"msnp2p: slotreadmessage: I do not care, it's a ack-flag =" <(INT) (unsigned char) (MSG. data () [startbinheader + 28]) <Endl;
Return;
}

If (msg. Size () <startbinheader + 48 + datamessagesize)
{
// The message's size is shorter than the announced size
// Todo error handling
Return;
}

Qstring datamessage = qcstring (msg. Data () + startbinheader + 48), datamessagesize );

If (m_msghandle.isempty ())
{// If these addresses were not previusly set, get it, They shoshould be provided in the first message at last.
Qregexp rx ("to: <msnmsgr :( [^>] *)> ");
If (RX. Search (datamessage )! =-1)
M_myhandle = Rx. CAP (1 );

RX = qregexp ("from: <msnmsgr :( [^>] *)> ");
If (RX. Search (datamessage )! =-1)
M_msghandle = Rx. CAP (1 );
}

// Send the ACK if needed
If (dataoffset + datamessagesize> = totalsize)
Sendp2pack (msg. Data () + startbinheader ));

 

If (m_file) // we are already downloading something to this file
{
M_file-> file ()-> writeblock (msg. Data () + startbinheader + 48), datamessagesize );

If (dataoffset + datamessagesize> = totalsize) // The file is complete
{
M_file-> close ();

/* // Todo: show the file in a better way
# If kde_is_version (3,1, 90)
Krun: runurl (m_file-> name (), "image/PNG", true );
# Else
Krun: runurl (m_file-> name (), "image/PNG ");
# Endif

Delete m_file ;*/
Emit filereceived (m_file, m_obj );
M_file = 0;

// send the bye message
qcstring datamessage = qstring (
"Bye msnmsgr: "+ m_msghandle +" msnslp/1.0 \ r \ n "
" to: \ r \ n "
" from: \ r \ n "
" via: msnslp/1.0/TLP; branch = {A0D624A6-6C0C-4283-A9E0-BC97B4B46D32} \ r \ n "
" CSeq: 0 \ r \ n "
" Call-ID: {"+ m_calrent.upper () + "} \ r \ n"
"Max-forwards: 0 \ r \ n"
"Content-Type: application/X-msnmsgr-sessionclosebody \ r \ n "
" Content-Length: 3 \ r \ n "). utf8 ();
sendp2pmessage (datamessage);

// deletelater ();
}< BR >}< br> else
{< br> kddebug (14141) <"msnp2p: slotreadmessage: datamessage: "

If (msg. Data () [startbinheader + 48] = '\ 0 ')
{// This can be only the data preparaion message. Prepare to download
M_file = new ktempfile (locatelocal ("tmp", "msnpicture-"), ". PNG ");
M_file-> setautodelete (true );
}
Else if (datamessage. Contains ("invite "))
{
// Parse the message to get some info for replying with the 200 OK message
Qregexp rx ("; branch =\{ ([0-9a-f \-] *) \\}\ r \ n ");
Rx. Search (datamessage );
Qstring branch = Rx. CAP (1 );

RX = qregexp ("Call-ID :\{ ([0-9a-f \-] *) \\}\ r \ n ");
Rx. Search (datamessage );
Qstring callid = Rx. CAP (1 );

RX = qregexp ("sessionid: ([0-9] *) \ r \ n ");
Rx. Search (datamessage );
Unsigned long int sessid = Rx. CAP (1). touint ();

RX = qregexp ("appid: ([0-9] *) \ r \ n ");
Rx. Search (datamessage );
Unsigned long int appid = Rx. CAP (1). touint ();

If (appid = 1) // ask for a MSN picture, or emoticon, currently, we always send the display picture
{

Qstring content = "sessionid:" + qstring: Number (sessid );

Qcstring datamessage = qstring (
"Msnslp/1.0 200 OK \ r \ n"
"To: <msnmsgr:" + m_msghandle + "> \ r \ n"
"From: <msnmsgr:" + m_myhandle + "> \ r \ n"
"Via: msnslp/1.0/TLP; branch = {" + branch + "} \ r \ n"
"CSeq: 1 \ r \ n"
"Call-ID: {" + callid + "} \ r \ n"
"Max-forwards: 0 \ r \ n"
"Content-Type: Application/X-msnmsgr-sessionreqbody \ r \ n"
"Content-Length:" + qstring: Number (content. Length () + 5) + "\ r \ n"
"\ R \ n" + content + "\ r \ n"). utf8 (); // \ 0

Sendp2pmessage (datamessage );

// Send the data preparation message
M_sessionid = sessid;
Qbytearray initm (4 );
Initm. Fill ('\ 0 ');
Sendp2pmessage (initm );

// Prepare to send the file
M_sfile = new qfile (locatelocal ("appdata", "msnpicture-" + m_myhandle.lower (). Replace (qregexp ("[./~] "),"-") +". PNG "));
If (! M_sfile-> open (io_readonly) {/* error? */}
M_totaldatasize = m_sfile-> size ();

Qtimer: singleshot (10, this, slot (slotsenddata (); // go for upload
}
Else
{
Qcstring datamessage = qstring (
"Msnslp/1.0 500 internal error \ r \ n"
"To: <msnmsgr:" + m_msghandle + "> \ r \ n"
"From: <msnmsgr:" + m_myhandle + "> \ r \ n"
"Via: msnslp/1.0/TLP; branch = {" + branch + "} \ r \ n"
"CSeq: 1 \ r \ n"
"Call-ID: {" + callid + "} \ r \ n"
"Max-forwards: 0 \ r \ n"
"Content-Type: NULL \ r \ n"
"Content-Length: 0 \ r \ n"). utf8 (); // \ 0
Sendp2pmessage (datamessage );
}
}
Else if (datamessage. Contains ("bye "))
{
// Deletelater ();
}
}
}
Else
{
// Kddebug (14140) <"msnswitchboardsocket: slotreadmessage: unknown type '" <type <Endl;
}

}

 

Void msnp2p: requestdisplaypicture (const qstring & myhandle, const qstring & msghandle, qstring msnobject)
{
// Reset some field
/* M_file = 0l;
M_sfile = 0l;
M_msgidentifier = 0;
M_sessionid = 0;
M_totaldatasize = 0;
M_offset = 0 ;*/
M_sessionid = 0;

M_myhandle = myhandle;
M_msghandle = msghandle;
M_obj = msnobject;

Msnobject = qstring: fromutf8 (kcodecs: base64encode (msnobject. utf8 ()));
Msnobject. Replace ("=", qstring: NULL );

Unsigned long int sessid = rand () % 0xffffff00 + 4;
Qstring branch = qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + "-" + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + "-" + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + "-" + qstring :: number (RAND () % 0 xaaff + 0x1111, 16) + "-" + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + qstring :: number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16 );
M_callid = qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + "-" + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + "-" + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + "-" + qstring :: number (RAND () % 0 xaaff + 0x1111, 16) + "-" + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + qstring: Number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16) + qstring :: number (unsigned long INT) rand () % 0 xaaff + 0x1111, 16 );;

Qstring content = "EUF-GUID: {A4268EEC-FEC5-49E5-95C3-F126696BDBF6} \ r \ n"
"Sessionid:" + qstring: Number (sessid) + "\ r \ n"
"Appid: 1 \ r \ n"
"Context:" + msnobject;

Qcstring datamessage = qstring (
"Invite msnmsgr:" + msghandle + "msnslp/1.0 \ r \ n"
"To: <msnmsgr:" + msghandle + "> \ r \ n"
"From: <msnmsgr:" + myhandle + "> \ r \ n"
"Via: msnslp/1.0/TLP; branch = {" + branch. Upper () + "} \ r \ n"
"CSeq: 0 \ r \ n"
"Call-ID: {" + m_cal0000.upper () + "} \ r \ n"
"Max-forwards: 0 \ r \ n"
"Content-Type: Application/X-msnmsgr-sessionreqbody \ r \ n"
"Content-Length:" + qstring: Number (content. Length () + 5) + "\ r \ n"
"\ R \ n" + content + "\ r \ n"). utf8 (); // \ 0

Sendp2pmessage (datamessage );
}

Void msnp2p: sendp2pmessage (const qbytearray & datamessage)
{
If (m_sessionid = 0)
Kddebugging (14141) <k_funcinfo <qcstring (datamessage. Data (), datamessage. Size () <Endl;

Qcstring messageheader = qstring (
"Mime-version: 1.0 \ r \ n"
"Content-Type: Application/x-msnmsgrp2p \ r \ n"
P2P-Dest: "+ m_msghandle +" \ r \ n "). utf8 ();

Qbytearray binheader (48 );
Binheader. Fill ('\ 0'); // fill with 0 for starting

If (m_msgidentifier = 0)
M_msgidentifier = rand () % 0x0ffffff0 + 4;
Else if (m_offset = 0)
M_msgidentifier ++;

// Sessionid
Binheader [0] = (char) (m_sessionid % 256 );
Binheader [1] = (char) (unsigned long INT) (m_sessionid/256) % 256 );
Binheader [2] = (char) (unsigned long INT) (m_sessionid/(256*256) % 256 );
Binheader [3] = (char) (unsigned long INT) (m_sessionid/(256*256*256) % 256 );

// Messageid
Binheader [4] = (char) (m_msgidentifier % 256 );
Binheader [5] = (char) (unsigned long INT) (m_msgidentifier/256) % 256 );
Binheader [6] = (char) (unsigned long INT) (m_msgidentifier/(256*256) % 256 );
Binheader [7] = (char) (unsigned long INT) (m_msgidentifier/(256*256*256) % 256 );

// Offset
Binheader [8] = (char) (m_offset % 256 );
Binheader [9] = (char) (unsigned long INT) (m_offset/256) % 256 );
Binheader [10] = (char) (unsigned long INT) (m_offset/(256*256) % 256 );
Binheader [11] = (char) (unsigned long INT) (m_offset/(256*256*256) % 256 );

Unsigned int size = datamessage. Size ();

If (m_totaldatasize) // It's a splitted message
{
Binheader [16] = (char) (m_totaldatasize % 256 );
Binheader [17] = (char) (unsigned long INT) (m_totaldatasize/256) % 256 );
Binheader [18] = (char) (unsigned long INT) (m_totaldatasize/(256*256) % 256 );
Binheader [19] = (char) (unsigned long INT) (m_totaldatasize/(256*256*256) % 256 );

// Update offset
M_offset + = size;
If (m_offset> = m_totaldatasize)
{// Message completely sent, reset values
M_offset = 0;
M_totaldatasize = 0;
}
}
Else // not a splitted message, the total size is the current size
{
Binheader [16] = (char) Size: % 256;
Binheader [17] = (INT) size/256;
}

// Message Size
Binheader [24] = (char) size = 256;
Binheader [25] = (INT) size/256;

// Ack sessionid
/* Binheader [32] = (char) (RAND () % 256 );
Binheader [33] = (char) (RAND () % 256 );
Binheader [34] = (char) (RAND () % 256 );
Binheader [35] = (char) (RAND () % 256 );*/

Binheader [32] = 0xde;
Binheader [33] = 0xc7;
Binheader [34] = 0x07;
Binheader [35] = 0x14;

// Merge all in a unique message
Qbytearray data (messageheader. Length () + binheader. Size () + datamessage. Size () + 4 );
For (unsigned int f = 0; F <messageheader. Length (); F ++)
Data [f] = messageheader [f];
For (unsigned int f = 0; F <binheader. Size (); F ++)
Data [messageheader. Length () + F] = binheader [f];
For (unsigned int f = 0; F <datamessage. Size (); F ++)
Data [messageheader. Length () + binheader. Size () + F] = datamessage [f];
For (unsigned int f = 0; F <4; F ++) // footer
Data [messageheader. Length () + binheader. Size () + datamessage. Size () + F] = '\ 0 ';

If (m_sessionid! = 0)
{// Then, the footer ends with \ 1
Data [messageheader. Length () + binheader. Size () + datamessage. Size () + 3] = '\ 1 ';
}

// Send the message
Emit sendcommand ("MSG", "D", true, Data, true );
}

Void msnp2p: sendp2pack (const char * originalheader)
{

Qcstring messageheader = qstring (
"Mime-version: 1.0 \ r \ n"
"Content-Type: Application/x-msnmsgrp2p \ r \ n"
P2P-Dest: "+ m_msghandle +" \ r \ n "). utf8 ();

Qbytearray binheader (48 );
Binheader. Fill ('\ 0'); // fill with 0 for starting

// Sessionid
Binheader [0] = originalheader [0];
Binheader [1] = originalheader [1];
Binheader [2] = originalheader [2];
Binheader [3] = originalheader [3];

// Messageid
Bool a = false;
If (m_msgidentifier = 0)
{
M_msgidentifier = rand () % 0xfffffe00 + 10;
A = true;
}
Else
M_msgidentifier ++;
Binheader [4] = (char) (m_msgidentifier % 256 );
Binheader [5] = (char) (unsigned long INT) (m_msgidentifier/256) % 256 );
Binheader [6] = (char) (unsigned long INT) (m_msgidentifier/(256*256) % 256 );
Binheader [7] = (char) (unsigned long INT) (m_msgidentifier/(256*256*256) % 256 );

If ()
M_msgidentifier-= 4;

// Total size
Binheader [16] = originalheader [16];
Binheader [17] = originalheader [17];
Binheader [18] = originalheader [18];
Binheader [19] = originalheader [19];
Binheader [20] = originalheader [20];
Binheader [21] = originalheader [21];
Binheader [22] = originalheader [22];
Binheader [23] = originalheader [23];

// Flag
Binheader [28] = (char) 0x02;

// Ack sessionid
Binheader [32] = originalheader [4];
Binheader [33] = originalheader [5];
Binheader [34] = originalheader [6];
Binheader [35] = originalheader [7];

// Ack unique ID
Binheader [36] = originalheader [32];
Binheader [37] = originalheader [33];
Binheader [38] = originalheader [34];
Binheader [39] = originalheader [35];

// Ack data size
Binheader [40] = originalheader [16];
Binheader [41] = originalheader [17];
Binheader [42] = originalheader [18];
Binheader [43] = originalheader [19];
Binheader [44] = originalheader [20];
Binheader [45] = originalheader [21];
Binheader [46] = originalheader [22];
Binheader [47] = originalheader [23];

Qbytearray data (messageheader. Length () + binheader. Size () + 4 );
For (unsigned int f = 0; F <messageheader. Length (); F ++)
Data [f] = messageheader [f];
For (unsigned int f = 0; F <binheader. Size (); F ++) // If binheader is a qcstring, it ends with \ 0, which is OK
Data [messageheader. Length () + F] = binheader [f];
For (unsigned int f = 0; F <4; F ++)
Data [messageheader. Length () + binheader. Size () + F] = '\ 0 ';

Emit sendcommand ("MSG", "D", true, Data, true );
}

Void msnp2p: slotsenddata ()
{
If (! M_sfile)
Return;

Char data [1200];
Int bytesread = m_sfile-& gt; readblock (data, 1200 );

Qbytearray databa (bytesread );
For (INT f = 0; F <bytesread; F ++)
Databa [f] = data [f];

// Kddebug (14140) <"msnp2p: slotsenddata: offset = "<m_offset <" size = "<bytesread <" totalsize = "<m_totaldatasize <" sent = "<m_offset + bytesread <Endl;

Sendp2pmessage (databa );

If (m_totaldatasize = 0) // This has been reseted bacause the file is completely send
{
// Kddebug (14140) <"msnp2p: slotsenddata: Finished! Wait for the bye message "<Endl;
Delete m_sfile;
M_sfile = 0l;
M_sessionid = 0;
}
Else
Qtimer: singleshot (10, this, slot (slotsenddata ()));
}

 

# Include "msnp2p. MOC"

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.