/
routes.go
175 lines (142 loc) · 5 KB
/
routes.go
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package routes
import (
"crypto/sha256"
"encoding/base64"
"errors"
"time"
"github.com/Liphium/station/main/integration"
"github.com/Liphium/station/pipes"
"github.com/Liphium/station/pipeshandler"
pipeshroutes "github.com/Liphium/station/pipeshandler/routes"
"github.com/Liphium/station/spacestation/caching"
"github.com/Liphium/station/spacestation/handler"
"github.com/Liphium/station/spacestation/util"
"github.com/bytedance/sonic"
"github.com/gofiber/fiber/v2"
)
func SetupRoutes(router fiber.Router) {
router.Post("/socketless", socketlessEvent)
router.Post("/ping", ping)
router.Post("/pub", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{
"pub": integration.PackageRSAPublicKey(integration.NodePublicKey),
})
})
// These are publicly accessible yk (cause this can be public information cause encryption and stuff)
router.Post("/leave", leaveRoom)
router.Post("/info", roomInfo)
setupPipesFiber(router)
}
func setupPipesFiber(router fiber.Router) {
caching.SSInstance = pipeshandler.Setup(pipeshandler.Config{
Secret: []byte(integration.JwtSecret),
ExpectedConnections: 10_0_0_0, // 10 thousand, but funny
SessionDuration: time.Hour * 24, // This is kinda important
// Report nodes as offline
NodeDisconnectHandler: func(node pipes.Node) {
integration.ReportOffline(node)
},
// Handle client disconnect
ClientDisconnectHandler: func(client *pipeshandler.Client) {
if integration.Testing {
util.Log.Println("Client disconnected:", client.ID)
}
// Remove from room
caching.RemoveMember(client.Session, client.ID)
caching.DeleteConnection(client.ID)
// Send leave event
handler.SendRoomData(client.Session)
},
// Validate token and create room
TokenValidateHandler: func(claims *pipeshandler.ConnectionTokenClaims, attachments string) bool {
// Create room (if needed)
_, valid := caching.GetRoom(claims.Session)
if !valid {
util.Log.Println("Creating new room for", claims.Account, "("+claims.Session+")")
caching.CreateRoom(claims.Session, "")
} else {
util.Log.Println("Room already exists for", claims.Account, "("+claims.Session+")")
}
return false
},
// Handle enter network
ClientConnectHandler: func(client *pipeshandler.Client, key string) bool {
// Get the AES key from attachments
aesKeyEncrypted, err := base64.StdEncoding.DecodeString(key)
if err != nil {
return true
}
// Decrypt AES key
aesKey, err := integration.DecryptRSA(integration.NodePrivateKey, aesKeyEncrypted)
if err != nil {
return true
}
// Set AES key in client data
client.Data = ExtraClientData{aesKey}
caching.SSInstance.UpdateClient(client)
if integration.Testing {
util.Log.Println("Client connected:", client.ID)
}
return false
},
// Handle client entering network
ClientEnterNetworkHandler: func(client *pipeshandler.Client, key string) bool {
return false
},
ErrorHandler: func(err error) {
util.Log.Println("Pipes error:", err)
},
// Set default encoding middleware
DecodingMiddleware: EncryptionDecodingMiddleware,
ClientEncodingMiddleware: EncryptionClientEncodingMiddleware,
})
router.Route("/", func(router fiber.Router) {
pipeshroutes.SetupRoutes(router, caching.SSNode, caching.SSInstance, false)
})
}
// Extra client data attached to the pipes-fiber client
type ExtraClientData struct {
Key []byte // AES encryption key
}
// Middleware for pipes-fiber to add encryption support
func EncryptionDecodingMiddleware(client *pipeshandler.Client, instance *pipeshandler.Instance, bytes []byte) (pipeshandler.Message, error) {
// Handle potential errors
defer func() {
if err := recover(); err != nil {
instance.ReportClientError(client, "encryption failure", errors.ErrUnsupported)
}
}()
// Decrypt the message using AES
key := client.Data.(ExtraClientData).Key
messageEncoded, err := integration.DecryptAES(key, bytes)
if err != nil {
return pipeshandler.Message{}, err
}
// Unmarshal the message using sonic
var message pipeshandler.Message
err = sonic.Unmarshal(messageEncoded, &message)
if err != nil {
return pipeshandler.Message{}, err
}
return message, nil
}
// Middleware for pipes-fiber to add encryption support (in encoding)
func EncryptionClientEncodingMiddleware(client *pipeshandler.Client, instance *pipeshandler.Instance, message []byte) ([]byte, error) {
// Handle potential errors
defer func() {
if err := recover(); err != nil {
instance.ReportClientError(client, "encryption failure", errors.ErrUnsupported)
}
}()
// Check if the encryption key is set
if client.Data == nil {
return nil, errors.New("no encryption key set")
}
// Encrypt the message using the client encryption key
key := client.Data.(ExtraClientData).Key
util.Log.Println("ENCODING KEY: "+base64.StdEncoding.EncodeToString(key), client.ID, string(message))
result, err := integration.EncryptAES(key, message)
hash := sha256.Sum256(result)
util.Log.Println("hash: " + base64.StdEncoding.EncodeToString(hash[:]))
return result, err
}