2022-10-12 13:31:45 +02:00
|
|
|
package ui
|
|
|
|
|
|
|
|
import (
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/conman"
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/log"
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/procmon"
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/ui/protocol"
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
"google.golang.org/grpc"
|
|
|
|
"google.golang.org/grpc/encoding/gzip"
|
|
|
|
)
|
|
|
|
|
|
|
|
// NewWarningAlert builts a new warning alert
|
|
|
|
func NewWarningAlert(what protocol.Alert_What, data interface{}) *protocol.Alert {
|
|
|
|
return NewAlert(protocol.Alert_WARNING, what, protocol.Alert_SHOW_ALERT, protocol.Alert_MEDIUM, data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewErrorAlert builts a new error alert
|
|
|
|
func NewErrorAlert(what protocol.Alert_What, data interface{}) *protocol.Alert {
|
|
|
|
return NewAlert(protocol.Alert_ERROR, what, protocol.Alert_SHOW_ALERT, protocol.Alert_HIGH, data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewAlert builts a new generic alert
|
|
|
|
func NewAlert(atype protocol.Alert_Type, what protocol.Alert_What, action protocol.Alert_Action, prio protocol.Alert_Priority, data interface{}) *protocol.Alert {
|
|
|
|
a := &protocol.Alert{
|
|
|
|
Id: uint64(time.Now().UnixNano()),
|
|
|
|
Type: atype,
|
|
|
|
Action: action,
|
|
|
|
What: what,
|
|
|
|
Priority: prio,
|
|
|
|
}
|
|
|
|
|
|
|
|
switch what {
|
|
|
|
case protocol.Alert_KERNEL_EVENT:
|
|
|
|
|
|
|
|
switch data.(type) {
|
|
|
|
case procmon.Process:
|
|
|
|
a.Data = &protocol.Alert_Proc{
|
|
|
|
data.(*procmon.Process).Serialize(),
|
|
|
|
}
|
|
|
|
case string:
|
|
|
|
a.Data = &protocol.Alert_Text{data.(string)}
|
|
|
|
a.Action = protocol.Alert_SHOW_ALERT
|
|
|
|
}
|
|
|
|
case protocol.Alert_CONNECTION:
|
|
|
|
a.Data = &protocol.Alert_Conn{
|
|
|
|
data.(*conman.Connection).Serialize(),
|
|
|
|
}
|
|
|
|
case protocol.Alert_GENERIC:
|
|
|
|
a.Data = &protocol.Alert_Text{data.(string)}
|
|
|
|
}
|
|
|
|
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendInfoAlert sends an info alert
|
|
|
|
func (c *Client) SendInfoAlert(data interface{}) {
|
|
|
|
c.PostAlert(protocol.Alert_INFO, protocol.Alert_GENERIC, protocol.Alert_SHOW_ALERT, protocol.Alert_LOW, data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendWarningAlert sends an warning alert
|
|
|
|
func (c *Client) SendWarningAlert(data interface{}) {
|
|
|
|
c.PostAlert(protocol.Alert_WARNING, protocol.Alert_GENERIC, protocol.Alert_SHOW_ALERT, protocol.Alert_MEDIUM, data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SendErrorAlert sends an error alert
|
|
|
|
func (c *Client) SendErrorAlert(data interface{}) {
|
|
|
|
c.PostAlert(protocol.Alert_ERROR, protocol.Alert_GENERIC, protocol.Alert_SHOW_ALERT, protocol.Alert_HIGH, data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// alertsDispatcher waits to be connected to the GUI.
|
|
|
|
// Once connected, dispatches all the queued alerts.
|
|
|
|
func (c *Client) alertsDispatcher() {
|
2022-12-09 17:03:02 +01:00
|
|
|
queuedAlerts := make(chan protocol.Alert, 32)
|
2022-10-12 13:31:45 +02:00
|
|
|
connected := false
|
|
|
|
|
2022-12-09 17:03:02 +01:00
|
|
|
isQueueFull := func(qdAlerts chan protocol.Alert) bool { return len(qdAlerts) > 31 }
|
2022-10-12 13:31:45 +02:00
|
|
|
isQueueEmpty := func(qdAlerts chan protocol.Alert) bool { return len(qdAlerts) == 0 }
|
|
|
|
queueAlert := func(qdAlerts chan protocol.Alert, pbAlert protocol.Alert) {
|
|
|
|
if isQueueFull(qdAlerts) {
|
|
|
|
v := <-qdAlerts
|
|
|
|
// empty queue before adding a new one
|
|
|
|
log.Debug("Discarding queued alert (%d): %v", len(qdAlerts), v)
|
|
|
|
}
|
|
|
|
select {
|
|
|
|
case qdAlerts <- pbAlert:
|
|
|
|
default:
|
|
|
|
log.Debug("Alert not sent to queue, full? (%d)", len(qdAlerts))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case pbAlert := <-c.alertsChan:
|
|
|
|
if !connected {
|
|
|
|
queueAlert(queuedAlerts, pbAlert)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
c.dispatchAlert(pbAlert)
|
|
|
|
case ready := <-c.isConnected:
|
|
|
|
connected = ready
|
|
|
|
if ready {
|
|
|
|
log.Important("UI connected, dispathing queued alerts: %d", len(c.alertsChan))
|
|
|
|
for {
|
|
|
|
if isQueueEmpty(queuedAlerts) {
|
|
|
|
// no more queued alerts, exit
|
|
|
|
break
|
|
|
|
}
|
|
|
|
c.dispatchAlert(<-queuedAlerts)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Client) dispatchAlert(pbAlert protocol.Alert) {
|
2023-12-31 20:12:44 +01:00
|
|
|
c.RLock()
|
|
|
|
isDisconnected := c.client == nil
|
|
|
|
c.RUnlock()
|
|
|
|
if isDisconnected {
|
2022-10-12 13:31:45 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
|
|
c.client.PostAlert(ctx, &pbAlert, grpc.UseCompressor(gzip.Name))
|
|
|
|
cancel()
|
|
|
|
}
|