safing-portmaster/base/api/client/message.go
Daniel Hååvi 80664d1a27
Restructure modules ()
* Move portbase into monorepo

* Add new simple module mgr

* [WIP] Switch to new simple module mgr

* Add StateMgr and more worker variants

* [WIP] Switch more modules

* [WIP] Switch more modules

* [WIP] swtich more modules

* [WIP] switch all SPN modules

* [WIP] switch all service modules

* [WIP] Convert all workers to the new module system

* [WIP] add new task system to module manager

* [WIP] Add second take for scheduling workers

* [WIP] Add FIXME for bugs in new scheduler

* [WIP] Add minor improvements to scheduler

* [WIP] Add new worker scheduler

* [WIP] Fix more bug related to new module system

* [WIP] Fix start handing of the new module system

* [WIP] Improve startup process

* [WIP] Fix minor issues

* [WIP] Fix missing subsystem in settings

* [WIP] Initialize managers in constructor

* [WIP] Move module event initialization to constrictors

* [WIP] Fix setting for enabling and disabling the SPN module

* [WIP] Move API registeration into module construction

* [WIP] Update states mgr for all modules

* [WIP] Add CmdLine operation support

* Add state helper methods to module group and instance

* Add notification and module status handling to status package

* Fix starting issues

* Remove pilot widget and update security lock to new status data

* Remove debug logs

* Improve http server shutdown

* Add workaround for cleanly shutting down firewall+netquery

* Improve logging

* Add syncing states with notifications for new module system

* Improve starting, stopping, shutdown; resolve FIXMEs/TODOs

* [WIP] Fix most unit tests

* Review new module system and fix minor issues

* Push shutdown and restart events again via API

* Set sleep mode via interface

* Update example/template module

* [WIP] Fix spn/cabin unit test

* Remove deprecated UI elements

* Make log output more similar for the logging transition phase

* Switch spn hub and observer cmds to new module system

* Fix log sources

* Make worker mgr less error prone

* Fix tests and minor issues

* Fix observation hub

* Improve shutdown and restart handling

* Split up big connection.go source file

* Move varint and dsd packages to structures repo

* Improve expansion test

* Fix linter warnings

* Fix interception module on windows

* Fix linter errors

---------

Co-authored-by: Vladimir Stoilov <vladimir@safing.io>
2024-08-09 18:15:48 +03:00

95 lines
2 KiB
Go

package client
import (
"bytes"
"errors"
"github.com/tevino/abool"
"github.com/safing/structures/container"
"github.com/safing/structures/dsd"
)
// ErrMalformedMessage is returned when a malformed message was encountered.
var ErrMalformedMessage = errors.New("malformed message")
// Message is an API message.
type Message struct {
OpID string
Type string
Key string
RawValue []byte
Value interface{}
sent *abool.AtomicBool
}
// ParseMessage parses the given raw data and returns a Message.
func ParseMessage(data []byte) (*Message, error) {
parts := bytes.SplitN(data, apiSeperatorBytes, 4)
if len(parts) < 2 {
return nil, ErrMalformedMessage
}
m := &Message{
OpID: string(parts[0]),
Type: string(parts[1]),
}
switch m.Type {
case MsgOk, MsgUpdate, MsgNew:
// parse key and data
// 127|ok|<key>|<data>
// 127|upd|<key>|<data>
// 127|new|<key>|<data>
if len(parts) != 4 {
return nil, ErrMalformedMessage
}
m.Key = string(parts[2])
m.RawValue = parts[3]
case MsgDelete:
// parse key
// 127|del|<key>
if len(parts) != 3 {
return nil, ErrMalformedMessage
}
m.Key = string(parts[2])
case MsgWarning, MsgError:
// parse message
// 127|error|<message>
// 127|warning|<message> // error with single record, operation continues
if len(parts) != 3 {
return nil, ErrMalformedMessage
}
m.Key = string(parts[2])
case MsgDone, MsgSuccess:
// nothing more to do
// 127|success
// 127|done
}
return m, nil
}
// Pack serializes a message into a []byte slice.
func (m *Message) Pack() ([]byte, error) {
c := container.New([]byte(m.OpID), apiSeperatorBytes, []byte(m.Type))
if m.Key != "" {
c.Append(apiSeperatorBytes)
c.Append([]byte(m.Key))
if len(m.RawValue) > 0 {
c.Append(apiSeperatorBytes)
c.Append(m.RawValue)
} else if m.Value != nil {
var err error
m.RawValue, err = dsd.Dump(m.Value, dsd.JSON)
if err != nil {
return nil, err
}
c.Append(apiSeperatorBytes)
c.Append(m.RawValue)
}
}
return c.CompileData(), nil
}