[Tkabber-dev] [tclxmpp] r167 committed - * xmpp/bosh.tcl: Initially implemented BOSH (XEP-0124 and XEP-0206)...

tclxmpp at googlecode.com tclxmpp at googlecode.com
Tue Dec 3 15:10:34 MSK 2013


Revision: 167
Author:   sgolovan
Date:     Tue Dec  3 11:10:12 2013 UTC
Log:      	* xmpp/bosh.tcl: Initially implemented BOSH (XEP-0124 and  
XEP-0206)
	  transport support.

	* xmpp/poll.tcl, xmpp/tcp.tcl, xmpp/tls.tcl, xmpp/zlib.tcl: Added
	  reopenStream command, enabled synchronous closing of XMPP stream.
	  Bumped package versions to 0.2.

	* xmpp/xmpp.tcl: Added synchronous closing of XMPP stream. Use
	  reopenStream transport command were appropriate. Bumped package
	  version to 0.1.1.

	* xmpp/pkgIndex.tcl: Bumped transport package versions to 0.2 because
	  their user interface has been changed and the XMPP package version
	  to 0.1.1.

	* xmpp/poll.tcl: Code cleanup with using security keys.

	* xmpp/transport.tcl: Added support for reopenStream command. Bumped
	  package version to 0.2.

	* xmpp/sasl.tcl: Added another call to Debug proc.

	* examples/jsend.tcl: Removed cdata payload from jabber:iq:last
	  response. Use synchronous stream closing before exit. Added BOSH
	  transport support.

http://code.google.com/p/tclxmpp/source/detail?r=167

Added:
  /trunk/xmpp/bosh.tcl
Modified:
  /trunk/ChangeLog
  /trunk/examples/jsend.tcl
  /trunk/xmpp/pkgIndex.tcl
  /trunk/xmpp/poll.tcl
  /trunk/xmpp/sasl.tcl
  /trunk/xmpp/tcp.tcl
  /trunk/xmpp/tls.tcl
  /trunk/xmpp/transport.tcl
  /trunk/xmpp/xmpp.tcl
  /trunk/xmpp/zlib.tcl

