Repository navigation
Expand file tree
/
Copy pathhandler.go
More file actions
144 lines (119 loc) · 3.78 KB
/
Copy pathhandler.go
File metadata and controls
144 lines (119 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package mhp
import (
"crypto/ed25519"
"log"
"time"
)
// HandlerResult indicates how an envelope was handled.
type HandlerResult int
const (
HandlerAccepted HandlerResult = iota
HandlerRejected
HandlerDeduped
)
// HandlerFriendStore provides friend lookup for the mhp handler.
type HandlerFriendStore interface {
IsFriend(agentID string) bool
GetPublicKey(agentID string) []byte
}
// FriendRequestCallback is called when a friend_request envelope is received from a new agent.
type FriendRequestCallback func(env *Envelope, payload *FriendRequestPayload)
// FriendAcceptCallback is called when a friend_accept envelope is received.
type FriendAcceptCallback func(env *Envelope, payload *FriendAcceptPayload)
// FriendRejectCallback is called when a friend_reject envelope is received.
type FriendRejectCallback func(env *Envelope, payload *FriendRejectPayload)
// HandlerConfig holds configuration for the mhp handler.
type HandlerConfig struct {
AgentID string
FriendStore HandlerFriendStore
OnFriendRequest FriendRequestCallback
OnFriendAccept FriendAcceptCallback
OnFriendReject FriendRejectCallback
}
// Handler processes inbound mhp Envelopes.
type Handler struct {
config HandlerConfig
dedup *MessageDedup
}
// NewHandler creates a new mhp handler.
func NewHandler(config HandlerConfig) *Handler {
return &Handler{
config: config,
dedup: NewMessageDedup(),
}
}
// HandleEnvelope processes an inbound envelope and returns a HandlerResult.
func (h *Handler) HandleEnvelope(env *Envelope) HandlerResult {
// Check for stale envelope first.
if time.Since(time.Unix(env.Timestamp, 0)) > MaxMessageAge {
return HandlerRejected
}
// Check for duplicate.
if !h.dedup.CheckAndAdd(env.ID, env.Timestamp) {
return HandlerDeduped
}
if env.To != h.config.AgentID {
log.Printf("mhp: envelope addressed to %s, not us (%s)", env.To, h.config.AgentID)
return HandlerRejected
}
pubKey := h.config.FriendStore.GetPublicKey(env.From)
if pubKey == nil && env.Type != MsgFriendRequest {
log.Printf("mhp: unknown sender %s for type %s", env.From, env.Type)
return HandlerRejected
}
if pubKey != nil {
if err := env.Verify(ed25519.PublicKey(pubKey)); err != nil {
log.Printf("mhp: signature verification failed from %s: %v", env.From, err)
return HandlerRejected
}
}
switch env.Type {
case MsgFriendRequest:
return h.handleFriendRequest(env)
case MsgFriendAccept:
return h.handleFriendAccept(env)
case MsgFriendReject:
return h.handleFriendReject(env)
default:
log.Printf("mhp: unhandled message type %s from %s", env.Type, env.From)
return HandlerRejected
}
}
func (h *Handler) handleFriendRequest(env *Envelope) HandlerResult {
if h.config.OnFriendRequest == nil {
return HandlerRejected
}
payload, err := DecodePayload[FriendRequestPayload](env)
if err != nil {
log.Printf("mhp: failed to decode friend_request payload: %v", err)
return HandlerRejected
}
if h.config.FriendStore.GetPublicKey(env.From) != nil {
log.Printf("mhp: friend request already exists from %s", env.From)
return HandlerRejected
}
h.config.OnFriendRequest(env, payload)
return HandlerAccepted
}
func (h *Handler) handleFriendAccept(env *Envelope) HandlerResult {
payload, err := DecodePayload[FriendAcceptPayload](env)
if err != nil {
log.Printf("mhp: failed to decode friend_accept payload: %v", err)
return HandlerRejected
}
if h.config.OnFriendAccept != nil {
h.config.OnFriendAccept(env, payload)
}
return HandlerAccepted
}
func (h *Handler) handleFriendReject(env *Envelope) HandlerResult {
payload, err := DecodePayload[FriendRejectPayload](env)
if err != nil {
log.Printf("mhp: failed to decode friend_reject payload: %v", err)
return HandlerRejected
}
if h.config.OnFriendReject != nil {
h.config.OnFriendReject(env, payload)
}
return HandlerRejected
}