1
::snit::type P2PMessage {
16
#TODO: remove me when object is destroyed in the right place
17
after 30000 $self destroy
20
#creates a P2PMessage object from a normal Message object
21
method createFromMessage { message } {
22
# array set headers [$message getHeaders]
23
# set data [$message getBody]
24
# set idx [string first "\r\n\r\n" $data]
25
# set head [string range $data 0 [expr $idx -1]]
26
## set body [string range $data [expr $idx +4] end]
27
set body [$message getBody]
28
# set head [string map {"\r" ""} $head]
29
# set heads [split $head "\n"]
30
# foreach header $heads {
31
# set idx [string first ": " $header]
32
# array set headers [list [string range $header 0 [expr $idx -1]] \
33
# [string range $header [expr $idx +2] end]]
35
binary scan [string range $body 0 48] iiiiiiiiiiii cSid cId cOffset1 cOffset2 cTotalDataSize1 cTotalDataSize2 cMsgSize cFlags cAckId cAckUID cAckSize1 cAckSize2
36
set body [string range $body 48 end]
37
set options(-sessionid) $cSid
38
set options(-identifier) $cId
39
set options(-offset) [int2word $cOffset1 $cOffset2]
40
set options(-totalsize) [int2word $cTotalDataSize1 $cTotalDataSize2]
41
set options(-datalength) $cMsgSize
42
set options(-flag) $cFlags
43
set options(-ackid) $cAckId
44
set options(-ackuid) $cAckUID
45
set options(-acksize) [int2word $cAckSize1 $cAckSize2]
48
method toString { {humanReadable 0} } {
50
foreach { header info } [array get headers] {
51
set str "$str$header: $info\r\n"
53
set str "$str\r\n\r\n"
54
if { $humanReadable } {
55
set str "${str}sessionid: $options(-sessionid)\n"
56
set str "${str}identifier: $options(-identifier)\n"
57
set str "${str}offset: $options(-offset)\n"
58
set str "${str}totalsize: $options(-totalsize)\n"
59
set str "${str}datalength: $options(-datalength)\n"
60
set str "${str}flag: $options(-flag)\n"
61
set str "${str}ackid: $options(-ackid)\n"
62
set str "${str}ackuid: $options(-ackuid)\n"
63
set str "${str}acksize: $options(-acksize)\n"
72
# proc ReadData { message chatid } {
73
# variable chunkedData
74
# # Get values from the header
75
## set idx [expr [string first "\r\n\r\n" $data] + 4]
76
## set headend [expr $idx + 48]
77
# set data [$message getBody]
79
# binary scan [string range $data 0 48] iiiiiiiiiiii cSid cId cOffset1 cOffset2 cTotalDataSize1 cTotalDataSize2 cMsgSize cFlags cAckId cAckUID cAckSize1 cAckSize2
81
# set cOffset [int2word $cOffset1 $cOffset2]
82
# set cTotalDataSize [int2word $cTotalDataSize1 $cTotalDataSize2]
83
# set cAckSize [int2word $cAckSize1 $cAckSize2]
85
# #status_log "Read header : $cSid $cId $cOffset $cTotalDataSize $cMsgSize $cFlags $cAckId $cAckUID $cAckSize\n" red
86
# #status_log "Sid : $cSid -> " red
88
# if {$cSid == "0" && $cMsgSize != "0" && $cMsgSize != $cTotalDataSize } {
90
# if { ![info exists chunkedData($cId)] } {
91
# set chunkedData($cId) "[string range $data 48 end-4]"
93
# set chunkedData($cId) "$chunkedData($cId)[string range $data 48 end-4]"
95
# #status_log "Data is now : $chunkedData($cId)\n\n";
97
# if { $cTotalDataSize != [string length $chunkedData($cId)] } {
100
# set data $chunkedData($cId)
102
# set cMsgSize $cTotalDataSize
119
method getHeader { name } {
120
return [lindex [array get headers $name] 1]
124
namespace eval ::MSNP2P {
125
namespace export loadUserPic SessionList ReadData MakePacket MakeACK MakeSLP
128
#Get picture from $user, if cached, or sets image as "loading", and request it
130
proc loadUserPic { chatid user {reload "0"} } {
131
if { [::config::getKey getdisppic] != 1 } {
132
status_log "Display Pics disabled, exiting loadUserPic\n" red
136
#status_log "::MSNP2P::GetUser: Checking if picture for user $user exists\n" blue
138
set msnobj [::abook::getVolatileData $user msnobj]
140
#status_log "::MSNP2P::GetUser: MSNOBJ is $msnobj\n" blue
142
#set filename [::MSNP2P::GetFilenameFromMSNOBJ $msnobj]
143
set filename [::abook::getContactData $user displaypicfile ""]
144
status_log "::MSNP2P::GetUser: filename is $filename\n" white
146
if { $filename == "" } {
151
#Reload 1 means that we force aMSN to reload a new display pic
152
#Destroy it before to avoid TkCxImage to redraw animated gif above the good display pic
153
destroy user_pic_$user
154
if { ![file readable "[file join $HOME displaypic cache ${filename}].png"] || $reload == "1" } {
155
status_log "::MSNP2P::GetUser: FILE [file join $HOME displaypic cache ${filename}] doesn't exist!!\n" white
156
image create photo user_pic_$user -file [::skin::GetSkinFile "displaypic" "loading.gif"] -format cximage
158
create_dir [file join $HOME displaypic]
159
create_dir [file join $HOME displaypic cache]
160
::MSNP2P::RequestObject $chatid $user $msnobj
162
catch {image create photo user_pic_$user -file "[file join $HOME displaypic cache ${filename}].png" -format cximage}
167
proc loadUserSmiley { chatid user msnobj } {
169
set filename [::MSNP2P::GetFilenameFromMSNOBJ $msnobj]
171
status_log "Got filename $filename for $chatid with $user and $msnobj\n" red
173
if { $filename == "" } {
177
image create photo custom_smiley_$filename -width 19 -height 19
179
status_log "::MSNP2P::GetUserPic: filename is $filename\n" white
183
if { [catch {image create photo custom_smiley_$filename -file "[file join $HOME smileys cache ${filename}].png" -format cximage}] } {
184
#We didn't manage to load the smiley (either we haven't it either it's bad) so we ask it
185
status_log "::MSNP2P::GetUser: FILE [file join $HOME smileys cache ${filename}] doesn't exist!!\n" white
186
image create photo custom_smiley_$filename -width 19 -height 19
188
create_dir [file join $HOME smileys]
189
create_dir [file join $HOME smileys cache]
190
::MSNP2P::RequestObject $chatid $user $msnobj
195
proc GetFilenameFromMSNOBJ { msnobj } {
196
set sha1d [split $msnobj " "]
197
set idx [lsearch $sha1d "SHA1D=*"]
198
set sha1d [lindex $sha1d $idx]
199
set sha1d [string range $sha1d 7 end-1]
200
if { $sha1d == "" } {
203
#return [::md5::md5 $sha1d]
204
binary scan $sha1d h* filename
208
proc GetFilenameFromContext { context } {
211
set old_msnobj [::base64::decode $context]
212
set msnobj [string range $old_msnobj [string first "<" $old_msnobj] [expr [string first "/>" $old_msnobj] + 1]]
214
status_log "GetFilenameFromContext : $context == $old_msnobj == $msnobj\n[string first "<" $old_msnobj] - [string first "/>" $old_msnobj]\n\n" red
215
if { [info exists msnobjcontext($msnobj)] } {
216
status_log "Found filename\n" red
217
return $msnobjcontext($msnobj)
219
status_log "Couln't find filename for context \n$context\n = $msnobj --- [array get msnobjcontext] --[info exists msnobjcontext($msnobj)] \n" red
226
#//////////////////////////////////////////////////////////////////////////////
227
# SessionList (action sid [varlist])
228
# Data Structure for MSNP2P Sessions, contains :
229
# 0 - Message Identifier (msgid)
230
# 1 - TotalDataSize (totalsize) This variable is only used if sending data in split packets
231
# 2 - Offset (offset)
232
# 3 - Destination (dest)
233
# 4 - Step to run after ack (AferAck) For now can be DATAPREP, SENDDATA
234
# 5 - CallID (MSNSLP) (callid)
235
# 6 - File Descriptor (fd)
236
# 7 - Session Type (type) bicon, emoticon, filetransfer
237
# 8 - Filename for transfer (Filename)
238
# 9 - branchid (branchid)
241
# get : This method returns a list with all the array info, 0 if non existent
242
# set : This method sets the variables for the given sessionid, takes a list as argument.
243
# unset : This method removes the given sessionid variables
244
# findid : This method searches all Sessions for one that has the given Identifier, returns session ID or -1 if not found
245
# findcallid : This method searches all Sessions for one that has the given Call-ID, returns session ID or -1 if not found
246
proc SessionList { action sid { varlist "" } } {
250
set ret [getObjOption $sid MsgId]
251
#status_log "getting $sid : [getObjOption $sid MsgId] - $ret" green
254
# Session found, return values
255
lappend ret [getObjOption $sid TotalSize]
256
lappend ret [getObjOption $sid Offset]
257
lappend ret [getObjOption $sid Destination]
258
lappend ret [getObjOption $sid AfterAck]
259
lappend ret [getObjOption $sid CallId]
260
lappend ret [getObjOption $sid Fd]
261
lappend ret [getObjOption $sid Type]
262
lappend ret [getObjOption $sid Filename]
263
lappend ret [getObjOption $sid branchid]
265
#status_log "returning $ret" green
268
#status_log "Not found" green
269
# Session not found, return 0
275
#status_log "setting $sid with $varlist" green
276
# This overwrites previous vars if they are set to something else than -1
277
if { [lindex $varlist 0] != -1 } {
278
setObjOption $sid MsgId [lindex $varlist 0]
279
setObjOption [lindex $varlist 0] sid $sid
281
if { [lindex $varlist 1] != -1 } {
282
setObjOption $sid TotalSize [lindex $varlist 1]
284
if { [lindex $varlist 2] != -1 } {
285
setObjOption $sid Offset [lindex $varlist 2]
287
if { [lindex $varlist 3] != -1 } {
288
setObjOption $sid Destination [lindex $varlist 3]
290
if { [lindex $varlist 4] != -1 } {
291
setObjOption $sid AfterAck [lindex $varlist 4]
293
if { [lindex $varlist 5] != -1 } {
294
setObjOption $sid CallId [lindex $varlist 5]
295
setObjOption [lindex $varlist 5] sid $sid
297
if { [lindex $varlist 6] != -1 } {
298
setObjOption $sid Fd [lindex $varlist 6]
300
if { [lindex $varlist 7] != -1 } {
301
setObjOption $sid Type [lindex $varlist 7]
303
if { [lindex $varlist 8] != -1 } {
304
setObjOption $sid Filename [lindex $varlist 8]
306
if { [lindex $varlist 9] != -1 } {
307
setObjOption $sid branchid [lindex $varlist 9]
312
#status_log "unsetting..." green
317
#status_log "Finding $action of $sid, found : [getObjOption $sid sid]" green
318
if { [getObjOption $sid sid] != "" } {
319
return [getObjOption $sid sid]
326
#//////////////////////////////////////////////////////////////////////////////
327
# ReadData ( data chatid )
328
# This is the handler for all received MSNP2P packets
329
# data is the MSNP2P packet
330
# chatid will be used to get the SB ?? Ack alvaro if it's better to use chatid or some way to use the dest email
331
# For now only manages buddy and emoticon transfer
332
# TODO : Error checking on fields (to, from, sizes, etc)
333
proc ReadData { message chatid } {
337
# set message [P2PMessage create %AUTO%]
338
# $message createFromMessage $msg
340
#status_log "called ReadData with $data\n" red
342
# Get values from the header
343
# set idx [expr [string first "\r\n\r\n" $data] + 4]
344
# set headend [expr $idx + 48]
345
# set data [$message getBody]
347
# binary scan [string range $data 0 48] iiiiiiiiiiii cSid cId cOffset1 cOffset2 cTotalDataSize1 cTotalDataSize2 cMsgSize cFlags cAckId cAckUID cAckSize1 cAckSize2
349
# set cOffset [int2word $cOffset1 $cOffset2]
350
# set cTotalDataSize [int2word $cTotalDataSize1 $cTotalDataSize2]
351
# set cAckSize [int2word $cAckSize1 $cAckSize2]
353
#status_log "Read header : $cSid $cId $cOffset $cTotalDataSize $cMsgSize $cFlags $cAckId $cAckUID $cAckSize\n" red
354
#status_log "Sid : $cSid -> " red
356
set cSid [$message cget -sessionid]
357
set cId [$message cget -identifier]
358
set cOffset [$message cget -offset]
359
set cTotalDataSize [$message cget -totalsize]
360
set cMsgSize [$message cget -datalength]
361
set cFlags [$message cget -flag]
362
set cAckId [$message cget -ackid]
363
set cAckUID [$message cget -ackuid]
364
set cAckSize [$message cget -acksize]
365
set data [$message getBody]
367
if {$cSid == "0" && $cMsgSize != "0" && $cMsgSize != $cTotalDataSize } {
369
if { ![info exists chunkedData($cId)] } {
370
set chunkedData($cId) "[string range $data 0 [expr { $cMsgSize - 1}]]"
372
set chunkedData($cId) "$chunkedData($cId)[string range $data 0 [expr { $cMsgSize - 1}]]"
374
# status_log "Data is now : $chunkedData($cId)\n\n";
375
status_log "chunked data : $cTotalDataSize - $cMsgSize - $cOffset - [string length $chunkedData($cId)]"
377
if { $cTotalDataSize != [expr $cMsgSize + $cOffset] } {
378
# status_log "not enough data to complete chunk...$cTotalDataSize - $cOffset - $cMsgSize - [string length $chunkedData($cId)]"
381
#status_log "data completed... $cTotalDataSize - $cOffset - [string length $chunkedData($cId)]"
382
set data $chunkedData($cId)
384
set cMsgSize $cTotalDataSize
389
if { [lindex [SessionList get $cSid] 7] == "ignore" } {
390
status_log "MSNP2P | $cSid -> Ignoring packet! not for us!\n"
395
# Check if this is an ACK Message
396
# TODO : Actually check if the ACK is good ? check size and all that crap...
397
if { $cMsgSize == 0 } {
399
# Let us check if any of our sessions is waiting for an ACK
400
set sid [SessionList findid $cAckId]
401
status_log "GOT SID : $sid for Ackid : $cAckId\n"
403
#status_log "MSNP2P | $sid -> Got MSNP2P ACK " red
405
# We found a session id that is waiting for an ACK
406
set step [lindex [SessionList get $sid] 4]
408
# Just these 2 for now, will probably need more with file transfers
411
# Set the right variables, prepare to send data after next ack
412
SessionList set $sid [list -1 4 0 -1 "SENDDATA" -1 -1 -1 -1 -1]
414
# We need to send a data preparation message
415
SendPacket [::MSN::SBFor $chatid] [MakePacket $sid [binary format i 0]]
416
status_log "MSNP2P | $sid -> Sent DATA Preparation\n" red
419
#status_log "MSNP2P | $sid -> Sending DATA now\n" red
420
set file [lindex [SessionList get $sid] 8]
422
SendData $sid $chatid "[lindex [SessionList get $sid] 8]"
424
SendData $sid $chatid "[::skin::GetSkinFile displaypic [::config::getKey displaypic]]"
428
SessionList set $sid [list -1 -1 0 -1 0 -1 -1 -1 -1 -1]
429
#status_log "MSNP2P | $sid -> Got ACK for sending data, now sending BYE\n" red
430
set branchid "[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]"
431
SendPacket [::MSN::SBFor $chatid] [MakePacket $sid [MakeMSNSLP "BYE" [lindex [SessionList get $sid] 3] [::config::getKey login] "$branchid" "0" [lindex [SessionList get $sid] 5] 0 0] 1]
437
#status_log "ReadData : data : $data"
438
# Check if this is an INVITE message
439
if { [string first "INVITE MSNMSGR" $data] != -1 } {
440
#status_log "Got an invitation!\n" red
442
# Let's get the session ID, destination email, branchUID, UID, AppID, Cseq
443
set idx [expr [string first "SessionID:" $data] + 11]
444
set idx2 [expr [string first "\r\n" $data $idx] - 1]
445
set sid [string range $data $idx $idx2]
447
set idx [expr [string first "From: <msnmsgr:" $data] + 15]
448
set idx2 [expr [string first "\r\n" $data $idx] - 2]
449
set dest [string range $data $idx $idx2]
451
set idx [expr [string first "branch=\{" $data] + 8]
452
set idx2 [expr [string first "\}" $data $idx] - 1]
453
set branchuid [string range $data $idx $idx2]
455
set idx [expr [string first "Call-ID: \{" $data] + 10]
456
set idx2 [expr [string first "\}" $data $idx] - 1]
457
set uid [string range $data $idx $idx2]
459
set idx [expr [string first "CSeq:" $data] + 6]
460
set idx2 [expr [string first "\r\n" $data $idx] - 1]
461
set cseq [string range $data $idx $idx2]
463
set idx [expr [string first "Content-Type: " $data $idx] + 14]
464
set idx2 [expr [string first "\r\n" $data $idx] - 1]
465
set ctype [string range $data $idx $idx2]
467
status_log "Got INVITE with content-type : $ctype\n" red
469
if { $ctype == "application/x-msnmsgr-transreqbody"} {
471
set sid [SessionList findcallid $uid]
472
set type [lindex [SessionList get $sid] 7]
474
#this catches an error with MSN7, still need to find out why sid = -1
475
if {$sid == -1} {return}
476
set idx [expr [string first "Conn-Type: " $data] + 11]
477
set idx2 [expr [string first "\r\n" $data $idx] - 1]
478
set conntype [string range $data $idx $idx2]
480
set idx [expr [string first "UPnPNat: " $data] + 9]
481
set idx2 [expr [string first "\r\n" $data $idx] - 1]
482
set upnp [string range $data $idx $idx2]
485
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
487
if { $type == "filetransfer" } {
488
# We received an invite for a FT, send 200 OK
489
::MSN6FT::answerFTInvite $sid $chatid $branchuid $conntype
490
} elseif { $type == "webcam" } {
491
::MSNCAM::answerCamInvite $sid $chatid $branchuid
494
} elseif { $ctype == "application/x-msnmsgr-sessionreqbody" } {
496
# Let's check if it's an invitation for buddy icon or emoticon
497
set idx [expr [string first "EUF-GUID:" $data] + 11]
498
set idx2 [expr [string first "\}" $data $idx] - 1]
499
set eufguid [string range $data $idx $idx2]
501
set idx [expr [string first "Context:" $data] + 9]
502
set idx2 [expr [string first "\r\n" $data $idx] - 1]
503
set context [string range $data $idx $idx2]
506
if { $eufguid == "A4268EEC-FEC5-49E5-95C3-F126696BDBF6" ||
507
$eufguid == "5D3E02AB-6190-11D3-BBBB-00C04F795683" ||
508
$eufguid == "E073B06B-636E-45B7-ACA4-6D4B5978C93C" ||
509
$eufguid == "4BD96FC0-AB17-4425-A14A-439185962DC8" ||
510
$eufguid == "1C9AA97E-9C05-4583-A3BD-908A196F1E92"} {
511
status_log "MSNP2P | $sid $dest -> Got INVITE for buddy icon, emoticon, or file transfer, or Wink(MSN 7)\n" red
512
# Make new data structure for this session id
513
if { $eufguid == "A4268EEC-FEC5-49E5-95C3-F126696BDBF6" } {
514
# Buddyicon or emoticon
515
if { [GetFilenameFromContext $context] != "" } {
516
SessionList set $sid [list 0 0 0 $dest 0 $uid 0 "bicon" [GetFilenameFromContext $context] ""]
518
status_log "MSNP2P | $sid -> This is not an invitation for us, don't reply.\n" red
519
# Now we tell this procedure to ignore all packets with this sid
520
SessionList set $sid [list 0 0 0 0 0 0 0 "ignore" 0 ""]
523
} elseif { $eufguid == "5D3E02AB-6190-11D3-BBBB-00C04F795683" } {
525
#check if a conversation is open with that contact
526
#no need to test either a chatwindow has been created or not, because MakeFor is going to do it !
527
::ChatWindow::MakeFor $chatid
528
SessionList set $sid [list 0 0 0 $dest 0 $uid 0 "filetransfer" "" "$branchuid"]
530
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
531
status_log "MSNP2P | $sid $dest -> Sent ACK for INVITE\n" red
533
# Let's get filename and filesize from context
534
set idx [expr [string first "Context:" $data] + 9]
535
set context [base64::decode [string range $data $idx end]]
536
::MSN6FT::GotFileTransferRequest $chatid $dest $branchuid $cseq $uid $sid $context
539
} elseif { $eufguid =="E073B06B-636E-45B7-ACA4-6D4B5978C93C"} {
541
status_log "####WINKS RECEIVED####\n" blue
542
set decoding [base64::decode $context]
543
status_log "$decoding\n" blue
544
status_log "######################\n" blue
546
# Let's notify the user that he/she has received a Wink
547
SendMessageFIFO [list ::amsn::WinWrite $chatid "\n [trans winkreceived [::abook::getDisplayNick $chatid]]\n" black "" 0] "::amsn::messages_stack($chatid)" "::amsn::messages_flushing($chatid)"
548
} elseif { $eufguid == "4BD96FC0-AB17-4425-A14A-439185962DC8" ||
549
$eufguid == "1C9AA97E-9C05-4583-A3BD-908A196F1E92" } {
550
#check if a conversation is open with that contact
551
#no need to test either a chatwindow has been created or not, because MakeFor is going to do it !
552
::ChatWindow::MakeFor $chatid
553
if { $eufguid == "4BD96FC0-AB17-4425-A14A-439185962DC8" } {
559
status_log "we got an webcam invitation" red
561
set context [base64::decode $context]
562
set context [FromUnicode $context]
564
#answerFtInvite $sid $chatid $branchuid $conntype
566
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
568
SessionList set $sid [list 0 0 0 $dest 0 $uid 0 "webcam" "" "$branchuid"]
570
if { $context != "\{B8BE70DE-E2CA-4400-AE03-88FF85B9F4E8\}" } {
571
status_log "Received a video conferenced invitation.. we do not support this"
572
::CAMGUI::InvitationRejected $chatid $sid $branchuid $uid
573
#::MSNCAM::RejectFT $chatid $sid $branchuid $uid
574
::CAMGUI::GotVideoConferenceInvitation $chatid
580
::CAMGUI::AcceptOrRefuse $chatid $dest $branchuid $cseq $uid $sid $producer
582
status_log "MSNP2P | $sid $dest -> Sent ACK for INVITE\n" red
587
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
588
status_log "MSNP2P | $sid $dest -> Sent ACK for INVITE\n" red
590
# Let's make and send a 200 OK Message
591
set slpdata [MakeMSNSLP "OK" $dest [::config::getKey login] $branchuid [expr $cseq + 1] $uid 0 0 $sid]
592
SendPacket [::MSN::SBFor $chatid] [MakePacket $sid $slpdata 1]
593
status_log "MSNP2P | $sid $dest -> Sent 200 OK Message\n" red
595
# Send Data Prep AFTER ACK received (set AfterAck)
596
SessionList set $sid [list -1 -1 -1 -1 "DATAPREP" -1 -1 -1 -1 -1]
600
} elseif { $ctype == "application/x-msnmsgr-transrespbody" } {
602
set idx [expr [string first "Call-ID: \{" $data] + 10]
603
set idx2 [expr [string first "\}" $data $idx] -1]
604
set uid [string range $data $idx $idx2]
605
set sid [SessionList findcallid $uid]
606
set idx [expr [string first "Listening: " $data] + 11]
607
set idx2 [expr [string first "\r\n" $data $idx] -1]
608
set listening [string range $data $idx $idx2]
610
#status_log "MSNP2P | $sid -> Got 200 OK for File transfer, parsing result\n"
611
#status_log "MSNP2P | $sid -> Found uid = $uid , lestening = $listening\n"
614
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
615
set type [lindex [SessionList get $sid] 7]
617
if { $listening == "true" } {
618
set idx [expr [string first "Nonce: \{" $data] + 8]
619
set idx2 [expr [string first "\r\n" $data $idx] -2]
620
set nonce [string range $data $idx $idx2]
622
if {[string first "IPv4External-Addrs: " $data] != -1 } {
623
set idx [expr [string first "IPv4External-Addrs: " $data] + 20]
624
set idx2 [expr [string first "\r\n" $data $idx] -1]
625
set addr [string range $data $idx $idx2]
627
set idx [expr [string first "IPv4External-Port: " $data] + 19]
628
set idx2 [expr [string first "\r\n" $data $idx] -1]
629
set port [string range $data $idx $idx2]
631
set idx [expr [string first "IPv4Internal-Addrs: " $data] + 20]
632
set idx2 [expr [string first "\r\n" $data $idx] -1]
633
set addr [string range $data $idx $idx2]
635
set idx [expr [string first "IPv4Internal-Port: " $data] + 19]
636
set idx2 [expr [string first "\r\n" $data $idx] -1]
637
set port [string range $data $idx $idx2]
640
status_log "MSNP2P | $sid -> Receiver is listening with $addr : $port\n" red
642
#after 5500 "::MSNP2P::SendData $sid $chatid [lindex [SessionList get $sid] 8]"
643
if {$type == "filetransfer" } {
644
::MSN6FT::ConnectSockets $sid $nonce $addr $port 0
645
} elseif { $type == "webcam" } {
646
::MSNCAM::connectMsnCam2 $sid $nonce $addr $port 0
652
# Check if it is a 200 OK message
653
if { [string first "MSNSLP/1.0 200 OK" $data] != -1 } {
655
set first [string first "SessionID:" $data]
656
if { $first != -1 } {
657
set idx [expr [string first "SessionID:" $data] + 11]
658
set idx2 [expr [string first "\r\n" $data $idx] -1]
659
set sid [string range $data $idx $idx2]
660
set type [lindex [SessionList get $sid] 7]
662
if { $type == "ignore" } {
663
#status_log "MSNP2P | $sid -> Ignoring packet! not for us!\n"
667
#status_log "MSNP2P | $sid -> Got 200 OK message, sending an ACK for it\n" red
668
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
669
if { $type == "filetransfer" } {
670
::MSN6FT::SendFTInvite $sid $chatid
673
set idx [expr [string first "Call-ID: \{" $data] + 10]
674
set idx2 [expr [string first "\}" $data $idx] -1]
675
set uid [string range $data $idx $idx2]
676
set sid [SessionList findcallid $uid]
677
set idx [expr [string first "Listening: " $data] + 11]
678
set idx2 [expr [string first "\r\n" $data $idx] -1]
679
set listening [string range $data $idx $idx2]
681
#status_log "MSNP2P | $sid -> Got 200 OK for File transfer, parsing result\n"
682
#status_log "MSNP2P | $sid -> Found uid = $uid , lestening = $listening\n"
685
set type [lindex [SessionList get $sid] 7]
688
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
690
if { $listening == "true" } {
691
set idx [expr [string first "Nonce: \{" $data] + 8]
692
set idx2 [expr [string first "\r\n" $data $idx] -2]
693
set nonce [string range $data $idx $idx2]
695
if {[string first "IPv4External-Addrs: " $data] != -1 } {
696
set idx [expr [string first "IPv4External-Addrs: " $data] + 20]
697
set idx2 [expr [string first "\r\n" $data $idx] -1]
698
set addr [string range $data $idx $idx2]
700
set idx [expr [string first "IPv4External-Port: " $data] + 19]
701
set idx2 [expr [string first "\r\n" $data $idx] -1]
702
set port [string range $data $idx $idx2]
704
set idx [expr [string first "IPv4Internal-Addrs: " $data] + 20]
705
set idx2 [expr [string first "\r\n" $data $idx] -1]
706
set addr [string range $data $idx $idx2]
708
set idx [expr [string first "IPv4Internal-Port: " $data] + 19]
709
set idx2 [expr [string first "\r\n" $data $idx] -1]
710
set port [string range $data $idx $idx2]
712
status_log "MSNP2P | $sid -> Receiver is listening with $addr : $port\n" red
713
#after 5500 "::MSNP2P::SendData $sid $chatid [lindex [SessionList get $sid] 8]"
714
if { $type == "filetransfer" } {
715
::MSN6FT::ConnectSockets $sid $nonce $addr $port 1
716
} elseif { $type == "webcam" } {
717
setObjOption $sid accepted 1
718
::MSNCAM::SendSyn $sid $chatid
720
} elseif { $listening == "false" } {
721
status_log "MSNP2P | $sid -> Receiver is not listening, sending INVITE\n" red
722
if { $type == "filetransfer" } {
723
::MSN6FT::SendFTInvite2 $sid $chatid
724
} elseif { $type == "webcam" } {
725
setObjOption $sid accepted 1
726
::MSNCAM::SendSyn $sid $chatid
727
#::MSNCAM::SendAcceptInvite $sid $chatid
730
status_log "Error sending file $filename, got answer to invite :\n$data\n\n" red
741
# Check if we got BYE message
742
if { [string first "BYE MSNMSGR:" $data] != -1 } {
743
# Lets get the call ID and find our SessionID
744
set idx [expr [string first "Call-ID: \{" $data] + 10]
745
set idx2 [expr [string first "\}" $data $idx] - 1]
746
set uid [string range $data $idx $idx2]
747
set sid [SessionList findcallid $uid]
748
status_log "MSNP2P | $sid -> Got BYE for UID : $uid\n" red
752
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
753
status_log "MSNP2P | $sid -> Sending BYE ACK\n" red
755
# If it's a file transfer, advise the user it has been canceled
756
if { [lindex [SessionList get $sid] 7] == "filetransfer" } {
757
status_log "File transfer canceled\n"
758
::MSNP2P::SessionList set $sid [list -1 -1 -1 -1 -1 -1 -1 "ftcanceled" -1 -1]
759
if { [::amsn::FTProgress ca $sid [lindex [SessionList get $sid] 6]] == -1 } {
760
::amsn::RejectFT $chatid "-2" $sid
763
if { [lindex [SessionList get $sid] 7] == "webcam" } {
764
status_log "Webcam canceled\n"
765
::MSNCAM::CamCanceled $chatid $sid
768
# Delete SessionID Data
769
SessionList unset $sid
772
status_log "MSNP2P | $sid -> Got a BYE for unexisting SessionID\n" red
776
# Check if we got DECLINE message
777
if { [string first "603 Decline" $data] != -1 } {
778
# Lets get the call ID and find our SessionID
779
set idx [expr [string first "Call-ID: \{" $data] + 10]
780
set idx2 [expr [string first "\}" $data $idx] - 1]
781
set uid [string range $data $idx $idx2]
782
set sid [SessionList findcallid $uid]
783
status_log "MSNP2P | $sid -> Got DECLINE for UID : $uid\n" red
787
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
788
status_log "MSNP2P | $sid -> Sending DECLINE ACK\n" red
790
# If it's a file transfer, advise the user it has been canceled
791
if { [lindex [SessionList get $sid] 7] == "webcam" } {
792
if { [getObjOption $sid accepted] != 1 } {
793
::CAMGUI::InvitationDeclined $chatid
795
::MSNCAM::SendSyn $sid $chatid
801
status_log "MSNP2P | $sid -> Got a DECLINE for unexisting SessionID\n" red
806
# Let's check for data preparation messages and data messages
808
# Make sure this isn't a canceled FT
809
if { [lindex [SessionList get $cSid] 7] == "ftcanceled" } { return }
811
set fd [lindex [SessionList get $cSid] 6]
812
set type [lindex [SessionList get $cSid] 7]
814
#If it's a file transfer, display Progress bar
815
if { $type == "filetransfer" } {
816
::amsn::FTProgress w $cSid "" [trans throughserver]
817
::amsn::FTProgress r $cSid [lindex [SessionList get $cSid] 6] $cOffset $cTotalDataSize
819
if { $type != "webcam" && $fd != "" && $fd != 0 && $fd != -1 } {
820
# File already open and being written to (fd exists)
821
# Lets write data to file
822
puts -nonewline $fd [string range $data 0 [expr $cMsgSize - 1]]
823
#status_log "MSNP2P | $sid -> FD EXISTS, file already open... with fd = $fd --- $cOffset + $cMsgSize + $cTotalDataSize . Writing DATA to file\n" red
824
# Check if this is last part if splitted
825
if { [expr $cOffset + $cMsgSize] >= $cTotalDataSize } {
828
set session_data [SessionList get $cSid]
829
set user_login [lindex $session_data 3]
830
set filename [lindex $session_data 8]
832
# Lets send an ACK followed by a BYE if it's a buddy icon or emoticon
833
#status_log "MSNP2P | $sid -> Sending an ACK for file received and sending a BYE\n" red
834
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid $cSid $cTotalDataSize $cId $cAckId]
836
if { [lindex [SessionList get $cSid] 7] == "bicon" } {
837
SendPacket [::MSN::SBFor $chatid] [MakePacket $sid [MakeMSNSLP "BYE" $user_login [::config::getKey login] "19A50529-4196-4DE9-A561-D68B0BF1E83F" 0 [lindex $session_data 5] 0 0] 1]
839
#set filename2 [::MSNP2P::GetFilenameFromMSNOBJ [::abook::getVolatileData $user_login msnobj]]
840
set filename2 [::abook::getContactData $user_login displaypicfile ""]
841
status_log "MSNP2P | $sid -> Got picture with file : $filename and $filename2\n" blue
842
if {$filename == $filename2 } {
844
status_log "MSNP2P | $sid -> Closed file $filename.. finished writing\n" red
845
#set file [png_to_gif [file join $HOME displaypic cache ${filename}.png]]
846
set file [file join $HOME displaypic cache ${filename}.png]
849
if {[catch {image create photo user_pic_${user_login} -file [file join $HOME displaypic cache "${filename}.png"] -format cximage}] } {
850
image create photo user_pic_${user_login} -file [::skin::GetSkinFile displaypic nopic.gif] -format cximage
853
set desc_file "[file join $HOME displaypic cache ${filename}.dat]"
854
create_dir [file join $HOME displaypic]
855
set fd [open [file join $HOME displaypic $desc_file] w]
856
status_log "Writing description to $desc_file\n"
857
puts $fd "[clock format [clock seconds] -format %x]\n$user_login"
862
#set file [png_to_gif [file join $HOME smileys cache ${filename}.png]]
863
set file [file join $HOME smileys cache ${filename}.png]
865
set tw [::ChatWindow::GetOutText [::ChatWindow::For $chatid]]
866
#set file [filenoext $file].gif
867
set scrolling [::ChatWindow::getScrolling $tw]
868
catch {image create photo custom_smiley_${filename} -file "[file join $HOME smileys cache ${filename}.png]" -format cximage}
869
if { $scrolling } { ::ChatWindow::Scroll $tw }
873
} elseif { [lindex [SessionList get $cSid] 7] == "filetransfer" } {
874
# Display message that file transfer is finished...
875
status_log "MSNP2P | $cSid -> File transfer finished!\n"
876
::amsn::FTProgress fr $cSid [lindex [SessionList get $cSid] 6] $cOffset $cTotalDataSize
877
SessionList set $cSid [list -1 -1 -1 -1 -1 -1 -1 "filetransfersuccessfull" -1 -1]
880
} elseif { $cMsgSize == 4 } {
881
# We got ourselves a DATA PREPARATION message, lets open file and send ACK
882
set session_data [SessionList get $sid]
883
set user_login [lindex $session_data 3]
884
#status_log "MSNP2P | $sid $user_login -> Got data preparation message, opening file for writing\n" red
885
set filename [lindex $session_data 8]
886
#set filename2 [::MSNP2P::GetFilenameFromMSNOBJ [::abook::getVolatileData $user_login msnobj]]
887
set filename2 [::abook::getContactData $user_login displaypicfile ""]
888
#status_log "MSNP2P | $sid $user_login -> opening file $filename for writing with $filename2 as user msnobj\n\n" blue
889
if { $filename == $filename2 } {
890
create_dir [file join $HOME displaypic cache]
891
set fd [open "[file join $HOME displaypic cache ${filename}.png]" w]
893
create_dir [file join $HOME smileys cache]
894
set fd [open "[file join $HOME smileys cache ${filename}.png]" w]
897
fconfigure $fd -translation {binary binary}
898
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid $cSid $cTotalDataSize $cId $cAckId]
899
#status_log "MSNP2P | $sid $user_login -> Sent an ACK for DATA PREP Message\n" red
900
SessionList set $sid [list -1 -1 -1 -1 -1 -1 $fd -1 -1 -1]
901
} elseif { $type == "webcam" } {
904
set h1 [string range $data 0 3]
905
set h2 [string range $data 4 9]
906
set msg [string range $data 10 [expr { $cMsgSize - 1}]]
908
set msg [FromUnicode $msg]
910
status_log "Received data for webcam $sid : $data\n$msg\n" red
912
if {[expr $cOffset + $cMsgSize] >= $cTotalDataSize} {
913
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid $cSid $cTotalDataSize $cId $cAckId]
916
if { $msg == "syn\x00" } {
918
::MSNCAM::SendSyn $sid $chatid
920
::MSNCAM::SendAck $sid $chatid
922
} elseif { $msg == "ack\x00" } {
923
set producer [getObjOption $sid producer]
924
status_log "Received the ack for webcam\n" red
927
status_log "We should send the XML\n" red
928
::MSNCAM::SendXML $chatid $sid
931
} elseif { $msg == "receivedViewerData\x00" } {
932
status_log "ReceivedViewData received\n" red
933
::MSNCAM::ConnectSockets $sid
934
} elseif {[string first "<producer>" $msg] == 0 || [string first "<viewer>" $msg] == 0 || $cOffset != 0} {
935
set xml [getObjOption $sid xml]
936
set xml "${xml}[string range $data 0 [expr { $cMsgSize - 1}]]"
938
setObjOption $sid xml $xml
940
if { [expr $cOffset + $cMsgSize] >= $cTotalDataSize } {
941
set xml [string range $xml 10 end]
942
setObjOption $sid xml $xml
944
::MSNCAM::ReceivedXML $chatid $sid
947
} elseif { [string first "ReflData:" $msg] == 0 } {
948
set refldata [string range $msg 9 end-1]
949
set refldata [binary format H* $refldata]
951
::MSNCAM::ConnectToReflector $sid $refldata
954
status_log "UNKNOWN" red
958
} elseif {$sid == 64} {
959
set msg [FromUnicode $data]
960
set ink_message [getObjOption $sid ink_message_$cId]
961
set ink_message "${ink_message}[string range $data 0 [expr { $cMsgSize - 1}]]"
962
setObjOption $sid ink_message_$cId $ink_message
964
if {[expr $cOffset + $cMsgSize] >= $cTotalDataSize} {
965
setObjOption $sid ink_message_$cId ""
966
SendPacket [::MSN::SBFor $chatid] [MakeACK $sid $cSid $cTotalDataSize $cId $cAckId]
967
set ink_message [FromUnicode $ink_message]
968
set idx [string first "\r\n\r\n" $ink_message]
970
if {[string first "\x00" $ink_message $idx] == $idx } {
973
set body [string range $ink_message $idx end]
975
if { [string first "base64:" $body] != -1 } {
976
set data [::base64::decode [string range $body 7 end]]
980
set img [image create photo -data $data]
981
set user [lindex [::MSN::usersInChat $chatid] 0]
982
set nick [::abook::getDisplayNick $user]
984
status_log "got ink from $user - $nick with image $img"
985
SendMessageFIFO [list ::amsn::ShowInk $chatid $user $nick $img ink $p4c_enabled] "::amsn::messages_stack($chatid)" "::amsn::messages_flushing($chatid)"
989
status_log "Received data for unknown type : $sid\n" red
994
#//////////////////////////////////////////////////////////////////////////////
995
# RequestObject ( chatid msnobject filename)
996
# This function creates the invitation packet in order to receive an MSNObject (custom emoticon and display buddy for now)
997
# chatid : Chatid from which we will request the object
998
# dest : The email of the user that will receive our request
999
# msnobject : The object we want to request (has to be url decoded)
1000
# filename: the file where data should be saved to
1001
proc RequestObject { chatid dest msnobject} {
1002
# Let's create a new session
1003
set sid [expr int([expr rand() * 1000000000])%125000000 + 4]
1004
# Generate BranchID and CallID
1005
set branchid "[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]"
1006
set callid "[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]"
1008
SessionList set $sid [list 0 0 0 $dest 0 $callid 0 "bicon" [::MSNP2P::GetFilenameFromMSNOBJ $msnobject] ""]
1010
# Create and send our packet
1011
set slpdata [MakeMSNSLP "INVITE" $dest [::config::getKey login] $branchid 0 $callid 0 0 "A4268EEC-FEC5-49E5-95C3-F126696BDBF6" $sid 1 [string map { "\n" "" } [::base64::encode "$msnobject\x00"]]]
1012
SendPacket [::MSN::SBFor $chatid] [MakePacket $sid $slpdata 1]
1013
status_log "Sent an INVITE to $dest on chatid $chatid of object $msnobject\n" red
1017
#//////////////////////////////////////////////////////////////////////////////
1018
# MakePacket ( sid slpdata [nullsid] [MsgId] [TotalSize] [Offset] [Destination] )
1019
# This function creates the appropriate MSNP2P packet with the given SLP info
1020
# This will be used for everything except for ACK's
1021
# slpdata : the SLP info created by MakeMSNSLP that will be included in the packet
1022
# it could also be binary data that will be sent in the P2P packet
1023
# sid : the session id
1024
# nullsid : 0 to add sid to header, 1 to put 0 instead of sid in header (usefull for negot + bye)
1025
# Returns the MSNP2P packet (half text half binary)
1026
proc MakePacket { sid slpdata {nullsid "0"} {MsgId "0"} {TotalSize "0"} {Offset "0"} {Destination "0"} {AfterAck "0"} {flags "0"}} {
1028
# Let's get our session id variables and put them in a list
1029
# If sessionid is 0, means we want to initiate a new session
1031
set SessionInfo [SessionList get $sid]
1032
set MsgId [lindex $SessionInfo 0]
1033
set TotalSize [lindex $SessionInfo 1]
1034
set Offset [lindex $SessionInfo 2]
1035
set Destination [lindex $SessionInfo 3]
1038
# Here is our text header
1039
set theader "MIME-Version: 1.0\r\nContent-Type: application/x-msnmsgrp2p\r\nP2P-Dest: $Destination\r\n\r\n"
1041
# We start by creating the 48 byte binary header
1042
if { $nullsid != 0 } {
1043
# session id field set to 0 during negotiation and bye
1044
set bheader [binary format i 0]
1047
set bheader [binary format i $sid]
1050
if { $MsgId == 0 } {
1051
# No MsgId let's generate one and add to our list
1052
set MsgId [expr int([expr rand() * 1000000]) + 4]
1053
} elseif { $Offset == 0 } {
1054
# Offset is different than 0, we need to incr the MsgId to prepare our next message
1058
if {[string is digit $Offset] == 0 || $Offset == ""} {
1062
append bheader [binary format i $MsgId]
1063
append bheader [binword $Offset]
1065
set CurrentSize [string length $slpdata]
1066
# We must set TotalSize to the size of data if it is > 1202 bytes otherwise we set to 0
1067
if { $TotalSize == 0 } {
1068
# This isn't a split message
1069
append bheader "[binword $CurrentSize][binary format i $CurrentSize]"
1071
# This is a split message
1072
append bheader "[binword $TotalSize][binary format i $CurrentSize]"
1073
incr Offset $CurrentSize
1074
if { $Offset >= $TotalSize } {
1075
# We have finished sending the last part of the message
1082
append bheader [binary format i $flags]
1084
# Just give the Ack Session ID some dumbo random number
1085
append bheader [binary format i [myRand 4369 6545000]]
1086
#append bheader [binary format i 67152542]
1088
# Set last 2 ack fields to 0
1089
append bheader [binary format i 0][binword 0]
1092
if { $nullsid == 1 } {
1093
# Negotiating Session so set to 0
1094
set bfooter [binary format I 0]
1096
# Either sending a display pic, or an emoticon so set to 1
1097
set bfooter [binary format I 1]
1101
set packet "${theader}${bheader}${slpdata}${bfooter}"
1102
#status_log "Sent a packet with header $theader\n" red
1108
# Save new Session Variables into SessionList
1109
SessionList set $sid [list $MsgId $TotalSize $Offset -1 -1 -1 -1 -1 -1 -1]
1115
#//////////////////////////////////////////////////////////////////////////////
1116
# MakeACK (sid originalsid originalsize originalid originaluid)
1117
# This function creates an ack packet for msnp2p
1118
# original* arguments are all arguments of the message we want to ack
1119
# sid has to be != 0
1120
# Returns the ACK packet
1121
proc MakeACK { sid originalsid originalsize originalid originaluid } {
1124
set SessionInfo [SessionList get $sid]
1125
set MsgId [lindex $SessionInfo 0]
1126
set Destination [lindex $SessionInfo 3]
1131
if { $MsgId == 0 } {
1132
# No MsgId let's generate one and add to our list
1133
set MsgId [expr int([expr rand() * 1000000]) + 10]
1140
set theader "MIME-Version: 1.0\r\nContent-Type: application/x-msnmsgrp2p\r\nP2P-Dest: $Destination\r\n\r\n"
1142
# Set the binary header and footer
1143
set b [binary format ii $originalsid $MsgId][binword 0][binword $originalsize][binary format iiii 0 2 $originalid $originaluid][binword $originalsize][binary format I 0]
1145
# Save new Session Variables into SessionList
1149
SessionList set $sid [list $MsgId -1 -1 -1 -1 -1 -1 -1 -1 -1]
1151
return "${theader}${b}"
1155
#//////////////////////////////////////////////////////////////////////////////
1156
# # MakeMSNSLP ( method to from branchuid cseq maxfwds contenttentype [A] [B] [C] [D] [E] [F] [G])
1157
# This function creates the appropriate MSNSLP packets
1158
# method : INVITE, BYE, OK, DECLINE
1159
# contenttype : 0 for application/x-msnmsgr-sessionreqbody (Starting a session) or sessionclosebody for a BYE
1160
# 1 for application/x-msnmsgr-transreqbody (Starting transfer) or sessionclosebody for a BYE and use A
1162
# 2 for application/x-msnmsgr-transrespbody (Starting transfer)
1163
# 3 for null (starting webcam)
1166
# If INVITE method is chosen then A, B, C, D and/or E are used dependinf on contenttype
1167
# for 0 we got : "EUF-GUID", "SessionID", "AppID" and "Context" (E not used)
1168
# for 1 we got : "Bridges", "NetID", "Conn-Type", "UPnPNat" and "ICF"
1169
# for 2 we got : "Bridge", "Listening", "Nonce", "IPv4External-Addrs","IPv4External-Port"
1170
# "IPv4Internal-Addrs" and "IPv4Internal-Port"
1172
# If OK method is chosen then A to G are used depending on contenttype
1173
# for 0 we got : "SessionID"
1174
# for 1 we got : "Bridge", "Listening", "Nonce", "IPv4External-Addrs","IPv4External-Port"
1175
# "IPv4Internal-Addrs" and "IPv4Internal-Port"
1176
# Returns the formated MSNSLP data
1177
proc MakeMSNSLP { method to from branchuid cseq uid maxfwds contenttype {A ""} {B ""} {C ""} {D ""} {E ""} {F ""} {G ""} } {
1179
# Generate start line
1180
if { $method == "INVITE" } {
1181
set data "INVITE MSNMSGR:${to} MSNSLP/1.0\r\n"
1182
} elseif { $method == "BYE" } {
1183
set data "BYE MSNMSGR:${to} MSNSLP/1.0\r\n"
1184
} elseif { $method == "OK" } {
1185
set data "MSNSLP/1.0 200 OK\r\n"
1186
} elseif { $method == "DECLINE" } {
1187
set data "MSNSLP/1.0 603 DECLINE\r\n"
1190
# Lets create our message body first (so we can calc it's length for the header)
1192
if { $method == "INVITE" } {
1193
if { $contenttype == 0 } {
1194
append body "EUF-GUID: {${A}}\r\nSessionID: ${B}\r\nAppID: ${C}\r\nContext: ${D}\r\n"
1195
} elseif { $contenttype == 1 } {
1196
append body "Bridges: ${A}\r\nNetID: ${B}\r\nConn-Type: ${C}\r\nUPnPNat: ${D}\r\nICF: ${E}\r\n"
1198
append body "Bridge: ${A}\r\nListening: ${B}\r\nNonce: \{${C}\}\r\n"
1199
if {${B} == "true" } {
1200
if { [::abook::getDemographicField conntype] == "IP-Restrict-NAT" } {
1201
append body "IPv4External-Addrs: ${D}\r\nIPv4External-Port: ${E}\r\nIPv4Internal-Addrs: ${F}\r\nIPv4Internal-Port: ${G}\r\n"
1203
append body "IPv4Internal-Addrs: ${D}\r\nIPv4Internal-Port: ${E}\r\n"
1208
} elseif { $method == "OK" } {
1209
if { $contenttype == 0 } {
1210
append body "SessionID: ${A}\r\n"
1212
append body "Bridge: ${A}\r\nListening: ${B}\r\nNonce: \{${C}\}\r\n"
1213
if {${B} == "true" } {
1214
if { [::abook::getDemographicField conntype] == "IP-Restrict-NAT" } {
1215
append body "IPv4External-Addrs: ${D}\r\nIPv4External-Port: ${E}\r\nIPv4Internal-Addrs: ${F}\r\nIPv4Internal-Port: ${G}\r\n"
1217
append body "IPv4Internal-Addrs: ${D}\r\nIPv4Internal-Port: ${E}\r\n"
1222
} elseif { $method == "DECLINE" } {
1223
append body "SessionID: ${A}\r\n"
1224
} elseif { $method == "BYE" && $contenttype == 1} {
1225
append body "Context: ${A}"
1228
append body "\r\n\x00"
1230
# Here comes the message header
1231
append data "To: <msnmsgr:${to}>\r\nFrom: <msnmsgr:${from}>\r\nVia: MSNSLP/1.0/TLP ;branch={${branchuid}}\r\nCSeq: ${cseq}\r\nCall-ID: {${uid}}\r\nMax-Forwards: ${maxfwds}\r\n"
1232
if { $method == "BYE" } {
1233
append data "Content-Type: application/x-msnmsgr-sessionclosebody\r\n"
1235
if { $contenttype == 0 } {
1236
append data "Content-Type: application/x-msnmsgr-sessionreqbody\r\n"
1237
} elseif { $contenttype == 1 } {
1238
append data "Content-Type: application/x-msnmsgr-transreqbody\r\n"
1239
} elseif { $contenttype == 2 } {
1240
append data "Content-Type: application/x-msnmsgr-transrespbody\r\n"
1241
} elseif { $contenttype == 3 } {
1242
append data "Content-Type: null\r\n"
1246
append data "Content-Length: [expr [string length $body]]\r\n\r\n"
1255
#//////////////////////////////////////////////////////////////////////////////
1256
# SendData ( sid chatid )
1257
# This procedure sends the data given by the filename in the Session vars given by SessionID
1258
proc SendData { sid chatid filename } {
1261
SessionList set $sid [list -1 [file size "${filename}"] -1 -1 -1 -1 -1 -1 -1 -1]
1262
set fd [lindex [SessionList get $sid] 6]
1264
set fd [open "${filename}"]
1265
SessionList set $sid [list -1 -1 -1 -1 -1 -1 $fd -1 -1 -1]
1266
fconfigure $fd -translation binary
1269
# set sock [sb get [MSN::SBFor $chatid] sock]
1271
# if { $sock != "" } {
1272
# fileevent $sock writable ""
1276
set chunk [read $fd 1200]
1277
SendPacket [::MSN::SBFor $chatid] [MakePacket $sid $chunk 0 0 0 0 0 0 32]
1280
#status_log "[SessionList get $sid]\n"
1281
if { [lindex [SessionList get $sid] 1] == 0 } {
1282
# All file has been sent
1285
# We finished sending the data, set appropriate Afterack and Fd
1286
SessionList set $sid [list -1 -1 -1 -1 DATASENT -1 0 -1 -1]
1288
# set sock [sb get [MSN::SBFor $chatid] sock]
1289
# Still need to send
1290
# if { $sock != "" } {
1291
after 100 "[list ::MSNP2P::SendData $sid $chatid ${filename}]"
1299
proc SendDataFile { sid chatid filename match } {
1303
if { [lindex [::MSNP2P::SessionList get $sid] 4] != "$match"} {
1307
status_log "state is [lindex [::MSNP2P::SessionList get $sid] 4] => sending through SB\n\n" red;
1311
SessionList set $sid [list -1 [file size "${filename}"] -1 -1 -1 -1 -1 -1 -1 -1]
1312
set fd [lindex [SessionList get $sid] 6]
1313
if { $fd == 0 || $fd == "" } {
1314
set fd [open "${filename}"]
1315
SessionList set $sid [list -1 -1 -1 -1 -1 -1 $fd -1 -1 -1]
1316
fconfigure $fd -translation {binary binary}
1321
::amsn::FTProgress w $sid "" [trans throughserver]
1323
# SendPacketExt [::MSN::SBFor $chatid] $sid [read $fd] 0 0 0 0 0 0 16777264
1327
set sbn [::MSN::SBFor $chatid]
1328
set sock [$sbn cget -sock]
1331
SessionList set $sid [list -1 -1 $offset -1 -1 -1 -1 -1 -1 -1]
1333
if { [fileevent $sock writable] == "" } {
1334
status_log "assining new fileevent proc\n"
1335
fileevent $sock writable "::MSNP2P::SendDataEvent $sbn $sid $fd"
1342
proc SendDataEvent { sbn sid fd } {
1345
set sock [$sbn cget -sock]
1346
fileevent $sock writable ""
1349
set offset [lindex [SessionList get $sid] 2]
1350
set filesize [lindex [SessionList get $sid] 1]
1352
if { $offset == "" } {
1357
if { [lindex [::MSNP2P::SessionList get $sid] 7] == "ftcanceled" } {
1362
set data [read $fd 1202]
1363
# status_log "Reading 1202 bytes of data : got [string length $data]"
1364
if { [string length $data] >= 1202 } {
1365
set msg [MakePacket $sid $data 0 0 0 0 0 0 16777264]
1366
set msg_len [string length $msg]
1367
puts -nonewline $sock "MSG [incr ::MSN::trid] D $msg_len\r\n$msg"
1368
set offset [expr $offset + 1202]
1369
SessionList set $sid [list -1 -1 $offset -1 -1 -1 -1 -1 -1 -1]
1370
::amsn::FTProgress s $sid "" $offset $filesize
1371
catch {after 200 [list fileevent $sock writable "::MSNP2P::SendDataEvent $sbn $sid $fd"]}
1374
set msg [MakePacket $sid $data 0 0 0 0 0 0 16777264]
1375
set msg_len [string length $msg]
1376
puts -nonewline $sock "MSG [incr ::MSN::trid] D $msg_len\r\n$msg"
1377
set offset [expr $offset + 1202]
1378
SessionList set $sid [list -1 -1 0 -1 -1 -1 -1 -1 -1 -1 ]
1380
set msgId [expr [lindex [SessionList get $sid] 0] + 1]
1381
SessionList set $sid [list $msgId -1 0 -1 DATASENT -1 0 -1 -1 -1]
1385
::amsn::FTProgress fs $sid ""
1391
#//////////////////////////////////////////////////////////////////////////////
1392
# SendPacket ( sbn msg )
1393
# This function sends the packet given by (msg) into the given (sbn)
1394
proc SendPacket { sbn msg } {
1395
# if { [string length $msg] > 1202 }
1396
set msg_len [string length $msg]
1397
::MSN::WriteSBNoNL $sbn "MSG" "D $msg_len\r\n$msg"
1400
proc SendPacketExt { sbn sid slpdata {nullsid "0"} {MsgId "0"} {TotalSize "0"} {Offset "0"} {Destination "0"} {AfterAck "0"} {flags "0"}} {
1402
SessionList set $sid [list -1 [string length $slpdata] $offset -1 -1 -1 -1 -1 -1 -1]
1403
set fd [$sbn cget -sock]
1404
status_log "Got socket $fd\n"
1405
if { [fileevent $fd writable] == "" } {
1406
status_log "assining new fileevent proc\n"
1407
fileevent $fd writable "::MSNP2P::SendPacketExtEvent $sbn $sid [list $slpdata] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags"
1411
proc SendPacketExtEvent { sbn sid slpdata {nullsid "0"} {MsgId "0"} {TotalSize "0"} {Offset "0"} {Destination "0"} {AfterAck "0"} {flags "0"} } {
1412
set fd [$sbn cget -sock]
1413
fileevent $fd writable ""
1415
#status_log "got sbn : $sbn, $fd\nsid : $sid\nslpdata: $slpdata \n$nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags\n\n" red
1417
set offset [lindex [SessionList get $sid] 2]
1419
if { $offset == "" } {
1423
if { [expr $offset + 1202] < [string length $slpdata] } {
1424
set msg [MakePacket $sid [string range $slpdata $offset [expr $offset + 1201]] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags]
1425
set msg_len [string length $msg]
1426
::MSN::WriteSBNoNL $sbn "MSG" "D $msg_len\r\n$msg"
1427
set offset [expr $offset + 1202]
1428
SessionList set $sid [list -1 -1 $offset -1 -1 -1 -1 -1 -1 -1]
1429
after 200 [list fileevent $fd writable "::MSNP2P::SendPacketExtEvent $sbn $sid [list $slpdata] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags" ]
1432
set msg [MakePacket $sid [string range $slpdata $offset [expr $offset + 1201]] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags]
1433
set msg_len [string length $msg]
1434
::MSN::WriteSBNoNL $sbn "MSG" "D $msg_len\r\n$msg"
1435
set offset [expr $offset + 1202]
1436
SessionList set $sid [list -1 -1 0 -1 -1 -1 -1 -1 -1 -1 ]