xmpp/roster.go
changeset 128 8342afcffc92
parent 126 367e76b3028e
child 134 80b764fa2f08
equal deleted inserted replaced
127:a8f9a0c07fc8 128:8342afcffc92
     6 
     6 
     7 // This file contains support for roster management, RFC 3921, Section 7.
     7 // This file contains support for roster management, RFC 3921, Section 7.
     8 
     8 
     9 import (
     9 import (
    10 	"encoding/xml"
    10 	"encoding/xml"
       
    11 	"reflect"
    11 )
    12 )
    12 
    13 
    13 // Roster query/result
    14 // Roster query/result
    14 type RosterQuery struct {
    15 type RosterQuery struct {
    15 	XMLName xml.Name     `xml:"jabber:iq:roster query"`
    16 	XMLName xml.Name     `xml:"jabber:iq:roster query"`
    30 	cb func()
    31 	cb func()
    31 }
    32 }
    32 
    33 
    33 type Roster struct {
    34 type Roster struct {
    34 	Extension
    35 	Extension
    35 	get chan []RosterItem
    36 	get       chan []RosterItem
    36 	callbacks chan rosterCb
    37 	callbacks chan rosterCb
    37 	toServer chan Stanza
    38 	toServer  chan Stanza
    38 }
    39 }
    39 
    40 
    40 type rosterClient struct {
    41 type rosterClient struct {
    41 	rosterChan   <-chan []RosterItem
    42 	rosterChan   <-chan []RosterItem
    42 	rosterUpdate chan<- RosterItem
    43 	rosterUpdate chan<- RosterItem
    43 }
       
    44 
       
    45 // Implicitly becomes part of NewClient's extStanza arg.
       
    46 func newRosterQuery(name *xml.Name) interface{} {
       
    47 	return &RosterQuery{}
       
    48 }
    44 }
    49 
    45 
    50 func (r *Roster) rosterMgr(upd <-chan Stanza) {
    46 func (r *Roster) rosterMgr(upd <-chan Stanza) {
    51 	roster := make(map[string]RosterItem)
    47 	roster := make(map[string]RosterItem)
    52 	waits := make(map[string]func())
    48 	waits := make(map[string]func())
    53 	var snapshot []RosterItem
    49 	var snapshot []RosterItem
    54 	for {
    50 	for {
    55 		select {
    51 		select {
    56 		case stan, ok := <- upd:
    52 		case stan, ok := <-upd:
    57 			if !ok {
    53 			if !ok {
    58 				return
    54 				return
    59 			}
    55 			}
    60 			hdr := stan.GetHeader()
    56 			hdr := stan.GetHeader()
    61 			if f := waits[hdr.Id] ; f != nil {
    57 			if f := waits[hdr.Id]; f != nil {
    62 				delete(waits, hdr.Id)
    58 				delete(waits, hdr.Id)
    63 				f()
    59 				f()
    64 			}
    60 			}
    65 			iq, ok := stan.(*Iq)
    61 			iq, ok := stan.(*Iq)
    66 			if iq.Type != "set" {
    62 			if iq.Type != "set" {
    82 			snapshot = []RosterItem{}
    78 			snapshot = []RosterItem{}
    83 			for _, ri := range roster {
    79 			for _, ri := range roster {
    84 				snapshot = append(snapshot, ri)
    80 				snapshot = append(snapshot, ri)
    85 			}
    81 			}
    86 		case r.get <- snapshot:
    82 		case r.get <- snapshot:
    87 		case cb := <- r.callbacks:
    83 		case cb := <-r.callbacks:
    88 			waits[cb.id] = cb.cb
    84 			waits[cb.id] = cb.cb
    89 		}
    85 		}
    90 	}
    86 	}
    91 }
    87 }
    92 
    88 
   102 	}
    98 	}
   103 	send := func(in <-chan Stanza, out chan<- Stanza) {
    99 	send := func(in <-chan Stanza, out chan<- Stanza) {
   104 		defer close(out)
   100 		defer close(out)
   105 		for {
   101 		for {
   106 			select {
   102 			select {
   107 			case stan, ok := <- in:
   103 			case stan, ok := <-in:
   108 				if !ok {
   104 				if !ok {
   109 					return
   105 					return
   110 				}
   106 				}
   111 				out <- stan
   107 				out <- stan
   112 			case stan := <- r.toServer:
   108 			case stan := <-r.toServer:
   113 				out <- stan
   109 				out <- stan
   114 			}
   110 			}
   115 		}
   111 		}
   116 	}
   112 	}
   117 	return recv, send
   113 	return recv, send
   118 }
   114 }
   119 
   115 
   120 func newRosterExt() *Roster {
   116 func newRosterExt() *Roster {
   121 	r := Roster{}
   117 	r := Roster{}
   122 	r.StanzaHandlers = make(map[string]func(*xml.Name) interface{})
   118 	r.StanzaHandlers = make(map[xml.Name]reflect.Type)
   123 	r.StanzaHandlers[NsRoster] = newRosterQuery
   119 	rName := xml.Name{Space: NsRoster, Local: "query"}
       
   120 	r.StanzaHandlers[rName] = reflect.TypeOf(RosterQuery{})
   124 	r.RecvFilter, r.SendFilter = r.makeFilters()
   121 	r.RecvFilter, r.SendFilter = r.makeFilters()
   125 	r.get = make(chan []RosterItem)
   122 	r.get = make(chan []RosterItem)
   126 	r.callbacks = make(chan rosterCb)
   123 	r.callbacks = make(chan rosterCb)
   127 	r.toServer = make(chan Stanza)
   124 	r.toServer = make(chan Stanza)
   128 	return &r
   125 	return &r