// Track the current status of the connection to the server.packagexmppimport("fmt")typestatmgrstruct{newStatuschanStatusnewlistenerchanchanStatus}funcnewStatmgr(clientchan<-Status)*statmgr{s:=statmgr{}s.newStatus=make(chanStatus)s.newlistener=make(chanchanStatus)gos.manager(client)return&s}func(s*statmgr)manager(clientchan<-Status){// We handle this specially, in case the client doesn't read// our final status message.deferfunc(){ifclient!=nil{select{caseclient<-StatusShutdown:default:}close(client)}}()stat:=StatusUnconnectedlisteners:=[]chanStatus{}for{select{casestat=<-s.newStatus:for_,l:=rangelisteners{sendToListener(l,stat)}ifclient!=nil&&stat!=StatusShutdown{client<-stat}casel,ok:=<-s.newlistener:if!ok{return}deferclose(l)sendToListener(l,stat)listeners=append(listeners,l)}}}funcsendToListener(listenchanStatus,statStatus){for{select{case<-listen:caselisten<-stat:return}}}func(cl*Client)setStatus(statStatus){cl.statmgr.setStatus(stat)}func(s*statmgr)setStatus(statStatus){s.newStatus<-stat}func(s*statmgr)newListener()<-chanStatus{l:=make(chanStatus,1)s.newlistener<-lreturnl}func(s*statmgr)close(){close(s.newlistener)}func(s*statmgr)awaitStatus(waitForStatus)error{// BUG(chris): This routine leaks one channel each time it's// called. Listeners are never removed.l:=s.newListener()forcurrent:=rangel{ifcurrent==waitFor{returnnil}ifcurrent==StatusShutdown{break}ifcurrent>waitFor{returnnil}}returnfmt.Errorf("shut down waiting for status change")}