Change Client struct to Confirmation struct in order to be more clear

This commit is contained in:
Chteufleur 2016-07-21 22:32:44 +02:00
parent 5ae82dfff6
commit 20dc1ee9e8
5 changed files with 133 additions and 126 deletions

View File

@ -34,7 +34,7 @@ HTTP
* http_timeoute_sec : Define a timeout if user did not give an answer to the request (default: 60) * http_timeoute_sec : Define a timeout if user did not give an answer to the request (default: 60)
### Utilization ### Usage
To ask authorization, just send an HTTP request to the path ``/auth`` with parameters: To ask authorization, just send an HTTP request to the path ``/auth`` with parameters:
* __jid__ : JID of the user (user@host/resource or user@host) * __jid__ : JID of the user (user@host/resource or user@host)
* __domain__ : Domain you want to access * __domain__ : Domain you want to access

View File

@ -74,13 +74,13 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
chanAnswer := make(chan string) chanAnswer := make(chan string)
client := new(xmpp.Client) confirmation := new(xmpp.Confirmation)
client.JID = jid confirmation.JID = jid
client.Method = method confirmation.Method = method
client.Domain = domain confirmation.Domain = domain
client.Transaction = transaction confirmation.Transaction = transaction
client.ChanReply = chanAnswer confirmation.ChanReply = chanAnswer
client.QueryClient() confirmation.SendConfirmation()
select { select {
case answer := <-chanAnswer: case answer := <-chanAnswer:
@ -101,14 +101,14 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
} }
switch client.TypeSend { switch confirmation.TypeSend {
case xmpp.TYPE_SEND_IQ: case xmpp.TYPE_SEND_IQ:
log.Printf("%sDelete IQ", LogDebug) log.Printf("%sDelete IQ", LogDebug)
delete(xmpp.WaitIqMessages, client.IdMap) delete(xmpp.WaitIqMessages, confirmation.IdMap)
case xmpp.TYPE_SEND_MESSAGE: case xmpp.TYPE_SEND_MESSAGE:
log.Printf("%sDelete Message", LogDebug) log.Printf("%sDelete Message", LogDebug)
delete(xmpp.WaitMessageAnswers, client.IdMap) delete(xmpp.WaitMessageAnswers, confirmation.IdMap)
} }
} }

View File

@ -1,93 +0,0 @@
package xmpp
import (
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
"crypto/rand"
"log"
"strconv"
)
const (
dictionary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
REPLY_UNREACHABLE = "reply_unreachable"
REPLY_DENY = "reply_deny"
REPLY_OK = "reply_ok"
TYPE_SEND_MESSAGE = "type_send_message"
TYPE_SEND_IQ = "type_send_iq"
)
type Client struct {
JID string
Method string
Domain string
Transaction string
TypeSend string
IdMap string
ChanReply chan string
}
func (client *Client) QueryClient() {
log.Printf("%sQuery JID %s", LogInfo, client.JID)
isAutoGeneratedTranctionID := false
if client.Transaction == "" {
// Random transaction ID generation
client.Transaction = TransactionID()
isAutoGeneratedTranctionID = true
}
clientJID, _ := xmpp.ParseJID(client.JID)
if clientJID.Resource == "" {
client.askViaMessage(isAutoGeneratedTranctionID)
} else {
client.askViaIQ()
}
}
func (client *Client) askViaIQ() {
stanzaID++
stanzaIDstr := strconv.Itoa(stanzaID)
m := xmpp.Iq{Type: xmpp.IQTypeGet, To: client.JID, From: jid.Domain, Id: stanzaIDstr}
confirm := &xmpp.Confirm{Id: client.Transaction, Method: client.Method, URL: client.Domain}
m.PayloadEncode(confirm)
WaitIqMessages[stanzaIDstr] = client
comp.Out <- m
client.TypeSend = TYPE_SEND_IQ
client.IdMap = stanzaIDstr
}
func (client *Client) askViaMessage(isAutoGeneratedTranctionID bool) {
m := xmpp.Message{From: jid.Domain, To: client.JID, Type: xmpp.MessageTypeNormal}
m.Thread = xmpp.SessionID()
m.Body = client.Domain + " (with method " + client.Method + ") need to validate your identity, do you agree ?"
m.Body += "\nValidation code : " + client.Transaction
if !isAutoGeneratedTranctionID {
// Send only if the transaction ID is not autogenerated
m.Body += "\nPlease check that this code is the same as on " + client.Domain
}
m.Body += "\n\nIf your client doesn't support that functionnality, please send back the validation code to confirm the request."
m.Confir = &xmpp.Confirm{Id: client.Transaction, Method: client.Method, URL: client.Domain}
log.Printf("%sSend message %v", LogInfo, m)
WaitMessageAnswers[client.Transaction] = client
comp.Out <- m
client.TypeSend = TYPE_SEND_MESSAGE
client.IdMap = client.Transaction
}
func TransactionID() string {
var bytes = make([]byte, 8)
if _, err := rand.Read(bytes); err != nil {
panic(err)
}
for k, v := range bytes {
bytes[k] = dictionary[v%byte(len(dictionary))]
}
return string(bytes)
}

