📄 msnp2p.tcl
字号:
# Just give the Ack Session ID some dumbo random number append bheader [binary format i [myRand 4369 6545000]] #append bheader [binary format i 67152542] # Set last 2 ack fields to 0 append bheader [binary format i 0][binword 0] # Now the footer if { $nullsid == 1 } { # Negotiating Session so set to 0 set bfooter [binary format I 0] } else { # Either sending a display pic, or an emoticon so set to 1 set bfooter [binary format I 1] } # Combine it all set packet "${theader}${bheader}${slpdata}${bfooter}" #status_log "Sent a packet with header $theader\n" red unset bheader unset bfooter unset slpdata # Save new Session Variables into SessionList SessionList set $sid [list $MsgId $TotalSize $Offset -1 -1 -1 -1 -1 -1 -1] return $packet } #////////////////////////////////////////////////////////////////////////////// # MakeACK (sid originalsid originalsize originalid originaluid) # This function creates an ack packet for msnp2p # original* arguments are all arguments of the message we want to ack # sid has to be != 0 # Returns the ACK packet proc MakeACK { sid originalsid originalsize originalid originaluid } { set new 0 if { $sid != 0 } { set SessionInfo [SessionList get $sid] set MsgId [lindex $SessionInfo 0] set Destination [lindex $SessionInfo 3] } else { return } if { $MsgId == 0 } { # No MsgId let's generate one and add to our list set MsgId [expr {int([expr rand() * 1000000]) + 10 } ] set new 1 } else { incr MsgId } # The text header set theader "MIME-Version: 1.0\r\nContent-Type: application/x-msnmsgrp2p\r\nP2P-Dest: $Destination\r\n\r\n" # Set the binary header and footer set b [binary format ii $originalsid $MsgId][binword 0][binword $originalsize][binary format iiii 0 2 $originalid $originaluid][binword $originalsize][binary format I 0] # Save new Session Variables into SessionList if { $new == 1 } { incr MsgId -4 } SessionList set $sid [list $MsgId -1 -1 -1 -1 -1 -1 -1 -1 -1] return "${theader}${b}" } #////////////////////////////////////////////////////////////////////////////// # # MakeMSNSLP ( method to from branchuid cseq maxfwds contenttentype [A] [B] [C] [D] [E] [F] [G]) # This function creates the appropriate MSNSLP packets # method : INVITE, BYE, OK, DECLINE # contenttype : 0 for application/x-msnmsgr-sessionreqbody (Starting a session) or sessionclosebody for a BYE # 1 for application/x-msnmsgr-transreqbody (Starting transfer) or sessionclosebody for a BYE and use A # as context # 2 for application/x-msnmsgr-transrespbody (Starting transfer) # 3 for null (starting webcam) # # # If INVITE method is chosen then A, B, C, D and/or E are used dependinf on contenttype # for 0 we got : "EUF-GUID", "SessionID", "AppID" and "Context" (E not used) # for 1 we got : "Bridges", "NetID", "Conn-Type", "UPnPNat" and "ICF" # for 2 we got : "Bridge", "Listening", "Nonce", "IPv4External-Addrs","IPv4External-Port" # "IPv4Internal-Addrs" and "IPv4Internal-Port" # # If OK method is chosen then A to G are used depending on contenttype # for 0 we got : "SessionID" # for 1 we got : "Bridge", "Listening", "Nonce", "IPv4External-Addrs","IPv4External-Port" # "IPv4Internal-Addrs" and "IPv4Internal-Port" # Returns the formated MSNSLP data proc MakeMSNSLP { method to from branchuid cseq uid maxfwds contenttype {A ""} {B ""} {C ""} {D ""} {E ""} {F ""} {G ""} } { # Generate start line if { $method == "INVITE" } { set data "INVITE MSNMSGR:${to} MSNSLP/1.0\r\n" } elseif { $method == "BYE" } { set data "BYE MSNMSGR:${to} MSNSLP/1.0\r\n" } elseif { $method == "OK" } { set data "MSNSLP/1.0 200 OK\r\n" } elseif { $method == "DECLINE" } { set data "MSNSLP/1.0 603 Decline\r\n" } # Lets create our message body first (so we can calc it's length for the header) set body "" if { $method == "INVITE" } { if { $contenttype == 0 } { append body "EUF-GUID: {${A}}\r\nSessionID: ${B}\r\nAppID: ${C}\r\nContext: ${D}\r\n" } elseif { $contenttype == 1 } { append body "Bridges: ${A}\r\nNetID: ${B}\r\nConn-Type: ${C}\r\nUPnPNat: ${D}\r\nICF: ${E}\r\n" } else { append body "Bridge: ${A}\r\nListening: ${B}\r\nNonce: \{${C}\}\r\n" if {${B} == "true" } { if { [::abook::getDemographicField conntype] == "IP-Restrict-NAT" } { append body "IPv4External-Addrs: ${D}\r\nIPv4External-Port: ${E}\r\nIPv4Internal-Addrs: ${F}\r\nIPv4Internal-Port: ${G}\r\n" } else { append body "IPv4Internal-Addrs: ${D}\r\nIPv4Internal-Port: ${E}\r\n" } } } } elseif { $method == "OK" } { if { $contenttype == 0 } { append body "SessionID: ${A}\r\n" } else { append body "Bridge: ${A}\r\nListening: ${B}\r\nNonce: \{${C}\}\r\n" if {${B} == "true" } { if { [::abook::getDemographicField conntype] == "IP-Restrict-NAT" } { append body "IPv4External-Addrs: ${D}\r\nIPv4External-Port: ${E}\r\nIPv4Internal-Addrs: ${F}\r\nIPv4Internal-Port: ${G}\r\n" } else { append body "IPv4Internal-Addrs: ${D}\r\nIPv4Internal-Port: ${E}\r\n" } } } } elseif { $method == "DECLINE" } { append body "SessionID: ${A}\r\n" } elseif { $method == "BYE" && $contenttype == 1} { append body "Context: ${A}" } append body "\r\n\x00" # Here comes the message header 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" if { $method == "BYE" } { append data "Content-Type: application/x-msnmsgr-sessionclosebody\r\n" } else { if { $contenttype == 0 } { append data "Content-Type: application/x-msnmsgr-sessionreqbody\r\n" } elseif { $contenttype == 1 } { append data "Content-Type: application/x-msnmsgr-transreqbody\r\n" } elseif { $contenttype == 2 } { append data "Content-Type: application/x-msnmsgr-transrespbody\r\n" } elseif { $contenttype == 3 } { append data "Content-Type: null\r\n" set body "" } } append data "Content-Length: [expr [string length $body]]\r\n\r\n" append data $body unset body #status_log $data return $data } #////////////////////////////////////////////////////////////////////////////// # SendData ( sid chatid ) # This procedure sends the data given by the filename in the Session vars given by SessionID proc SendData { sid chatid filename } { SessionList set $sid [list -1 [file size "${filename}"] -1 -1 -1 -1 -1 -1 -1 -1] set fd [lindex [SessionList get $sid] 6] if { $fd == 0 } { set fd [open "${filename}"] SessionList set $sid [list -1 -1 -1 -1 -1 -1 $fd -1 -1 -1] fconfigure $fd -translation binary } if { $fd == "" } { # set sock [sb get [MSN::SBFor $chatid] sock] # if { $sock != "" } { # fileevent $sock writable "" # } return } set chunk [read $fd 1200] SendPacket [::MSN::SBFor $chatid] [MakePacket $sid $chunk 0 0 0 0 0 0 32] unset chunk #status_log "[SessionList get $sid]\n" if { [lindex [SessionList get $sid] 1] == 0 } { # All file has been sent close $fd unset fd # We finished sending the data, set appropriate Afterack and Fd SessionList set $sid [list -1 -1 -1 -1 DATASENT -1 0 -1 -1] } else { # set sock [sb get [MSN::SBFor $chatid] sock] # Still need to send # if { $sock != "" } { after 100 "[list ::MSNP2P::SendData $sid $chatid ${filename}]" # } } } proc SendDataFile { sid chatid filename match } { if { [lindex [::MSNP2P::SessionList get $sid] 7] == "ftcanceled" } { return } if { [lindex [::MSNP2P::SessionList get $sid] 4] != "$match"} { return } status_log "state is [lindex [::MSNP2P::SessionList get $sid] 4] => sending through SB\n\n" red; #return SessionList set $sid [list -1 [file size "${filename}"] -1 -1 -1 -1 -1 -1 -1 -1] set fd [lindex [SessionList get $sid] 6] if { $fd == 0 || $fd == "" } { set fd [open "${filename}"] SessionList set $sid [list -1 -1 -1 -1 -1 -1 $fd -1 -1 -1] fconfigure $fd -translation {binary binary} } if { $fd == "" } { return } ::amsn::FTProgress w $sid "" [trans throughserver] # SendPacketExt [::MSN::SBFor $chatid] $sid [read $fd] 0 0 0 0 0 0 16777264 # close $fd set sbn [::MSN::SBFor $chatid] set sock [$sbn cget -sock] set offset 0 SessionList set $sid [list -1 -1 $offset -1 -1 -1 -1 -1 -1 -1] if { [fileevent $sock writable] == "" } { status_log "assining new fileevent proc\n" fileevent $sock writable "::MSNP2P::SendDataEvent $sbn $sid $fd" } } proc SendDataEvent { sbn sid fd } { set sock [$sbn cget -sock] fileevent $sock writable "" #return set offset [lindex [SessionList get $sid] 2] set filesize [lindex [SessionList get $sid] 1] if { $offset == "" } { close $fd return } if { [lindex [::MSNP2P::SessionList get $sid] 7] == "ftcanceled" } { close $fd return } set data [read $fd 1202] # status_log "Reading 1202 bytes of data : got [string length $data]" if { [string length $data] >= 1202 } { set msg [MakePacket $sid $data 0 0 0 0 0 0 16777264] set msg_len [string length $msg] puts -nonewline $sock "MSG [incr ::MSN::trid] D $msg_len\r\n$msg" set offset [expr {$offset + 1202}] SessionList set $sid [list -1 -1 $offset -1 -1 -1 -1 -1 -1 -1] ::amsn::FTProgress s $sid "" $offset $filesize #catch {after 200 [list catch {fileevent $sock writable "::MSNP2P::SendDataEvent $sbn $sid $fd"}]} after 200 [list ::MSNP2P::SetSendDataFileEvent $sock $sbn $sid $fd] } else { set msg [MakePacket $sid $data 0 0 0 0 0 0 16777264] set msg_len [string length $msg] puts -nonewline $sock "MSG [incr ::MSN::trid] D $msg_len\r\n$msg" set offset [expr {$offset + 1202}] SessionList set $sid [list -1 -1 0 -1 -1 -1 -1 -1 -1 -1 ] set msgId [expr {[lindex [SessionList get $sid] 0] + 1}] SessionList set $sid [list $msgId -1 0 -1 DATASENT -1 0 -1 -1 -1] close $fd unset fd ::amsn::FTProgress fs $sid "" } } proc SetSendDataFileEvent { sock sbn sid fd } { catch { fileevent $sock writable "::MSNP2P::SendDataEvent $sbn $sid $fd" } } #////////////////////////////////////////////////////////////////////////////// # SendPacket ( sbn msg ) # This function sends the packet given by (msg) into the given (sbn) proc SendPacket { sbn msg } { # if { [string length $msg] > 1202 } set msg_len [string length $msg] catch {::MSN::WriteSBNoNL $sbn "MSG" "D $msg_len\r\n$msg"} } proc SendPacketExt { sbn sid slpdata {nullsid "0"} {MsgId "0"} {TotalSize "0"} {Offset "0"} {Destination "0"} {AfterAck "0"} {flags "0"}} { set offset 0 SessionList set $sid [list -1 [string length $slpdata] $offset -1 -1 -1 -1 -1 -1 -1] set fd [$sbn cget -sock] status_log "Got socket $fd\n" if { [fileevent $fd writable] == "" } { status_log "assining new fileevent proc\n" fileevent $fd writable "::MSNP2P::SendPacketExtEvent $sbn $sid [list $slpdata] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags" } } proc SendPacketExtEvent { sbn sid slpdata {nullsid "0"} {MsgId "0"} {TotalSize "0"} {Offset "0"} {Destination "0"} {AfterAck "0"} {flags "0"} } { set fd [$sbn cget -sock] fileevent $fd writable "" #status_log "got sbn : $sbn, $fd\nsid : $sid\nslpdata: $slpdata \n$nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags\n\n" red set offset [lindex [SessionList get $sid] 2] if { $offset == "" } { return } if { [expr {$offset + 1202}] < [string length $slpdata] } { set msg [MakePacket $sid [string range $slpdata $offset [expr {$offset + 1201}]] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags] set msg_len [string length $msg] ::MSN::WriteSBNoNL $sbn "MSG" "D $msg_len\r\n$msg" set offset [expr {$offset + 1202}] SessionList set $sid [list -1 -1 $offset -1 -1 -1 -1 -1 -1 -1] after 200 [list fileevent $fd writable "::MSNP2P::SendPacketExtEvent $sbn $sid [list $slpdata] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags" ] } else { set msg [MakePacket $sid [string range $slpdata $offset [expr {$offset + 1201}]] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags] set msg_len [string length $msg] ::MSN::WriteSBNoNL $sbn "MSG" "D $msg_len\r\n$msg" set offset [expr {$offset + 1202}] SessionList set $sid [list -1 -1 0 -1 -1 -1 -1 -1 -1 -1 ] } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -