mirror of
https://codeberg.org/cunicu/cunicu.git
synced 2025-10-05 08:47:03 +08:00
131 lines
3.2 KiB
Go
131 lines
3.2 KiB
Go
package hooks
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
|
|
"go.uber.org/zap"
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
"google.golang.org/protobuf/encoding/protojson"
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
"github.com/stv0g/cunicu/pkg/config"
|
|
"github.com/stv0g/cunicu/pkg/core"
|
|
"github.com/stv0g/cunicu/pkg/daemon/feature/epdisc"
|
|
"github.com/stv0g/cunicu/pkg/util/buildinfo"
|
|
"github.com/stv0g/cunicu/pkg/wg"
|
|
|
|
icex "github.com/stv0g/cunicu/pkg/ice"
|
|
hooksproto "github.com/stv0g/cunicu/pkg/proto/feature/hooks"
|
|
rpcproto "github.com/stv0g/cunicu/pkg/proto/rpc"
|
|
)
|
|
|
|
type WebHook struct {
|
|
*config.WebHookSetting
|
|
|
|
logger *zap.Logger
|
|
}
|
|
|
|
func (h *Interface) NewWebHook(cfg *config.WebHookSetting) {
|
|
hk := &WebHook{
|
|
WebHookSetting: cfg,
|
|
logger: h.logger.Named("web").With(
|
|
zap.Any("url", cfg.URL),
|
|
),
|
|
}
|
|
|
|
h.logger.Debug("Created new web hook", zap.Any("hook", hk))
|
|
|
|
h.registerHook(hk)
|
|
}
|
|
|
|
func (h *WebHook) run(msg proto.Message) {
|
|
req := &http.Request{
|
|
Method: h.Method,
|
|
URL: &h.URL.URL,
|
|
Header: http.Header{},
|
|
}
|
|
|
|
req.Header.Add("user-agent", buildinfo.UserAgent())
|
|
req.Header.Add("content-type", "application/json")
|
|
|
|
for key, value := range h.Headers {
|
|
req.Header.Add(key, value)
|
|
}
|
|
|
|
mo := protojson.MarshalOptions{
|
|
Multiline: true,
|
|
Indent: " ",
|
|
UseProtoNames: true,
|
|
EmitUnpopulated: false,
|
|
}
|
|
|
|
if buf, err := mo.Marshal(msg); err == nil {
|
|
req.Body = io.NopCloser(bytes.NewReader(buf))
|
|
}
|
|
|
|
if resp, err := http.DefaultClient.Do(req); err != nil {
|
|
h.logger.Error("Failed to invoke web-hook", zap.Error(err))
|
|
} else if resp.StatusCode != http.StatusOK {
|
|
h.logger.Warn("Webhook endpoint responded with non-200 code",
|
|
zap.String("status", resp.Status),
|
|
zap.Int("status_code", resp.StatusCode))
|
|
}
|
|
}
|
|
|
|
func (h *WebHook) OnInterfaceAdded(i *core.Interface) {
|
|
go h.run(&hooksproto.WebHookBody{
|
|
Type: rpcproto.EventType_INTERFACE_ADDED,
|
|
Interface: marshalRedactedInterface(i),
|
|
})
|
|
}
|
|
|
|
func (h *WebHook) OnInterfaceRemoved(i *core.Interface) {
|
|
go h.run(&hooksproto.WebHookBody{
|
|
Type: rpcproto.EventType_INTERFACE_REMOVED,
|
|
Interface: marshalRedactedInterface(i),
|
|
})
|
|
}
|
|
|
|
func (h *WebHook) OnInterfaceModified(i *core.Interface, old *wg.Device, m core.InterfaceModifier) {
|
|
go h.run(&hooksproto.WebHookBody{
|
|
Type: rpcproto.EventType_INTERFACE_MODIFIED,
|
|
Interface: marshalRedactedInterface(i),
|
|
Modified: m.Strings(),
|
|
})
|
|
}
|
|
|
|
func (h *WebHook) OnPeerAdded(p *core.Peer) {
|
|
go h.run(&hooksproto.WebHookBody{
|
|
Type: rpcproto.EventType_PEER_ADDED,
|
|
Peer: marshalRedactedPeer(p),
|
|
})
|
|
}
|
|
|
|
func (h *WebHook) OnPeerRemoved(p *core.Peer) {
|
|
go h.run(&hooksproto.WebHookBody{
|
|
Type: rpcproto.EventType_PEER_REMOVED,
|
|
Peer: marshalRedactedPeer(p),
|
|
})
|
|
}
|
|
|
|
func (h *WebHook) OnPeerModified(p *core.Peer, old *wgtypes.Peer, m core.PeerModifier, ipsAdded, ipsRemoved []net.IPNet) {
|
|
go h.run(&hooksproto.WebHookBody{
|
|
Type: rpcproto.EventType_PEER_MODIFIED,
|
|
Peer: marshalRedactedPeer(p),
|
|
Modified: m.Strings(),
|
|
})
|
|
}
|
|
|
|
func (h *WebHook) OnConnectionStateChange(p *epdisc.Peer, new, prev icex.ConnectionState) {
|
|
pm := marshalRedactedPeer(p.Peer)
|
|
pm.Ice = p.Marshal()
|
|
|
|
go h.run(&hooksproto.WebHookBody{
|
|
Type: rpcproto.EventType_PEER_CONNECTION_STATE_CHANGED,
|
|
Peer: pm,
|
|
})
|
|
}
|