xmpp.go
changeset 118 fb9bb98a8d70
parent 116 5c6d6d51d3ba
child 119 712aa5780660
equal deleted inserted replaced
116:5c6d6d51d3ba 118:fb9bb98a8d70
    17 	"sync"
    17 	"sync"
    18 )
    18 )
    19 
    19 
    20 const (
    20 const (
    21 	// Version of RFC 3920 that we implement.
    21 	// Version of RFC 3920 that we implement.
    22 	Version = "1.0"
    22 	XMPPVersion = "1.0"
    23 
    23 
    24 	// Various XML namespaces.
    24 	// Various XML namespaces.
    25 	NsClient  = "jabber:client"
    25 	NsClient  = "jabber:client"
    26 	NsStreams = "urn:ietf:params:xml:ns:xmpp-streams"
    26 	NsStreams = "urn:ietf:params:xml:ns:xmpp-streams"
    27 	NsStream  = "http://etherx.jabber.org/streams"
    27 	NsStream  = "http://etherx.jabber.org/streams"
    33 
    33 
    34 	// DNS SRV names
    34 	// DNS SRV names
    35 	serverSrv = "xmpp-server"
    35 	serverSrv = "xmpp-server"
    36 	clientSrv = "xmpp-client"
    36 	clientSrv = "xmpp-client"
    37 )
    37 )
    38 
       
    39 // This channel may be used as a convenient way to generate a unique
       
    40 // id for an iq, message, or presence stanza.
       
    41 var Id <-chan string
       
    42 
       
    43 func init() {
       
    44 	// Start the unique id generator.
       
    45 	idCh := make(chan string)
       
    46 	Id = idCh
       
    47 	go func(ch chan<- string) {
       
    48 		id := int64(1)
       
    49 		for {
       
    50 			str := fmt.Sprintf("id_%d", id)
       
    51 			ch <- str
       
    52 			id++
       
    53 		}
       
    54 	}(idCh)
       
    55 }
       
    56 
    38 
    57 // Extensions can add stanza filters and/or new XML element types.
    39 // Extensions can add stanza filters and/or new XML element types.
    58 type Extension struct {
    40 type Extension struct {
    59 	StanzaHandlers map[string]func(*xml.Name) interface{}
    41 	StanzaHandlers map[string]func(*xml.Name) interface{}
    60 	Start          func(*Client)
    42 	Start          func(*Client)
   133 	if tcp == nil {
   115 	if tcp == nil {
   134 		return nil, err
   116 		return nil, err
   135 	}
   117 	}
   136 
   118 
   137 	cl := new(Client)
   119 	cl := new(Client)
   138 	cl.Uid = <-Id
   120 	cl.Uid = NextId()
   139 	cl.password = password
   121 	cl.password = password
   140 	cl.Jid = *jid
   122 	cl.Jid = *jid
   141 	cl.socket = tcp
   123 	cl.socket = tcp
   142 	cl.handlers = make(chan *stanzaHandler, 100)
   124 	cl.handlers = make(chan *stanzaHandler, 100)
   143 	cl.inputControl = make(chan int)
   125 	cl.inputControl = make(chan int)
   171 	for _, ext := range exts {
   153 	for _, ext := range exts {
   172 		ext.Start(cl)
   154 		ext.Start(cl)
   173 	}
   155 	}
   174 
   156 
   175 	// Initial handshake.
   157 	// Initial handshake.
   176 	hsOut := &stream{To: jid.Domain, Version: Version}
   158 	hsOut := &stream{To: jid.Domain, Version: XMPPVersion}
   177 	cl.xmlOut <- hsOut
   159 	cl.xmlOut <- hsOut
   178 
   160 
   179 	return cl, nil
   161 	return cl, nil
   180 }
   162 }
   181 
   163 
   265 // immediately after creating the Client in order to start the
   247 // immediately after creating the Client in order to start the
   266 // session, retrieve the roster, and broadcast an initial
   248 // session, retrieve the roster, and broadcast an initial
   267 // presence. The presence can be as simple as a newly-initialized
   249 // presence. The presence can be as simple as a newly-initialized
   268 // Presence struct.  See RFC 3921, Section 3.
   250 // Presence struct.  See RFC 3921, Section 3.
   269 func (cl *Client) StartSession(getRoster bool, pr *Presence) error {
   251 func (cl *Client) StartSession(getRoster bool, pr *Presence) error {
   270 	id := <-Id
   252 	id := NextId()
   271 	iq := &Iq{Header: Header{To: cl.Jid.Domain, Id: id, Type: "set",
   253 	iq := &Iq{Header: Header{To: cl.Jid.Domain, Id: id, Type: "set",
   272 		Nested: []interface{}{Generic{XMLName: xml.Name{Space: NsSession, Local: "session"}}}}}
   254 		Nested: []interface{}{Generic{XMLName: xml.Name{Space: NsSession, Local: "session"}}}}}
   273 	ch := make(chan error)
   255 	ch := make(chan error)
   274 	f := func(st Stanza) bool {
   256 	f := func(st Stanza) bool {
   275 		iq, ok := st.(*Iq)
   257 		iq, ok := st.(*Iq)