Compare commits

...

8 Commits

6 changed files with 144 additions and 41 deletions

View File

@ -91,7 +91,9 @@ func (newLine *DatabaseLine) UpdateLine() bool {
} }
if newLine.SteamPwd == "" { if newLine.SteamPwd == "" {
oldLine := GetLine(newLine.Jid) oldLine := GetLine(newLine.Jid)
newLine.SteamPwd = oldLine.SteamPwd if oldLine != nil {
newLine.SteamPwd = oldLine.SteamPwd
}
} }
_, err = stmt.Exec(newLine.SteamLogin, newLine.SteamPwd, debug, newLine.Jid) _, err = stmt.Exec(newLine.SteamLogin, newLine.SteamPwd, debug, newLine.Jid)
if err != nil { if err != nil {

View File

@ -1,6 +1,8 @@
package gateway package gateway
import ( import (
"sync"
"github.com/Philipp15b/go-steam" "github.com/Philipp15b/go-steam"
) )
@ -23,20 +25,35 @@ type GatewayInfo struct {
SteamLoginInfo *steam.LogOnDetails SteamLoginInfo *steam.LogOnDetails
SteamClient *steam.Client SteamClient *steam.Client
SentryFile string SentryFile string
FriendSteamId map[string]*StatusSteamFriend friendSteamId *FriendSteam
SteamConnecting bool SteamConnecting bool
Deleting bool Deleting bool
// XMPP // XMPP
XMPP_JID_Client string XMPP_JID_Client string
XMPP_Out chan interface{} XMPP_Out chan interface{}
XMPP_Connected_Client map[string]bool xmpp_Connected_Client *XmppConnectedClient
DebugMessage bool DebugMessage bool
XMPP_IQ_RemoteRoster_Request map[string]string xmpp_IQ_RemoteRoster_Request *XmppRemoteRosterRequest
AllowEditRoster bool AllowEditRoster bool
ChatstateNotificationData chan string ChatstateNotificationData chan string
} }
type FriendSteam struct {
steamId map[string]*StatusSteamFriend
sync.RWMutex
}
type XmppConnectedClient struct {
client map[string]bool
sync.RWMutex
}
type XmppRemoteRosterRequest struct {
request map[string]string
sync.RWMutex
}
type StatusSteamFriend struct { type StatusSteamFriend struct {
XMPP_Status string XMPP_Status string
XMPP_Type string XMPP_Type string
@ -68,3 +85,82 @@ func (g *GatewayInfo) Delete() {
g.Disconnect() g.Disconnect()
} }
func (s *GatewayInfo) CreateSteamIds() {
s.friendSteamId = &FriendSteam{steamId: make(map[string]*StatusSteamFriend)}
}
func (s *GatewayInfo) GetFriendSteamId(steamId string) *StatusSteamFriend {
s.friendSteamId.RLock()
defer s.friendSteamId.RUnlock()
return s.friendSteamId.steamId[steamId]
}
func (s *GatewayInfo) GetAllFriendSteamId() []string {
s.friendSteamId.RLock()
defer s.friendSteamId.RUnlock()
allSteamIds := make([]string, len(s.friendSteamId.steamId))
i := 0
for steamId := range s.friendSteamId.steamId {
allSteamIds[i] = steamId
i++
}
return allSteamIds
}
func (s *GatewayInfo) SetFriendSteamId(steamId string, status *StatusSteamFriend) {
s.friendSteamId.Lock()
s.friendSteamId.steamId[steamId] = status
s.friendSteamId.Unlock()
}
func (s *GatewayInfo) RemoveFriendSteamId(steamId string) {
s.friendSteamId.Lock()
delete(s.friendSteamId.steamId, steamId)
s.friendSteamId.Unlock()
}
func (s *GatewayInfo) CreateXmppConnectedClient() {
s.xmpp_Connected_Client = &XmppConnectedClient{client: make(map[string]bool)}
}
func (s *GatewayInfo) SetXmppConnectedClient(jid string) {
s.xmpp_Connected_Client.Lock()
s.xmpp_Connected_Client.client[jid] = true
s.xmpp_Connected_Client.Unlock()
}
func (s *GatewayInfo) RemoveXmppConnectedClient(jid string) {
s.xmpp_Connected_Client.Lock()
delete(s.xmpp_Connected_Client.client, jid)
s.xmpp_Connected_Client.Unlock()
}
func (s *GatewayInfo) GetLenXmppConnectedClient() int {
s.xmpp_Connected_Client.RLock()
defer s.xmpp_Connected_Client.RUnlock()
return len(s.xmpp_Connected_Client.client)
}
func (s *GatewayInfo) CreateXmppRemoteRosterRequest() {
s.xmpp_IQ_RemoteRoster_Request = &XmppRemoteRosterRequest{request: make(map[string]string)}
}
func (s *GatewayInfo) SetXmppRemoteRosterRequest(iqId, value string) {
s.xmpp_IQ_RemoteRoster_Request.Lock()
s.xmpp_IQ_RemoteRoster_Request.request[iqId] = value
s.xmpp_IQ_RemoteRoster_Request.Unlock()
}
func (s *GatewayInfo) RemoveXmppRemoteRosterRequest(iqId string) {
s.xmpp_IQ_RemoteRoster_Request.Lock()
delete(s.xmpp_IQ_RemoteRoster_Request.request, iqId)
s.xmpp_IQ_RemoteRoster_Request.Unlock()
}
func (s *GatewayInfo) GetXmppRemoteRosterRequest(iqId string) string {
s.xmpp_IQ_RemoteRoster_Request.RLock()
defer s.xmpp_IQ_RemoteRoster_Request.RUnlock()
return s.xmpp_IQ_RemoteRoster_Request.request[iqId]
}

View File

@ -127,15 +127,16 @@ func (g *GatewayInfo) mainSteam() {
status = Status_extended_away status = Status_extended_away
tpye = Type_available tpye = Type_available
} }
if _, ok := g.FriendSteamId[steamId]; !ok { steamFriendId := g.GetFriendSteamId(steamId)
if steamFriendId == nil {
// Send subscribsion // Send subscribsion
g.SendXmppPresence(status, Type_subscribe, "", steamId+"@"+XmppJidComponent, gameName, name) g.SendXmppPresence(status, Type_subscribe, "", steamId+"@"+XmppJidComponent, gameName, name)
g.FriendSteamId[steamId] = &StatusSteamFriend{XMPP_Status: status, XMPP_Type: tpye} g.SetFriendSteamId(steamId, &StatusSteamFriend{XMPP_Status: status, XMPP_Type: tpye})
} else { } else {
g.FriendSteamId[steamId].XMPP_Status = status steamFriendId.XMPP_Status = status
g.FriendSteamId[steamId].XMPP_Type = tpye steamFriendId.XMPP_Type = tpye
g.FriendSteamId[steamId].SteamGameName = gameName steamFriendId.SteamGameName = gameName
g.FriendSteamId[steamId].SteamName = name steamFriendId.SteamName = name
} }
g.SendXmppPresence(status, tpye, "", steamId+"@"+XmppJidComponent, gameName, name) g.SendXmppPresence(status, tpye, "", steamId+"@"+XmppJidComponent, gameName, name)
@ -226,9 +227,9 @@ func (g *GatewayInfo) SteamDisconnect() {
func (g *GatewayInfo) DisconnectAllSteamFriend() { func (g *GatewayInfo) DisconnectAllSteamFriend() {
logger.Debug.Printf("[%s] Disconnect all Steam friend", g.XMPP_JID_Client) logger.Debug.Printf("[%s] Disconnect all Steam friend", g.XMPP_JID_Client)
for sid := range g.FriendSteamId { for _, sid := range g.GetAllFriendSteamId() {
g.SendXmppPresence(Status_offline, Type_unavailable, "", sid+"@"+XmppJidComponent, "", "") g.SendXmppPresence(Status_offline, Type_unavailable, "", sid+"@"+XmppJidComponent, "", "")
delete(g.FriendSteamId, sid) g.RemoveFriendSteamId(sid)
} }
} }

View File

@ -56,14 +56,14 @@ func (g *GatewayInfo) ReceivedXMPP_Presence(presence *xmpp.Presence) {
if len(jid) == 2 { if len(jid) == 2 {
// Resource exist —> client speaking // Resource exist —> client speaking
if presence.Type == Type_available { if presence.Type == Type_available {
g.XMPP_Connected_Client[presence.From] = true g.SetXmppConnectedClient(presence.From)
} else if presence.Type == Type_unavailable { } else if presence.Type == Type_unavailable {
delete(g.XMPP_Connected_Client, presence.From) g.RemoveXmppConnectedClient(presence.From)
} }
} }
if presence.Type == Type_probe { if presence.Type == Type_probe {
steamFriendStatus := g.FriendSteamId[steamJid[0]] steamFriendStatus := g.GetFriendSteamId(steamJid[0])
if steamFriendStatus != nil { if steamFriendStatus != nil {
g.SendXmppPresence(steamFriendStatus.XMPP_Status, steamFriendStatus.XMPP_Type, "", steamJid[0]+"@"+XmppJidComponent, steamFriendStatus.SteamGameName, steamFriendStatus.SteamName) g.SendXmppPresence(steamFriendStatus.XMPP_Status, steamFriendStatus.XMPP_Type, "", steamJid[0]+"@"+XmppJidComponent, steamFriendStatus.SteamGameName, steamFriendStatus.SteamName)
} }
@ -79,10 +79,13 @@ func (g *GatewayInfo) ReceivedXMPP_Presence(presence *xmpp.Presence) {
// Destination is gateway itself // Destination is gateway itself
if presence.Type == Type_unavailable { if presence.Type == Type_unavailable {
// Disconnect // Disconnect
if len(g.XMPP_Connected_Client) <= 0 { if g.GetLenXmppConnectedClient() <= 0 {
g.Disconnect() g.Disconnect()
} }
} else { } else {
if presence.Type == Type_available {
g.addUserIntoRoster(presence.To, "xmpp4steam gateway")
}
go g.SteamConnect() go g.SteamConnect()
transfertPresence = true transfertPresence = true
} }
@ -133,10 +136,11 @@ func (g *GatewayInfo) ReceivedXMPP_Message(message *xmpp.Message) {
} }
} }
func (g *GatewayInfo) ReceivedXMPP_IQ(iq *xmpp.Iq) bool { func (g *GatewayInfo) ReceivedXMPP_IQ(iq *xmpp.IQ) bool {
ret := false ret := false
if g.XMPP_IQ_RemoteRoster_Request[iq.Id] == RemoteRosterRequestPermission { remoteRosterRequestValue := g.GetXmppRemoteRosterRequest(iq.ID)
delete(g.XMPP_IQ_RemoteRoster_Request, iq.Id) if remoteRosterRequestValue == RemoteRosterRequestPermission {
g.RemoveXmppRemoteRosterRequest(iq.ID)
if iq.Type == xmpp.IQTypeError && iq.Error.Condition() == xmpp.ErrorForbidden { if iq.Type == xmpp.IQTypeError && iq.Error.Condition() == xmpp.ErrorForbidden {
g.AllowEditRoster = false g.AllowEditRoster = false
@ -157,15 +161,15 @@ func (g *GatewayInfo) ReceivedXMPP_IQ(iq *xmpp.Iq) bool {
logger.Info.Printf("Check roster edition authorisation by querying roster's user") logger.Info.Printf("Check roster edition authorisation by querying roster's user")
// Remote roster namespace may not be supported (like prosody), so we send a roster query // Remote roster namespace may not be supported (like prosody), so we send a roster query
iqId := NextIqId() iqId := NextIqId()
g.XMPP_IQ_RemoteRoster_Request[iqId] = RemoteRosterRequestRoster g.SetXmppRemoteRosterRequest(iqId, RemoteRosterRequestRoster)
iqSend := &xmpp.Iq{Id: iqId, Type: xmpp.IQTypeGet, From: iq.To, To: iq.From} iqSend := &xmpp.IQ{ID: iqId, Type: xmpp.IQTypeGet, From: iq.To, To: iq.From}
iqSend.PayloadEncode(&xmpp.RosterQuery{}) iqSend.PayloadEncode(&xmpp.RosterQuery{})
g.XMPP_Out <- iqSend g.XMPP_Out <- iqSend
} }
ret = true ret = true
} else if g.XMPP_IQ_RemoteRoster_Request[iq.Id] == RemoteRosterRequestRoster { } else if remoteRosterRequestValue == RemoteRosterRequestRoster {
delete(g.XMPP_IQ_RemoteRoster_Request, iq.Id) g.RemoveXmppRemoteRosterRequest(iq.ID)
if iq.Type == xmpp.IQTypeResult && iq.PayloadName().Space == xmpp.NSRoster { if iq.Type == xmpp.IQTypeResult && iq.PayloadName().Space == xmpp.NSRoster {
g.AllowEditRoster = true g.AllowEditRoster = true
} else { } else {
@ -218,7 +222,7 @@ func (g *GatewayInfo) SendXmppPresence(status, tpye, to, from, message, nick str
} }
func (g *GatewayInfo) addUserIntoRoster(jid, nick string) { func (g *GatewayInfo) addUserIntoRoster(jid, nick string) {
iq := xmpp.Iq{To: g.XMPP_JID_Client, Type: xmpp.IQTypeSet, Id: NextIqId()} iq := xmpp.IQ{To: g.XMPP_JID_Client, Type: xmpp.IQTypeSet, ID: NextIqId()}
query := &xmpp.RosterQuery{} query := &xmpp.RosterQuery{}
queryItem := &xmpp.RosterItem{JID: jid, Name: nick, Subscription: xmpp.RosterSubscriptionBoth} queryItem := &xmpp.RosterItem{JID: jid, Name: nick, Subscription: xmpp.RosterSubscriptionBoth}
queryItem.Groupes = append(queryItem.Groupes, XmppGroupUser) queryItem.Groupes = append(queryItem.Groupes, XmppGroupUser)
@ -231,7 +235,7 @@ func (g *GatewayInfo) addUserIntoRoster(jid, nick string) {
func (g *GatewayInfo) removeAllUserFromRoster() { func (g *GatewayInfo) removeAllUserFromRoster() {
// Friends // Friends
for steamId := range g.SteamClient.Social.Friends.GetCopy() { for steamId := range g.SteamClient.Social.Friends.GetCopy() {
iq := xmpp.Iq{To: g.XMPP_JID_Client, Type: xmpp.IQTypeSet, Id: NextIqId()} iq := xmpp.IQ{To: g.XMPP_JID_Client, Type: xmpp.IQTypeSet, ID: NextIqId()}
query := &xmpp.RosterQuery{} query := &xmpp.RosterQuery{}
query.Items = append(query.Items, *&xmpp.RosterItem{JID: steamId.ToString() + "@" + XmppJidComponent, Subscription: xmpp.RosterSubscriptionRemove}) query.Items = append(query.Items, *&xmpp.RosterItem{JID: steamId.ToString() + "@" + XmppJidComponent, Subscription: xmpp.RosterSubscriptionRemove})
iq.PayloadEncode(query) iq.PayloadEncode(query)
@ -239,7 +243,7 @@ func (g *GatewayInfo) removeAllUserFromRoster() {
g.XMPP_Out <- iq g.XMPP_Out <- iq
} }
// Myself // Myself
iq := xmpp.Iq{To: g.XMPP_JID_Client, Type: xmpp.IQTypeSet, Id: NextIqId()} iq := xmpp.IQ{To: g.XMPP_JID_Client, Type: xmpp.IQTypeSet, ID: NextIqId()}
query := &xmpp.RosterQuery{} query := &xmpp.RosterQuery{}
query.Items = append(query.Items, *&xmpp.RosterItem{JID: g.SteamClient.SteamId().ToString() + "@" + XmppJidComponent, Subscription: xmpp.RosterSubscriptionRemove}) query.Items = append(query.Items, *&xmpp.RosterItem{JID: g.SteamClient.SteamId().ToString() + "@" + XmppJidComponent, Subscription: xmpp.RosterSubscriptionRemove})
iq.PayloadEncode(query) iq.PayloadEncode(query)

View File

@ -26,7 +26,7 @@ var (
identityClients = &xmpp.DiscoIdentity{Category: "client", Type: "pc", Name: "Steam client"} identityClients = &xmpp.DiscoIdentity{Category: "client", Type: "pc", Name: "Steam client"}
) )
func execDiscoCommand(iq *xmpp.Iq) { func execDiscoCommand(iq *xmpp.IQ) {
logger.Info.Printf("Ad-Hoc Command") logger.Info.Printf("Ad-Hoc Command")
// Disco Ad-Hoc // Disco Ad-Hoc
@ -67,7 +67,7 @@ func execDiscoCommand(iq *xmpp.Iq) {
comp.Out <- reply comp.Out <- reply
} }
func execDisco(iq *xmpp.Iq) { func execDisco(iq *xmpp.IQ) {
logger.Info.Printf("Disco Feature") logger.Info.Printf("Disco Feature")
jidBareTo := strings.SplitN(iq.To, "/", 2)[0] jidBareTo := strings.SplitN(iq.To, "/", 2)[0]
@ -111,7 +111,7 @@ func execDisco(iq *xmpp.Iq) {
} }
} }
func execCommandAdHoc(iq *xmpp.Iq) { func execCommandAdHoc(iq *xmpp.IQ) {
adHoc := &xmpp.AdHocCommand{} adHoc := &xmpp.AdHocCommand{}
iq.PayloadDecode(adHoc) iq.PayloadDecode(adHoc)
jidBareFrom := strings.SplitN(iq.From, "/", 2)[0] jidBareFrom := strings.SplitN(iq.From, "/", 2)[0]
@ -317,7 +317,7 @@ func getXFormRegistration(steamLogin string) *xmpp.AdHocXForm {
return cmdXForm return cmdXForm
} }
func getUser(fields []xmpp.AdHocField, iq *xmpp.Iq) *database.DatabaseLine { func getUser(fields []xmpp.AdHocField, iq *xmpp.IQ) *database.DatabaseLine {
// Command Auth Code // Command Auth Code
steamLogin := "" steamLogin := ""
steamPwd := "" steamPwd := ""

View File

@ -64,8 +64,8 @@ func mainXMPP() {
jidBareTo := strings.SplitN(v.To, "/", 2)[0] jidBareTo := strings.SplitN(v.To, "/", 2)[0]
g := MapGatewayInfo[jidBareFrom] g := MapGatewayInfo[jidBareFrom]
if g != nil { if g != nil {
if jidBareTo == jid.Domain { if jidBareTo == jid.Domain || v.Type == gateway.Type_probe {
// Forward only if presence is for component, in order to to not spam set presence on Steam // Forward only if presence is for component or is type probe, in order not to spam set presence on Steam
logger.Debug.Printf("Presence transferred to %s", jidBareFrom) logger.Debug.Printf("Presence transferred to %s", jidBareFrom)
go g.ReceivedXMPP_Presence(v) go g.ReceivedXMPP_Presence(v)
} }
@ -85,7 +85,7 @@ func mainXMPP() {
SendMessage(v.From, "", "Your are not registred. If you want to register, please, send an Ad-Hoc command.") SendMessage(v.From, "", "Your are not registred. If you want to register, please, send an Ad-Hoc command.")
} }
case *xmpp.Iq: case *xmpp.IQ:
jidBareFrom := strings.SplitN(v.From, "/", 2)[0] jidBareFrom := strings.SplitN(v.From, "/", 2)[0]
jidBareTo := strings.SplitN(v.To, "/", 2)[0] jidBareTo := strings.SplitN(v.To, "/", 2)[0]
@ -166,7 +166,7 @@ func must(v interface{}, err error) interface{} {
return v return v
} }
func treatmentNSRegister(iq *xmpp.Iq) { func treatmentNSRegister(iq *xmpp.IQ) {
reply := iq.Response(xmpp.IQTypeResult) reply := iq.Response(xmpp.IQTypeResult)
jidBareFrom := strings.SplitN(iq.From, "/", 2)[0] jidBareFrom := strings.SplitN(iq.From, "/", 2)[0]
registerQuery := &xmpp.RegisterQuery{} registerQuery := &xmpp.RegisterQuery{}
@ -208,12 +208,12 @@ func treatmentNSRegister(iq *xmpp.Iq) {
comp.Out <- reply comp.Out <- reply
} }
func treatmentNSPing(iq *xmpp.Iq) { func treatmentNSPing(iq *xmpp.IQ) {
reply := iq.Response(xmpp.IQTypeResult) reply := iq.Response(xmpp.IQTypeResult)
comp.Out <- reply comp.Out <- reply
} }
func sendNotSupportedFeature(iq *xmpp.Iq) { func sendNotSupportedFeature(iq *xmpp.IQ) {
if iq.Type != xmpp.IQTypeError && iq.Type != xmpp.IQTypeResult { if iq.Type != xmpp.IQTypeError && iq.Type != xmpp.IQTypeResult {
reply := iq.Response(xmpp.IQTypeError) reply := iq.Response(xmpp.IQTypeError)
reply.PayloadEncode(xmpp.NewError("cancel", xmpp.ErrorFeatureNotImplemented, "")) reply.PayloadEncode(xmpp.NewError("cancel", xmpp.ErrorFeatureNotImplemented, ""))
@ -277,13 +277,13 @@ func AddNewUser(jidUser, steamLogin, steamPwd string, debugMessage bool) {
g.SteamPassword = steamPwd g.SteamPassword = steamPwd
g.XMPP_JID_Client = jidUser g.XMPP_JID_Client = jidUser
g.SentryFile = gateway.SentryDirectory + jidUser g.SentryFile = gateway.SentryDirectory + jidUser
g.FriendSteamId = make(map[string]*gateway.StatusSteamFriend) g.CreateSteamIds()
g.Deleting = false g.Deleting = false
g.XMPP_Out = comp.Out g.XMPP_Out = comp.Out
g.XMPP_Connected_Client = make(map[string]bool) g.CreateXmppConnectedClient()
g.DebugMessage = debugMessage g.DebugMessage = debugMessage
g.XMPP_IQ_RemoteRoster_Request = make(map[string]string) g.CreateXmppRemoteRosterRequest()
g.AllowEditRoster = false g.AllowEditRoster = false
MapGatewayInfo[jidUser] = g MapGatewayInfo[jidUser] = g
@ -292,8 +292,8 @@ func AddNewUser(jidUser, steamLogin, steamPwd string, debugMessage bool) {
logger.Info.Printf("Check roster edition by asking with remote roster manager namespace") logger.Info.Printf("Check roster edition by asking with remote roster manager namespace")
// Ask if remote roster is allow // Ask if remote roster is allow
iqId := gateway.NextIqId() iqId := gateway.NextIqId()
g.XMPP_IQ_RemoteRoster_Request[iqId] = gateway.RemoteRosterRequestPermission g.SetXmppRemoteRosterRequest(iqId, gateway.RemoteRosterRequestPermission)
iq := xmpp.Iq{To: jidUser, From: jid.Domain, Type: xmpp.IQTypeGet, Id: iqId} iq := xmpp.IQ{To: jidUser, From: jid.Domain, Type: xmpp.IQTypeGet, ID: iqId}
// iq.PayloadEncode(&xmpp.RosterQuery{}) // iq.PayloadEncode(&xmpp.RosterQuery{})
iq.PayloadEncode(&xmpp.RemoteRosterManagerQuery{Reason: "Manage contacts in the Steam contact list", Type: xmpp.RemoteRosterManagerTypeRequest}) iq.PayloadEncode(&xmpp.RemoteRosterManagerQuery{Reason: "Manage contacts in the Steam contact list", Type: xmpp.RemoteRosterManagerTypeRequest})
comp.Out <- iq comp.Out <- iq