feat: enhance portal functionality with metadata support

MyungSub0519 committed Nov 12, 2025 at 22:46 UTC bc18286f976a291e06369cd9b5e57d583126c815
7 files changed +211 -304
cmd/demo-app/main.go
+7 -1
@@ -188,7 +188,13 @@ func runPaint() error {
188 defer client.Close()
189
190 // 3) Register lease and obtain a net.Listener that accepts relayed connections
191 - listener, err := client.Listen(cred, flagName, []string{"http/1.1"})
191 + metadata := sdk.Metadata{
192 + Description: "Portal demo paint app",
193 + Tags: []string{"demo", "paint"},
194 + Owner: "PortalApp Developer",
195 + Country: "KR",
196 + }
197 + listener, err := client.Listen(cred, flagName, []string{"http/1.1"}, metadata)
198 if err != nil {
199 return fmt.Errorf("listen: %w", err)
200 }
portal/core/proto/rdsec/rdsec.pb.go
+2 -4
@@ -1,7 +1,7 @@
1 // Code generated by protoc-gen-go. DO NOT EDIT.
2 // versions:
3 // protoc-gen-go v1.36.10
4 -// protoc (unknown)
4 +// protoc v6.33.0
5 // source: portal/core/proto/rdsec/rdsec.proto
6
7 package rdsec
@@ -363,9 +363,7 @@ const file_portal_core_proto_rdsec_rdsec_proto_rawDesc = "" +
363 "\x04alpn\x18\x05 \x01(\tR\x04alpn\x12,\n" +
364 "\x12session_public_key\x18\x06 \x01(\fR\x10sessionPublicKey*)\n" +
365 "\x0fProtocolVersion\x12\x16\n" +
366 - "\x12PROTOCOL_VERSION_1\x10\x00B|\n" +
367 - "\tcom.rdsecB\n" +
368 - "RdsecProtoP\x01Z/gosuda.org/portal/portal/core/proto/rdsec;rdsec\xa2\x02\x03RXX\xaa\x02\x05Rdsec\xca\x02\x05Rdsec\xe2\x02\x11Rdsec\\GPBMetadata\xea\x02\x05Rdsecb\x06proto3"
366 + "\x12PROTOCOL_VERSION_1\x10\x00B1Z/gosuda.org/portal/portal/core/proto/rdsec;rdsecb\x06proto3"
367
368 var (
369 file_portal_core_proto_rdsec_rdsec_proto_rawDescOnce sync.Once
portal/core/proto/rdverb/rdverb.pb.go
+13 -6
@@ -1,7 +1,7 @@
1 // Code generated by protoc-gen-go. DO NOT EDIT.
2 // versions:
3 // protoc-gen-go v1.36.10
4 -// protoc (unknown)
4 +// protoc v6.33.0
5 // source: portal/core/proto/rdverb/rdverb.proto
6
7 package rdverb
@@ -345,6 +345,7 @@ type Lease struct {
345 Expires int64 `protobuf:"varint,2,opt,name=expires,proto3" json:"expires,omitempty"`
346 Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
347 Alpn []string `protobuf:"bytes,4,rep,name=alpn,proto3" json:"alpn,omitempty"`
348 + Metadata string `protobuf:"bytes,5,opt,name=metadata,proto3" json:"metadata,omitempty"`
349 unknownFields protoimpl.UnknownFields
350 sizeCache protoimpl.SizeCache
351 }
@@ -407,6 +408,13 @@ func (x *Lease) GetAlpn() []string {
408 return nil
409 }
410
411 +func (x *Lease) GetMetadata() string {
412 + if x != nil {
413 + return x.Metadata
414 + }
415 + return ""
416 +}
417 +
418 type LeaseUpdateRequest struct {
419 state protoimpl.MessageState `protogen:"open.v1"`
420 Lease *Lease `protobuf:"bytes,1,opt,name=lease,proto3" json:"lease,omitempty"`
@@ -726,12 +734,13 @@ const file_portal_core_proto_rdverb_rdverb_proto_rawDesc = "" +
734 "\x10RelayInfoRequest\"E\n" +
735 "\x11RelayInfoResponse\x120\n" +
736 "\n" +
729 - "relay_info\x18\x01 \x01(\v2\x11.rdverb.RelayInfoR\trelayInfo\"v\n" +
737 + "relay_info\x18\x01 \x01(\v2\x11.rdverb.RelayInfoR\trelayInfo\"\x92\x01\n" +
738 "\x05Lease\x12+\n" +
739 "\bidentity\x18\x01 \x01(\v2\x0f.rdsec.IdentityR\bidentity\x12\x18\n" +
740 "\aexpires\x18\x02 \x01(\x03R\aexpires\x12\x12\n" +
741 "\x04name\x18\x03 \x01(\tR\x04name\x12\x12\n" +
734 - "\x04alpn\x18\x04 \x03(\tR\x04alpn\"m\n" +
742 + "\x04alpn\x18\x04 \x03(\tR\x04alpn\x12\x1a\n" +
743 + "\bmetadata\x18\x05 \x01(\tR\bmetadata\"m\n" +
744 "\x12LeaseUpdateRequest\x12#\n" +
745 "\x05lease\x18\x01 \x01(\v2\r.rdverb.LeaseR\x05lease\x12\x14\n" +
746 "\x05nonce\x18\x02 \x01(\fR\x05nonce\x12\x1c\n" +
@@ -766,9 +775,7 @@ const file_portal_core_proto_rdverb_rdverb_proto_rawDesc = "" +
775 "\x1eRESPONSE_CODE_INVALID_IDENTITY\x10\x03\x12\x1e\n" +
776 "\x1aRESPONSE_CODE_INVALID_NAME\x10\x04\x12\x1e\n" +
777 "\x1aRESPONSE_CODE_INVALID_ALPN\x10\x05\x12\x1a\n" +
769 - "\x16RESPONSE_CODE_REJECTED\x10\x06B\x84\x01\n" +
770 - "\n" +
771 - "com.rdverbB\vRdverbProtoP\x01Z1gosuda.org/portal/portal/core/proto/rdverb;rdverb\xa2\x02\x03RXX\xaa\x02\x06Rdverb\xca\x02\x06Rdverb\xe2\x02\x12Rdverb\\GPBMetadata\xea\x02\x06Rdverbb\x06proto3"
778 + "\x16RESPONSE_CODE_REJECTED\x10\x06B3Z1gosuda.org/portal/portal/core/proto/rdverb;rdverbb\x06proto3"
779
780 var (
781 file_portal_core_proto_rdverb_rdverb_proto_rawDescOnce sync.Once
portal/core/proto/rdverb/rdverb.proto
+1
@@ -54,6 +54,7 @@ message Lease {
54 int64 expires = 2;
55 string name = 3;
56 repeated string alpn = 4;
57 + string metadata = 5;
58 }
59
60 message LeaseUpdateRequest {
portal/core/proto/rdverb/rdverb_vtproto.pb.go
+158 -292
@@ -48,13 +48,7 @@ func (m *RelayInfo) CloneVT() *RelayInfo {
48 return (*RelayInfo)(nil)
49 }
50 r := new(RelayInfo)
51 - if rhs := m.Identity; rhs != nil {
52 - if vtpb, ok := interface{}(rhs).(interface{ CloneVT() *rdsec.Identity }); ok {
53 - r.Identity = vtpb.CloneVT()
54 - } else {
55 - r.Identity = proto.Clone(rhs).(*rdsec.Identity)
56 - }
57 - }
51 + r.Identity = m.Identity.CloneVT()
52 if rhs := m.Address; rhs != nil {
53 tmpContainer := make([]string, len(rhs))
54 copy(tmpContainer, rhs)
@@ -116,15 +110,10 @@ func (m *Lease) CloneVT() *Lease {
110 return (*Lease)(nil)
111 }
112 r := new(Lease)
113 + r.Identity = m.Identity.CloneVT()
114 r.Expires = m.Expires
115 r.Name = m.Name
121 - if rhs := m.Identity; rhs != nil {
122 - if vtpb, ok := interface{}(rhs).(interface{ CloneVT() *rdsec.Identity }); ok {
123 - r.Identity = vtpb.CloneVT()
124 - } else {
125 - r.Identity = proto.Clone(rhs).(*rdsec.Identity)
126 - }
127 - }
116 + r.Metadata = m.Metadata
117 if rhs := m.Alpn; rhs != nil {
118 tmpContainer := make([]string, len(rhs))
119 copy(tmpContainer, rhs)
@@ -186,14 +175,8 @@ func (m *LeaseDeleteRequest) CloneVT() *LeaseDeleteRequest {
175 return (*LeaseDeleteRequest)(nil)
176 }
177 r := new(LeaseDeleteRequest)
178 + r.Identity = m.Identity.CloneVT()
179 r.Timestamp = m.Timestamp
190 - if rhs := m.Identity; rhs != nil {
191 - if vtpb, ok := interface{}(rhs).(interface{ CloneVT() *rdsec.Identity }); ok {
192 - r.Identity = vtpb.CloneVT()
193 - } else {
194 - r.Identity = proto.Clone(rhs).(*rdsec.Identity)
195 - }
196 - }
180 if rhs := m.Nonce; rhs != nil {
181 tmpBytes := make([]byte, len(rhs))
182 copy(tmpBytes, rhs)
@@ -233,13 +216,7 @@ func (m *ConnectionRequest) CloneVT() *ConnectionRequest {
216 }
217 r := new(ConnectionRequest)
218 r.LeaseId = m.LeaseId
236 - if rhs := m.ClientIdentity; rhs != nil {
237 - if vtpb, ok := interface{}(rhs).(interface{ CloneVT() *rdsec.Identity }); ok {
238 - r.ClientIdentity = vtpb.CloneVT()
239 - } else {
240 - r.ClientIdentity = proto.Clone(rhs).(*rdsec.Identity)
241 - }
242 - }
219 + r.ClientIdentity = m.ClientIdentity.CloneVT()
220 if len(m.unknownFields) > 0 {
221 r.unknownFields = make([]byte, len(m.unknownFields))
222 copy(r.unknownFields, m.unknownFields)
@@ -296,11 +273,7 @@ func (this *RelayInfo) EqualVT(that *RelayInfo) bool {
273 } else if this == nil || that == nil {
274 return false
275 }
299 - if equal, ok := interface{}(this.Identity).(interface{ EqualVT(*rdsec.Identity) bool }); ok {
300 - if !equal.EqualVT(that.Identity) {
301 - return false
302 - }
303 - } else if !proto.Equal(this.Identity, that.Identity) {
276 + if !this.Identity.EqualVT(that.Identity) {
277 return false
278 }
279 if len(this.Address) != len(that.Address) {
@@ -380,11 +353,7 @@ func (this *Lease) EqualVT(that *Lease) bool {
353 } else if this == nil || that == nil {
354 return false
355 }
383 - if equal, ok := interface{}(this.Identity).(interface{ EqualVT(*rdsec.Identity) bool }); ok {
384 - if !equal.EqualVT(that.Identity) {
385 - return false
386 - }
387 - } else if !proto.Equal(this.Identity, that.Identity) {
356 + if !this.Identity.EqualVT(that.Identity) {
357 return false
358 }
359 if this.Expires != that.Expires {
@@ -402,6 +371,9 @@ func (this *Lease) EqualVT(that *Lease) bool {
371 return false
372 }
373 }
374 + if this.Metadata != that.Metadata {
375 + return false
376 + }
377 return string(this.unknownFields) == string(that.unknownFields)
378 }
379
@@ -462,11 +434,7 @@ func (this *LeaseDeleteRequest) EqualVT(that *LeaseDeleteRequest) bool {
434 } else if this == nil || that == nil {
435 return false
436 }
465 - if equal, ok := interface{}(this.Identity).(interface{ EqualVT(*rdsec.Identity) bool }); ok {
466 - if !equal.EqualVT(that.Identity) {
467 - return false
468 - }
469 - } else if !proto.Equal(this.Identity, that.Identity) {
437 + if !this.Identity.EqualVT(that.Identity) {
438 return false
439 }
440 if string(this.Nonce) != string(that.Nonce) {
@@ -513,11 +481,7 @@ func (this *ConnectionRequest) EqualVT(that *ConnectionRequest) bool {
481 if this.LeaseId != that.LeaseId {
482 return false
483 }
516 - if equal, ok := interface{}(this.ClientIdentity).(interface{ EqualVT(*rdsec.Identity) bool }); ok {
517 - if !equal.EqualVT(that.ClientIdentity) {
518 - return false
519 - }
520 - } else if !proto.Equal(this.ClientIdentity, that.ClientIdentity) {
484 + if !this.ClientIdentity.EqualVT(that.ClientIdentity) {
485 return false
486 }
487 return string(this.unknownFields) == string(that.unknownFields)
@@ -646,24 +610,12 @@ func (m *RelayInfo) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
610 }
611 }
612 if m.Identity != nil {
649 - if vtmsg, ok := interface{}(m.Identity).(interface {
650 - MarshalToSizedBufferVT([]byte) (int, error)
651 - }); ok {
652 - size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
653 - if err != nil {
654 - return 0, err
655 - }
656 - i -= size
657 - i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
658 - } else {
659 - encoded, err := proto.Marshal(m.Identity)
660 - if err != nil {
661 - return 0, err
662 - }
663 - i -= len(encoded)
664 - copy(dAtA[i:], encoded)
665 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
613 + size, err := m.Identity.MarshalToSizedBufferVT(dAtA[:i])
614 + if err != nil {
615 + return 0, err
616 }
617 + i -= size
618 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
619 i--
620 dAtA[i] = 0xa
621 }
@@ -776,6 +728,13 @@ func (m *Lease) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
728 i -= len(m.unknownFields)
729 copy(dAtA[i:], m.unknownFields)
730 }
731 + if len(m.Metadata) > 0 {
732 + i -= len(m.Metadata)
733 + copy(dAtA[i:], m.Metadata)
734 + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Metadata)))
735 + i--
736 + dAtA[i] = 0x2a
737 + }
738 if len(m.Alpn) > 0 {
739 for iNdEx := len(m.Alpn) - 1; iNdEx >= 0; iNdEx-- {
740 i -= len(m.Alpn[iNdEx])
@@ -798,24 +757,12 @@ func (m *Lease) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
757 dAtA[i] = 0x10
758 }
759 if m.Identity != nil {
801 - if vtmsg, ok := interface{}(m.Identity).(interface {
802 - MarshalToSizedBufferVT([]byte) (int, error)
803 - }); ok {
804 - size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
805 - if err != nil {
806 - return 0, err
807 - }
808 - i -= size
809 - i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
810 - } else {
811 - encoded, err := proto.Marshal(m.Identity)
812 - if err != nil {
813 - return 0, err
814 - }
815 - i -= len(encoded)
816 - copy(dAtA[i:], encoded)
817 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
760 + size, err := m.Identity.MarshalToSizedBufferVT(dAtA[:i])
761 + if err != nil {
762 + return 0, err
763 }
764 + i -= size
765 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
766 i--
767 dAtA[i] = 0xa
768 }
@@ -958,24 +905,12 @@ func (m *LeaseDeleteRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
905 dAtA[i] = 0x12
906 }
907 if m.Identity != nil {
961 - if vtmsg, ok := interface{}(m.Identity).(interface {
962 - MarshalToSizedBufferVT([]byte) (int, error)
963 - }); ok {
964 - size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
965 - if err != nil {
966 - return 0, err
967 - }
968 - i -= size
969 - i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
970 - } else {
971 - encoded, err := proto.Marshal(m.Identity)
972 - if err != nil {
973 - return 0, err
974 - }
975 - i -= len(encoded)
976 - copy(dAtA[i:], encoded)
977 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
908 + size, err := m.Identity.MarshalToSizedBufferVT(dAtA[:i])
909 + if err != nil {
910 + return 0, err
911 }
912 + i -= size
913 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
914 i--
915 dAtA[i] = 0xa
916 }
@@ -1051,24 +986,12 @@ func (m *ConnectionRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
986 copy(dAtA[i:], m.unknownFields)
987 }
988 if m.ClientIdentity != nil {
1054 - if vtmsg, ok := interface{}(m.ClientIdentity).(interface {
1055 - MarshalToSizedBufferVT([]byte) (int, error)
1056 - }); ok {
1057 - size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
1058 - if err != nil {
1059 - return 0, err
1060 - }
1061 - i -= size
1062 - i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1063 - } else {
1064 - encoded, err := proto.Marshal(m.ClientIdentity)
1065 - if err != nil {
1066 - return 0, err
1067 - }
1068 - i -= len(encoded)
1069 - copy(dAtA[i:], encoded)
1070 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
989 + size, err := m.ClientIdentity.MarshalToSizedBufferVT(dAtA[:i])
990 + if err != nil {
991 + return 0, err
992 }
993 + i -= size
994 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
995 i--
996 dAtA[i] = 0x12
997 }
@@ -1217,24 +1140,12 @@ func (m *RelayInfo) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
1140 }
1141 }
1142 if m.Identity != nil {
1220 - if vtmsg, ok := interface{}(m.Identity).(interface {
1221 - MarshalToSizedBufferVTStrict([]byte) (int, error)
1222 - }); ok {
1223 - size, err := vtmsg.MarshalToSizedBufferVTStrict(dAtA[:i])
1224 - if err != nil {
1225 - return 0, err
1226 - }
1227 - i -= size
1228 - i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1229 - } else {
1230 - encoded, err := proto.Marshal(m.Identity)
1231 - if err != nil {
1232 - return 0, err
1233 - }
1234 - i -= len(encoded)
1235 - copy(dAtA[i:], encoded)
1236 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
1143 + size, err := m.Identity.MarshalToSizedBufferVTStrict(dAtA[:i])
1144 + if err != nil {
1145 + return 0, err
1146 }
1147 + i -= size
1148 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1149 i--
1150 dAtA[i] = 0xa
1151 }
@@ -1347,6 +1258,13 @@ func (m *Lease) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
1258 i -= len(m.unknownFields)
1259 copy(dAtA[i:], m.unknownFields)
1260 }
1261 + if len(m.Metadata) > 0 {
1262 + i -= len(m.Metadata)
1263 + copy(dAtA[i:], m.Metadata)
1264 + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Metadata)))
1265 + i--
1266 + dAtA[i] = 0x2a
1267 + }
1268 if len(m.Alpn) > 0 {
1269 for iNdEx := len(m.Alpn) - 1; iNdEx >= 0; iNdEx-- {
1270 i -= len(m.Alpn[iNdEx])
@@ -1369,24 +1287,12 @@ func (m *Lease) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
1287 dAtA[i] = 0x10
1288 }
1289 if m.Identity != nil {
1372 - if vtmsg, ok := interface{}(m.Identity).(interface {
1373 - MarshalToSizedBufferVTStrict([]byte) (int, error)
1374 - }); ok {
1375 - size, err := vtmsg.MarshalToSizedBufferVTStrict(dAtA[:i])
1376 - if err != nil {
1377 - return 0, err
1378 - }
1379 - i -= size
1380 - i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1381 - } else {
1382 - encoded, err := proto.Marshal(m.Identity)
1383 - if err != nil {
1384 - return 0, err
1385 - }
1386 - i -= len(encoded)
1387 - copy(dAtA[i:], encoded)
1388 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
1290 + size, err := m.Identity.MarshalToSizedBufferVTStrict(dAtA[:i])
1291 + if err != nil {
1292 + return 0, err
1293 }
1294 + i -= size
1295 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1296 i--
1297 dAtA[i] = 0xa
1298 }
@@ -1529,24 +1435,12 @@ func (m *LeaseDeleteRequest) MarshalToSizedBufferVTStrict(dAtA []byte) (int, err
1435 dAtA[i] = 0x12
1436 }
1437 if m.Identity != nil {
1532 - if vtmsg, ok := interface{}(m.Identity).(interface {
1533 - MarshalToSizedBufferVTStrict([]byte) (int, error)
1534 - }); ok {
1535 - size, err := vtmsg.MarshalToSizedBufferVTStrict(dAtA[:i])
1536 - if err != nil {
1537 - return 0, err
1538 - }
1539 - i -= size
1540 - i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1541 - } else {
1542 - encoded, err := proto.Marshal(m.Identity)
1543 - if err != nil {
1544 - return 0, err
1545 - }
1546 - i -= len(encoded)
1547 - copy(dAtA[i:], encoded)
1548 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
1438 + size, err := m.Identity.MarshalToSizedBufferVTStrict(dAtA[:i])
1439 + if err != nil {
1440 + return 0, err
1441 }
1442 + i -= size
1443 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1444 i--
1445 dAtA[i] = 0xa
1446 }
@@ -1622,24 +1516,12 @@ func (m *ConnectionRequest) MarshalToSizedBufferVTStrict(dAtA []byte) (int, erro
1516 copy(dAtA[i:], m.unknownFields)
1517 }
1518 if m.ClientIdentity != nil {
1625 - if vtmsg, ok := interface{}(m.ClientIdentity).(interface {
1626 - MarshalToSizedBufferVTStrict([]byte) (int, error)
1627 - }); ok {
1628 - size, err := vtmsg.MarshalToSizedBufferVTStrict(dAtA[:i])
1629 - if err != nil {
1630 - return 0, err
1631 - }
1632 - i -= size
1633 - i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1634 - } else {
1635 - encoded, err := proto.Marshal(m.ClientIdentity)
1636 - if err != nil {
1637 - return 0, err
1638 - }
1639 - i -= len(encoded)
1640 - copy(dAtA[i:], encoded)
1641 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(encoded)))
1519 + size, err := m.ClientIdentity.MarshalToSizedBufferVTStrict(dAtA[:i])
1520 + if err != nil {
1521 + return 0, err
1522 }
1523 + i -= size
1524 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1525 i--
1526 dAtA[i] = 0x12
1527 }
@@ -1715,13 +1597,7 @@ func (m *RelayInfo) SizeVT() (n int) {
1597 var l int
1598 _ = l
1599 if m.Identity != nil {
1718 - if size, ok := interface{}(m.Identity).(interface {
1719 - SizeVT() int
1720 - }); ok {
1721 - l = size.SizeVT()
1722 - } else {
1723 - l = proto.Size(m.Identity)
1724 - }
1600 + l = m.Identity.SizeVT()
1601 n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
1602 }
1603 if len(m.Address) > 0 {
@@ -1771,13 +1647,7 @@ func (m *Lease) SizeVT() (n int) {
1647 var l int
1648 _ = l
1649 if m.Identity != nil {
1774 - if size, ok := interface{}(m.Identity).(interface {
1775 - SizeVT() int
1776 - }); ok {
1777 - l = size.SizeVT()
1778 - } else {
1779 - l = proto.Size(m.Identity)
1780 - }
1650 + l = m.Identity.SizeVT()
1651 n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
1652 }
1653 if m.Expires != 0 {
@@ -1793,6 +1663,10 @@ func (m *Lease) SizeVT() (n int) {
1663 n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
1664 }
1665 }
1666 + l = len(m.Metadata)
1667 + if l > 0 {
1668 + n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
1669 + }
1670 n += len(m.unknownFields)
1671 return n
1672 }
@@ -1838,13 +1712,7 @@ func (m *LeaseDeleteRequest) SizeVT() (n int) {
1712 var l int
1713 _ = l
1714 if m.Identity != nil {
1841 - if size, ok := interface{}(m.Identity).(interface {
1842 - SizeVT() int
1843 - }); ok {
1844 - l = size.SizeVT()
1845 - } else {
1846 - l = proto.Size(m.Identity)
1847 - }
1715 + l = m.Identity.SizeVT()
1716 n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
1717 }
1718 l = len(m.Nonce)
@@ -1882,13 +1750,7 @@ func (m *ConnectionRequest) SizeVT() (n int) {
1750 n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
1751 }
1752 if m.ClientIdentity != nil {
1885 - if size, ok := interface{}(m.ClientIdentity).(interface {
1886 - SizeVT() int
1887 - }); ok {
1888 - l = size.SizeVT()
1889 - } else {
1890 - l = proto.Size(m.ClientIdentity)
1891 - }
1753 + l = m.ClientIdentity.SizeVT()
1754 n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
1755 }
1756 n += len(m.unknownFields)
@@ -2073,16 +1935,8 @@ func (m *RelayInfo) UnmarshalVT(dAtA []byte) error {
1935 if m.Identity == nil {
1936 m.Identity = &rdsec.Identity{}
1937 }
2076 - if unmarshal, ok := interface{}(m.Identity).(interface {
2077 - UnmarshalVT([]byte) error
2078 - }); ok {
2079 - if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
2080 - return err
2081 - }
2082 - } else {
2083 - if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Identity); err != nil {
2084 - return err
2085 - }
1938 + if err := m.Identity.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
1939 + return err
1940 }
1941 iNdEx = postIndex
1942 case 2:
@@ -2372,16 +2226,8 @@ func (m *Lease) UnmarshalVT(dAtA []byte) error {
2226 if m.Identity == nil {
2227 m.Identity = &rdsec.Identity{}
2228 }
2375 - if unmarshal, ok := interface{}(m.Identity).(interface {
2376 - UnmarshalVT([]byte) error
2377 - }); ok {
2378 - if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
2379 - return err
2380 - }
2381 - } else {
2382 - if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Identity); err != nil {
2383 - return err
2384 - }
2229 + if err := m.Identity.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
2230 + return err
2231 }
2232 iNdEx = postIndex
2233 case 2:
@@ -2467,6 +2313,38 @@ func (m *Lease) UnmarshalVT(dAtA []byte) error {
2313 }
2314 m.Alpn = append(m.Alpn, string(dAtA[iNdEx:postIndex]))
2315 iNdEx = postIndex
2316 + case 5:
2317 + if wireType != 2 {
2318 + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType)
2319 + }
2320 + var stringLen uint64
2321 + for shift := uint(0); ; shift += 7 {
2322 + if shift >= 64 {
2323 + return protohelpers.ErrIntOverflow
2324 + }
2325 + if iNdEx >= l {
2326 + return io.ErrUnexpectedEOF
2327 + }
2328 + b := dAtA[iNdEx]
2329 + iNdEx++
2330 + stringLen |= uint64(b&0x7F) << shift
2331 + if b < 0x80 {
2332 + break
2333 + }
2334 + }
2335 + intStringLen := int(stringLen)
2336 + if intStringLen < 0 {
2337 + return protohelpers.ErrInvalidLength
2338 + }
2339 + postIndex := iNdEx + intStringLen
2340 + if postIndex < 0 {
2341 + return protohelpers.ErrInvalidLength
2342 + }
2343 + if postIndex > l {
2344 + return io.ErrUnexpectedEOF
2345 + }
2346 + m.Metadata = string(dAtA[iNdEx:postIndex])
2347 + iNdEx = postIndex
2348 default:
2349 iNdEx = preIndex
2350 skippy, err := protohelpers.Skip(dAtA[iNdEx:])
@@ -2760,16 +2638,8 @@ func (m *LeaseDeleteRequest) UnmarshalVT(dAtA []byte) error {
2638 if m.Identity == nil {
2639 m.Identity = &rdsec.Identity{}
2640 }
2763 - if unmarshal, ok := interface{}(m.Identity).(interface {
2764 - UnmarshalVT([]byte) error
2765 - }); ok {
2766 - if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
2767 - return err
2768 - }
2769 - } else {
2770 - if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Identity); err != nil {
2771 - return err
2772 - }
2641 + if err := m.Identity.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
2642 + return err
2643 }
2644 iNdEx = postIndex
2645 case 2:
@@ -3010,16 +2880,8 @@ func (m *ConnectionRequest) UnmarshalVT(dAtA []byte) error {
2880 if m.ClientIdentity == nil {
2881 m.ClientIdentity = &rdsec.Identity{}
2882 }
3013 - if unmarshal, ok := interface{}(m.ClientIdentity).(interface {
3014 - UnmarshalVT([]byte) error
3015 - }); ok {
3016 - if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
3017 - return err
3018 - }
3019 - } else {
3020 - if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.ClientIdentity); err != nil {
3021 - return err
3022 - }
2883 + if err := m.ClientIdentity.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
2884 + return err
2885 }
2886 iNdEx = postIndex
2887 default:
@@ -3276,16 +3138,8 @@ func (m *RelayInfo) UnmarshalVTUnsafe(dAtA []byte) error {
3138 if m.Identity == nil {
3139 m.Identity = &rdsec.Identity{}
3140 }
3279 - if unmarshal, ok := interface{}(m.Identity).(interface {
3280 - UnmarshalVTUnsafe([]byte) error
3281 - }); ok {
3282 - if err := unmarshal.UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil {
3283 - return err
3284 - }
3285 - } else {
3286 - if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Identity); err != nil {
3287 - return err
3288 - }
3141 + if err := m.Identity.UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil {
3142 + return err
3143 }
3144 iNdEx = postIndex
3145 case 2:
@@ -3579,16 +3433,8 @@ func (m *Lease) UnmarshalVTUnsafe(dAtA []byte) error {
3433 if m.Identity == nil {
3434 m.Identity = &rdsec.Identity{}
3435 }
3582 - if unmarshal, ok := interface{}(m.Identity).(interface {
3583 - UnmarshalVTUnsafe([]byte) error
3584 - }); ok {
3585 - if err := unmarshal.UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil {
3586 - return err
3587 - }
3588 - } else {
3589 - if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Identity); err != nil {
3590 - return err
3591 - }
3436 + if err := m.Identity.UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil {
3437 + return err
3438 }
3439 iNdEx = postIndex
3440 case 2:
@@ -3682,6 +3528,42 @@ func (m *Lease) UnmarshalVTUnsafe(dAtA []byte) error {
3528 }
3529 m.Alpn = append(m.Alpn, stringValue)
3530 iNdEx = postIndex
3531 + case 5:
3532 + if wireType != 2 {
3533 + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType)
3534 + }
3535 + var stringLen uint64
3536 + for shift := uint(0); ; shift += 7 {
3537 + if shift >= 64 {
3538 + return protohelpers.ErrIntOverflow
3539 + }
3540 + if iNdEx >= l {
3541 + return io.ErrUnexpectedEOF
3542 + }
3543 + b := dAtA[iNdEx]
3544 + iNdEx++
3545 + stringLen |= uint64(b&0x7F) << shift
3546 + if b < 0x80 {
3547 + break
3548 + }
3549 + }
3550 + intStringLen := int(stringLen)
3551 + if intStringLen < 0 {
3552 + return protohelpers.ErrInvalidLength
3553 + }
3554 + postIndex := iNdEx + intStringLen
3555 + if postIndex < 0 {
3556 + return protohelpers.ErrInvalidLength
3557 + }
3558 + if postIndex > l {
3559 + return io.ErrUnexpectedEOF
3560 + }
3561 + var stringValue string
3562 + if intStringLen > 0 {
3563 + stringValue = unsafe.String(&dAtA[iNdEx], intStringLen)
3564 + }
3565 + m.Metadata = stringValue
3566 + iNdEx = postIndex
3567 default:
3568 iNdEx = preIndex
3569 skippy, err := protohelpers.Skip(dAtA[iNdEx:])
@@ -3972,16 +3854,8 @@ func (m *LeaseDeleteRequest) UnmarshalVTUnsafe(dAtA []byte) error {
3854 if m.Identity == nil {
3855 m.Identity = &rdsec.Identity{}
3856 }
3975 - if unmarshal, ok := interface{}(m.Identity).(interface {
3976 - UnmarshalVTUnsafe([]byte) error
3977 - }); ok {
3978 - if err := unmarshal.UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil {
3979 - return err
3980 - }
3981 - } else {
3982 - if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Identity); err != nil {
3983 - return err
3984 - }
3857 + if err := m.Identity.UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil {
3858 + return err
3859 }
3860 iNdEx = postIndex
3861 case 2:
@@ -4223,16 +4097,8 @@ func (m *ConnectionRequest) UnmarshalVTUnsafe(dAtA []byte) error {
4097 if m.ClientIdentity == nil {
4098 m.ClientIdentity = &rdsec.Identity{}
4099 }
4226 - if unmarshal, ok := interface{}(m.ClientIdentity).(interface {
4227 - UnmarshalVTUnsafe([]byte) error
4228 - }); ok {
4229 - if err := unmarshal.UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil {
4230 - return err
4231 - }
4232 - } else {
4233 - if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.ClientIdentity); err != nil {
4234 - return err
4235 - }
4100 + if err := m.ClientIdentity.UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil {
4101 + return err
4102 }
4103 iNdEx = postIndex
4104 default:
portal/handlers.go
+1
@@ -77,6 +77,7 @@ func (g *RelayServer) handleLeaseUpdateRequest(ctx *StreamContext, packet *rdver
77 log.Debug().
78 Str("lease_id", leaseID).
79 Str("lease_name", req.Lease.Name).
80 + RawJSON("metadata", []byte(req.Lease.Metadata)).
81 Int64("connection_id", ctx.ConnectionID).
82 Msg("[RelayServer] Lease update completed successfully")
83 } else {
sdk/sdk.go
+29 -1
@@ -2,6 +2,7 @@ package sdk
2
3 import (
4 "context"
5 + "encoding/json"
6 "errors"
7 "fmt"
8 "io"
@@ -168,6 +169,14 @@ type RDListener struct {
169 closed bool
170 }
171
172 +type Metadata struct {
173 + Description string `json:"description"`
174 + Tags []string `json:"tags"`
175 + Thumbnail string `json:"thumbnail"`
176 + Owner string `json:"owner"`
177 + Country string `json:"country"`
178 +}
179 +
180 type RDClient struct {
181 mu sync.Mutex
182
@@ -188,6 +197,7 @@ var (
197 ErrRelayNotFound = errors.New("relay not found")
198 ErrInvalidName = errors.New("lease name contains invalid characters (only alphanumeric, hyphen, underscore allowed)")
199 ErrFailedToCreateClient = errors.New("failed to create relay client")
200 + ErrInvalidMetadata = errors.New("invalid metadata")
201 )
202
203 func NewClient(opt ...Option) (*RDClient, error) {
@@ -306,11 +316,12 @@ func (g *RDClient) Dial(cred *cryptoops.Credential, leaseID string, alpn string)
316 return nil, ErrNoAvailableRelay
317 }
318
309 -func (g *RDClient) Listen(cred *cryptoops.Credential, name string, alpns []string) (*RDListener, error) {
319 +func (g *RDClient) Listen(cred *cryptoops.Credential, name string, alpns []string, metadata ...Metadata) (*RDListener, error) {
320 log.Debug().
321 Str("lease_id", cred.ID()).
322 Str("name", name).
323 Strs("alpns", alpns).
324 + Int("metadata_count", len(metadata)).
325 Msg("[SDK] Creating listener")
326
327 // Validate name is URL-safe
@@ -321,6 +332,22 @@ func (g *RDClient) Listen(cred *cryptoops.Credential, name string, alpns []strin
332 return nil, ErrInvalidName
333 }
334
335 + if len(metadata) > 1 {
336 + log.Error().Msg("[SDK] Too many metadata arguments")
337 + return nil, ErrInvalidMetadata
338 + }
339 +
340 + metadataValue := ""
341 +
342 + if len(metadata) > 0 {
343 + metadataJSON, err := json.Marshal(metadata[0])
344 + if err != nil {
345 + log.Error().Err(err).Msg("[SDK] Failed to marshal metadata")
346 + return nil, ErrInvalidMetadata
347 + }
348 + metadataValue = string(metadataJSON)
349 + }
350 +
351 g.mu.Lock()
352 defer g.mu.Unlock()
353
@@ -346,6 +373,7 @@ func (g *RDClient) Listen(cred *cryptoops.Credential, name string, alpns []strin
373 },
374 Name: name,
375 Alpn: alpns,
376 + Metadata: metadataValue,
377 }
378
379 // Create listener with lease metadata for re-registration