parent
							
								
									f21db8eaa8
								
							
						
					
					
						commit
						29cf678106
					
				|  | @ -52,12 +52,8 @@ func main() { | ||||||
| 		DisableTimestamp: !config.Log.Timestamp, | 		DisableTimestamp: !config.Log.Timestamp, | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	// just for more beautiful config file - jere
 |  | ||||||
| 	config.XMPP.EndpointURL = config.EndpointURL |  | ||||||
| 	config.XMPP.JWTSecret = config.JWTSecret |  | ||||||
| 
 |  | ||||||
| 	go func() { | 	go func() { | ||||||
| 		if err := config.XMPP.Run(); err != nil { | 		if err := config.XMPP.Run(config.JWTSecret, config.EndpointURL); err != nil { | ||||||
| 			log.Panicf("startup xmpp: %v", err) | 			log.Panicf("startup xmpp: %v", err) | ||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
							
								
								
									
										143
									
								
								gateway/xmpp.go
								
								
								
								
							
							
						
						
									
										143
									
								
								gateway/xmpp.go
								
								
								
								
							|  | @ -10,8 +10,11 @@ import ( | ||||||
| 	"mellium.im/xmlstream" | 	"mellium.im/xmlstream" | ||||||
| 	"mellium.im/xmpp" | 	"mellium.im/xmpp" | ||||||
| 	"mellium.im/xmpp/component" | 	"mellium.im/xmpp/component" | ||||||
|  | 	"mellium.im/xmpp/disco" | ||||||
|  | 	"mellium.im/xmpp/disco/info" | ||||||
| 	"mellium.im/xmpp/jid" | 	"mellium.im/xmpp/jid" | ||||||
| 	"mellium.im/xmpp/mux" | 	"mellium.im/xmpp/mux" | ||||||
|  | 	"mellium.im/xmpp/ping" | ||||||
| 	"mellium.im/xmpp/stanza" | 	"mellium.im/xmpp/stanza" | ||||||
| 
 | 
 | ||||||
| 	"dev.sum7.eu/genofire/unified-push-xmpp/messages" | 	"dev.sum7.eu/genofire/unified-push-xmpp/messages" | ||||||
|  | @ -21,13 +24,10 @@ type XMPPService struct { | ||||||
| 	Addr    string `toml:"address"` | 	Addr    string `toml:"address"` | ||||||
| 	JID     string `toml:"jid"` | 	JID     string `toml:"jid"` | ||||||
| 	Secret  string `toml:"secret"` | 	Secret  string `toml:"secret"` | ||||||
| 	// hidden here for beautiful config file
 |  | ||||||
| 	EndpointURL string    `toml:"-"` |  | ||||||
| 	JWTSecret   JWTSecret `toml"-"` |  | ||||||
| 	session *xmpp.Session | 	session *xmpp.Session | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (s *XMPPService) Run() error { | func (s *XMPPService) Run(jwt JWTSecret, endpoint string) error { | ||||||
| 	var err error | 	var err error | ||||||
| 	j := jid.MustParse(s.JID) | 	j := jid.MustParse(s.JID) | ||||||
| 	ctx := context.TODO() | 	ctx := context.TODO() | ||||||
|  | @ -53,17 +53,94 @@ func (s *XMPPService) Run() error { | ||||||
| 	}() | 	}() | ||||||
| 	log.Infof("connected with %s", s.session.LocalAddr()) | 	log.Infof("connected with %s", s.session.LocalAddr()) | ||||||
| 	return s.session.Serve(mux.New( | 	return s.session.Serve(mux.New( | ||||||
| 		// register - get + set
 | 		disco.Handle(), | ||||||
| 		mux.IQFunc(stanza.SetIQ, xml.Name{Local: messages.LocalRegister, Space: messages.Space}, s.handleRegister), | 		ping.Handle(), | ||||||
| 		mux.IQFunc(stanza.GetIQ, xml.Name{Local: messages.LocalRegister, Space: messages.Space}, s.handleRegister), | 		XMPPUpHandle(jwt, endpoint), | ||||||
| 		// unregister - get + set
 |  | ||||||
| 		mux.IQFunc(stanza.SetIQ, xml.Name{Local: messages.LocalUnregister, Space: messages.Space}, s.handleUnregister), |  | ||||||
| 		mux.IQFunc(stanza.GetIQ, xml.Name{Local: messages.LocalUnregister, Space: messages.Space}, s.handleUnregister), |  | ||||||
| 		// mux.IQFunc("", xml.Name{}, s.handleDisco),
 |  | ||||||
| 	)) | 	)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (s *XMPPService) handleRegister(iq stanza.IQ, t xmlstream.TokenReadEncoder, start *xml.StartElement) error { | // SendMessage of an UP Notification
 | ||||||
|  | func (s *XMPPService) SendMessage(to jid.JID, publicToken, content string) error { | ||||||
|  | 	log.WithFields(map[string]interface{}{ | ||||||
|  | 		"to":          to.String(), | ||||||
|  | 		"publicToken": publicToken, | ||||||
|  | 	}).Debug("forward message to xmpp") | ||||||
|  | 	return s.session.Encode(context.TODO(), messages.Message{ | ||||||
|  | 		Message: stanza.Message{ | ||||||
|  | 			To:   to, | ||||||
|  | 			From: jid.MustParse(s.JID), | ||||||
|  | 			// Type: stanza.ChatMessage,
 | ||||||
|  | 			Type: stanza.NormalMessage, | ||||||
|  | 		}, | ||||||
|  | 		PublicToken: publicToken, | ||||||
|  | 		Body:        content, | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // XMPPUpHandler struct
 | ||||||
|  | // for handling UnifiedPush specifical requests
 | ||||||
|  | type XMPPUpHandler struct { | ||||||
|  | 	jwtSecret JWTSecret | ||||||
|  | 	endpoint  string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // XMPPUpHandle - setup UnfiedPush handler to mux
 | ||||||
|  | func XMPPUpHandle(jwt JWTSecret, endpoint string) mux.Option { | ||||||
|  | 	return func(m *mux.ServeMux) { | ||||||
|  | 		s := &XMPPUpHandler{jwtSecret: jwt, endpoint: endpoint} | ||||||
|  | 		// register - get + set - need direct handler (not IQFunc) to bind ForIdentities and ForFeatures to disco
 | ||||||
|  | 		mux.IQ(stanza.SetIQ, xml.Name{Local: messages.LocalRegister, Space: messages.Space}, s)(m) | ||||||
|  | 		mux.IQ(stanza.GetIQ, xml.Name{Local: messages.LocalRegister, Space: messages.Space}, s)(m) | ||||||
|  | 		// unregister - get + set
 | ||||||
|  | 		mux.IQFunc(stanza.SetIQ, xml.Name{Local: messages.LocalUnregister, Space: messages.Space}, s.handleUnregister)(m) | ||||||
|  | 		mux.IQFunc(stanza.GetIQ, xml.Name{Local: messages.LocalUnregister, Space: messages.Space}, s.handleUnregister)(m) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	upIdentity = info.Identity{ | ||||||
|  | 		Category: "pubsub", | ||||||
|  | 		Type:     "push", | ||||||
|  | 		Name:     "Unified Push over XMPP", | ||||||
|  | 	} | ||||||
|  | 	upFeature = info.Feature{Var: messages.Space} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // ForIdentities disco handler
 | ||||||
|  | func (h *XMPPUpHandler) ForIdentities(node string, f func(info.Identity) error) error { | ||||||
|  | 	if node != "" { | ||||||
|  | 		log.Debugf("response disco feature for %s", node) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	var err error | ||||||
|  | 	err = f(upIdentity) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	log.Debug("response disco identity") | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ForFeatures disco handler
 | ||||||
|  | func (h *XMPPUpHandler) ForFeatures(node string, f func(info.Feature) error) error { | ||||||
|  | 	if node != "" { | ||||||
|  | 		log.Debugf("response disco feature for %s", node) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	var err error | ||||||
|  | 	err = f(upFeature) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	log.Debug("response disco feature") | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // HandleIQ - handleRegister for UnifiedPush request
 | ||||||
|  | func (h *XMPPUpHandler) HandleIQ(iq stanza.IQ, t xmlstream.TokenReadEncoder, start *xml.StartElement) error { | ||||||
|  | 	if start.Name.Local != "register" || start.Name.Space != messages.Space { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
| 	reply := messages.RegisterIQ{ | 	reply := messages.RegisterIQ{ | ||||||
| 		IQ: stanza.IQ{ | 		IQ: stanza.IQ{ | ||||||
| 			ID:   iq.ID, | 			ID:   iq.ID, | ||||||
|  | @ -92,19 +169,21 @@ func (s *XMPPService) handleRegister(iq stanza.IQ, t xmlstream.TokenReadEncoder, | ||||||
| 		reply.Register.Error = &messages.ErrorData{Body: "no token"} | 		reply.Register.Error = &messages.ErrorData{Body: "no token"} | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	endpointToken, err := s.JWTSecret.Generate(iq.From, publicToken) | 	endpointToken, err := h.jwtSecret.Generate(iq.From, publicToken) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Errorf("unable entpointToken generation: %v", err) | 		log.Errorf("unable entpointToken generation: %v", err) | ||||||
| 		reply.Register.Error = &messages.ErrorData{Body: "endpointToken error on gateway"} | 		reply.Register.Error = &messages.ErrorData{Body: "endpointToken error on gateway"} | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| 	endpoint := s.EndpointURL + "/UP?token=" + endpointToken | 	endpoint := h.endpoint + "/UP?token=" + endpointToken | ||||||
| 	reply.IQ.Type = stanza.ResultIQ | 	reply.IQ.Type = stanza.ResultIQ | ||||||
| 	reply.Register.Endpoint = &messages.EndpointData{Body: endpoint} | 	reply.Register.Endpoint = &messages.EndpointData{Body: endpoint} | ||||||
| 	log.Debugf("generate respone: %v", endpoint) | 	log.Debugf("generate respone: %v", endpoint) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| func (s *XMPPService) handleUnregister(iq stanza.IQ, t xmlstream.TokenReadEncoder, start *xml.StartElement) error { | 
 | ||||||
|  | // handleUnregister for UnifiedPush request
 | ||||||
|  | func (h *XMPPUpHandler) handleUnregister(iq stanza.IQ, t xmlstream.TokenReadEncoder, start *xml.StartElement) error { | ||||||
| 	reply := messages.UnregisterIQ{ | 	reply := messages.UnregisterIQ{ | ||||||
| 		IQ: stanza.IQ{ | 		IQ: stanza.IQ{ | ||||||
| 			ID:   iq.ID, | 			ID:   iq.ID, | ||||||
|  | @ -123,37 +202,3 @@ func (s *XMPPService) handleUnregister(iq stanza.IQ, t xmlstream.TokenReadEncode | ||||||
| 	reply.Unregister.Error = "not implemented" | 	reply.Unregister.Error = "not implemented" | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 |  | ||||||
| func (s *XMPPService) handleDisco(iq stanza.IQ, t xmlstream.TokenReadEncoder, start *xml.StartElement) error { |  | ||||||
| 	reply := stanza.IQ{ |  | ||||||
| 		ID:   iq.ID, |  | ||||||
| 		Type: stanza.ErrorIQ, |  | ||||||
| 		From: iq.To, |  | ||||||
| 		To:   iq.From, |  | ||||||
| 	} |  | ||||||
| 	defer func() { |  | ||||||
| 		if err := t.Encode(reply); err != nil { |  | ||||||
| 			log.Errorf("sending response: %v", err) |  | ||||||
| 		} |  | ||||||
| 	}() |  | ||||||
| 	log.Debugf("recieved iq: %v", iq) |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // SendMessage of an UP Notification
 |  | ||||||
| func (s *XMPPService) SendMessage(to jid.JID, publicToken, content string) error { |  | ||||||
| 	log.WithFields(map[string]interface{}{ |  | ||||||
| 		"to":          to.String(), |  | ||||||
| 		"publicToken": publicToken, |  | ||||||
| 	}).Debug("forward message to xmpp") |  | ||||||
| 	return s.session.Encode(context.TODO(), messages.Message{ |  | ||||||
| 		Message: stanza.Message{ |  | ||||||
| 			To:   to, |  | ||||||
| 			From: jid.MustParse(s.JID), |  | ||||||
| 			// Type: stanza.ChatMessage,
 |  | ||||||
| 			Type: stanza.NormalMessage, |  | ||||||
| 		}, |  | ||||||
| 		PublicToken: publicToken, |  | ||||||
| 		Body:        content, |  | ||||||
| 	}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue