roster.go
changeset 74 e619e18dcec3
parent 72 53f15893a1a7
child 75 03a923eb5c01
equal deleted inserted replaced
73:acca351fb8f0 74:e619e18dcec3
     3 // license that can be found in the LICENSE file.
     3 // license that can be found in the LICENSE file.
     4 
     4 
     5 package xmpp
     5 package xmpp
     6 
     6 
     7 import (
     7 import (
       
     8 	"errors"
     8 	"fmt"
     9 	"fmt"
     9 	"os"
    10 
    10 	"xml"
    11 	"encoding/xml"
    11 )
    12 )
    12 
    13 
    13 // This file contains support for roster management, RFC 3921, Section 7.
    14 // This file contains support for roster management, RFC 3921, Section 7.
    14 
    15 
    15 var rosterExt Extension = Extension{StanzaHandlers: map[string]func(*xml.Name) interface{}{NsRoster: newRosterQuery}, Start: startRosterFilter}
    16 var rosterExt Extension = Extension{StanzaHandlers: map[string]func(*xml.Name) interface{}{NsRoster: newRosterQuery}, Start: startRosterFilter}
    44 }
    45 }
    45 
    46 
    46 // Synchronously fetch this entity's roster from the server and cache
    47 // Synchronously fetch this entity's roster from the server and cache
    47 // that information. This is called once from a fairly deep call stack
    48 // that information. This is called once from a fairly deep call stack
    48 // as part of XMPP negotiation.
    49 // as part of XMPP negotiation.
    49 func fetchRoster(client *Client) os.Error {
    50 func fetchRoster(client *Client) error {
    50 	rosterUpdate := rosterClients[client.Uid].rosterUpdate
    51 	rosterUpdate := rosterClients[client.Uid].rosterUpdate
    51 
    52 
    52 	iq := &Iq{From: client.Jid.String(), Id: <-Id, Type: "get",
    53 	iq := &Iq{From: client.Jid.String(), Id: <-Id, Type: "get",
    53 		Nested: []interface{}{RosterQuery{}}}
    54 		Nested: []interface{}{RosterQuery{}}}
    54 	ch := make(chan os.Error)
    55 	ch := make(chan error)
    55 	f := func(st Stanza) bool {
    56 	f := func(st Stanza) bool {
    56 		defer close(ch)
    57 		defer close(ch)
    57 		if iq.Type == "error" {
    58 		if iq.Type == "error" {
    58 			ch <- iq.Error
    59 			ch <- iq.Error
    59 			return false
    60 			return false
    64 				rq = q
    65 				rq = q
    65 				break
    66 				break
    66 			}
    67 			}
    67 		}
    68 		}
    68 		if rq == nil {
    69 		if rq == nil {
    69 			ch <- os.NewError(fmt.Sprintf(
    70 			ch <- errors.New(fmt.Sprintf(
    70 				"Roster query result not query: %v", st))
    71 				"Roster query result not query: %v", st))
    71 			return false
    72 			return false
    72 		}
    73 		}
    73 		for _, item := range rq.Item {
    74 		for _, item := range rq.Item {
    74 			rosterUpdate <- item
    75 			rosterUpdate <- item
   129 	snapshot := []RosterItem{}
   130 	snapshot := []RosterItem{}
   130 	for {
   131 	for {
   131 		select {
   132 		select {
   132 		case newIt := <-rosterUpdate:
   133 		case newIt := <-rosterUpdate:
   133 			if newIt.Subscription == "remove" {
   134 			if newIt.Subscription == "remove" {
   134 				roster[newIt.Jid] = RosterItem{}, false
   135 				delete(roster, newIt.Jid)
   135 			} else {
   136 			} else {
   136 				roster[newIt.Jid] = newIt
   137 				roster[newIt.Jid] = newIt
   137 			}
   138 			}
   138 		case rosterCh <- snapshot:
   139 		case rosterCh <- snapshot:
   139 		}
   140 		}