Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
kdudkov committed Oct 21, 2023
1 parent dea30d5 commit 5705935
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 61 deletions.
21 changes: 17 additions & 4 deletions cmd/goatak_server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,12 @@ func (app *App) MessageProcessor() {
}

func (app *App) route(msg *cot.CotMessage) {
if len(msg.Detail.GetDest()) > 0 {
for _, s := range msg.Detail.GetDest() {
if dest := msg.Detail.GetDest(); len(dest) > 0 {
for _, s := range dest {
app.SendToCallsign(s, msg.TakMessage)
}
} else {
app.SendToAllOther(msg)
app.SendBroadcast(msg)
}
}

Expand Down Expand Up @@ -366,7 +366,7 @@ func (app *App) cleanOldUnits() {
}
}

func (app *App) SendToAllOther(msg *cot.CotMessage) {
func (app *App) SendBroadcast(msg *cot.CotMessage) {
app.ForAllClients(func(ch client.ClientHandler) bool {
if ch.GetName() != msg.From && ch.CanSeeScope(msg.Scope) {
if err := ch.SendMsg(msg.TakMessage); err != nil {
Expand All @@ -384,6 +384,19 @@ func (app *App) SendToCallsign(callsign string, msg *cotproto.TakMessage) {
if err := ch.SendMsg(msg); err != nil {
app.Logger.Errorf("error: %v", err)
}
}
}
return true
})
}

func (app *App) SendToUid(uid string, msg *cotproto.TakMessage) {
app.ForAllClients(func(ch client.ClientHandler) bool {
for c := range ch.GetUids() {
if c == uid {
if err := ch.SendMsg(msg); err != nil {
app.Logger.Errorf("error: %v", err)
}
return false
}
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/goatak_server/processors.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ func (app *App) loggerProcessor(msg *cot.CotMessage) {

func (app *App) removeItemProcessor(msg *cot.CotMessage) {
// t-x-d-d
if msg.Detail != nil && msg.Detail.Has("link") {
uid := msg.Detail.GetFirst("link").GetAttr("uid")
typ := msg.Detail.GetFirst("link").GetAttr("type")
if link := msg.GetFirstLink("p-p"); link != nil {
uid := link.GetAttr("uid")
typ := link.GetAttr("type")
if uid == "" {
app.Logger.Warnf("invalid remove message: %s", msg.Detail)
return
Expand Down
2 changes: 1 addition & 1 deletion cmd/webclient/http_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func addMessageHandler(app *App) func(req *air.Request, res *air.Response) error
}

if msg.Id == "" {
msg.Id = uuid.New().String()
msg.Id = uuid.NewString()
}
app.SendMsg(model.MakeChatMessage(msg))
app.messages.Add(msg)
Expand Down
7 changes: 3 additions & 4 deletions cmd/webclient/processors.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ func (app *App) loggerProcessor(msg *cot.CotMessage) {

func (app *App) removeItemProcessor(msg *cot.CotMessage) {
// t-x-d-d
if msg.Detail != nil && msg.Detail.Has("link") {
uid := msg.Detail.GetFirst("link").GetAttr("uid")
typ := msg.Detail.GetFirst("link").GetAttr("type")
if link := msg.GetFirstLink("p-p"); link != nil {
uid := link.GetAttr("uid")
typ := link.GetAttr("type")
if uid == "" {
app.Logger.Warnf("invalid remove message: %s", msg.Detail)
return
Expand All @@ -60,7 +60,6 @@ func (app *App) removeItemProcessor(msg *cot.CotMessage) {
case model.CONTACT:
app.Logger.Debugf("remove %s by message", uid)
v.SetOffline()
app.processChange(v)
return
case model.UNIT, model.POINT:
app.Logger.Debugf("remove unit/point %s type %s by message", uid, typ)
Expand Down
19 changes: 17 additions & 2 deletions pkg/cot/cotmessage.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ func (m *CotMessage) IsChat() bool {
if m == nil || m.TakMessage == nil {
return false
}
return m.GetType() == "b-t-f" && m.Detail != nil && m.Detail.Has("__chat")
return m.GetType() == "b-t-f"
}

func (m *CotMessage) IsChatReceipt() bool {
if m == nil || m.TakMessage == nil {
return false
}
return (m.GetType() == "b-t-f-r" || m.GetType() == "b-t-f-d") && m.Detail != nil && m.Detail.Has("__chatreceipt")
return m.GetType() == "b-t-f-r" || m.GetType() == "b-t-f-d"
}

func (m *CotMessage) PrintChat() string {
Expand Down Expand Up @@ -161,6 +161,9 @@ func (m *CotMessage) GetLon() float64 {
}

func (m *CotMessage) GetParent() (string, string) {
if m.Detail == nil {
return "", ""
}
for _, link := range m.Detail.GetAll("link") {
if link.GetAttr("relation") == "p-p" {
return link.GetAttr("uid"), link.GetAttr("parent_callsign")
Expand All @@ -169,6 +172,18 @@ func (m *CotMessage) GetParent() (string, string) {
return "", ""
}

func (m *CotMessage) GetFirstLink(relation string) *Node {
if m.Detail == nil {
return nil
}
for _, link := range m.Detail.GetAll("link") {
if link.GetAttr("relation") == relation {
return link
}
}
return nil
}

func TimeFromMillis(ms uint64) time.Time {
return time.Unix(0, 1000000*int64(ms))
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/cot/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ func DetailsFromString(s string) (*Node, error) {
return x, err
}

func (n *Node) AddLink(uid, typ, parent string) {
func (n *Node) AddPpLink(uid, typ, callsign string) {
params := make(map[string]string)
if uid != "" {
params["uid"] = uid
}
if typ != "" {
params["type"] = typ
}
if parent != "" {
params["parent_callsign"] = parent
if callsign != "" {
params["parent_callsign"] = callsign
}
//params["production_time"] = prodTime.UTC().Format(time.RFC3339)
params["relation"] = "p-p"
Expand Down
4 changes: 2 additions & 2 deletions pkg/cot/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func MakeOfflineMsg(uid string, typ string) *cotproto.TakMessage {
msg := BasicMsg("t-x-d-d", uuid.New().String(), time.Minute*3)
msg.CotEvent.How = "h-g-i-g-o"
xd := NewXmlDetails()
xd.AddLink(uid, typ, "")
xd.AddPpLink(uid, typ, "")
msg.CotEvent.Detail = &cotproto.Detail{XmlDetail: xd.AsXMLString()}
return msg
}
Expand All @@ -54,7 +54,7 @@ func MakeDpMsg(uid string, typ string, name string, lat float64, lon float64) *c
msg.CotEvent.Lat = lat
msg.CotEvent.Lon = lon
xd := NewXmlDetails()
xd.AddLink(uid, typ, "")
xd.AddPpLink(uid, typ, "")
msg.CotEvent.Detail = &cotproto.Detail{
XmlDetail: xd.AsXMLString(),
Contact: &cotproto.Contact{Callsign: name},
Expand Down
53 changes: 11 additions & 42 deletions pkg/model/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,41 +78,6 @@ func (m *ChatMessage) String() string {
return fmt.Sprintf("Chat %s (%s) -> %s (%s) \"%s\"", m.From, m.FromUid, m.Chatroom, m.ToUid, m.Text)
}

// direct
// <__chat parent="RootContactGroup" groupOwner="false" chatroom="Cl1" id="{{uid_to}}" senderCallsign="Kott">
// <chatgrp uid0="{{uid_from}}" uid1="{{uid_to}}" id="{{uid_to}}"/></__chat>
// <link uid="{{uid_from}}" type="a-f-G-U-C" relation="p-p"/>
// <remarks source="BAO.F.ATAK.{{uid_from}}" to="{{uid_to}}" time="2021-04-10T16:40:57.445Z">Roger</remarks>
// <__serverdestination destinations="192.168.0.15:4242:tcp:{{uid_from}}"/>
// <marti><dest callsign="Cl1"/></marti>

// chatroom
// <__chat parent="RootContactGroup" groupOwner="false" chatroom="All Chat Rooms" id="All Chat Rooms" senderCallsign="Kott">
// <chatgrp uid0="{{uid_from}}" uid1="All Chat Rooms" id="All Chat Rooms"/></__chat>
// <link uid="{{uid_from}}" type="a-f-G-U-C" relation="p-p"/>
// <remarks source="BAO.F.ATAK.{{uid_from}}" to="All Chat Rooms" time="2021-04-10T16:43:05.294Z">Roger</remarks>
// <__serverdestination destinations="192.168.0.15:4242:tcp:{{uid_from}}"/>

// red
// <__chat parent="TeamGroups" groupOwner="false" chatroom="Red" id="Red" senderCallsign="Kott">
// <chatgrp uid0="ANDROID-dc4a1fb7ad4180be" uid1="ANDROID-05740daaf44f01" id="Red"/></__chat>
// <link uid="ANDROID-dc4a1fb7ad4180be" type="a-f-G-U-C" relation="p-p"/>
// <remarks source="BAO.F.ATAK.ANDROID-dc4a1fb7ad4180be" time="2021-04-10T16:44:29.371Z">at VDO</remarks>
// <__serverdestination destinations="192.168.0.15:4242:tcp:ANDROID-dc4a1fb7ad4180be"/>
// <marti><dest callsign="Cl1"/></marti>

// add contact to group
// <__chat parent="UserGroups" groupOwner="true" messageId="82741635-04dc-413b-9b66-289fde3e22f0" chatroom="j" id="c06c2986-f122-4e85-b213-88498a6fe8bb" senderCallsign="Kott">
// <chatgrp uid0="ANDROID-765a942cbe30d010" uid1="ANDROID-80d62ea2265d8a" id="c06c2986-f122-4e85-b213-88498a6fe8bb"/>
// <hierarchy><group uid="UserGroups" name="Groups">
// <group uid="c06c2986-f122-4e85-b213-88498a6fe8bb" name="j">
// <contact uid="ANDROID-80d62ea2265d8a" name="test1"/>
// <contact uid="ANDROID-765a942cbe30d010" name="Kott"/>
// </group></group></hierarchy></__chat>
// <link uid="ANDROID-765a942cbe30d010" type="a-f-G-U-C" relation="p-p"/>
// <__serverdestination destinations="192.168.1.72:4242:tcp:ANDROID-765a942cbe30d010"/>
// <remarks source="BAO.F.ATAK.ANDROID-765a942cbe30d010" time="2022-04-05T08:26:51.718Z">[UPDATED CONTACTS]</remarks>

func MsgToChat(m *cot.CotMessage) *ChatMessage {
chat := m.Detail.GetFirst("__chat")
if chat == nil {
Expand All @@ -125,19 +90,23 @@ func MsgToChat(m *cot.CotMessage) *ChatMessage {
Parent: chat.GetAttr("parent"),
Chatroom: chat.GetAttr("chatroom"),
From: chat.GetAttr("senderCallsign"),
ToUid: chat.GetAttr("id"),
}

if cg := chat.GetFirst("chatgrp"); cg != nil {
c.FromUid = cg.GetAttr("uid0")
c.ToUid = cg.GetAttr("uid1")
}

for _, dest := range m.Detail.GetFirst("marti").GetAll("dest") {
if dest.GetAttr("callsign") != "" {
c.Direct = true
if link := m.GetFirstLink("p-p"); link != nil {
if uid := link.GetAttr("uid"); uid != "" {
c.FromUid = uid
}
}

if c.Chatroom != c.ToUid {
c.Direct = true
}

if rem := m.Detail.GetFirst("remarks"); rem != nil {
c.Text = html.UnescapeString(rem.GetText())
} else {
Expand All @@ -152,14 +121,14 @@ func MakeChatMessage(c *ChatMessage) *cotproto.TakMessage {
msgUid := fmt.Sprintf("GeoChat.%s.%s.%s", c.FromUid, c.ToUid, c.Id)
msg := cot.BasicMsg("b-t-f", msgUid, time.Second*10)
xd := cot.NewXmlDetails()
xd.AddLink(c.FromUid, "", "")
xd.AddPpLink(c.FromUid, "", "")

chat := xd.AddChild("__chat", map[string]string{"parent": "RootContactGroup", "groupOwner": "false", "chatroom": c.Chatroom, "senderCallsign": c.From, "id": c.ToUid, "messageId": c.Id}, "")
chat := xd.AddChild("__chat", map[string]string{"parent": c.Parent, "groupOwner": "false", "chatroom": c.Chatroom, "senderCallsign": c.From, "id": c.ToUid, "messageId": c.Id}, "")
chat.AddChild("chatgrp", map[string]string{"uid0": c.FromUid, "uid1": c.ToUid, "id": c.ToUid}, "")

xd.AddChild("remarks", map[string]string{"source": "BAO.F.ATAK." + c.FromUid, "to": c.ToUid, "time": t}, html.EscapeString(c.Text))

if c.Chatroom != c.ToUid {
if c.Direct {
marti := xd.AddChild("marti", nil, "")
marti.AddChild("dest", map[string]string{"callsign": c.Chatroom}, "")
}
Expand Down
99 changes: 99 additions & 0 deletions pkg/model/chat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package model

import (
"github.com/kdudkov/goatak/pkg/cot"
"github.com/kdudkov/goatak/pkg/cotproto"
"github.com/magiconair/properties/assert"
"testing"
"time"
)

func TestChat(t *testing.T) {
// user1 (uid1) -> user2 (uid2)

d := "<__chat parent=\"RootContactGroup\" groupOwner=\"false\" messageId=\"4de0262c-633f-46eb-b8e5-5ef1eb1e5e22\" chatroom=\"user2\" id=\"uid2\" senderCallsign=\"user1\">" +
"<chatgrp uid0=\"uid1\" uid1=\"uid2\" id=\"uid2\"/></__chat>" +
"<link uid=\"uid1\" type=\"a-f-G-U-C\" relation=\"p-p\"/>" +
"<__serverdestination destinations=\"1.1.1.1:4242:tcp:uid1\"/>" +
"<remarks source=\"BAO.F.ATAK.uid1\" to=\"uid2\" time=\"2023-10-21T20:28:58.991Z\">at breach</remarks>" +
"<marti><dest callsign=\"user2\"/></marti>"

m := cot.BasicMsg("b-t-f", "GeoChat.uid1.uid2.4de0262c-633f-46eb-b8e5-5ef1eb1e5e22", time.Minute)
xd, _ := cot.DetailsFromString(d)
m.CotEvent.Detail = &cotproto.Detail{XmlDetail: xd.AsXMLString()}
msg := cot.CotMessage{TakMessage: m, Detail: xd}

assert.Equal(t, msg.IsChat(), true)

cm := MsgToChat(&msg)

assert.Equal(t, cm.From, "user1")
assert.Equal(t, cm.FromUid, "uid1")
assert.Equal(t, cm.ToUid, "uid2")
assert.Equal(t, cm.Chatroom, "user2")
assert.Equal(t, cm.Direct, true)
}

func TestBtfd(t *testing.T) {
d := "<__chatreceipt parent=\"RootContactGroup\" groupOwner=\"false\" messageId=\"4de0262c-633f-46eb-b8e5-5ef1eb1e5e22\" chatroom=\"user1\" id=\"uid1\" senderCallsign=\"user2\">" +
"<chatgrp uid0=\"uid2\" uid1=\"uid1\" id=\"uid1\"/></__chatreceipt>" +
"<link uid=\"uid2\" type=\"a-f-G-U-C\" relation=\"p-p\"/>" +
"<__serverdestination destinations=\"2.2.2.2:4242:tcp:uid2\"/>" +
"<marti><dest callsign=\"user1\"/></marti>"

m := cot.BasicMsg("b-t-f-d", "4de0262c-633f-46eb-b8e5-5ef1eb1e5e22", time.Minute)
xd, _ := cot.DetailsFromString(d)
m.CotEvent.Detail = &cotproto.Detail{XmlDetail: xd.AsXMLString()}
msg := cot.CotMessage{TakMessage: m, Detail: xd}

assert.Equal(t, msg.IsChatReceipt(), true)

//cm := MsgToChat(&msg)
//
//assert.Equal(t, cm.From, "user1")
//assert.Equal(t, cm.FromUid, "uid1")
//assert.Equal(t, cm.ToUid, "uid2")
//assert.Equal(t, cm.Chatroom, "user2")
//assert.Equal(t, cm.Direct, true)
}

func TestBtfr(t *testing.T) {
d := "<__chatreceipt parent=\"RootContactGroup\" groupOwner=\"false\" messageId=\"4de0262c-633f-46eb-b8e5-5ef1eb1e5e22\" chatroom=\"user1\" id=\"uid1\" senderCallsign=\"user2\">" +
"<chatgrp uid0=\"uid2\" uid1=\"uid1\" id=\"uid1\"/></__chatreceipt>" +
"<link uid=\"uid2\" type=\"a-f-G-U-C\" relation=\"p-p\"/>" +
"<__serverdestination destinations=\"2.2.2.2:4242:tcp:uid2\"/>" +
"<marti><dest callsign=\"user1\"/></marti>"

m := cot.BasicMsg("b-t-f-r", "4de0262c-633f-46eb-b8e5-5ef1eb1e5e22", time.Minute)
xd, _ := cot.DetailsFromString(d)
m.CotEvent.Detail = &cotproto.Detail{XmlDetail: xd.AsXMLString()}
msg := cot.CotMessage{TakMessage: m, Detail: xd}

assert.Equal(t, msg.IsChatReceipt(), true)
}

func TestMsgRed(t *testing.T) {
// user1 - Red
d := "<__chat parent=\"TeamGroups\" groupOwner=\"false\" messageId=\"9f46716f-c875-43b0-8162-3da74196353f\" chatroom=\"Red\" id=\"Red\" senderCallsign=\"user1\">" +
"<chatgrp uid2=\"uid3\" uid0=\"uid1\" uid1=\"uid2\" id=\"Red\"/></__chat>" +
"<link uid=\"uid1\" type=\"a-f-G-U-C\" relation=\"p-p\"/>" +
"<__serverdestination destinations=\"1.1.1.1:4242:tcp:uid1\"/>" +
"<remarks source=\"BAO.F.ATAK.uid1\" time=\"2023-10-21T21:06:00.852Z\">Roger</remarks>" +
"<marti><dest callsign=\"user2\"/></marti>"

m := cot.BasicMsg("b-t-f", "GeoChat.uid1.Red.9f46716f-c875-43b0-8162-3da74196353f", time.Minute)
xd, _ := cot.DetailsFromString(d)
m.CotEvent.Detail = &cotproto.Detail{XmlDetail: xd.AsXMLString()}
msg := cot.CotMessage{TakMessage: m, Detail: xd}

assert.Equal(t, msg.IsChat(), true)

cm := MsgToChat(&msg)

assert.Equal(t, cm.From, "user1")
assert.Equal(t, cm.FromUid, "uid1")
assert.Equal(t, cm.ToUid, "Red")
assert.Equal(t, cm.Chatroom, "Red")
assert.Equal(t, cm.Direct, false)
assert.Equal(t, cm.Text, "Roger")
}

0 comments on commit 5705935

Please sign in to comment.