100
xmpp/confirmation.go Normal file
View File

@ -0,0 +1,100 @@
package xmpp
import (
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
"crypto/rand"
"log"
"strconv"
)
const (
dictionary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
REPLY_UNREACHABLE = "reply_unreachable"
REPLY_DENY = "reply_deny"
REPLY_OK = "reply_ok"
TYPE_SEND_MESSAGE = "type_send_message"
TYPE_SEND_IQ = "type_send_iq"
)
type Confirmation struct {
JID string
Method string
Domain string
Transaction string
TypeSend string
IdMap string
ChanReply chan string
}
/*
type Transport interface {
Run()
Out(chan interface{})
}
*/
func (confirmation *Confirmation) SendConfirmation() {
log.Printf("%sQuery JID %s", LogInfo, confirmation.JID)
isAutoGeneratedTranctionID := false
if confirmation.Transaction == "" {
// Random transaction ID generation
confirmation.Transaction = TransactionID()
isAutoGeneratedTranctionID = true
}
clientJID, _ := xmpp.ParseJID(confirmation.JID)
if clientJID.Resource == "" {
confirmation.askViaMessage(isAutoGeneratedTranctionID)
} else {
confirmation.askViaIQ()
}
}
func (confirmation *Confirmation) askViaIQ() {
stanzaID++
stanzaIDstr := strconv.Itoa(stanzaID)
m := xmpp.Iq{Type: xmpp.IQTypeGet, To: confirmation.JID, From: jid.Domain, Id: stanzaIDstr}
confirm := &xmpp.Confirm{Id: confirmation.Transaction, Method: confirmation.Method, URL: confirmation.Domain}
m.PayloadEncode(confirm)
WaitIqMessages[stanzaIDstr] = confirmation
comp.Out <- m
confirmation.TypeSend = TYPE_SEND_IQ
confirmation.IdMap = stanzaIDstr
}
func (confirmation *Confirmation) askViaMessage(isAutoGeneratedTranctionID bool) {
m := xmpp.Message{From: jid.Domain, To: confirmation.JID, Type: xmpp.MessageTypeNormal}
m.Thread = xmpp.SessionID()
m.Body = confirmation.Domain + " (with method " + confirmation.Method + ") need to validate your identity, do you agree ?"
m.Body += "\nValidation code : " + confirmation.Transaction
if !isAutoGeneratedTranctionID {
// Send only if the transaction ID is not autogenerated
m.Body += "\nPlease check that this code is the same as on " + confirmation.Domain
}
m.Body += "\n\nIf your client doesn't support that functionnality, please send back the validation code to confirm the request."
m.Confir = &xmpp.Confirm{Id: confirmation.Transaction, Method: confirmation.Method, URL: confirmation.Domain}
log.Printf("%sSend message %v", LogInfo, m)
WaitMessageAnswers[confirmation.Transaction] = confirmation
comp.Out <- m
confirmation.TypeSend = TYPE_SEND_MESSAGE
confirmation.IdMap = confirmation.Transaction
}
func TransactionID() string {
var bytes = make([]byte, 8)
if _, err := rand.Read(bytes); err != nil {
panic(err)
}
for k, v := range bytes {
bytes[k] = dictionary[v%byte(len(dictionary))]
}
return string(bytes)
}

View File

