feat(proto): update RelayInfo leases to use structured Lease objects

- Changed leases field in RelayInfo from repeated string to repeated Lease in protobuf definition - Regenerated Go protobuf code to reflect the new structure - Fixed link generation in view.go to use lease.Name instead of identityID for proper URL construction with structured lease data

lemon-mint committed Nov 4, 2025 at 00:17 UTC cdd0fd6806cab50911eb6feacfeff77cb944c2fd
7 files changed +103 -54
cmd/relay-server/view.go
+1 -1
@@ -348,7 +348,7 @@ func convertLeaseEntriesToRows(serv *portal.RelayServer) []leaseRow {
348 dnsLabel = dnsLabel[:8] + "..."
349 }
350
351 - link := fmt.Sprintf("https://%s.portal.gosuda.org/", identityID)
351 + link := fmt.Sprintf("https://%s.portal.gosuda.org/", lease.Name)
352
353 row := leaseRow{
354 Peer: identityID,
cmd/webclient/main_js.go
+5
@@ -33,6 +33,11 @@ var (
33 )
34
35 var rdDialer = func(ctx context.Context, network, address string) (net.Conn, error) {
36 + lease, err := rdClient.LookUpName(address)
37 + if err == nil && lease != nil {
38 + address = lease.Identity.Id
39 + }
40 +
41 address = strings.TrimSuffix(address, ":80")
42 address = strings.TrimSuffix(address, ":443")
43 cred := sdk.NewCredential()
portal/core/proto/rdverb/rdverb.pb.go
+19 -18
@@ -203,7 +203,7 @@ type RelayInfo struct {
203 state protoimpl.MessageState `protogen:"open.v1"`
204 Identity *rdsec.Identity `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
205 Address []string `protobuf:"bytes,2,rep,name=address,proto3" json:"address,omitempty"`
206 - Leases []string `protobuf:"bytes,3,rep,name=leases,proto3" json:"leases,omitempty"`
206 + Leases []*Lease `protobuf:"bytes,3,rep,name=leases,proto3" json:"leases,omitempty"`
207 unknownFields protoimpl.UnknownFields
208 sizeCache protoimpl.SizeCache
209 }
@@ -252,7 +252,7 @@ func (x *RelayInfo) GetAddress() []string {
252 return nil
253 }
254
255 -func (x *RelayInfo) GetLeases() []string {
255 +func (x *RelayInfo) GetLeases() []*Lease {
256 if x != nil {
257 return x.Leases
258 }
@@ -718,11 +718,11 @@ const file_portal_core_proto_rdverb_rdverb_proto_rawDesc = "" +
718 "%portal/core/proto/rdverb/rdverb.proto\x12\x06rdverb\x1a#portal/core/proto/rdsec/rdsec.proto\"J\n" +
719 "\x06Packet\x12&\n" +
720 "\x04type\x18\x01 \x01(\x0e2\x12.rdverb.PacketTypeR\x04type\x12\x18\n" +
721 - "\apayload\x18\x02 \x01(\fR\apayload\"j\n" +
721 + "\apayload\x18\x02 \x01(\fR\apayload\"y\n" +
722 "\tRelayInfo\x12+\n" +
723 "\bidentity\x18\x01 \x01(\v2\x0f.rdsec.IdentityR\bidentity\x12\x18\n" +
724 - "\aaddress\x18\x02 \x03(\tR\aaddress\x12\x16\n" +
725 - "\x06leases\x18\x03 \x03(\tR\x06leases\"\x12\n" +
724 + "\aaddress\x18\x02 \x03(\tR\aaddress\x12%\n" +
725 + "\x06leases\x18\x03 \x03(\v2\r.rdverb.LeaseR\x06leases\"\x12\n" +
726 "\x10RelayInfoRequest\"E\n" +
727 "\x11RelayInfoResponse\x120\n" +
728 "\n" +
@@ -803,19 +803,20 @@ var file_portal_core_proto_rdverb_rdverb_proto_goTypes = []any{
803 var file_portal_core_proto_rdverb_rdverb_proto_depIdxs = []int32{
804 0, // 0: rdverb.Packet.type:type_name -> rdverb.PacketType
805 13, // 1: rdverb.RelayInfo.identity:type_name -> rdsec.Identity
806 - 3, // 2: rdverb.RelayInfoResponse.relay_info:type_name -> rdverb.RelayInfo
807 - 13, // 3: rdverb.Lease.identity:type_name -> rdsec.Identity
808 - 6, // 4: rdverb.LeaseUpdateRequest.lease:type_name -> rdverb.Lease
809 - 1, // 5: rdverb.LeaseUpdateResponse.code:type_name -> rdverb.ResponseCode
810 - 13, // 6: rdverb.LeaseDeleteRequest.identity:type_name -> rdsec.Identity
811 - 1, // 7: rdverb.LeaseDeleteResponse.code:type_name -> rdverb.ResponseCode
812 - 13, // 8: rdverb.ConnectionRequest.client_identity:type_name -> rdsec.Identity
813 - 1, // 9: rdverb.ConnectionResponse.code:type_name -> rdverb.ResponseCode
814 - 10, // [10:10] is the sub-list for method output_type
815 - 10, // [10:10] is the sub-list for method input_type
816 - 10, // [10:10] is the sub-list for extension type_name
817 - 10, // [10:10] is the sub-list for extension extendee
818 - 0, // [0:10] is the sub-list for field type_name
806 + 6, // 2: rdverb.RelayInfo.leases:type_name -> rdverb.Lease
807 + 3, // 3: rdverb.RelayInfoResponse.relay_info:type_name -> rdverb.RelayInfo
808 + 13, // 4: rdverb.Lease.identity:type_name -> rdsec.Identity
809 + 6, // 5: rdverb.LeaseUpdateRequest.lease:type_name -> rdverb.Lease
810 + 1, // 6: rdverb.LeaseUpdateResponse.code:type_name -> rdverb.ResponseCode
811 + 13, // 7: rdverb.LeaseDeleteRequest.identity:type_name -> rdsec.Identity
812 + 1, // 8: rdverb.LeaseDeleteResponse.code:type_name -> rdverb.ResponseCode
813 + 13, // 9: rdverb.ConnectionRequest.client_identity:type_name -> rdsec.Identity
814 + 1, // 10: rdverb.ConnectionResponse.code:type_name -> rdverb.ResponseCode
815 + 11, // [11:11] is the sub-list for method output_type
816 + 11, // [11:11] is the sub-list for method input_type
817 + 11, // [11:11] is the sub-list for extension type_name
818 + 11, // [11:11] is the sub-list for extension extendee
819 + 0, // [0:11] is the sub-list for field type_name
820 }
821
822 func init() { file_portal_core_proto_rdverb_rdverb_proto_init() }
portal/core/proto/rdverb/rdverb.proto
+1 -1
@@ -40,7 +40,7 @@ message Packet {
40 message RelayInfo {
41 rdsec.Identity identity = 1;
42 repeated string address = 2;
43 - repeated string leases = 3;
43 + repeated Lease leases = 3;
44 }
45
46 message RelayInfoRequest {}
portal/core/proto/rdverb/rdverb_vtproto.pb.go
+43 -27
@@ -61,8 +61,10 @@ func (m *RelayInfo) CloneVT() *RelayInfo {
61 r.Address = tmpContainer
62 }
63 if rhs := m.Leases; rhs != nil {
64 - tmpContainer := make([]string, len(rhs))
65 - copy(tmpContainer, rhs)
64 + tmpContainer := make([]*Lease, len(rhs))
65 + for k, v := range rhs {
66 + tmpContainer[k] = v.CloneVT()
67 + }
68 r.Leases = tmpContainer
69 }
70 if len(m.unknownFields) > 0 {
@@ -315,8 +317,16 @@ func (this *RelayInfo) EqualVT(that *RelayInfo) bool {
317 }
318 for i, vx := range this.Leases {
319 vy := that.Leases[i]
318 - if vx != vy {
319 - return false
320 + if p, q := vx, vy; p != q {
321 + if p == nil {
322 + p = &Lease{}
323 + }
324 + if q == nil {
325 + q = &Lease{}
326 + }
327 + if !p.EqualVT(q) {
328 + return false
329 + }
330 }
331 }
332 return string(this.unknownFields) == string(that.unknownFields)
@@ -616,9 +626,12 @@ func (m *RelayInfo) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
626 }
627 if len(m.Leases) > 0 {
628 for iNdEx := len(m.Leases) - 1; iNdEx >= 0; iNdEx-- {
619 - i -= len(m.Leases[iNdEx])
620 - copy(dAtA[i:], m.Leases[iNdEx])
621 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Leases[iNdEx])))
629 + size, err := m.Leases[iNdEx].MarshalToSizedBufferVT(dAtA[:i])
630 + if err != nil {
631 + return 0, err
632 + }
633 + i -= size
634 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
635 i--
636 dAtA[i] = 0x1a
637 }
@@ -1184,9 +1197,12 @@ func (m *RelayInfo) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) {
1197 }
1198 if len(m.Leases) > 0 {
1199 for iNdEx := len(m.Leases) - 1; iNdEx >= 0; iNdEx-- {
1187 - i -= len(m.Leases[iNdEx])
1188 - copy(dAtA[i:], m.Leases[iNdEx])
1189 - i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Leases[iNdEx])))
1200 + size, err := m.Leases[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i])
1201 + if err != nil {
1202 + return 0, err
1203 + }
1204 + i -= size
1205 + i = protohelpers.EncodeVarint(dAtA, i, uint64(size))
1206 i--
1207 dAtA[i] = 0x1a
1208 }
@@ -1715,8 +1731,8 @@ func (m *RelayInfo) SizeVT() (n int) {
1731 }
1732 }
1733 if len(m.Leases) > 0 {
1718 - for _, s := range m.Leases {
1719 - l = len(s)
1734 + for _, e := range m.Leases {
1735 + l = e.SizeVT()
1736 n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
1737 }
1738 }
@@ -2105,7 +2121,7 @@ func (m *RelayInfo) UnmarshalVT(dAtA []byte) error {
2121 if wireType != 2 {
2122 return fmt.Errorf("proto: wrong wireType = %d for field Leases", wireType)
2123 }
2108 - var stringLen uint64
2124 + var msglen int
2125 for shift := uint(0); ; shift += 7 {
2126 if shift >= 64 {
2127 return protohelpers.ErrIntOverflow
@@ -2115,23 +2131,25 @@ func (m *RelayInfo) UnmarshalVT(dAtA []byte) error {
2131 }
2132 b := dAtA[iNdEx]
2133 iNdEx++
2118 - stringLen |= uint64(b&0x7F) << shift
2134 + msglen |= int(b&0x7F) << shift
2135 if b < 0x80 {
2136 break
2137 }
2138 }
2123 - intStringLen := int(stringLen)
2124 - if intStringLen < 0 {
2139 + if msglen < 0 {
2140 return protohelpers.ErrInvalidLength
2141 }
2127 - postIndex := iNdEx + intStringLen
2142 + postIndex := iNdEx + msglen
2143 if postIndex < 0 {
2144 return protohelpers.ErrInvalidLength
2145 }
2146 if postIndex > l {
2147 return io.ErrUnexpectedEOF
2148 }
2134 - m.Leases = append(m.Leases, string(dAtA[iNdEx:postIndex]))
2149 + m.Leases = append(m.Leases, &Lease{})
2150 + if err := m.Leases[len(m.Leases)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
2151 + return err
2152 + }
2153 iNdEx = postIndex
2154 default:
2155 iNdEx = preIndex
@@ -3310,7 +3328,7 @@ func (m *RelayInfo) UnmarshalVTUnsafe(dAtA []byte) error {
3328 if wireType != 2 {
3329 return fmt.Errorf("proto: wrong wireType = %d for field Leases", wireType)
3330 }
3313 - var stringLen uint64
3331 + var msglen int
3332 for shift := uint(0); ; shift += 7 {
3333 if shift >= 64 {
3334 return protohelpers.ErrIntOverflow
@@ -3320,27 +3338,25 @@ func (m *RelayInfo) UnmarshalVTUnsafe(dAtA []byte) error {
3338 }
3339 b := dAtA[iNdEx]
3340 iNdEx++
3323 - stringLen |= uint64(b&0x7F) << shift
3341 + msglen |= int(b&0x7F) << shift
3342 if b < 0x80 {
3343 break
3344 }
3345 }
3328 - intStringLen := int(stringLen)
3329 - if intStringLen < 0 {
3346 + if msglen < 0 {
3347 return protohelpers.ErrInvalidLength
3348 }
3332 - postIndex := iNdEx + intStringLen
3349 + postIndex := iNdEx + msglen
3350 if postIndex < 0 {
3351 return protohelpers.ErrInvalidLength
3352 }
3353 if postIndex > l {
3354 return io.ErrUnexpectedEOF
3355 }
3339 - var stringValue string
3340 - if intStringLen > 0 {
3341 - stringValue = unsafe.String(&dAtA[iNdEx], intStringLen)
3356 + m.Leases = append(m.Leases, &Lease{})
3357 + if err := m.Leases[len(m.Leases)-1].UnmarshalVTUnsafe(dAtA[iNdEx:postIndex]); err != nil {
3358 + return err
3359 }
3343 - m.Leases = append(m.Leases, stringValue)
3360 iNdEx = postIndex
3361 default:
3362 iNdEx = preIndex
portal/relay.go
+1 -1
@@ -250,7 +250,7 @@ func (g *RelayServer) relayInfo() *rdverb.RelayInfo {
250 return &rdverb.RelayInfo{
251 Identity: g.identity,
252 Address: g.address,
253 - Leases: leaseIds,
253 + Leases: g.leaseManager.GetAllLeases(),
254 }
255 }
256
sdk/sdk.go
+33 -6
@@ -7,7 +7,7 @@ import (
7 "io"
8 "net"
9 "regexp"
10 - "slices"
10 + "strings"
11 "sync"
12 "time"
13
@@ -262,11 +262,14 @@ func (g *RDClient) Dial(cred *cryptoops.Credential, leaseID string, alpn string)
262 return
263 }
264
265 - if slices.Contains(info.Leases, leaseID) {
266 - log.Debug().Str("relay", relay.addr).Str("lease_id", leaseID).Msg("[SDK] Found lease on relay")
267 - availableRelaysMu.Lock()
268 - availableRelays = append(availableRelays, relay)
269 - availableRelaysMu.Unlock()
265 + for _, lease := range info.Leases {
266 + if lease.Identity.Id == leaseID {
267 + log.Debug().Str("relay", relay.addr).Str("lease_id", leaseID).Msg("[SDK] Found lease on relay")
268 + availableRelaysMu.Lock()
269 + availableRelays = append(availableRelays, relay)
270 + availableRelaysMu.Unlock()
271 + break
272 + }
273 }
274 }(relay)
275 }
@@ -780,3 +783,27 @@ func (g *RDClient) GetRelays() []string {
783
784 return relays
785 }
786 +
787 +func (g *RDClient) LookUpName(name string) (*rdverb.Lease, error) {
788 + var relays []*rdRelay
789 +
790 + g.mu.Lock()
791 + for _, server := range g.relays {
792 + relays = append(relays, server)
793 + }
794 + g.mu.Unlock()
795 +
796 + for _, relay := range relays {
797 + info, err := relay.client.GetRelayInfo()
798 + if err != nil {
799 + continue
800 + }
801 +
802 + for _, lease := range info.Leases {
803 + if strings.EqualFold(lease.Name, name) {
804 + return lease, nil
805 + }
806 + }
807 + }
808 + return nil, ErrNoAvailableRelay
809 +}