=======================================
--- /dev/null
+++ /trunk/xmpp/bosh.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -0,0 +1,1137 @@
+# bosh.tcl --
+#
+#       This file is a part of the XMPP library. It implements XMPP over  
BOSH
+#       (XEP-0124 and XEP-0206).
+#
+# Copyright (c) 2013 Sergei Golovan <sgolovan at nes.ru>
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAMER OF ALL WARRANTIES.
+#
+# $Id$
+
+package require sha1
+package require http
+
+package require xmpp::transport 0.2
+package require xmpp::xml
+
+package provide xmpp::transport::bosh 0.2
+
+namespace eval ::xmpp::transport::bosh {
+    namespace export open abort close reset flush ip outXML outText \
+                     openStream reopenStream closeStream
+
+    ::xmpp::transport::register bosh \
+            -opencommand         [namespace code open]         \
+            -abortcommand        [namespace code abort]        \
+            -closecommand        [namespace code close]        \
+            -resetcommand        [namespace code reset]        \
+            -flushcommand        [namespace code flush]        \
+            -ipcommand           [namespace code ip]           \
+            -outxmlcommand       [namespace code outXML]       \
+            -outtextcommand      [namespace code outText]      \
+            -openstreamcommand   [namespace code openStream]   \
+            -reopenstreamcommand [namespace code reopenStream] \
+            -closestreamcommand  [namespace code closeStream]
+
+    if {![catch { package require tls 1.4 }]} {
+        ::http::register https 443 ::tls::socket
+    }
+
+    # Supported BOSH version
+    variable ver 1.10
+
+    # Namespaces used in BOSH and XMPP over BOSH
+    variable NS
+    array set NS {bind http://jabber.org/protocol/httpbind
+                  bosh urn:xmpp:xbosh}
+
+    # Set this to 1 or 2 to get debug messages on standard output
+    variable debug 0
+}
+
+# ::xmpp::transport::bosh::open --
+#
+#       Open connection to XMPP server. For BOSH transport this means
+#       "store BOSH parameters, create XML parser, and return or call back
+#       with success.
+#
+# Arguments:
+#       server                      (ignored, -url option is used) XMPP  
server
+#                                   hostname.
+#       port                        (ignored, -url option is used) XMPP  
server
+#                                   port.
+#       -url url                    (mandatory) BOSH URL to request.
+#       -streamheadercommand cmd    Command to call when server stream  
header
+#                                   is parsed.
+#       -streamtrailercommand cmd   Command to call when server stream  
trailer
+#                                   is parsed.
+#       -stanzacommand cmd          Command to call when top-level stream
+#                                   stanza is parsed.
+#       -eofcommand cmd             Command to call when server (or proxy)
+#                                   breaks connection.
+#       -command cmd                Command to call upon a successfull or
+#                                   failed connect (for this transport  
failing
+#                                   during connect is impossible).
+#       -timeout timeout            Timeout for HTTP queries (it's value  
must
+#                                   be higher than -wait).
+#       -wait int                   The longest time the connection  
manager is
+#                                   allowed to wait before responding (in
+#                                   milliseconds).
+#       -hold requests              Maximum number of requests the  
connection
+#                                   manager is allowed to keep waiting.
+#       -usekeys usekeys            (default true) Use security keys to
+#                                   protect connection.
+#       -numkeys numkeys            (default 100) Number of keys in a  
series.
+#       -host proxyHost             Proxy hostname.
+#       -port proxyPort             Proxy port.
+#       -username proxyUsername     Proxy username.
+#       -password proxyPassword     Proxy password.
+#       -useragent proxyUseragent   Proxy useragent.
+#
+# Result:
+#       Transport token which is to be used for communication with XMPP  
server.
+#
+# Side effects:
+#       A new variable is created where BOSH options are stored. Also, a  
new
+#       XML parser is created.
+
+proc ::xmpp::transport::bosh::open {server port args} {
+    variable id
+
+    if {![info exists id]} {
+        set id 0
+    }
+
+    set token [namespace current]::[incr id]
+    variable $token
+    upvar 0 $token state
+
+    set state(transport) bosh
+
+    set state(streamHeaderCmd)  #
+    set state(streamTrailerCmd) #
+    set state(stanzaCmd)        #
+    set state(eofCmd)           #
+    set state(-timeout)         0
+    set state(-wait)            30000
+    set state(-hold)            1
+    set state(-url)             ""
+    set state(-usekeys)         0
+    set state(-numkeys)         100
+
+    foreach {key val} $args {
+        switch -- $key {
+            -streamheadercommand  {set state(streamHeaderCmd)  $val}
+            -streamtrailercommand {set state(streamTrailerCmd) $val}
+            -stanzacommand        {set state(stanzaCmd)        $val}
+            -eofcommand           {set state(eofCmd)           $val}
+            -command              {set cmd                     $val}
+            -timeout     -
+            -wait        -
+            -hold        -
+            -url         -
+            -usekeys     -
+            -numkeys     {set state($key)    $val}
+            -proxyfilter {set proxyFilter    $val}
+            -host        {set proxyHost      $val}
+            -port        {set proxyPort      $val}
+            -username    {set proxyUsername  $val}
+            -password    {set proxyPassword  $val}
+            -useragent   {set proxyUseragent $val}
+        }
+    }
+
+    set state(open)      0
+    set state(secure)    0
+    set state(outdata)   ""
+    set state(keys)      {}
+    set state(proxyAuth) {}
+    set state(wait)      disconnected
+    set state(sid)       ""
+    set state(requests)  [expr {$state(-hold)+1}]
+    set state(queries)   0
+    set state(polling)   10000
+    set state(id)        ""
+
+    if {[info exists proxyUseragent]} {
+        ::http::config -useragent $proxyUseragent
+    }
+
+    if {[info exists proxyFilter]} {
+        # URLmatcher is borrowed from http package.
+        set URLmatcher {(?x)                    # this is _expanded_ syntax
+            ^
+            (?: (\w+) : ) ?                     # <protocol scheme>
+            (?: //
+                (?:
+                    (
+                        [^@/\#?]+               # <userinfo part of  
authority>
+                    ) @
+                )?
+                ( [^/:\#?]+ )                   # <host part of authority>
+                (?: : (\d+) )?                  # <port part of authority>
+            )?
+            ( / [^\#?]* (?: \? [^\#?]* )?)?     # <path> (including query)
+            (?: \# (.*) )?                      # <fragment>
+            $
+        }
+
+        if {[regexp -- $URLmatcher $state(-url) -> \
+                       proto user host port srvurl]} {
+            if {![catch {eval $proxyFilter $host} answer]} {
+                foreach {phost pport proxyUsername proxyPassword} $answer {
+                    break
+                }
+            }
+        }
+
+        ::http::config -proxyfilter $proxyFilter
+    }
+
+    if {[info exists proxyHost] && [info exists proxyPort]} {
+        ::http::config -proxyhost $proxyHost -proxyport $proxyPort
+    }
+
+    if {[info exists proxyUsername] && [info exists proxyPassword] && \
+            !([string equal $proxyUsername ""] && \
+              [string equal $proxyPassword ""])} {
+        set auth \
+            [base64::encode \
+                    [encoding convertto $proxyUsername:$proxyPassword]]
+        set state(proxyAuth) [list Proxy-Authorization "Basic $auth"]
+    }
+
+    if {$state(-usekeys)} {
+        Debug $token 2 "generating keys"
+        set state(keys) [GenKeys $state(-numkeys)]
+    }
+
+    # BOSH doesn't wrap stanzas into <stream:stream/>, so we don't need  
parser
+    # to call back for stream header and trailer.
+
+    set state(parser) \
+        [::xmpp::xml::new # # \
+                [namespace code [list InXML $token \
+                                            $state(streamHeaderCmd) \
+                                            $state(streamTrailerCmd) \
+                                            $state(stanzaCmd)]]]
+
+    SetWait $token connected
+
+    if {[info exists cmd]} {
+        # Asynchronous mode is almost synchronous
+        CallBack $cmd [list ok $token]
+    }
+
+    return $token
+}
+
+# ::xmpp::transport::bosh::outText --
+#
+#       Send text to XMPP server.
+#
+# Arguments:
+#       token           Transport token.
+#       text            Text to send.
+#       attrs           (optional, defaults to {}) A list of attributes for
+#                       the <body/> element (body of the POST query).
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       Sending text to the server is scheduled.
+
+proc ::xmpp::transport::bosh::outText {token text {attrs {}}} {
+    variable $token
+    upvar 0 $token state
+
+    if {![info exists state(wait)]} {
+        return -1
+    }
+
+    switch -- $state(wait) {
+        disconnected -
+        disconnecting {
+            # TODO
+            return -1
+        }
+        default {
+            Request $token $text $attrs
+        }
+    }
+    # TODO
+    return [string bytelength $text]
+}
+
+# ::xmpp::transport::bosh::outXML --
+#
+#       Send XML element to XMPP server.
+#
+# Arguments:
+#       token           Transport token.
+#       xml             XML stanza to send.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       Sending XML to the server is scheduled.
+
+proc ::xmpp::transport::bosh::outXML {token xml} {
+    variable $token
+    upvar 0 $token state
+
+    if {![info exists state(wait)] || [string equal $state(wait)  
disconnected]} {
+        return -1
+    }
+
+    ::xmpp::xml::split $xml tag xmlns attrs1 cdata subels nextCdata
+
+    # The default XMLNS of BOSH <body/> element is
+    # http://jabber.org/protocol/httpbind, so stanzas require specifying
+    # XMLNS explicitly.
+
+    if {[string equal $xmlns ""]} {
+        set xml [::xmpp::xml::merge $tag $state(xmlns) $attrs1 \
+                                    $cdata $subels $nextCdata]
+    }
+
+    # HACK: Adding xmlns:stream definition if stream prefix is found
+    # in the stanza
+
+    if {[FindXMLNS $xml $state(xmlns:stream)]} {
+        set attrs [list xmlns:stream $state(xmlns:stream)]
+    } else {
+        set attrs {}
+    }
+
+    return [outText $token [::xmpp::xml::toText $xml] $attrs]
+}
+
+# ::xmpp::transport::bosh::FindXMLNS --
+#
+#       Return 1 if the XML element contains the given XMLNS.
+#
+# Arguments:
+#       xml             XML stanza to check.
+#       ns              XMLNS to find.
+#
+# Result:
+#       1 if the namespace is found, 0 otherwise.
+#
+# Side effects:
+#       None.
+
+proc ::xmpp::transport::bosh::FindXMLNS {xml ns} {
+    ::xmpp::xml::split $xml tag xmlns attrs cdata subels
+
+    if {[string equal $xmlns $ns]} {
+        return 1
+    }
+
+    foreach subel $subels {
+        if {[FindXMLNS $subel $ns]} {
+            return 1
+        }
+    }
+
+    return 0
+}
+
+# ::xmpp::transport::bosh::openStream --
+#
+#        Initiate new BOSH session.
+#
+# Arguments:
+#       token           Transport token.
+#       server          XMPP server.
+#       args            Arguments for [::xmpp::xml::streamHeader].
+#
+# Result:
+#       0
+#
+# Side effects:
+#       Sending string to the server is scheduled.
+
+proc ::xmpp::transport::bosh::openStream {token server args} {
+    eval OpenStreamAux [list $token open $server] $args
+}
+
+# ::xmpp::transport::bosh::reopenStream --
+#
+#       Reopen BOSH stream.
+#
+# Arguments:
+#       token           Transport token.
+#       server          XMPP server.
+#       args            Arguments for [::xmpp::xml::streamHeader].
+#
+# Result:
+#       0
+#
+# Side effects:
+#       Sending string to the server is scheduled.
+
+proc ::xmpp::transport::bosh::reopenStream {token server args} {
+    eval OpenStreamAux [list $token reopen $server] $args
+}
+
+# ::xmpp::transport::bosh::OpenStreamAux --
+#
+#        Auxiliary proc which opens or reopens BOSH session.
+#
+# Arguments:
+#       token           Transport token.
+#       mode            'open' or 'reopen'
+#       server          XMPP server.
+#       args            Arguments for [::xmpp::xml::streamHeader].
+#
+# Result:
+#       0
+#
+# Side effects:
+#       Sending string to the server is scheduled.
+
+proc ::xmpp::transport::bosh::OpenStreamAux {token mode server args} {
+    variable $token
+    upvar 0 $token state
+    variable ver
+    variable NS
+
+    if {![info exists state(wait)] || [string equal $state(wait)  
disconnected]} {
+        return -1
+    }
+
+    Debug $token 2 "$mode $server $args"
+
+    # Fake XMPP stream header (parser invokes callback for every level 1
+    # stanza).
+
+    ::xmpp::xml::parser $state(parser) parse <stream>
+
+    set appendXmlns 0
+    set attrs [list xmlns $NS(bind) ver $ver to $server]
+
+    if {[string equal $mode open]} {
+        # Opening a new stream
+
+        lappend attrs wait [expr {int(($state(-wait)+999)/1000.0)}] \
+                      hold $state(-hold)
+    } else {
+        # Reopening stream
+
+        lappend attrs sid          $state(sid) \
+                      xmpp:restart true
+        set appendXmlnsXmpp 1
+    }
+
+    foreach {key val} $args {
+        switch -- $key {
+            -from {
+                lappend attrs from $val
+            }
+            -xml:lang {
+                lappend attrs xml:lang $val
+            }
+            -version {
+                lappend attrs xmpp:version $val
+                set appendXmlnsXmpp 1
+            }
+            -xmlns:stream {
+                set state(xmlns:stream) $val
+            }
+            -xmlns {
+                set state(xmlns) $val
+            }
+            default {
+                return -code error [::msgcat::mc "Invalid option \"%s\""  
$key]
+            }
+        }
+    }
+
+    if {$appendXmlnsXmpp} {
+        # Define XMLNS for xmpp prefix if it was used
+
+        lappend attrs xmlns:xmpp $NS(bosh)
+    }
+
+    set state(open) 0
+
+    return [outText $token "" $attrs]
+}
+
+# ::xmpp::transport::bosh::closeStream --
+#
+#       Send XMPP stream trailer to XMPP server and start disconnecting
+#       procedure.
+#
+# Arguments:
+#       token           Transport token.
+#       -wait bool      (optional, default is 0) Wait for real disconnect.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       Sending stream trailer to the server is scheduled.
+
+proc ::xmpp::transport::bosh::closeStream {token args} {
+    variable $token
+    upvar 0 $token state
+
+    if {![info exists state(wait)] || [string equal $state(wait)  
disconnected]} {
+        return -1
+    }
+
+    Debug $token 2 ""
+
+    set attrs [list type terminate]
+    set len [outText $token "" $attrs]
+
+    SetWait $token disconnecting
+
+    set wait 0
+    foreach {key val} $args {
+        switch -- $key {
+            -wait {
+                set wait $val
+            }
+        }
+    }
+
+    if {$wait} {
+        while {[info exists state(wait)] && \
+                            ![string equal $state(wait) disconnected]} {
+            vwait $token\(wait)
+        }
+    }
+
+    return $len
+}
+
+# ::xmpp::transport::bosh::flush --
+#
+#       Flush XMPP channel.
+#
+# Arguments:
+#       token           Transport token.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       Pending data is sent to the server.
+
+proc ::xmpp::transport::bosh::flush {token} {
+    # TODO
+}
+
+# ::xmpp::transport::bosh::ip --
+#
+#       Return IP of an outgoing socket.
+#
+# Arguments:
+#       token           Transport token.
+#
+# Result:
+#       Empty string (until really implemented).
+#
+# Side effects:
+#       None.
+
+proc ::xmpp::transport::bosh::ip {token} {
+    variable $token
+    upvar 0 $token state
+
+    # TODO
+    return ""
+}
+
+# ::xmpp::transport::bosh::close --
+#
+#       Close XMPP channel.
+#
+# Arguments:
+#       token           Transport token.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       Transport token and XML parser are destroyed.
+
+proc ::xmpp::transport::bosh::close {token} {
+    variable $token
+    upvar 0 $token state
+
+    if {![info exists state(wait)]} {
+        # The channel is already closed
+        return
+    }
+
+    SetWait $token disconnected
+
+    if {[info exists state(parser)]} {
+        ::xmpp::xml::free $state(parser)
+    }
+
+    catch {unset state}
+    return
+}
+
+# ::xmpp::transport::bosh::reset --
+#
+#       Reset XMPP stream.
+#
+# Arguments:
+#       token           Transport token.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       XML parser is reset.
+
+proc ::xmpp::transport::bosh::reset {token} {
+    variable $token
+    upvar 0 $token state
+
+    if {![info exists state(wait)] || [string equal $state(wait)  
disconnected]} {
+        return
+    }
+
+    Debug $token 2 ""
+
+    ::xmpp::xml::reset $state(parser)
+    return
+}
+
+# ::xmpp::transport::bosh::InText --
+#
+#       A helper procedure which is called when a new portion of data is
+#       received from XMPP server. It feeds XML parser with this data.
+#
+# Arguments:
+#       token           Transport token.
+#       text            Text to parse.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       The text is parsed and if it completes top-level stanza then an
+#       appropriate callback is invoked.
+
+proc ::xmpp::transport::bosh::InText {token text} {
+    variable $token
+    upvar 0 $token state
+
+    Debug $token 2 $text
+
+    ::xmpp::xml::parser $state(parser) parse $text
+
+    return
+}
+
+# ::xmpp::transport::bosh::InXML --
+#
+#       A helper procedure which is called when a new XML stanza is parsed.
+#       It then calls a specified command as an idle callback.
+#
+# Arguments:
+#       token           Transport token.
+#       headerCmd       Command to call if XMPP session is started.
+#       trailerCmd      Command to call if XMPP session is ended.
+#       stanzaCmdmd     Command to call if XMPP stanza is received.
+#       xml             BOSH body XML stanza.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       After entering event loop the specified command is called.
+
+proc ::xmpp::transport::bosh::InXML {token headerCmd trailerCmd stanzaCmd  
xml} {
+    variable $token
+    upvar $token state
+    variable NS
+
+    Debug $token 2 "$state(open) $xml"
+
+    ::xmpp::xml::split $xml tag xmlns attrs cdata subels
+
+    if {![string equal $xmlns $NS(bind)]} {
+        return -code error "Unexpected XMLNS in BOSH reply: $xmlns"
+    }
+
+    set type ""
+    set condition ""
+    foreach {key val} $attrs {
+        switch -- $key \
+            sid {
+                set state(sid) $val
+            } \
+            wait {
+                set state(-wait) [expr {$val*1000}]
+            } \
+            ver {
+                set state(var) $val
+            } \
+            polling {
+                set state(polling) [expr {$val*1000}]
+            } \
+            inactivity {
+                # TODO
+            } \
+            requests {
+                set requests $val
+            } \
+            maxpause {
+                # TODO
+            } \
+            secure {
+                set state(secure) $val
+            } \
+            accept {
+                # TODO
+            } \
+            ack {
+                # TODO
+            } \
+            hold {
+                set state(-hold) $val
+            } \
+            from {
+                set state(-from) $val
+            } \
+            $NS(bosh):version {
+                set state(-version) $val
+            } \
+            authid {
+                set state(-id) $val
+            } \
+            type {
+                set type $val
+            } \
+            condition {
+                set condition $val
+            }
+    }
+
+    if {![info exists requests]} {
+        set state(requests) [expr {$state(-hold)+1}]
+    } else {
+        set state(requests) $requests
+    }
+
+    if {!$state(open)} {
+        set newattrs {}
+        foreach key {from version id} {
+            if {[info exists state(-$key)]} {
+                lappend newattrs $key $state(-$key)
+            }
+        }
+
+        set state(open) 1
+        CallBack $headerCmd [list $newattrs]
+    }
+
+    # Process received stanzas
+
+    foreach subel $subels {
+        CallBack $stanzaCmd [list $subel]
+    }
+
+    if {[string equal $type terminate]} {
+        SetWait $token disconnected
+        CallBack $state(eofCmd)
+    }
+
+    return
+}
+
+# ::xmpp::transport::bosh::CallBack --
+#
+#       A helper procedure which is called when XMPP stream is finished.
+#       It then calls a specified command as an idle callback.
+#
+# Arguments:
+#       cmd             Command to call.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       After entering event loop the specified command is called.
+
+proc ::xmpp::transport::bosh::CallBack {cmd args} {
+    eval [list after idle $cmd] $args
+    return
+}
+
+# ::xmpp::transport::bosh::Body --
+#
+#       Create textual representation of BOSH body XML element.
+#
+# Arguments:
+#       token       Tranport token.
+#       attrs       Attribute key-value pairs list.
+#       text        (Optional, defaults to empty string) Textual  
representation
+#                   of body subelements.
+#
+# Result:
+#       BOSH body XML element.
+#
+# Side effects:
+#       None.
+
+proc ::xmpp::transport::bosh::Body {token attrs {text ""}} {
+    variable $token
+    upvar 0 $token state
+    variable NS
+
+    if {![::xmpp::xml::isAttr $attrs xmlns]} {
+        set attrs [linsert $attrs 0 xmlns $NS(bind) \
+                                    sid   $state(sid)]
+    }
+
+    # We have to construct body XML element by hands to be able to put
+    # arbitrary text inside it.
+    set retext "<body"
+    foreach {attr value} $attrs {
+        append retext " $attr='[::xmpp::xml::Escape $value]'"
+    }
+    if {[string equal $text ""]} {
+        append retext "/>"
+    } else {
+        append retext ">$text</body>"
+    }
+
+    return $retext
+}
+
+# ::xmpp::transport::bosh::Request --
+#
+#       Schedule BOSH request procedure to output given text.
+#
+# Arguments:
+#       token               Tranport token.
+#       text                Text to output.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       If there's no request which is waited for then a new request is  
sent,
+#       otherwise a new call to [Request] is scheduled.
+
+proc ::xmpp::transport::bosh::Request {token text attrs} {
+    variable $token
+    upvar 0 $token state
+
+    Debug $token 2 "'$text' '$attrs'"
+
+    if {![info exists state(wait)]} {
+        # Trying to poll an already closed connection
+        Debug $token 2 NON-EXISTENT
+        return
+    }
+
+    append state(outdata) $text
+
+    switch -- $state(wait) {
+        disconnected {
+            Debug $token 2 DISCONNECTED
+
+            return
+        }
+        disconnecting {
+            Debug $token 2 DISCONNECTING
+
+            return
+        }
+        default {
+            if {$state(queries) >= $state(requests) && \
+                    ![string equal [::xmpp::xml::getAttr $attrs type]  
terminate]} {
+                Debug $token 2 RESCHEDULING
+
+                after cancel $state(id)
+                set state(id) \
+                    [after $state(polling) \
+                           [namespace code [list Request $token ""  
$attrs]]]
+                return
+            }
+        }
+    }
+
+    set newattrs $attrs
+    if {![info exists state(rid)]} {
+        # The first request ever
+
+        set state(rid) [expr {round(rand()*10000000)}]
+
+        if {$state(-usekeys)} {
+            # Won't work with number of keys equal to 1 (which is  
ridiculous
+            # anyway)
+
+            lappend newattrs newkey [lindex $state(keys) end]
+            set state(keys) [lrange $state(keys) 0 end-1]
+        }
+    } else {
+        # The next request ID
+
+        set state(rid) [NextRid $state(rid)]
+
+        if {$state(-usekeys)} {
+            lappend newattrs key [lindex $state(keys) end]
+            set state(keys) [lrange $state(keys) 0 end-1]
+
+            if {[llength $state(keys)] == 0} {
+                # Regenerate keys
+
+                Debug $token 2 "Regenerating keys"
+                set state(keys) [GenKeys $state(-numkeys)]
+
+                lappend newattrs newkey [lindex $state(keys) end]
+                set state(keys) [lrange $state(keys) 0 end-1]
+            }
+        }
+    }
+
+    set query [Body $token [linsert $newattrs 0 rid $state(rid)]  
$state(outdata)]
+
+    Debug $token 2 "query: '$query'"
+
+    incr state(queries)
+    set state(outdata) ""
+
+    after cancel $state(id)
+    set state(id) \
+        [after $state(polling) [namespace code [list Request $token ""  
$attrs]]]
+
+    GetURL $token 0 [encoding convertto utf-8 $query]
+    return
+}
+
+# ::xmpp::transport::bosh::ProcessReply --
+#
+#       Process BOSH reply from the XMPP server.
+#
+# Arguments:
+#       token               Tranport token.
+#       try                 Number of the previous requests of the same  
query.
+#       query               Query string.
+#       httpToken           HTTP token to get server answer.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       If query failed then it is retried (not more than thrice),  
otherwise the
+#       answer is received and pushed to XML parser.
+
+proc ::xmpp::transport::bosh::ProcessReply {token try query httpToken} {
+    variable $token
+    upvar 0 $token state
+
+    if {![info exists state(wait)]} {
+        # A reply for an already closed connection
+        return
+    }
+
+    upvar #0 $httpToken httpState
+
+    if {[::http::ncode $httpToken] != 200} {
+        Debug $token 1 "HTTP returned [::http::ncode $httpToken]\
+                                      [http::status $httpToken]"
+        Debug $token 2 "[::http::meta $httpToken]"
+        Debug $token 2 "[::http::data $httpToken]"
+
+        if {$try < 3} {
+            GetURL $token [incr try] $query
+        } else {
+            # Don't care about state(queries) since the connection is  
broken
+
+            SetWait $token disconnected
+            CallBack $state(eofCmd)
+        }
+        ::http::cleanup $httpToken
+        return
+    }
+
+    incr state(queries) -1
+    if {$state(queries) < 0} {
+        # Something wrong, received more replies then sent
+
+        Debug $token 1 "state(queries) < 0"
+        set state(queries) 0
+    }
+
+    Debug $token 2 [::http::meta $httpToken]
+
+    set inmsg [encoding convertfrom utf-8 [::http::data $httpToken]]
+    ::http::cleanup $httpToken
+
+    Debug $token 2 '$inmsg'
+
+    InText $token $inmsg
+}
+
+# ::xmpp::transport::bosh::GetURL --
+#
+#       Fetch BOSH URL.
+#
+# Arguments:
+#       token               Transport token.
+#       try                 Number of previous tries of the same query
+#                           (sometimes query fails because of proxy  
errors, so
+#                           it's better to try once more).
+#       query               Query to send to the server.
+#
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       BOSH HTTP request is sent and ProcessReply call is scheduled on  
reply.
***The diff for this file has been truncated for email.***
=======================================
--- /trunk/ChangeLog	Sun Nov 10 12:46:38 2013 UTC
+++ /trunk/ChangeLog	Tue Dec  3 11:10:12 2013 UTC
@@ -1,3 +1,31 @@
+2013-12-03  Sergei Golovan  <sgolovan at nes.ru>
+
+	* xmpp/bosh.tcl: Initially implemented BOSH (XEP-0124 and XEP-0206)
+	  transport support.
+
+	* xmpp/poll.tcl, xmpp/tcp.tcl, xmpp/tls.tcl, xmpp/zlib.tcl: Added
+	  reopenStream command, enabled synchronous closing of XMPP stream.
+	  Bumped package versions to 0.2.
+
+	* xmpp/xmpp.tcl: Added synchronous closing of XMPP stream. Use
+	  reopenStream transport command were appropriate. Bumped package
+	  version to 0.1.1.
+
+	* xmpp/pkgIndex.tcl: Bumped transport package versions to 0.2 because
+	  their user interface has been changed and the XMPP package version
+	  to 0.1.1.
+
+	* xmpp/poll.tcl: Code cleanup with using security keys.
+
+	* xmpp/transport.tcl: Added support for reopenStream command. Bumped
+	  package version to 0.2.
+
+	* xmpp/sasl.tcl: Added another call to Debug proc.
+
+	* examples/jsend.tcl: Removed cdata payload from jabber:iq:last
+	  response. Use synchronous stream closing before exit. Added BOSH
+	  transport support.
+
  2013-11-10  Sergei Golovan  <sgolovan at nes.ru>

  	* license.terms: Fixed copyright years.
=======================================
--- /trunk/examples/jsend.tcl	Fri Nov  8 07:44:11 2013 UTC
+++ /trunk/examples/jsend.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -17,6 +17,7 @@
  package require tls

  package require xmpp
+package require xmpp::transport::bosh
  package require xmpp::auth
  package require xmpp::sasl
  package require xmpp::starttls
@@ -54,6 +55,7 @@
                              -date        ""    \
                              -description ""    \
                              -url         ""    \
+                            -bosh        ""    \
                              -tls         false \
                              -starttls    true  \
                              -sasl        true  \
@@ -161,7 +163,10 @@
          # Create an XMPP library instance
          set xlib [::xmpp::new]

-        if {$options(-tls)} {
+        if (![string equal $options(-bosh) ""]) {
+            set transport bosh
+            set port 0
+        } elseif {$options(-tls)} {
              set transport tls
              if {![string equal $options(-port) ""]} {
                  set port $options(-port)
@@ -178,9 +183,11 @@
          }

          # Connect to a server
-        ::xmpp::connect $xlib $options(-host) $port -transport $transport
+        ::xmpp::connect $xlib $options(-host) $port \
+                              -transport $transport \
+                              -url $options(-bosh)

-        if {!$options(-tls) && $options(-starttls)} {
+        if {[string equal $options(-bosh) ""] && !$options(-tls) &&  
$options(-starttls)} {
              # Open XMPP stream
              set sessionID [::xmpp::openStream $xlib $domain \
                                                      -version 1.0]
@@ -250,7 +257,7 @@
      }
      if {!$stayP} {
          set jsend::stayP 0
-        ::xmpp::disconnect $xlib
+        ::xmpp::disconnect $xlib -wait 1
      }

      return 1
@@ -308,8 +315,7 @@
      set xmldata \
          [::xmpp::xml::create query -xmlns jabber:iq:last \
                                     -attrs [list seconds \
-                                                [expr {$now -  
$lib(lastwhen)}]] \
-                                   -cdata $lib(lastwhat)]
+                                                [expr {$now -  
$lib(lastwhen)}]]]
      return [list result $xmldata]
  }

@@ -515,6 +521,7 @@
              -xhtml       string
              -description string
              -url         string
+            -bosh        string (BOSH URL)
              -tls         boolean (e.g., 'false')
              -starttls    boolean (e.g., 'true')
              -sasl        boolean (e.g., 'true')
=======================================
--- /trunk/xmpp/pkgIndex.tcl	Fri May 18 05:31:17 2012 UTC
+++ /trunk/xmpp/pkgIndex.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -3,7 +3,7 @@
  #       This file is part of the XMPP library. It registeres XMPP packages
  #       for Tcl.
  #
-# Copyright (c) 2008-2010 Sergei Golovan <sgolovan at nes.ru>
+# Copyright (c) 2008-2013 Sergei Golovan <sgolovan at nes.ru>
  #
  # See the file "license.terms" for information on usage and redistribution
  # of this file, and for a DISCLAMER OF ALL WARRANTIES.
@@ -14,7 +14,7 @@
  package ifneeded pconnect::https 0.1            [list source [file join  
$dir https.tcl]]
  package ifneeded pconnect::socks4 0.1           [list source [file join  
$dir socks4.tcl]]
  package ifneeded pconnect::socks5 0.1           [list source [file join  
$dir socks5.tcl]]
-package ifneeded xmpp 0.1                       [list source [file join  
$dir xmpp.tcl]]
+package ifneeded xmpp 0.1.1                     [list source [file join  
$dir xmpp.tcl]]
  package ifneeded xmpp::auth 0.1                 [list source [file join  
$dir auth.tcl]]
  package ifneeded xmpp::bob 0.1                  [list source [file join  
$dir bob.tcl]]
  package ifneeded xmpp::component 0.1            [list source [file join  
$dir component.tcl]]
@@ -44,18 +44,19 @@
  package ifneeded xmpp::stanzaerror 0.1          [list source [file join  
$dir stanzaerror.tcl]]
  package ifneeded xmpp::starttls 0.1             [list source [file join  
$dir starttls.tcl]]
  package ifneeded xmpp::streamerror 0.1          [list source [file join  
$dir streamerror.tcl]]
-package ifneeded xmpp::transport 0.1            [list source [file join  
$dir transport.tcl]]
-package ifneeded xmpp::transport::poll 0.1      [list source [file join  
$dir poll.tcl]]
-package ifneeded xmpp::transport::tcp 0.1       [list source [file join  
$dir tcp.tcl]]
-package ifneeded xmpp::transport::tls 0.1       [list source [file join  
$dir tls.tcl]]
-package ifneeded xmpp::transport::zlib 0.1      [list source [file join  
$dir zlib.tcl]]
+package ifneeded xmpp::transport 0.2            [list source [file join  
$dir transport.tcl]]
+package ifneeded xmpp::transport::bosh 0.2      [list source [file join  
$dir bosh.tcl]]
+package ifneeded xmpp::transport::poll 0.2      [list source [file join  
$dir poll.tcl]]
+package ifneeded xmpp::transport::tcp 0.2       [list source [file join  
$dir tcp.tcl]]
+package ifneeded xmpp::transport::tls 0.2       [list source [file join  
$dir tls.tcl]]
+package ifneeded xmpp::transport::zlib 0.2      [list source [file join  
$dir zlib.tcl]]
  package ifneeded xmpp::xml 0.1                  [list source [file join  
$dir xml.tcl]]

-package ifneeded xmpp::full 0.1 {
+package ifneeded xmpp::full 0.1.1 {
      package require pconnect::https 0.1
      package require pconnect::socks4 0.1
      package require pconnect::socks5 0.1
-    package require xmpp 0.1
+    package require xmpp 0.1.1
      package require xmpp::auth 0.1
      package require xmpp::bob 0.1
      package require xmpp::component 0.1
@@ -74,11 +75,12 @@
      package require xmpp::roster::metacontacts 0.1
      package require xmpp::sasl 0.1
      package require xmpp::starttls 0.1
-    package require xmpp::transport::poll 0.1
-    package require xmpp::transport::tls 0.1
-    package require xmpp::transport::zlib 0.1
+    package require xmpp::transport::bosh 0.2
+    package require xmpp::transport::poll 0.2
+    package require xmpp::transport::tls 0.2
+    package require xmpp::transport::zlib 0.2

-    package provide xmpp::full 0.1
+    package provide xmpp::full 0.1.1
  }

  # vim:ts=8:sw=4:sts=4:et
=======================================
--- /trunk/xmpp/poll.tcl	Mon Jan 25 17:14:37 2010 UTC
+++ /trunk/xmpp/poll.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -2,7 +2,7 @@
  #
  #       This file is a part of the XMPP library. It implements  
HTTP-polling.
  #
-# Copyright (c) 2008-2010 Sergei Golovan <sgolovan at nes.ru>
+# Copyright (c) 2008-2013 Sergei Golovan <sgolovan at nes.ru>
  #
  # See the file "license.terms" for information on usage and redistribution
  # of this file, and for a DISCLAMER OF ALL WARRANTIES.
@@ -12,26 +12,27 @@
  package require sha1
  package require http 2

-package require xmpp::transport
+package require xmpp::transport 0.2
  package require xmpp::xml

-package provide xmpp::transport::poll 0.1
+package provide xmpp::transport::poll 0.2

  namespace eval ::xmpp::transport::poll {
      namespace export open abort close reset flush ip outXML outText \
                       openStream closeStream

      ::xmpp::transport::register poll \
-            -opencommand        [namespace code open]       \
-            -abortcommand       [namespace code abort]      \
-            -closecommand       [namespace code close]      \
-            -resetcommand       [namespace code reset]      \
-            -flushcommand       [namespace code flush]      \
-            -ipcommand          [namespace code ip]         \
-            -outxmlcommand      [namespace code outXML]     \
-            -outtextcommand     [namespace code outText]    \
-            -openstreamcommand  [namespace code openStream] \
-            -closestreamcommand [namespace code closeStream]
+            -opencommand         [namespace code open]       \
+            -abortcommand        [namespace code abort]      \
+            -closecommand        [namespace code close]      \
+            -resetcommand        [namespace code reset]      \
+            -flushcommand        [namespace code flush]      \
+            -ipcommand           [namespace code ip]         \
+            -outxmlcommand       [namespace code outXML]     \
+            -outtextcommand      [namespace code outText]    \
+            -openstreamcommand   [namespace code openStream] \
+            -reopenstreamcommand [namespace code openStream] \
+            -closestreamcommand  [namespace code closeStream]

      if {![catch { package require tls 1.4 }]} {
          ::http::register https 443 ::tls::socket
@@ -289,6 +290,8 @@
  #
  # Arguments:
  #       token           Transport token.
+#       -wait bool      (optional, default 0) Wait for the server side to
+#                       close stream.
  #
  # Result:
  #       Empty string.
@@ -296,7 +299,7 @@
  # Side effects:
  #       Sending stream trailer to the server is scheduled.

-proc ::xmpp::transport::poll::closeStream {token} {
+proc ::xmpp::transport::poll::closeStream {token args} {
      variable $token
      upvar 0 $token state

@@ -313,8 +316,16 @@
          }
      }

-    # TODO
-    if {0} {
+    set wait 0
+    foreach {key val} $args {
+        switch -- $key {
+            -wait {
+                set wait $val
+            }
+        }
+    }
+
+    if {$wait} {
          while {[info exists state(wait)] && \
                              ![string equal $state(wait) disconnected]} {
              vwait $token\(wait)
@@ -452,7 +463,7 @@
  #       Empty string.
  #
  # Side effects:
-#       After entering event loop the spaecified command is called.
+#       After entering event loop the specified command is called.

  proc ::xmpp::transport::poll::InXML {cmd xml} {
      after idle $cmd [list $xml]
@@ -471,7 +482,7 @@
  #       Empty string.
  #
  # Side effects:
-#       After entering event loop the spaecified command is called.
+#       After entering event loop the specified command is called.

  proc ::xmpp::transport::poll::InEmpty {cmd} {
      after idle $cmd
@@ -544,7 +555,7 @@
              set secondkey [lindex $state(keys) end]
          }
          set l [llength $state(keys)]
-        set state(keys) [lrange $state(keys) 0 [expr {$l - 2}]]
+        set state(keys) [lrange $state(keys) 0 end-1]

          if {[string length $firstkey]} {
              set firstkey ";$firstkey"
@@ -699,8 +710,14 @@

      Debug $token 2 $try

+    # Option -keepalive 1 (which reuse open sockets - a good thing) doesn't
+    # work well if we do multiple requests in parallel (it's required for
+    # multiuser support), so do open a separate socket for every request
+    # (which creates a lot of overhead, but...)
+
      ::http::geturl $state(-url) \
                     -binary  1 \
+                   -keepalive 0 \
                     -headers $state(proxyAuth) \
                     -query   $query \
                     -timeout $state(-timeout) \
=======================================
--- /trunk/xmpp/sasl.tcl	Fri Nov  8 07:40:42 2013 UTC
+++ /trunk/xmpp/sasl.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -772,6 +772,8 @@
      upvar 0 $token state
      set xlib $state(xlib)

+    ::xmpp::Debug $xlib 2 "$token $featuresList"
+
      if {[info exists state(-username)]} {
          foreach feature $featuresList {
              ::xmpp::xml::split $feature tag xmlns attrs cdata subels
=======================================
--- /trunk/xmpp/tcp.tcl	Thu May 10 20:11:54 2012 UTC
+++ /trunk/xmpp/tcp.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -3,7 +3,7 @@
  #       This file is part of the XMPP library. It provides support for the
  #       XMPP stream over TCP sockets.
  #
-# Copyright (c) 2008-2012 Sergei Golovan <sgolovan at nes.ru>
+# Copyright (c) 2008-2013 Sergei Golovan <sgolovan at nes.ru>
  #
  # See the file "license.terms" for information on usage and redistribution
  # of this file, and for a DISCLAMER OF ALL WARRANTIES.
@@ -11,26 +11,27 @@
  # $Id$

  package require pconnect
-package require xmpp::transport
+package require xmpp::transport 0.2
  package require xmpp::xml

-package provide xmpp::transport::tcp 0.1
+package provide xmpp::transport::tcp 0.2

  namespace eval ::xmpp::transport::tcp {
      namespace export open abort close reset flush ip outXML outText \
                       openStream closeStream

      ::xmpp::transport::register tcp \
-            -opencommand        [namespace code open]       \
-            -abortcommand       [namespace code abort]      \
-            -closecommand       [namespace code close]      \
-            -resetcommand       [namespace code reset]      \
-            -flushcommand       [namespace code flush]      \
-            -ipcommand          [namespace code ip]         \
-            -outxmlcommand      [namespace code outXML]     \
-            -outtextcommand     [namespace code outText]    \
-            -openstreamcommand  [namespace code openStream] \
-            -closestreamcommand [namespace code closeStream]
+            -opencommand         [namespace code open]       \
+            -abortcommand        [namespace code abort]      \
+            -closecommand        [namespace code close]      \
+            -resetcommand        [namespace code reset]      \
+            -flushcommand        [namespace code flush]      \
+            -ipcommand           [namespace code ip]         \
+            -outxmlcommand       [namespace code outXML]     \
+            -outtextcommand      [namespace code outText]    \
+            -openstreamcommand   [namespace code openStream] \
+            -reopenstreamcommand [namespace code openStream] \
+            -closestreamcommand  [namespace code closeStream]
  }

  # ::xmpp::transport::tcp::open --
@@ -299,6 +300,8 @@
  #
  # Arguments:
  #       token           Transport token.
+#       -wait bool      (optional, default 0) Wait for the server side to
+#                       close stream.
  #
  # Result:
  #       Bytelength of a textual representation of a sent header.
@@ -306,19 +309,28 @@
  # Side effects:
  #       Text is sent to the server.

-proc ::xmpp::transport::tcp::closeStream {token} {
+proc ::xmpp::transport::tcp::closeStream {token args} {
      variable $token
      upvar 0 $token state

      set len [outText $token [::xmpp::xml::streamTrailer]]

-    # TODO
-    if {1} {
+    set wait 0
+    foreach {key val} $args {
+        switch -- $key {
+            -wait {
+                set wait $val
+            }
+        }
+    }
+
+    if {!$wait} {
          ::flush $state(sock)
      } else {
          fconfigure $state(sock) -blocking 1
          ::flush $state(sock)
-        vwait $token\(sock)
+        # TODO
+        #vwait $token\(sock)
      }

      return $len
@@ -463,7 +475,7 @@
  #       Empty string.
  #
  # Side effects:
-#       After entering event loop the spaecified command is called.
+#       After entering event loop the specified command is called.

  proc ::xmpp::transport::tcp::InXML {cmd xml} {
      after idle $cmd [list $xml]
@@ -481,7 +493,7 @@
  #       Empty string.
  #
  # Side effects:
-#       After entering event loop the spaecified command is called.
+#       After entering event loop the specified command is called.

  proc ::xmpp::transport::tcp::InEmpty {cmd} {
      after idle $cmd
=======================================
--- /trunk/xmpp/tls.tcl	Thu May 10 20:11:54 2012 UTC
+++ /trunk/xmpp/tls.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -3,7 +3,7 @@
  #       This file is part of the XMPP library. It provides support for the
  #       XMPP stream over TLS encrypted TCP sockets.
  #
-# Copyright (c) 2008-2012 Sergei Golovan <sgolovan at nes.ru>
+# Copyright (c) 2008-2013 Sergei Golovan <sgolovan at nes.ru>
  #
  # See the file "license.terms" for information on usage and redistribution
  # of this file, and for a DISCLAMER OF ALL WARRANTIES.
@@ -13,27 +13,28 @@
  package require tls 1.4

  package require pconnect
-package require xmpp::transport
+package require xmpp::transport 0.2
  package require xmpp::xml

-package provide xmpp::transport::tls 0.1
+package provide xmpp::transport::tls 0.2

  namespace eval ::xmpp::transport::tls {
      namespace export open abort close reset flush ip outXML outText \
                       openStream closeStream import

      ::xmpp::transport::register tls \
-            -opencommand        [namespace code open]        \
-            -abortcommand       [namespace code abort]       \
-            -closecommand       [namespace code close]       \
-            -resetcommand       [namespace code reset]       \
-            -flushcommand       [namespace code flush]       \
-            -ipcommand          [namespace code ip]          \
-            -outxmlcommand      [namespace code outXML]      \
-            -outtextcommand     [namespace code outText]     \
-            -openstreamcommand  [namespace code openStream]  \
-            -closestreamcommand [namespace code closeStream] \
-            -importcommand      [namespace code import]
+            -opencommand         [namespace code open]        \
+            -abortcommand        [namespace code abort]       \
+            -closecommand        [namespace code close]       \
+            -resetcommand        [namespace code reset]       \
+            -flushcommand        [namespace code flush]       \
+            -ipcommand           [namespace code ip]          \
+            -outxmlcommand       [namespace code outXML]      \
+            -outtextcommand      [namespace code outText]     \
+            -openstreamcommand   [namespace code openStream]  \
+            -reopenstreamcommand [namespace code openStream]  \
+            -closestreamcommand  [namespace code closeStream] \
+            -importcommand       [namespace code import]
  }

  # ::xmpp::transport::tls::open --
@@ -428,6 +429,8 @@
  #
  # Arguments:
  #       token           Transport token.
+#       -wait bool      (optional, default 0) Wait for the server side to
+#                       close stream.
  #
  # Result:
  #       Bytelength of a textual representation of a sent header.
@@ -435,19 +438,28 @@
  # Side effects:
  #       Text is sent to the server.

-proc ::xmpp::transport::tls::closeStream {token} {
+proc ::xmpp::transport::tls::closeStream {token args} {
      variable $token
      upvar 0 $token state

      set len [outText $token [::xmpp::xml::streamTrailer]]

-    # TODO
-    if {1} {
+    set wait 0
+    foreach {key val} $args {
+        switch -- $key {
+            -wait {
+                set wait $val
+            }
+        }
+    }
+
+    if {!$wait} {
          ::flush $state(sock)
      } else {
          fconfigure $state(sock) -blocking 1
          ::flush $state(sock)
-        vwait $token\(sock)
+        # TODO
+        #vwait $token\(sock)
      }

      return $len
@@ -590,7 +602,7 @@
  #       Empty string.
  #
  # Side effects:
-#       After entering event loop the spaecified command is called.
+#       After entering event loop the specified command is called.

  proc ::xmpp::transport::tls::InXML {cmd xml} {
      after idle $cmd [list $xml]
@@ -608,7 +620,7 @@
  #       Empty string.
  #
  # Side effects:
-#       After entering event loop the spaecified command is called.
+#       After entering event loop the specified command is called.

  proc ::xmpp::transport::tls::InEmpty {cmd} {
      after idle $cmd
=======================================
--- /trunk/xmpp/transport.tcl	Mon Jan 25 17:14:37 2010 UTC
+++ /trunk/xmpp/transport.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -3,7 +3,7 @@
  #       This file is part of the XMPP library. It implements the XMPP
  #       transports infrastructure.
  #
-# Copyright (c) 2008-2010 Sergei Golovan <sgolovan at nes.ru>
+# Copyright (c) 2008-2013 Sergei Golovan <sgolovan at nes.ru>
  #
  # See the file "license.terms" for information on usage and redistribution
  # of this file, and for a DISCLAMER OF ALL WARRANTIES.
@@ -12,7 +12,7 @@

  package require msgcat

-package provide xmpp::transport 0.1
+package provide xmpp::transport 0.2

  namespace eval ::xmpp::transport {
      namespace export list register unregister use switch
@@ -45,26 +45,28 @@
  #
  # Arguments:
  #       transport                   Transport name.
-#       -opencommand        cmd0    Command to call when opening connection
+#       -opencommand         cmd0   Command to call when opening connection
  #                                   (e.g. TCP socket).
-#       -abortcommand       cmd1    Command to call when aborting  
connection if
+#       -abortcommand        cmd1   Command to call when aborting  
connection if
  #                                   opening is asynchronous.
-#       -closecommand       cmd2    Command to call when closing an opened
+#       -closecommand        cmd2   Command to call when closing an opened
  #                                   connection.
-#       -resetcommand       cmd3    Command to call when resetting an  
opened
+#       -resetcommand        cmd3   Command to call when resetting an  
opened
  #                                   connection (usually it resets XML  
parser).
-#       -flushcommand       cmd4    Command to flush buffer (if any) to a
+#       -flushcommand        cmd4   Command to flush buffer (if any) to a
  #                                   connection.
-#       -outxmlcommand      cmd5    Command which converts XML (e.g.  
returned
+#       -outxmlcommand       cmd5   Command which converts XML (e.g.  
returned
  #                                   by ::xmpp::xml::create) to text and  
sends
  #                                   it to a connection.
-#       -outtextcommand     cmd6    Command which sends raw text to a
+#       -outtextcommand      cmd6   Command which sends raw text to a
  #                                   connection.
-#       -openstreamcommand  cmd7    Command which opens XMPP stream over a
+#       -openstreamcommand   cmd7   Command which opens XMPP stream over a
  #                                   connection.
-#       -closestreamcommand cmd8    Command which closes XMPP stream over a
+#       -reopenstreamcommand cmd8   Command which reopens XMPP stream over  
a
  #                                   connection.
-#       -importcommand      icmd    (optional) Import command
+#       -closestreamcommand  cmd9   Command which closes XMPP stream over a
+#                                   connection.
+#       -importcommand       icmd   (optional) Import command
  #
  # Result:
  #       Transport name in case of success or error if the specified  
transport
@@ -84,16 +86,17 @@

      foreach {key val} $args {
          ::switch -- $key {
-            -opencommand        -
-            -abortcommand       -
-            -closecommand       -
-            -resetcommand       -
-            -flushcommand       -
-            -ipcommand          -
-            -outxmlcommand      -
-            -outtextcommand     -
-            -openstreamcommand  -
-            -closestreamcommand -
+            -opencommand         -
+            -abortcommand        -
+            -closecommand        -
+            -resetcommand        -
+            -flushcommand        -
+            -ipcommand           -
+            -outxmlcommand       -
+            -outtextcommand      -
+            -openstreamcommand   -
+            -reopenstreamcommand -
+            -closestreamcommand  -
              -importcommand {
                  set attrs($key) $val
              }
@@ -113,6 +116,7 @@
                   -outxmlcommand
                   -outtextcommand
                   -openstreamcommand
+                 -reopenstreamcommand
                   -closestreamcommand} {
          if {![info exists attrs($key)]} {
              unset Transports($transport)
@@ -180,8 +184,9 @@
  # Arguments:
  #       token               XMPP transport token.
  #       command             One of open, abort, close, flush, outXML,
-#                           outText, openStream, closeStream (corresponding
-#                           to ::xmpp::transport::register options).
+#                           outText, openStream, reopenStream closeStream
+#                           (corresponding to ::xmpp::transport::register
+#                           options).
  #       args                Arguments depending on command.
  #
  # Result:
@@ -204,15 +209,16 @@
      }

      ::switch -- $command {
-        abort       {set key -abortcommand}
-        close       {set key -closecommand}
-        reset       {set key -resetcommand}
-        flush       {set key -flushcommand}
-        ip          {set key -ipcommand}
-        outXML      {set key -outxmlcommand}
-        outText     {set key -outtextcommand}
-        openStream  {set key -openstreamcommand}
-        closeStream {set key -closestreamcommand}
+        abort        {set key -abortcommand}
+        close        {set key -closecommand}
+        reset        {set key -resetcommand}
+        flush        {set key -flushcommand}
+        ip           {set key -ipcommand}
+        outXML       {set key -outxmlcommand}
+        outText      {set key -outtextcommand}
+        openStream   {set key -openstreamcommand}
+        reopenStream {set key -reopenstreamcommand}
+        closeStream  {set key -closestreamcommand}
          default {
              return -code error [::msgcat::mc "Illegal command \"%s\""  
$command]
          }
=======================================
--- /trunk/xmpp/xmpp.tcl	Mon Sep 27 08:04:55 2010 UTC
+++ /trunk/xmpp/xmpp.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -3,7 +3,7 @@
  #       This file is part of the XMPP library. It implements the main  
library
  #       routines.
  #
-# Copyright (c) 2008-2010 Sergei Golovan <sgolovan at nes.ru>
+# Copyright (c) 2008-2013 Sergei Golovan <sgolovan at nes.ru>
  #
  # See the file "license.terms" for information on usage and redistribution
  # of this file, and for a DISCLAMER OF ALL WARRANTIES.
@@ -13,13 +13,13 @@
  package require msgcat
  package require xmpp::jid
  package require xmpp::xml
-package require xmpp::transport::tcp
+package require xmpp::transport::tcp 0.2
  package require xmpp::streamerror
  package require xmpp::stanzaerror
  package require xmpp::iq
  package require xmpp::presence

-package provide xmpp 0.1
+package provide xmpp 0.1.1

  namespace eval ::xmpp {

@@ -357,7 +357,7 @@

      set state(server) $server

-    eval [list OpenStreamAux $xlib] $args
+    eval [list OpenStreamAux $xlib open] $args
  }

  # ::xmpp::ReopenStream --
@@ -397,7 +397,7 @@
          set vargs {}
      }

-    eval [list OpenStreamAux $xlib \
+    eval [list OpenStreamAux $xlib reopen \
                               -xmlns:stream $state(-xmlns:stream) \
                               -xmlns $state(-xmlns) \
                               -xml:lang $state(-xml:lang)] $vargs $args
@@ -409,8 +409,9 @@
  #       reopening XMPP streams.
  #
  # Arguments:
-#       The same as for openStream (except server which is taken from state
-#       variable).
+#       mode    'open' or 'reopen'.
+#       The others are the same as for openStream (except server which is
+#       taken from state variable).
  #
  # Result:
  #       Empty string in asynchronous mode, session id or error in  
synchronous
@@ -424,7 +425,7 @@
  #       Only stream XMLNS http://etherx.jabber.org/streams is supported.
  #       On the other hand there's no other defined stream XMLNS currently.

-proc ::xmpp::OpenStreamAux {xlib args} {
+proc ::xmpp::OpenStreamAux {xlib mode args} {
      variable $xlib
      upvar 0 $xlib state

@@ -475,7 +476,7 @@
              [namespace code [list GotStream $xlib abort {}]]
      }

-    eval [list transport::use $state(transport) openStream $state(server)]  
\
+    eval [list transport::use $state(transport) ${mode}Stream  
$state(server)] \
           [array get params]

      if {[info exists state(openStreamCommand)]} {
@@ -849,6 +850,7 @@
  #
  # Arguments:
  #       xlib            XMPP token.
+#       -wait bool      (optional, default 0) Wait for the server side.
  #
  # Result:
  #       Length of the sent stream trailer.
@@ -856,7 +858,7 @@
  # Side effects:
  #       XMPP stream trailer is sent to the server.

-proc ::xmpp::closeStream {xlib} {
+proc ::xmpp::closeStream {xlib args} {
      variable $xlib
      upvar 0 $xlib state

@@ -864,7 +866,7 @@
      Debug $xlib 2 "$msg"
      CallBack $xlib log output text $msg

-    transport::use $state(transport) closeStream
+    eval [list transport::use $state(transport) closeStream] $args
  }

  # ::xmpp::EndOfParse --
@@ -987,6 +989,8 @@
  #
  # Arguments:
  #       xlib            XMPP token.
+#       -wait bool      (optional, default 0) Wait for the server side when
+#                       closing XMPP stream.
  #
  # Result:
  #       Empty string.
@@ -996,7 +1000,7 @@
  #       aborts any pending operation, closes the XMPP stream and channel,  
and
  #       clears the token state.

-proc ::xmpp::disconnect {xlib} {
+proc ::xmpp::disconnect {xlib args} {
      variable $xlib
      upvar 0 $xlib state

@@ -1013,7 +1017,7 @@
                  catch {unset state(abortCommand)}
              }

-            if {[catch {closeStream $xlib} msg]} {
+            if {[catch {eval [list closeStream $xlib] $args} msg]} {
                  Debug $xlib 1 "Closing stream failed: $msg"
              }
              if {[catch {transport::use $state(transport) close} msg]} {
=======================================
--- /trunk/xmpp/zlib.tcl	Fri May 18 05:31:17 2012 UTC
+++ /trunk/xmpp/zlib.tcl	Tue Dec  3 11:10:12 2013 UTC
@@ -3,7 +3,7 @@
  #       This file is part of the XMPP library. It provides support for the
  #       XMPP stream over Zlib compressed TCP sockets.
  #
-# Copyright (c) 2008-2012 Sergei Golovan <sgolovan at nes.ru>
+# Copyright (c) 2008-2013 Sergei Golovan <sgolovan at nes.ru>
  #
  # See the file "license.terms" for information on usage and redistribution
  # of this file, and for a DISCLAMER OF ALL WARRANTIES.
@@ -53,27 +53,28 @@
  }

  package require pconnect
-package require xmpp::transport
+package require xmpp::transport 0.2
  package require xmpp::xml

-package provide xmpp::transport::zlib 0.1
+package provide xmpp::transport::zlib 0.2

  namespace eval ::xmpp::transport::zlib {
      namespace export open abort close reset flush ip outXML outText \
                       openStream closeStream import

      ::xmpp::transport::register zlib \
-            -opencommand        [namespace code open]        \
-            -abortcommand       [namespace code abort]       \
-            -closecommand       [namespace code close]       \
-            -resetcommand       [namespace code reset]       \
-            -flushcommand       [namespace code flush]       \
-            -ipcommand          [namespace code ip]          \
-            -outxmlcommand      [namespace code outXML]      \
-            -outtextcommand     [namespace code outText]     \
-            -openstreamcommand  [namespace code openStream]  \
-            -closestreamcommand [namespace code closeStream] \
-            -importcommand      [namespace code import]
+            -opencommand         [namespace code open]        \
+            -abortcommand        [namespace code abort]       \
+            -closecommand        [namespace code close]       \
+            -resetcommand        [namespace code reset]       \
+            -flushcommand        [namespace code flush]       \
+            -ipcommand           [namespace code ip]          \
+            -outxmlcommand       [namespace code outXML]      \
+            -outtextcommand      [namespace code outText]     \
+            -openstreamcommand   [namespace code openStream]  \
+            -reopenstreamcommand [namespace code openStream]  \
+            -closestreamcommand  [namespace code closeStream] \
+            -importcommand       [namespace code import]
  }

  # ::xmpp::transport::zlib::open --
@@ -404,6 +405,8 @@
  #
  # Arguments:
  #       token           Transport token.
+#       -wait bool      (optional, default 0) Wait for the server side to
+#                       close stream.
  #
  # Result:
  #       Bytelength of a textual representation of a sent header.
@@ -411,15 +414,23 @@
  # Side effects:
  #       Text is sent to the server.

-proc ::xmpp::transport::zlib::closeStream {token} {
+proc ::xmpp::transport::zlib::closeStream {token args} {
      variable zlibpack
      variable $token
      upvar 0 $token state

      set len [outText $token [::xmpp::xml::streamTrailer]]

-    # TODO
-    if {1} {
+    set wait 0
+    foreach {key val} $args {
+        switch -- $key {
+            -wait {
+                set wait $val
+            }
+        }
+    }
+
+    if {!$wait} {
          ::flush $state(sock)
          switch -- $zlibpack {
              ztcl {
@@ -440,7 +451,8 @@
                  fconfigure $state(sock) -flush full
              }
          }
-        vwait $token\(sock)
+        # TODO
+        #vwait $token\(sock)
      }

      return $len
@@ -598,7 +610,7 @@
  #       Empty string.
  #
  # Side effects:
-#       After entering event loop the spaecified command is called.
+#       After entering event loop the specified command is called.

  proc ::xmpp::transport::zlib::InXML {cmd xml} {
      after idle $cmd [list $xml]
@@ -616,7 +628,7 @@
  #       Empty string.
  #
  # Side effects:
-#       After entering event loop the spaecified command is called.
+#       After entering event loop the specified command is called.

  proc ::xmpp::transport::zlib::InEmpty {cmd} {
      after idle $cmd


More information about the Tkabber-dev mailing list