@ -28,8 +28,8 @@ var (
ChanAction = make(chan string) ChanAction = make(chan string)
WaitMessageAnswers = make(map[string]*Client) WaitMessageAnswers = make(map[string]*Confirmation)
WaitIqMessages = make(map[string]*Client) WaitIqMessages = make(map[string]*Confirmation)
Debug = true Debug = true
) )
@ -54,15 +54,15 @@ func mainXMPP() {
case *xmpp.Message: case *xmpp.Message:
confirm := v.Confir confirm := v.Confir
if confirm != nil { if confirm != nil {
client := WaitMessageAnswers[confirm.Id] confirmation := WaitMessageAnswers[confirm.Id]
processConfirm(v, client) processConfirm(v, confirmation)
} else { } else {
// If body is the confirmation id, it will be considerated as accepted. // If body is the confirmation id, it will be considerated as accepted.
// In order to be compatible with all clients. // In order to be compatible with all confirmations.
client := WaitMessageAnswers[v.Body] confirmation := WaitMessageAnswers[v.Body]
jidFrom, _ := xmpp.ParseJID(v.From) jidFrom, _ := xmpp.ParseJID(v.From)
if client != nil && client.JID == jidFrom.Bare() { if confirmation != nil && confirmation.JID == jidFrom.Bare() {
processConfirm(v, client) processConfirm(v, confirmation)
} }
} }
@ -85,15 +85,15 @@ func mainXMPP() {
case xmpp.NSHTTPAuth: case xmpp.NSHTTPAuth:
confirm := &xmpp.Confirm{} confirm := &xmpp.Confirm{}
v.PayloadDecode(confirm) v.PayloadDecode(confirm)
client := WaitIqMessages[v.Id] confirmation := WaitIqMessages[v.Id]
processConfirm(v, client) processConfirm(v, confirmation)
default: default:
// Handle reply iq that doesn't contain HTTP-Auth namespace // Handle reply iq that doesn't contain HTTP-Auth namespace
client := WaitIqMessages[v.Id] confirmation := WaitIqMessages[v.Id]
processConfirm(v, client) processConfirm(v, confirmation)
if client == nil { if confirmation == nil {
reply := v.Response(xmpp.IQTypeError) reply := v.Response(xmpp.IQTypeError)
reply.PayloadEncode(xmpp.NewError("cancel", xmpp.FeatureNotImplemented, "")) reply.PayloadEncode(xmpp.NewError("cancel", xmpp.FeatureNotImplemented, ""))
comp.Out <- reply comp.Out <- reply
@ -106,19 +106,19 @@ func mainXMPP() {
} }
} }
func processConfirm(x interface{}, client *Client) { func processConfirm(x interface{}, confirmation *Confirmation) {
mes, mesOK := x.(*xmpp.Message) mes, mesOK := x.(*xmpp.Message)
iq, iqOK := x.(*xmpp.Iq) iq, iqOK := x.(*xmpp.Iq)
if client != nil { if confirmation != nil {
if mesOK && mes.Error != nil { if mesOK && mes.Error != nil {
// Message error // Message error
errCondition := mes.Error.Condition() errCondition := mes.Error.Condition()
if errCondition == xmpp.ServiceUnavailable { if errCondition == xmpp.ServiceUnavailable {
// unreachable // unreachable
client.ChanReply <- REPLY_UNREACHABLE confirmation.ChanReply <- REPLY_UNREACHABLE
} else { } else {
client.ChanReply <- REPLY_DENY confirmation.ChanReply <- REPLY_DENY
} }
} else if iqOK && iq.Error != nil { } else if iqOK && iq.Error != nil {
@ -126,18 +126,18 @@ func processConfirm(x interface{}, client *Client) {
errCondition := iq.Error.Condition() errCondition := iq.Error.Condition()
if errCondition == xmpp.ServiceUnavailable || errCondition == xmpp.FeatureNotImplemented { if errCondition == xmpp.ServiceUnavailable || errCondition == xmpp.FeatureNotImplemented {
// send by message if client doesn't implemente it // send by message if client doesn't implemente it
client.JID = strings.SplitN(client.JID, "/", 2)[0] confirmation.JID = strings.SplitN(confirmation.JID, "/", 2)[0]
go client.QueryClient() go confirmation.SendConfirmation()
} else if errCondition == xmpp.RemoteServerNotFound { } else if errCondition == xmpp.RemoteServerNotFound {
// unreachable // unreachable
client.ChanReply <- REPLY_UNREACHABLE confirmation.ChanReply <- REPLY_UNREACHABLE
} else { } else {
client.ChanReply <- REPLY_DENY confirmation.ChanReply <- REPLY_DENY
} }
} else { } else {
// No error // No error
client.ChanReply <- REPLY_OK confirmation.ChanReply <- REPLY_OK
} }
} }
} }