mirror of https://github.com/libp2p/go-libp2p.git
Browse Source
* autorelay: remove support for circuit v1 nodes * circuitv2: remove v1 backwards compatibility * remove circuitv1 implementation only used for testing * remove circuitv1 protocol implementationpull/2114/head
Marten Seemann
2 years ago
committed by
GitHub
26 changed files with 24 additions and 3593 deletions
@ -1,448 +0,0 @@ |
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|||
// versions:
|
|||
// protoc-gen-go v1.28.1
|
|||
// protoc v3.21.12
|
|||
// source: pb/circuitv1.proto
|
|||
|
|||
package pb |
|||
|
|||
import ( |
|||
protoreflect "google.golang.org/protobuf/reflect/protoreflect" |
|||
protoimpl "google.golang.org/protobuf/runtime/protoimpl" |
|||
reflect "reflect" |
|||
sync "sync" |
|||
) |
|||
|
|||
const ( |
|||
// Verify that this generated code is sufficiently up-to-date.
|
|||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) |
|||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
|||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) |
|||
) |
|||
|
|||
type CircuitRelay_Status int32 |
|||
|
|||
const ( |
|||
CircuitRelay_SUCCESS CircuitRelay_Status = 100 |
|||
CircuitRelay_HOP_SRC_ADDR_TOO_LONG CircuitRelay_Status = 220 |
|||
CircuitRelay_HOP_DST_ADDR_TOO_LONG CircuitRelay_Status = 221 |
|||
CircuitRelay_HOP_SRC_MULTIADDR_INVALID CircuitRelay_Status = 250 |
|||
CircuitRelay_HOP_DST_MULTIADDR_INVALID CircuitRelay_Status = 251 |
|||
CircuitRelay_HOP_NO_CONN_TO_DST CircuitRelay_Status = 260 |
|||
CircuitRelay_HOP_CANT_DIAL_DST CircuitRelay_Status = 261 |
|||
CircuitRelay_HOP_CANT_OPEN_DST_STREAM CircuitRelay_Status = 262 |
|||
CircuitRelay_HOP_CANT_SPEAK_RELAY CircuitRelay_Status = 270 |
|||
CircuitRelay_HOP_CANT_RELAY_TO_SELF CircuitRelay_Status = 280 |
|||
CircuitRelay_STOP_SRC_ADDR_TOO_LONG CircuitRelay_Status = 320 |
|||
CircuitRelay_STOP_DST_ADDR_TOO_LONG CircuitRelay_Status = 321 |
|||
CircuitRelay_STOP_SRC_MULTIADDR_INVALID CircuitRelay_Status = 350 |
|||
CircuitRelay_STOP_DST_MULTIADDR_INVALID CircuitRelay_Status = 351 |
|||
CircuitRelay_STOP_RELAY_REFUSED CircuitRelay_Status = 390 |
|||
CircuitRelay_MALFORMED_MESSAGE CircuitRelay_Status = 400 |
|||
) |
|||
|
|||
// Enum value maps for CircuitRelay_Status.
|
|||
var ( |
|||
CircuitRelay_Status_name = map[int32]string{ |
|||
100: "SUCCESS", |
|||
220: "HOP_SRC_ADDR_TOO_LONG", |
|||
221: "HOP_DST_ADDR_TOO_LONG", |
|||
250: "HOP_SRC_MULTIADDR_INVALID", |
|||
251: "HOP_DST_MULTIADDR_INVALID", |
|||
260: "HOP_NO_CONN_TO_DST", |
|||
261: "HOP_CANT_DIAL_DST", |
|||
262: "HOP_CANT_OPEN_DST_STREAM", |
|||
270: "HOP_CANT_SPEAK_RELAY", |
|||
280: "HOP_CANT_RELAY_TO_SELF", |
|||
320: "STOP_SRC_ADDR_TOO_LONG", |
|||
321: "STOP_DST_ADDR_TOO_LONG", |
|||
350: "STOP_SRC_MULTIADDR_INVALID", |
|||
351: "STOP_DST_MULTIADDR_INVALID", |
|||
390: "STOP_RELAY_REFUSED", |
|||
400: "MALFORMED_MESSAGE", |
|||
} |
|||
CircuitRelay_Status_value = map[string]int32{ |
|||
"SUCCESS": 100, |
|||
"HOP_SRC_ADDR_TOO_LONG": 220, |
|||
"HOP_DST_ADDR_TOO_LONG": 221, |
|||
"HOP_SRC_MULTIADDR_INVALID": 250, |
|||
"HOP_DST_MULTIADDR_INVALID": 251, |
|||
"HOP_NO_CONN_TO_DST": 260, |
|||
"HOP_CANT_DIAL_DST": 261, |
|||
"HOP_CANT_OPEN_DST_STREAM": 262, |
|||
"HOP_CANT_SPEAK_RELAY": 270, |
|||
"HOP_CANT_RELAY_TO_SELF": 280, |
|||
"STOP_SRC_ADDR_TOO_LONG": 320, |
|||
"STOP_DST_ADDR_TOO_LONG": 321, |
|||
"STOP_SRC_MULTIADDR_INVALID": 350, |
|||
"STOP_DST_MULTIADDR_INVALID": 351, |
|||
"STOP_RELAY_REFUSED": 390, |
|||
"MALFORMED_MESSAGE": 400, |
|||
} |
|||
) |
|||
|
|||
func (x CircuitRelay_Status) Enum() *CircuitRelay_Status { |
|||
p := new(CircuitRelay_Status) |
|||
*p = x |
|||
return p |
|||
} |
|||
|
|||
func (x CircuitRelay_Status) String() string { |
|||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) |
|||
} |
|||
|
|||
func (CircuitRelay_Status) Descriptor() protoreflect.EnumDescriptor { |
|||
return file_pb_circuitv1_proto_enumTypes[0].Descriptor() |
|||
} |
|||
|
|||
func (CircuitRelay_Status) Type() protoreflect.EnumType { |
|||
return &file_pb_circuitv1_proto_enumTypes[0] |
|||
} |
|||
|
|||
func (x CircuitRelay_Status) Number() protoreflect.EnumNumber { |
|||
return protoreflect.EnumNumber(x) |
|||
} |
|||
|
|||
// Deprecated: Do not use.
|
|||
func (x *CircuitRelay_Status) UnmarshalJSON(b []byte) error { |
|||
num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
*x = CircuitRelay_Status(num) |
|||
return nil |
|||
} |
|||
|
|||
// Deprecated: Use CircuitRelay_Status.Descriptor instead.
|
|||
func (CircuitRelay_Status) EnumDescriptor() ([]byte, []int) { |
|||
return file_pb_circuitv1_proto_rawDescGZIP(), []int{0, 0} |
|||
} |
|||
|
|||
type CircuitRelay_Type int32 |
|||
|
|||
const ( |
|||
CircuitRelay_HOP CircuitRelay_Type = 1 |
|||
CircuitRelay_STOP CircuitRelay_Type = 2 |
|||
CircuitRelay_STATUS CircuitRelay_Type = 3 |
|||
CircuitRelay_CAN_HOP CircuitRelay_Type = 4 |
|||
) |
|||
|
|||
// Enum value maps for CircuitRelay_Type.
|
|||
var ( |
|||
CircuitRelay_Type_name = map[int32]string{ |
|||
1: "HOP", |
|||
2: "STOP", |
|||
3: "STATUS", |
|||
4: "CAN_HOP", |
|||
} |
|||
CircuitRelay_Type_value = map[string]int32{ |
|||
"HOP": 1, |
|||
"STOP": 2, |
|||
"STATUS": 3, |
|||
"CAN_HOP": 4, |
|||
} |
|||
) |
|||
|
|||
func (x CircuitRelay_Type) Enum() *CircuitRelay_Type { |
|||
p := new(CircuitRelay_Type) |
|||
*p = x |
|||
return p |
|||
} |
|||
|
|||
func (x CircuitRelay_Type) String() string { |
|||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) |
|||
} |
|||
|
|||
func (CircuitRelay_Type) Descriptor() protoreflect.EnumDescriptor { |
|||
return file_pb_circuitv1_proto_enumTypes[1].Descriptor() |
|||
} |
|||
|
|||
func (CircuitRelay_Type) Type() protoreflect.EnumType { |
|||
return &file_pb_circuitv1_proto_enumTypes[1] |
|||
} |
|||
|
|||
func (x CircuitRelay_Type) Number() protoreflect.EnumNumber { |
|||
return protoreflect.EnumNumber(x) |
|||
} |
|||
|
|||
// Deprecated: Do not use.
|
|||
func (x *CircuitRelay_Type) UnmarshalJSON(b []byte) error { |
|||
num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
*x = CircuitRelay_Type(num) |
|||
return nil |
|||
} |
|||
|
|||
// Deprecated: Use CircuitRelay_Type.Descriptor instead.
|
|||
func (CircuitRelay_Type) EnumDescriptor() ([]byte, []int) { |
|||
return file_pb_circuitv1_proto_rawDescGZIP(), []int{0, 1} |
|||
} |
|||
|
|||
type CircuitRelay struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Type *CircuitRelay_Type `protobuf:"varint,1,opt,name=type,enum=circuitv1.pb.CircuitRelay_Type" json:"type,omitempty"` // Type of the message
|
|||
SrcPeer *CircuitRelay_Peer `protobuf:"bytes,2,opt,name=srcPeer" json:"srcPeer,omitempty"` // srcPeer and dstPeer are used when Type is HOP or STOP
|
|||
DstPeer *CircuitRelay_Peer `protobuf:"bytes,3,opt,name=dstPeer" json:"dstPeer,omitempty"` |
|||
Code *CircuitRelay_Status `protobuf:"varint,4,opt,name=code,enum=circuitv1.pb.CircuitRelay_Status" json:"code,omitempty"` // Status code, used when Type is STATUS
|
|||
} |
|||
|
|||
func (x *CircuitRelay) Reset() { |
|||
*x = CircuitRelay{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_pb_circuitv1_proto_msgTypes[0] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *CircuitRelay) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*CircuitRelay) ProtoMessage() {} |
|||
|
|||
func (x *CircuitRelay) ProtoReflect() protoreflect.Message { |
|||
mi := &file_pb_circuitv1_proto_msgTypes[0] |
|||
if protoimpl.UnsafeEnabled && x != nil { |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
if ms.LoadMessageInfo() == nil { |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
return ms |
|||
} |
|||
return mi.MessageOf(x) |
|||
} |
|||
|
|||
// Deprecated: Use CircuitRelay.ProtoReflect.Descriptor instead.
|
|||
func (*CircuitRelay) Descriptor() ([]byte, []int) { |
|||
return file_pb_circuitv1_proto_rawDescGZIP(), []int{0} |
|||
} |
|||
|
|||
func (x *CircuitRelay) GetType() CircuitRelay_Type { |
|||
if x != nil && x.Type != nil { |
|||
return *x.Type |
|||
} |
|||
return CircuitRelay_HOP |
|||
} |
|||
|
|||
func (x *CircuitRelay) GetSrcPeer() *CircuitRelay_Peer { |
|||
if x != nil { |
|||
return x.SrcPeer |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *CircuitRelay) GetDstPeer() *CircuitRelay_Peer { |
|||
if x != nil { |
|||
return x.DstPeer |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *CircuitRelay) GetCode() CircuitRelay_Status { |
|||
if x != nil && x.Code != nil { |
|||
return *x.Code |
|||
} |
|||
return CircuitRelay_SUCCESS |
|||
} |
|||
|
|||
type CircuitRelay_Peer struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Id []byte `protobuf:"bytes,1,req,name=id" json:"id,omitempty"` // peer id
|
|||
Addrs [][]byte `protobuf:"bytes,2,rep,name=addrs" json:"addrs,omitempty"` // peer's known addresses
|
|||
} |
|||
|
|||
func (x *CircuitRelay_Peer) Reset() { |
|||
*x = CircuitRelay_Peer{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_pb_circuitv1_proto_msgTypes[1] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *CircuitRelay_Peer) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*CircuitRelay_Peer) ProtoMessage() {} |
|||
|
|||
func (x *CircuitRelay_Peer) ProtoReflect() protoreflect.Message { |
|||
mi := &file_pb_circuitv1_proto_msgTypes[1] |
|||
if protoimpl.UnsafeEnabled && x != nil { |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
if ms.LoadMessageInfo() == nil { |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
return ms |
|||
} |
|||
return mi.MessageOf(x) |
|||
} |
|||
|
|||
// Deprecated: Use CircuitRelay_Peer.ProtoReflect.Descriptor instead.
|
|||
func (*CircuitRelay_Peer) Descriptor() ([]byte, []int) { |
|||
return file_pb_circuitv1_proto_rawDescGZIP(), []int{0, 0} |
|||
} |
|||
|
|||
func (x *CircuitRelay_Peer) GetId() []byte { |
|||
if x != nil { |
|||
return x.Id |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *CircuitRelay_Peer) GetAddrs() [][]byte { |
|||
if x != nil { |
|||
return x.Addrs |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
var File_pb_circuitv1_proto protoreflect.FileDescriptor |
|||
|
|||
var file_pb_circuitv1_proto_rawDesc = []byte{ |
|||
0x0a, 0x12, 0x70, 0x62, 0x2f, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x76, 0x31, 0x2e, 0x70, |
|||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x76, 0x31, 0x2e, |
|||
0x70, 0x62, 0x22, 0x97, 0x06, 0x0a, 0x0c, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x52, 0x65, |
|||
0x6c, 0x61, 0x79, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, |
|||
0x0e, 0x32, 0x1f, 0x2e, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x76, 0x31, 0x2e, 0x70, 0x62, |
|||
0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x54, 0x79, |
|||
0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x73, 0x72, 0x63, 0x50, |
|||
0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x69, 0x72, 0x63, |
|||
0x75, 0x69, 0x74, 0x76, 0x31, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, |
|||
0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, |
|||
0x65, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x18, 0x03, |
|||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x76, 0x31, |
|||
0x2e, 0x70, 0x62, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x79, |
|||
0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x07, 0x64, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x35, |
|||
0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x63, |
|||
0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x76, 0x31, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x69, 0x72, 0x63, |
|||
0x75, 0x69, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, |
|||
0x04, 0x63, 0x6f, 0x64, 0x65, 0x1a, 0x2c, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, |
|||
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, |
|||
0x05, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x61, 0x64, |
|||
0x64, 0x72, 0x73, 0x22, 0xc2, 0x03, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, |
|||
0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x64, 0x12, 0x1a, 0x0a, 0x15, 0x48, |
|||
0x4f, 0x50, 0x5f, 0x53, 0x52, 0x43, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, |
|||
0x4c, 0x4f, 0x4e, 0x47, 0x10, 0xdc, 0x01, 0x12, 0x1a, 0x0a, 0x15, 0x48, 0x4f, 0x50, 0x5f, 0x44, |
|||
0x53, 0x54, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x4f, 0x4e, 0x47, |
|||
0x10, 0xdd, 0x01, 0x12, 0x1e, 0x0a, 0x19, 0x48, 0x4f, 0x50, 0x5f, 0x53, 0x52, 0x43, 0x5f, 0x4d, |
|||
0x55, 0x4c, 0x54, 0x49, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, |
|||
0x10, 0xfa, 0x01, 0x12, 0x1e, 0x0a, 0x19, 0x48, 0x4f, 0x50, 0x5f, 0x44, 0x53, 0x54, 0x5f, 0x4d, |
|||
0x55, 0x4c, 0x54, 0x49, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, |
|||
0x10, 0xfb, 0x01, 0x12, 0x17, 0x0a, 0x12, 0x48, 0x4f, 0x50, 0x5f, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, |
|||
0x4e, 0x4e, 0x5f, 0x54, 0x4f, 0x5f, 0x44, 0x53, 0x54, 0x10, 0x84, 0x02, 0x12, 0x16, 0x0a, 0x11, |
|||
0x48, 0x4f, 0x50, 0x5f, 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x44, 0x49, 0x41, 0x4c, 0x5f, 0x44, 0x53, |
|||
0x54, 0x10, 0x85, 0x02, 0x12, 0x1d, 0x0a, 0x18, 0x48, 0x4f, 0x50, 0x5f, 0x43, 0x41, 0x4e, 0x54, |
|||
0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x44, 0x53, 0x54, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, |
|||
0x10, 0x86, 0x02, 0x12, 0x19, 0x0a, 0x14, 0x48, 0x4f, 0x50, 0x5f, 0x43, 0x41, 0x4e, 0x54, 0x5f, |
|||
0x53, 0x50, 0x45, 0x41, 0x4b, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x10, 0x8e, 0x02, 0x12, 0x1b, |
|||
0x0a, 0x16, 0x48, 0x4f, 0x50, 0x5f, 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, |
|||
0x5f, 0x54, 0x4f, 0x5f, 0x53, 0x45, 0x4c, 0x46, 0x10, 0x98, 0x02, 0x12, 0x1b, 0x0a, 0x16, 0x53, |
|||
0x54, 0x4f, 0x50, 0x5f, 0x53, 0x52, 0x43, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x54, 0x4f, 0x4f, |
|||
0x5f, 0x4c, 0x4f, 0x4e, 0x47, 0x10, 0xc0, 0x02, 0x12, 0x1b, 0x0a, 0x16, 0x53, 0x54, 0x4f, 0x50, |
|||
0x5f, 0x44, 0x53, 0x54, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x4f, |
|||
0x4e, 0x47, 0x10, 0xc1, 0x02, 0x12, 0x1f, 0x0a, 0x1a, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x53, 0x52, |
|||
0x43, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x49, 0x4e, 0x56, 0x41, |
|||
0x4c, 0x49, 0x44, 0x10, 0xde, 0x02, 0x12, 0x1f, 0x0a, 0x1a, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x44, |
|||
0x53, 0x54, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x49, 0x4e, 0x56, |
|||
0x41, 0x4c, 0x49, 0x44, 0x10, 0xdf, 0x02, 0x12, 0x17, 0x0a, 0x12, 0x53, 0x54, 0x4f, 0x50, 0x5f, |
|||
0x52, 0x45, 0x4c, 0x41, 0x59, 0x5f, 0x52, 0x45, 0x46, 0x55, 0x53, 0x45, 0x44, 0x10, 0x86, 0x03, |
|||
0x12, 0x16, 0x0a, 0x11, 0x4d, 0x41, 0x4c, 0x46, 0x4f, 0x52, 0x4d, 0x45, 0x44, 0x5f, 0x4d, 0x45, |
|||
0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x90, 0x03, 0x22, 0x32, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, |
|||
0x12, 0x07, 0x0a, 0x03, 0x48, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, |
|||
0x50, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x10, 0x03, 0x12, |
|||
0x0b, 0x0a, 0x07, 0x43, 0x41, 0x4e, 0x5f, 0x48, 0x4f, 0x50, 0x10, 0x04, |
|||
} |
|||
|
|||
var ( |
|||
file_pb_circuitv1_proto_rawDescOnce sync.Once |
|||
file_pb_circuitv1_proto_rawDescData = file_pb_circuitv1_proto_rawDesc |
|||
) |
|||
|
|||
func file_pb_circuitv1_proto_rawDescGZIP() []byte { |
|||
file_pb_circuitv1_proto_rawDescOnce.Do(func() { |
|||
file_pb_circuitv1_proto_rawDescData = protoimpl.X.CompressGZIP(file_pb_circuitv1_proto_rawDescData) |
|||
}) |
|||
return file_pb_circuitv1_proto_rawDescData |
|||
} |
|||
|
|||
var file_pb_circuitv1_proto_enumTypes = make([]protoimpl.EnumInfo, 2) |
|||
var file_pb_circuitv1_proto_msgTypes = make([]protoimpl.MessageInfo, 2) |
|||
var file_pb_circuitv1_proto_goTypes = []interface{}{ |
|||
(CircuitRelay_Status)(0), // 0: circuitv1.pb.CircuitRelay.Status
|
|||
(CircuitRelay_Type)(0), // 1: circuitv1.pb.CircuitRelay.Type
|
|||
(*CircuitRelay)(nil), // 2: circuitv1.pb.CircuitRelay
|
|||
(*CircuitRelay_Peer)(nil), // 3: circuitv1.pb.CircuitRelay.Peer
|
|||
} |
|||
var file_pb_circuitv1_proto_depIdxs = []int32{ |
|||
1, // 0: circuitv1.pb.CircuitRelay.type:type_name -> circuitv1.pb.CircuitRelay.Type
|
|||
3, // 1: circuitv1.pb.CircuitRelay.srcPeer:type_name -> circuitv1.pb.CircuitRelay.Peer
|
|||
3, // 2: circuitv1.pb.CircuitRelay.dstPeer:type_name -> circuitv1.pb.CircuitRelay.Peer
|
|||
0, // 3: circuitv1.pb.CircuitRelay.code:type_name -> circuitv1.pb.CircuitRelay.Status
|
|||
4, // [4:4] is the sub-list for method output_type
|
|||
4, // [4:4] is the sub-list for method input_type
|
|||
4, // [4:4] is the sub-list for extension type_name
|
|||
4, // [4:4] is the sub-list for extension extendee
|
|||
0, // [0:4] is the sub-list for field type_name
|
|||
} |
|||
|
|||
func init() { file_pb_circuitv1_proto_init() } |
|||
func file_pb_circuitv1_proto_init() { |
|||
if File_pb_circuitv1_proto != nil { |
|||
return |
|||
} |
|||
if !protoimpl.UnsafeEnabled { |
|||
file_pb_circuitv1_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*CircuitRelay); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
file_pb_circuitv1_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*CircuitRelay_Peer); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
} |
|||
type x struct{} |
|||
out := protoimpl.TypeBuilder{ |
|||
File: protoimpl.DescBuilder{ |
|||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), |
|||
RawDescriptor: file_pb_circuitv1_proto_rawDesc, |
|||
NumEnums: 2, |
|||
NumMessages: 2, |
|||
NumExtensions: 0, |
|||
NumServices: 0, |
|||
}, |
|||
GoTypes: file_pb_circuitv1_proto_goTypes, |
|||
DependencyIndexes: file_pb_circuitv1_proto_depIdxs, |
|||
EnumInfos: file_pb_circuitv1_proto_enumTypes, |
|||
MessageInfos: file_pb_circuitv1_proto_msgTypes, |
|||
}.Build() |
|||
File_pb_circuitv1_proto = out.File |
|||
file_pb_circuitv1_proto_rawDesc = nil |
|||
file_pb_circuitv1_proto_goTypes = nil |
|||
file_pb_circuitv1_proto_depIdxs = nil |
|||
} |
@ -1,44 +0,0 @@ |
|||
syntax = "proto2"; |
|||
|
|||
package circuitv1.pb; |
|||
|
|||
message CircuitRelay { |
|||
|
|||
enum Status { |
|||
SUCCESS = 100; |
|||
HOP_SRC_ADDR_TOO_LONG = 220; |
|||
HOP_DST_ADDR_TOO_LONG = 221; |
|||
HOP_SRC_MULTIADDR_INVALID = 250; |
|||
HOP_DST_MULTIADDR_INVALID = 251; |
|||
HOP_NO_CONN_TO_DST = 260; |
|||
HOP_CANT_DIAL_DST = 261; |
|||
HOP_CANT_OPEN_DST_STREAM = 262; |
|||
HOP_CANT_SPEAK_RELAY = 270; |
|||
HOP_CANT_RELAY_TO_SELF = 280; |
|||
STOP_SRC_ADDR_TOO_LONG = 320; |
|||
STOP_DST_ADDR_TOO_LONG = 321; |
|||
STOP_SRC_MULTIADDR_INVALID = 350; |
|||
STOP_DST_MULTIADDR_INVALID = 351; |
|||
STOP_RELAY_REFUSED = 390; |
|||
MALFORMED_MESSAGE = 400; |
|||
} |
|||
|
|||
enum Type { // RPC identifier, either HOP, STOP or STATUS |
|||
HOP = 1; |
|||
STOP = 2; |
|||
STATUS = 3; |
|||
CAN_HOP = 4; |
|||
} |
|||
|
|||
message Peer { |
|||
required bytes id = 1; // peer id |
|||
repeated bytes addrs = 2; // peer's known addresses |
|||
} |
|||
|
|||
optional Type type = 1; // Type of the message |
|||
|
|||
optional Peer srcPeer = 2; // srcPeer and dstPeer are used when Type is HOP or STOP |
|||
optional Peer dstPeer = 3; |
|||
|
|||
optional Status code = 4; // Status code, used when Type is STATUS |
|||
} |
@ -1,3 +0,0 @@ |
|||
package circuitv1 |
|||
|
|||
//go:generate protoc --proto_path=$PWD:$PWD/../../.. --go_out=. --go_opt=Mpb/circuitv1.proto=./pb pb/circuitv1.proto
|
@ -1,46 +0,0 @@ |
|||
package relay |
|||
|
|||
import ( |
|||
"github.com/libp2p/go-libp2p/core/peer" |
|||
) |
|||
|
|||
type Resources struct { |
|||
// MaxCircuits is the maximum number of active relay connections
|
|||
MaxCircuits int |
|||
|
|||
// MaxCircuitsPerPeer is the maximum number of active relay connections per peer
|
|||
MaxCircuitsPerPeer int |
|||
|
|||
// BufferSize is the buffer size for relaying in each direction
|
|||
BufferSize int |
|||
} |
|||
|
|||
func DefaultResources() Resources { |
|||
return Resources{ |
|||
MaxCircuits: 1024, |
|||
MaxCircuitsPerPeer: 64, |
|||
BufferSize: 4096, |
|||
} |
|||
} |
|||
|
|||
type ACLFilter interface { |
|||
AllowHop(src, dest peer.ID) bool |
|||
} |
|||
|
|||
type Option func(r *Relay) error |
|||
|
|||
// WithResources specifies resource limits for the relay
|
|||
func WithResources(rc Resources) Option { |
|||
return func(r *Relay) error { |
|||
r.rc = rc |
|||
return nil |
|||
} |
|||
} |
|||
|
|||
// WithACL specifies an ACLFilter for access control
|
|||
func WithACL(acl ACLFilter) Option { |
|||
return func(r *Relay) error { |
|||
r.acl = acl |
|||
return nil |
|||
} |
|||
} |
@ -1,452 +0,0 @@ |
|||
package relay |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"io" |
|||
"sync" |
|||
"sync/atomic" |
|||
"time" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/host" |
|||
"github.com/libp2p/go-libp2p/core/network" |
|||
"github.com/libp2p/go-libp2p/core/peer" |
|||
pb "github.com/libp2p/go-libp2p/p2p/protocol/circuitv1/pb" |
|||
"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/util" |
|||
|
|||
logging "github.com/ipfs/go-log/v2" |
|||
pool "github.com/libp2p/go-buffer-pool" |
|||
ma "github.com/multiformats/go-multiaddr" |
|||
) |
|||
|
|||
var log = logging.Logger("relay") |
|||
|
|||
const ( |
|||
ProtoID = "/libp2p/circuit/relay/0.1.0" |
|||
|
|||
ServiceName = "libp2p.relay/v1" |
|||
|
|||
StreamTimeout = time.Minute |
|||
ConnectTimeout = 30 * time.Second |
|||
HandshakeTimeout = time.Minute |
|||
|
|||
relayHopTag = "relay-v1-hop" |
|||
relayHopTagValue = 2 |
|||
|
|||
maxMessageSize = 4096 |
|||
) |
|||
|
|||
type Relay struct { |
|||
closed atomic.Bool |
|||
ctx context.Context |
|||
cancel context.CancelFunc |
|||
|
|||
host host.Host |
|||
rc Resources |
|||
acl ACLFilter |
|||
scope network.ResourceScopeSpan |
|||
|
|||
mx sync.Mutex |
|||
conns map[peer.ID]int |
|||
active int |
|||
} |
|||
|
|||
func NewRelay(h host.Host, opts ...Option) (*Relay, error) { |
|||
r := &Relay{ |
|||
host: h, |
|||
rc: DefaultResources(), |
|||
conns: make(map[peer.ID]int), |
|||
} |
|||
r.ctx, r.cancel = context.WithCancel(context.Background()) |
|||
|
|||
for _, opt := range opts { |
|||
err := opt(r) |
|||
if err != nil { |
|||
return nil, fmt.Errorf("error applying relay option: %w", err) |
|||
} |
|||
} |
|||
|
|||
// get a scope for memory reservations at service level
|
|||
err := h.Network().ResourceManager().ViewService(ServiceName, |
|||
func(s network.ServiceScope) error { |
|||
var err error |
|||
r.scope, err = s.BeginSpan() |
|||
return err |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
h.SetStreamHandler(ProtoID, r.handleStream) |
|||
|
|||
return r, nil |
|||
} |
|||
|
|||
func (r *Relay) Close() error { |
|||
if r.closed.CompareAndSwap(false, true) { |
|||
r.host.RemoveStreamHandler(ProtoID) |
|||
r.scope.Done() |
|||
r.cancel() |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (r *Relay) handleStream(s network.Stream) { |
|||
log.Debugf("new relay stream from: %s", s.Conn().RemotePeer()) |
|||
|
|||
if err := s.Scope().SetService(ServiceName); err != nil { |
|||
log.Debugf("error attaching stream to relay service: %s", err) |
|||
s.Reset() |
|||
return |
|||
} |
|||
|
|||
if err := s.Scope().ReserveMemory(maxMessageSize, network.ReservationPriorityAlways); err != nil { |
|||
log.Debugf("error reserving memory for stream: %s", err) |
|||
s.Reset() |
|||
return |
|||
} |
|||
defer s.Scope().ReleaseMemory(maxMessageSize) |
|||
|
|||
rd := util.NewDelimitedReader(s, maxMessageSize) |
|||
defer rd.Close() |
|||
|
|||
s.SetReadDeadline(time.Now().Add(StreamTimeout)) |
|||
|
|||
var msg pb.CircuitRelay |
|||
|
|||
err := rd.ReadMsg(&msg) |
|||
if err != nil { |
|||
r.handleError(s, pb.CircuitRelay_MALFORMED_MESSAGE) |
|||
return |
|||
} |
|||
s.SetReadDeadline(time.Time{}) |
|||
|
|||
switch msg.GetType() { |
|||
case pb.CircuitRelay_HOP: |
|||
r.handleHopStream(s, &msg) |
|||
case pb.CircuitRelay_CAN_HOP: |
|||
r.handleCanHop(s, &msg) |
|||
case pb.CircuitRelay_STOP: |
|||
r.handleError(s, pb.CircuitRelay_STOP_RELAY_REFUSED) |
|||
default: |
|||
log.Warnf("unexpected relay handshake: %d", msg.GetType()) |
|||
r.handleError(s, pb.CircuitRelay_MALFORMED_MESSAGE) |
|||
} |
|||
} |
|||
|
|||
func (r *Relay) handleHopStream(s network.Stream, msg *pb.CircuitRelay) { |
|||
span, err := r.scope.BeginSpan() |
|||
if err != nil { |
|||
log.Debugf("failed to begin relay transaction: %s", err) |
|||
r.handleError(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
return |
|||
} |
|||
|
|||
fail := func(code pb.CircuitRelay_Status) { |
|||
span.Done() |
|||
r.handleError(s, code) |
|||
} |
|||
|
|||
// reserve buffers for the relay
|
|||
if err := span.ReserveMemory(2*r.rc.BufferSize, network.ReservationPriorityHigh); err != nil { |
|||
log.Debugf("error reserving memory for relay: %s", err) |
|||
fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
return |
|||
} |
|||
|
|||
src, err := peerToPeerInfo(msg.GetSrcPeer()) |
|||
if err != nil { |
|||
fail(pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) |
|||
return |
|||
} |
|||
|
|||
if src.ID != s.Conn().RemotePeer() { |
|||
fail(pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) |
|||
return |
|||
} |
|||
|
|||
dest, err := peerToPeerInfo(msg.GetDstPeer()) |
|||
if err != nil { |
|||
fail(pb.CircuitRelay_HOP_DST_MULTIADDR_INVALID) |
|||
return |
|||
} |
|||
|
|||
if dest.ID == r.host.ID() { |
|||
fail(pb.CircuitRelay_HOP_CANT_RELAY_TO_SELF) |
|||
return |
|||
} |
|||
|
|||
if r.acl != nil && !r.acl.AllowHop(src.ID, dest.ID) { |
|||
log.Debugf("refusing hop from %s to %s; ACL refused", src.ID, dest.ID) |
|||
fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
return |
|||
} |
|||
|
|||
r.mx.Lock() |
|||
if r.active >= r.rc.MaxCircuits { |
|||
r.mx.Unlock() |
|||
log.Debugf("refusing connection from %s to %s; too many active circuits", src.ID, dest.ID) |
|||
fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
return |
|||
} |
|||
|
|||
srcConns := r.conns[src.ID] |
|||
if srcConns >= r.rc.MaxCircuitsPerPeer { |
|||
r.mx.Unlock() |
|||
log.Debugf("refusing connection from %s to %s; too many connections from %s", src.ID, dest.ID, src) |
|||
fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
return |
|||
} |
|||
|
|||
destConns := r.conns[dest.ID] |
|||
if destConns >= r.rc.MaxCircuitsPerPeer { |
|||
r.mx.Unlock() |
|||
log.Debugf("refusing connection from %s to %s; too many connecitons to %s", src.ID, dest.ID, dest.ID) |
|||
fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
return |
|||
} |
|||
|
|||
r.active++ |
|||
r.addConn(src.ID) |
|||
r.addConn(src.ID) |
|||
r.mx.Unlock() |
|||
|
|||
cleanup := func() { |
|||
span.Done() |
|||
r.mx.Lock() |
|||
r.active-- |
|||
r.rmConn(src.ID) |
|||
r.rmConn(dest.ID) |
|||
r.mx.Unlock() |
|||
} |
|||
|
|||
// open stream
|
|||
ctx, cancel := context.WithTimeout(r.ctx, ConnectTimeout) |
|||
defer cancel() |
|||
|
|||
ctx = network.WithNoDial(ctx, "relay hop") |
|||
bs, err := r.host.NewStream(ctx, dest.ID, ProtoID) |
|||
if err != nil { |
|||
log.Debugf("error opening relay stream to %s: %s", dest.ID.Pretty(), err.Error()) |
|||
if err == network.ErrNoConn { |
|||
r.handleError(s, pb.CircuitRelay_HOP_NO_CONN_TO_DST) |
|||
} else { |
|||
r.handleError(s, pb.CircuitRelay_HOP_CANT_DIAL_DST) |
|||
} |
|||
cleanup() |
|||
return |
|||
} |
|||
|
|||
fail = func(code pb.CircuitRelay_Status) { |
|||
bs.Reset() |
|||
cleanup() |
|||
r.handleError(s, code) |
|||
} |
|||
|
|||
if err := bs.Scope().SetService(ServiceName); err != nil { |
|||
log.Debugf("error attaching stream to relay service: %s", err) |
|||
fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
return |
|||
} |
|||
|
|||
// stop handshake
|
|||
if err := bs.Scope().ReserveMemory(maxMessageSize, network.ReservationPriorityAlways); err != nil { |
|||
log.Debugf("failed to reserve memory for stream: %s", err) |
|||
fail(pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
return |
|||
} |
|||
defer bs.Scope().ReleaseMemory(maxMessageSize) |
|||
|
|||
rd := util.NewDelimitedReader(bs, maxMessageSize) |
|||
wr := util.NewDelimitedWriter(bs) |
|||
defer rd.Close() |
|||
|
|||
// set handshake deadline
|
|||
bs.SetDeadline(time.Now().Add(HandshakeTimeout)) |
|||
|
|||
msg.Type = pb.CircuitRelay_STOP.Enum() |
|||
|
|||
err = wr.WriteMsg(msg) |
|||
if err != nil { |
|||
log.Debugf("error writing stop handshake: %s", err.Error()) |
|||
fail(pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) |
|||
return |
|||
} |
|||
|
|||
msg.Reset() |
|||
|
|||
err = rd.ReadMsg(msg) |
|||
if err != nil { |
|||
log.Debugf("error reading stop response: %s", err.Error()) |
|||
fail(pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) |
|||
return |
|||
} |
|||
|
|||
if msg.GetType() != pb.CircuitRelay_STATUS { |
|||
log.Debugf("unexpected relay stop response: not a status message (%d)", msg.GetType()) |
|||
fail(pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) |
|||
return |
|||
} |
|||
|
|||
if msg.GetCode() != pb.CircuitRelay_SUCCESS { |
|||
log.Debugf("relay stop failure: %d", msg.GetCode()) |
|||
fail(msg.GetCode()) |
|||
return |
|||
} |
|||
|
|||
err = r.writeResponse(s, pb.CircuitRelay_SUCCESS) |
|||
if err != nil { |
|||
log.Debugf("error writing relay response: %s", err.Error()) |
|||
bs.Reset() |
|||
s.Reset() |
|||
cleanup() |
|||
return |
|||
} |
|||
|
|||
// relay connection
|
|||
log.Infof("relaying connection between %s and %s", src.ID.Pretty(), dest.ID.Pretty()) |
|||
|
|||
// reset deadline
|
|||
bs.SetDeadline(time.Time{}) |
|||
|
|||
var goroutines atomic.Int32 |
|||
goroutines.Store(2) |
|||
done := func() { |
|||
if goroutines.Add(-1) == 0 { |
|||
s.Close() |
|||
bs.Close() |
|||
cleanup() |
|||
} |
|||
} |
|||
|
|||
go r.relayConn(s, bs, src.ID, dest.ID, done) |
|||
go r.relayConn(bs, s, dest.ID, src.ID, done) |
|||
} |
|||
|
|||
func (r *Relay) addConn(p peer.ID) { |
|||
conns := r.conns[p] |
|||
conns++ |
|||
r.conns[p] = conns |
|||
if conns == 1 { |
|||
r.host.ConnManager().TagPeer(p, relayHopTag, relayHopTagValue) |
|||
} |
|||
} |
|||
|
|||
func (r *Relay) rmConn(p peer.ID) { |
|||
conns := r.conns[p] |
|||
conns-- |
|||
if conns > 0 { |
|||
r.conns[p] = conns |
|||
} else { |
|||
delete(r.conns, p) |
|||
r.host.ConnManager().UntagPeer(p, relayHopTag) |
|||
} |
|||
} |
|||
|
|||
func (r *Relay) relayConn(src, dest network.Stream, srcID, destID peer.ID, done func()) { |
|||
defer done() |
|||
|
|||
buf := pool.Get(r.rc.BufferSize) |
|||
defer pool.Put(buf) |
|||
|
|||
count, err := io.CopyBuffer(dest, src, buf) |
|||
if err != nil { |
|||
log.Debugf("relay copy error: %s", err) |
|||
// Reset both.
|
|||
src.Reset() |
|||
dest.Reset() |
|||
} else { |
|||
// propagate the close
|
|||
dest.CloseWrite() |
|||
} |
|||
|
|||
log.Debugf("relayed %d bytes from %s to %s", count, srcID, destID) |
|||
} |
|||
|
|||
func (r *Relay) handleCanHop(s network.Stream, msg *pb.CircuitRelay) { |
|||
err := r.writeResponse(s, pb.CircuitRelay_SUCCESS) |
|||
|
|||
if err != nil { |
|||
s.Reset() |
|||
log.Debugf("error writing relay response: %s", err.Error()) |
|||
} else { |
|||
s.Close() |
|||
} |
|||
} |
|||
|
|||
func (r *Relay) handleError(s network.Stream, code pb.CircuitRelay_Status) { |
|||
log.Warnf("relay error: %s", code) |
|||
err := r.writeResponse(s, code) |
|||
if err != nil { |
|||
s.Reset() |
|||
log.Debugf("error writing relay response: %s", err.Error()) |
|||
} else { |
|||
s.Close() |
|||
} |
|||
} |
|||
|
|||
// Queries a peer for support of hop relay
|
|||
func CanHop(ctx context.Context, host host.Host, id peer.ID) (bool, error) { |
|||
s, err := host.NewStream(ctx, id, ProtoID) |
|||
if err != nil { |
|||
return false, err |
|||
} |
|||
defer s.Close() |
|||
|
|||
rd := util.NewDelimitedReader(s, maxMessageSize) |
|||
wr := util.NewDelimitedWriter(s) |
|||
defer rd.Close() |
|||
|
|||
var msg pb.CircuitRelay |
|||
|
|||
msg.Type = pb.CircuitRelay_CAN_HOP.Enum() |
|||
|
|||
if err := wr.WriteMsg(&msg); err != nil { |
|||
s.Reset() |
|||
return false, err |
|||
} |
|||
|
|||
msg.Reset() |
|||
|
|||
if err := rd.ReadMsg(&msg); err != nil { |
|||
s.Reset() |
|||
return false, err |
|||
} |
|||
|
|||
if msg.GetType() != pb.CircuitRelay_STATUS { |
|||
return false, fmt.Errorf("unexpected relay response; not a status message (%d)", msg.GetType()) |
|||
} |
|||
|
|||
return msg.GetCode() == pb.CircuitRelay_SUCCESS, nil |
|||
} |
|||
|
|||
func (r *Relay) writeResponse(s network.Stream, code pb.CircuitRelay_Status) error { |
|||
wr := util.NewDelimitedWriter(s) |
|||
|
|||
var msg pb.CircuitRelay |
|||
msg.Type = pb.CircuitRelay_STATUS.Enum() |
|||
msg.Code = code.Enum() |
|||
|
|||
return wr.WriteMsg(&msg) |
|||
} |
|||
|
|||
func peerToPeerInfo(p *pb.CircuitRelay_Peer) (peer.AddrInfo, error) { |
|||
if p == nil { |
|||
return peer.AddrInfo{}, fmt.Errorf("nil peer") |
|||
} |
|||
|
|||
id, err := peer.IDFromBytes(p.Id) |
|||
if err != nil { |
|||
return peer.AddrInfo{}, err |
|||
} |
|||
|
|||
addrs := make([]ma.Multiaddr, 0, len(p.Addrs)) |
|||
for _, addrBytes := range p.Addrs { |
|||
a, err := ma.NewMultiaddrBytes(addrBytes) |
|||
if err == nil { |
|||
addrs = append(addrs, a) |
|||
} |
|||
} |
|||
|
|||
return peer.AddrInfo{ID: id, Addrs: addrs}, nil |
|||
} |
@ -1,7 +1,6 @@ |
|||
package proto |
|||
|
|||
const ( |
|||
ProtoIDv1 = "/libp2p/circuit/relay/0.1.0" |
|||
ProtoIDv2Hop = "/libp2p/circuit/relay/0.2.0/hop" |
|||
ProtoIDv2Stop = "/libp2p/circuit/relay/0.2.0/stop" |
|||
) |
|||
|
@ -1,179 +0,0 @@ |
|||
package relay_test |
|||
|
|||
import ( |
|||
"bytes" |
|||
"context" |
|||
"fmt" |
|||
"io" |
|||
"testing" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/host" |
|||
"github.com/libp2p/go-libp2p/core/network" |
|||
"github.com/libp2p/go-libp2p/core/peer" |
|||
"github.com/libp2p/go-libp2p/core/transport" |
|||
relayv1 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv1/relay" |
|||
compatv1 "github.com/libp2p/go-libp2p/p2p/protocol/internal/circuitv1-deprecated" |
|||
|
|||
ma "github.com/multiformats/go-multiaddr" |
|||
) |
|||
|
|||
func addTransportV1(t *testing.T, h host.Host, upgrader transport.Upgrader) { |
|||
err := compatv1.AddRelayTransport(h, upgrader) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
} |
|||
|
|||
func TestRelayCompatV2DialV1(t *testing.T) { |
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts, upgraders := getNetHosts(t, ctx, 3) |
|||
addTransportV1(t, hosts[0], upgraders[0]) |
|||
addTransport(t, hosts[2], upgraders[2]) |
|||
|
|||
rch := make(chan []byte, 1) |
|||
hosts[0].SetStreamHandler("test", func(s network.Stream) { |
|||
defer s.Close() |
|||
defer close(rch) |
|||
|
|||
buf := make([]byte, 1024) |
|||
nread := 0 |
|||
for nread < len(buf) { |
|||
n, err := s.Read(buf[nread:]) |
|||
nread += n |
|||
if err != nil { |
|||
if err == io.EOF { |
|||
break |
|||
} |
|||
t.Fatal(err) |
|||
} |
|||
} |
|||
|
|||
rch <- buf[:nread] |
|||
}) |
|||
|
|||
r, err := relayv1.NewRelay(hosts[1]) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
defer r.Close() |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
connect(t, hosts[1], hosts[2]) |
|||
|
|||
raddr, err := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s/p2p-circuit/p2p/%s", hosts[1].ID(), hosts[0].ID())) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
err = hosts[2].Connect(ctx, peer.AddrInfo{ID: hosts[0].ID(), Addrs: []ma.Multiaddr{raddr}}) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
conns := hosts[2].Network().ConnsToPeer(hosts[0].ID()) |
|||
if len(conns) != 1 { |
|||
t.Fatalf("expected 1 connection, but got %d", len(conns)) |
|||
} |
|||
if conns[0].Stat().Transient { |
|||
t.Fatal("expected non transient connection") |
|||
} |
|||
|
|||
s, err := hosts[2].NewStream(ctx, hosts[0].ID(), "test") |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
msg := []byte("relay works!") |
|||
nwritten, err := s.Write(msg) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
if nwritten != len(msg) { |
|||
t.Fatalf("expected to write %d bytes, but wrote %d instead", len(msg), nwritten) |
|||
} |
|||
s.CloseWrite() |
|||
|
|||
got := <-rch |
|||
if !bytes.Equal(msg, got) { |
|||
t.Fatalf("Wrong echo; expected %s but got %s", string(msg), string(got)) |
|||
} |
|||
} |
|||
|
|||
func TestRelayCompatV1DialV2(t *testing.T) { |
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts, upgraders := getNetHosts(t, ctx, 3) |
|||
addTransport(t, hosts[0], upgraders[0]) |
|||
addTransportV1(t, hosts[2], upgraders[2]) |
|||
|
|||
rch := make(chan []byte, 1) |
|||
hosts[0].SetStreamHandler("test", func(s network.Stream) { |
|||
defer s.Close() |
|||
defer close(rch) |
|||
|
|||
buf := make([]byte, 1024) |
|||
nread := 0 |
|||
for nread < len(buf) { |
|||
n, err := s.Read(buf[nread:]) |
|||
nread += n |
|||
if err != nil { |
|||
if err == io.EOF { |
|||
break |
|||
} |
|||
t.Fatal(err) |
|||
} |
|||
} |
|||
|
|||
rch <- buf[:nread] |
|||
}) |
|||
|
|||
r, err := relayv1.NewRelay(hosts[1]) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
defer r.Close() |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
connect(t, hosts[1], hosts[2]) |
|||
|
|||
raddr, err := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s/p2p-circuit/p2p/%s", hosts[1].ID(), hosts[0].ID())) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
err = hosts[2].Connect(ctx, peer.AddrInfo{ID: hosts[0].ID(), Addrs: []ma.Multiaddr{raddr}}) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
conns := hosts[2].Network().ConnsToPeer(hosts[0].ID()) |
|||
if len(conns) != 1 { |
|||
t.Fatalf("expected 1 connection, but got %d", len(conns)) |
|||
} |
|||
if conns[0].Stat().Transient { |
|||
t.Fatal("expected non transient connection") |
|||
} |
|||
|
|||
s, err := hosts[2].NewStream(ctx, hosts[0].ID(), "test") |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
msg := []byte("relay works!") |
|||
nwritten, err := s.Write(msg) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
if nwritten != len(msg) { |
|||
t.Fatalf("expected to write %d bytes, but wrote %d instead", len(msg), nwritten) |
|||
} |
|||
s.CloseWrite() |
|||
|
|||
got := <-rch |
|||
if !bytes.Equal(msg, got) { |
|||
t.Fatalf("Wrong echo; expected %s but got %s", string(msg), string(got)) |
|||
} |
|||
} |
@ -1,124 +0,0 @@ |
|||
package relay |
|||
|
|||
import ( |
|||
"fmt" |
|||
"net" |
|||
"time" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/host" |
|||
"github.com/libp2p/go-libp2p/core/network" |
|||
"github.com/libp2p/go-libp2p/core/peer" |
|||
|
|||
ma "github.com/multiformats/go-multiaddr" |
|||
manet "github.com/multiformats/go-multiaddr/net" |
|||
) |
|||
|
|||
// HopTagWeight is the connection manager weight for connections carrying relay hop streams
|
|||
var HopTagWeight = 5 |
|||
|
|||
type Conn struct { |
|||
stream network.Stream |
|||
remote peer.AddrInfo |
|||
host host.Host |
|||
relay *Relay |
|||
} |
|||
|
|||
type NetAddr struct { |
|||
Relay string |
|||
Remote string |
|||
} |
|||
|
|||
func (n *NetAddr) Network() string { |
|||
return "libp2p-circuit-relay" |
|||
} |
|||
|
|||
func (n *NetAddr) String() string { |
|||
return fmt.Sprintf("relay[%s-%s]", n.Remote, n.Relay) |
|||
} |
|||
|
|||
func (c *Conn) Close() error { |
|||
c.untagHop() |
|||
return c.stream.Reset() |
|||
} |
|||
|
|||
func (c *Conn) Read(buf []byte) (int, error) { |
|||
return c.stream.Read(buf) |
|||
} |
|||
|
|||
func (c *Conn) Write(buf []byte) (int, error) { |
|||
return c.stream.Write(buf) |
|||
} |
|||
|
|||
func (c *Conn) SetDeadline(t time.Time) error { |
|||
return c.stream.SetDeadline(t) |
|||
} |
|||
|
|||
func (c *Conn) SetReadDeadline(t time.Time) error { |
|||
return c.stream.SetReadDeadline(t) |
|||
} |
|||
|
|||
func (c *Conn) SetWriteDeadline(t time.Time) error { |
|||
return c.stream.SetWriteDeadline(t) |
|||
} |
|||
|
|||
func (c *Conn) RemoteAddr() net.Addr { |
|||
return &NetAddr{ |
|||
Relay: c.stream.Conn().RemotePeer().Pretty(), |
|||
Remote: c.remote.ID.Pretty(), |
|||
} |
|||
} |
|||
|
|||
// Increment the underlying relay connection tag by 1, thus increasing its protection from
|
|||
// connection pruning. This ensures that connections to relays are not accidentally closed,
|
|||
// by the connection manager, taking with them all the relayed connections (that may themselves
|
|||
// be protected).
|
|||
func (c *Conn) tagHop() { |
|||
c.relay.mx.Lock() |
|||
defer c.relay.mx.Unlock() |
|||
|
|||
p := c.stream.Conn().RemotePeer() |
|||
c.relay.hopCount[p]++ |
|||
if c.relay.hopCount[p] == 1 { |
|||
c.host.ConnManager().TagPeer(p, "relay-hop-stream", HopTagWeight) |
|||
} |
|||
} |
|||
|
|||
// Decrement the underlying relay connection tag by 1; this is performed when we close the
|
|||
// relayed connection.
|
|||
func (c *Conn) untagHop() { |
|||
c.relay.mx.Lock() |
|||
defer c.relay.mx.Unlock() |
|||
|
|||
p := c.stream.Conn().RemotePeer() |
|||
c.relay.hopCount[p]-- |
|||
if c.relay.hopCount[p] == 0 { |
|||
c.host.ConnManager().UntagPeer(p, "relay-hop-stream") |
|||
delete(c.relay.hopCount, p) |
|||
} |
|||
} |
|||
|
|||
// TODO: is it okay to cast c.Conn().RemotePeer() into a multiaddr? might be "user input"
|
|||
func (c *Conn) RemoteMultiaddr() ma.Multiaddr { |
|||
// TODO: We should be able to do this directly without converting to/from a string.
|
|||
relayAddr, err := ma.NewComponent( |
|||
ma.ProtocolWithCode(ma.P_P2P).Name, |
|||
c.stream.Conn().RemotePeer().Pretty(), |
|||
) |
|||
if err != nil { |
|||
panic(err) |
|||
} |
|||
return ma.Join(c.stream.Conn().RemoteMultiaddr(), relayAddr, circuitAddr) |
|||
} |
|||
|
|||
func (c *Conn) LocalMultiaddr() ma.Multiaddr { |
|||
return c.stream.Conn().LocalMultiaddr() |
|||
} |
|||
|
|||
func (c *Conn) LocalAddr() net.Addr { |
|||
na, err := manet.ToNetAddr(c.stream.Conn().LocalMultiaddr()) |
|||
if err != nil { |
|||
log.Error("failed to convert local multiaddr to net addr:", err) |
|||
return nil |
|||
} |
|||
return na |
|||
} |
@ -1,57 +0,0 @@ |
|||
package relay |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/network" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/peer" |
|||
"github.com/libp2p/go-libp2p/core/transport" |
|||
ma "github.com/multiformats/go-multiaddr" |
|||
) |
|||
|
|||
func (d *RelayTransport) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (transport.CapableConn, error) { |
|||
c, err := d.Relay().Dial(ctx, a, p) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
c.tagHop() |
|||
scope, _ := (&network.NullResourceManager{}).OpenConnection(network.DirOutbound, false, a) |
|||
return d.upgrader.Upgrade(ctx, d, c, network.DirOutbound, p, scope) |
|||
} |
|||
|
|||
func (r *Relay) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (*Conn, error) { |
|||
// split /a/p2p-circuit/b into (/a, /p2p-circuit/b)
|
|||
relayaddr, destaddr := ma.SplitFunc(a, func(c ma.Component) bool { |
|||
return c.Protocol().Code == ma.P_CIRCUIT |
|||
}) |
|||
|
|||
// If the address contained no /p2p-circuit part, the second part is nil.
|
|||
if destaddr == nil { |
|||
return nil, fmt.Errorf("%s is not a relay address", a) |
|||
} |
|||
|
|||
if relayaddr == nil { |
|||
return nil, fmt.Errorf( |
|||
"can't dial a p2p-circuit without specifying a relay: %s", |
|||
a, |
|||
) |
|||
} |
|||
|
|||
// Strip the /p2p-circuit prefix from the destaddr.
|
|||
_, destaddr = ma.SplitFirst(destaddr) |
|||
|
|||
dinfo := &peer.AddrInfo{ID: p, Addrs: []ma.Multiaddr{}} |
|||
if destaddr != nil { |
|||
dinfo.Addrs = append(dinfo.Addrs, destaddr) |
|||
} |
|||
|
|||
var rinfo *peer.AddrInfo |
|||
rinfo, err := peer.AddrInfoFromP2pAddr(relayaddr) |
|||
if err != nil { |
|||
return nil, fmt.Errorf("error parsing multiaddr '%s': %s", relayaddr.String(), err) |
|||
} |
|||
|
|||
return r.DialPeer(ctx, *rinfo, *dinfo) |
|||
} |
@ -1,61 +0,0 @@ |
|||
package relay |
|||
|
|||
import ( |
|||
"net" |
|||
|
|||
pb "github.com/libp2p/go-libp2p/p2p/protocol/internal/circuitv1-deprecated/pb" |
|||
|
|||
ma "github.com/multiformats/go-multiaddr" |
|||
manet "github.com/multiformats/go-multiaddr/net" |
|||
) |
|||
|
|||
var _ manet.Listener = (*RelayListener)(nil) |
|||
|
|||
type RelayListener Relay |
|||
|
|||
func (l *RelayListener) Relay() *Relay { |
|||
return (*Relay)(l) |
|||
} |
|||
|
|||
func (r *Relay) Listener() *RelayListener { |
|||
// TODO: Only allow one!
|
|||
return (*RelayListener)(r) |
|||
} |
|||
|
|||
func (l *RelayListener) Accept() (manet.Conn, error) { |
|||
for { |
|||
select { |
|||
case c := <-l.incoming: |
|||
err := l.Relay().writeResponse(c.stream, pb.CircuitRelay_SUCCESS) |
|||
if err != nil { |
|||
log.Debugf("error writing relay response: %s", err.Error()) |
|||
c.stream.Reset() |
|||
continue |
|||
} |
|||
|
|||
// TODO: Pretty print.
|
|||
log.Infof("accepted relay connection: %q", c) |
|||
|
|||
c.tagHop() |
|||
return c, nil |
|||
case <-l.ctx.Done(): |
|||
return nil, l.ctx.Err() |
|||
} |
|||
} |
|||
} |
|||
|
|||
func (l *RelayListener) Addr() net.Addr { |
|||
return &NetAddr{ |
|||
Relay: "any", |
|||
Remote: "any", |
|||
} |
|||
} |
|||
|
|||
func (l *RelayListener) Multiaddr() ma.Multiaddr { |
|||
return circuitAddr |
|||
} |
|||
|
|||
func (l *RelayListener) Close() error { |
|||
// TODO: noop?
|
|||
return nil |
|||
} |
@ -1,447 +0,0 @@ |
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|||
// versions:
|
|||
// protoc-gen-go v1.28.1
|
|||
// protoc v3.21.12
|
|||
// source: pb/relay.proto
|
|||
|
|||
package pb |
|||
|
|||
import ( |
|||
protoreflect "google.golang.org/protobuf/reflect/protoreflect" |
|||
protoimpl "google.golang.org/protobuf/runtime/protoimpl" |
|||
reflect "reflect" |
|||
sync "sync" |
|||
) |
|||
|
|||
const ( |
|||
// Verify that this generated code is sufficiently up-to-date.
|
|||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) |
|||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
|||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) |
|||
) |
|||
|
|||
type CircuitRelay_Status int32 |
|||
|
|||
const ( |
|||
CircuitRelay_SUCCESS CircuitRelay_Status = 100 |
|||
CircuitRelay_HOP_SRC_ADDR_TOO_LONG CircuitRelay_Status = 220 |
|||
CircuitRelay_HOP_DST_ADDR_TOO_LONG CircuitRelay_Status = 221 |
|||
CircuitRelay_HOP_SRC_MULTIADDR_INVALID CircuitRelay_Status = 250 |
|||
CircuitRelay_HOP_DST_MULTIADDR_INVALID CircuitRelay_Status = 251 |
|||
CircuitRelay_HOP_NO_CONN_TO_DST CircuitRelay_Status = 260 |
|||
CircuitRelay_HOP_CANT_DIAL_DST CircuitRelay_Status = 261 |
|||
CircuitRelay_HOP_CANT_OPEN_DST_STREAM CircuitRelay_Status = 262 |
|||
CircuitRelay_HOP_CANT_SPEAK_RELAY CircuitRelay_Status = 270 |
|||
CircuitRelay_HOP_CANT_RELAY_TO_SELF CircuitRelay_Status = 280 |
|||
CircuitRelay_STOP_SRC_ADDR_TOO_LONG CircuitRelay_Status = 320 |
|||
CircuitRelay_STOP_DST_ADDR_TOO_LONG CircuitRelay_Status = 321 |
|||
CircuitRelay_STOP_SRC_MULTIADDR_INVALID CircuitRelay_Status = 350 |
|||
CircuitRelay_STOP_DST_MULTIADDR_INVALID CircuitRelay_Status = 351 |
|||
CircuitRelay_STOP_RELAY_REFUSED CircuitRelay_Status = 390 |
|||
CircuitRelay_MALFORMED_MESSAGE CircuitRelay_Status = 400 |
|||
) |
|||
|
|||
// Enum value maps for CircuitRelay_Status.
|
|||
var ( |
|||
CircuitRelay_Status_name = map[int32]string{ |
|||
100: "SUCCESS", |
|||
220: "HOP_SRC_ADDR_TOO_LONG", |
|||
221: "HOP_DST_ADDR_TOO_LONG", |
|||
250: "HOP_SRC_MULTIADDR_INVALID", |
|||
251: "HOP_DST_MULTIADDR_INVALID", |
|||
260: "HOP_NO_CONN_TO_DST", |
|||
261: "HOP_CANT_DIAL_DST", |
|||
262: "HOP_CANT_OPEN_DST_STREAM", |
|||
270: "HOP_CANT_SPEAK_RELAY", |
|||
280: "HOP_CANT_RELAY_TO_SELF", |
|||
320: "STOP_SRC_ADDR_TOO_LONG", |
|||
321: "STOP_DST_ADDR_TOO_LONG", |
|||
350: "STOP_SRC_MULTIADDR_INVALID", |
|||
351: "STOP_DST_MULTIADDR_INVALID", |
|||
390: "STOP_RELAY_REFUSED", |
|||
400: "MALFORMED_MESSAGE", |
|||
} |
|||
CircuitRelay_Status_value = map[string]int32{ |
|||
"SUCCESS": 100, |
|||
"HOP_SRC_ADDR_TOO_LONG": 220, |
|||
"HOP_DST_ADDR_TOO_LONG": 221, |
|||
"HOP_SRC_MULTIADDR_INVALID": 250, |
|||
"HOP_DST_MULTIADDR_INVALID": 251, |
|||
"HOP_NO_CONN_TO_DST": 260, |
|||
"HOP_CANT_DIAL_DST": 261, |
|||
"HOP_CANT_OPEN_DST_STREAM": 262, |
|||
"HOP_CANT_SPEAK_RELAY": 270, |
|||
"HOP_CANT_RELAY_TO_SELF": 280, |
|||
"STOP_SRC_ADDR_TOO_LONG": 320, |
|||
"STOP_DST_ADDR_TOO_LONG": 321, |
|||
"STOP_SRC_MULTIADDR_INVALID": 350, |
|||
"STOP_DST_MULTIADDR_INVALID": 351, |
|||
"STOP_RELAY_REFUSED": 390, |
|||
"MALFORMED_MESSAGE": 400, |
|||
} |
|||
) |
|||
|
|||
func (x CircuitRelay_Status) Enum() *CircuitRelay_Status { |
|||
p := new(CircuitRelay_Status) |
|||
*p = x |
|||
return p |
|||
} |
|||
|
|||
func (x CircuitRelay_Status) String() string { |
|||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) |
|||
} |
|||
|
|||
func (CircuitRelay_Status) Descriptor() protoreflect.EnumDescriptor { |
|||
return file_pb_relay_proto_enumTypes[0].Descriptor() |
|||
} |
|||
|
|||
func (CircuitRelay_Status) Type() protoreflect.EnumType { |
|||
return &file_pb_relay_proto_enumTypes[0] |
|||
} |
|||
|
|||
func (x CircuitRelay_Status) Number() protoreflect.EnumNumber { |
|||
return protoreflect.EnumNumber(x) |
|||
} |
|||
|
|||
// Deprecated: Do not use.
|
|||
func (x *CircuitRelay_Status) UnmarshalJSON(b []byte) error { |
|||
num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
*x = CircuitRelay_Status(num) |
|||
return nil |
|||
} |
|||
|
|||
// Deprecated: Use CircuitRelay_Status.Descriptor instead.
|
|||
func (CircuitRelay_Status) EnumDescriptor() ([]byte, []int) { |
|||
return file_pb_relay_proto_rawDescGZIP(), []int{0, 0} |
|||
} |
|||
|
|||
type CircuitRelay_Type int32 |
|||
|
|||
const ( |
|||
CircuitRelay_HOP CircuitRelay_Type = 1 |
|||
CircuitRelay_STOP CircuitRelay_Type = 2 |
|||
CircuitRelay_STATUS CircuitRelay_Type = 3 |
|||
CircuitRelay_CAN_HOP CircuitRelay_Type = 4 |
|||
) |
|||
|
|||
// Enum value maps for CircuitRelay_Type.
|
|||
var ( |
|||
CircuitRelay_Type_name = map[int32]string{ |
|||
1: "HOP", |
|||
2: "STOP", |
|||
3: "STATUS", |
|||
4: "CAN_HOP", |
|||
} |
|||
CircuitRelay_Type_value = map[string]int32{ |
|||
"HOP": 1, |
|||
"STOP": 2, |
|||
"STATUS": 3, |
|||
"CAN_HOP": 4, |
|||
} |
|||
) |
|||
|
|||
func (x CircuitRelay_Type) Enum() *CircuitRelay_Type { |
|||
p := new(CircuitRelay_Type) |
|||
*p = x |
|||
return p |
|||
} |
|||
|
|||
func (x CircuitRelay_Type) String() string { |
|||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) |
|||
} |
|||
|
|||
func (CircuitRelay_Type) Descriptor() protoreflect.EnumDescriptor { |
|||
return file_pb_relay_proto_enumTypes[1].Descriptor() |
|||
} |
|||
|
|||
func (CircuitRelay_Type) Type() protoreflect.EnumType { |
|||
return &file_pb_relay_proto_enumTypes[1] |
|||
} |
|||
|
|||
func (x CircuitRelay_Type) Number() protoreflect.EnumNumber { |
|||
return protoreflect.EnumNumber(x) |
|||
} |
|||
|
|||
// Deprecated: Do not use.
|
|||
func (x *CircuitRelay_Type) UnmarshalJSON(b []byte) error { |
|||
num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
*x = CircuitRelay_Type(num) |
|||
return nil |
|||
} |
|||
|
|||
// Deprecated: Use CircuitRelay_Type.Descriptor instead.
|
|||
func (CircuitRelay_Type) EnumDescriptor() ([]byte, []int) { |
|||
return file_pb_relay_proto_rawDescGZIP(), []int{0, 1} |
|||
} |
|||
|
|||
type CircuitRelay struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Type *CircuitRelay_Type `protobuf:"varint,1,opt,name=type,enum=relay.pb.CircuitRelay_Type" json:"type,omitempty"` // Type of the message
|
|||
SrcPeer *CircuitRelay_Peer `protobuf:"bytes,2,opt,name=srcPeer" json:"srcPeer,omitempty"` // srcPeer and dstPeer are used when Type is HOP or STOP
|
|||
DstPeer *CircuitRelay_Peer `protobuf:"bytes,3,opt,name=dstPeer" json:"dstPeer,omitempty"` |
|||
Code *CircuitRelay_Status `protobuf:"varint,4,opt,name=code,enum=relay.pb.CircuitRelay_Status" json:"code,omitempty"` // Status code, used when Type is STATUS
|
|||
} |
|||
|
|||
func (x *CircuitRelay) Reset() { |
|||
*x = CircuitRelay{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_pb_relay_proto_msgTypes[0] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *CircuitRelay) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*CircuitRelay) ProtoMessage() {} |
|||
|
|||
func (x *CircuitRelay) ProtoReflect() protoreflect.Message { |
|||
mi := &file_pb_relay_proto_msgTypes[0] |
|||
if protoimpl.UnsafeEnabled && x != nil { |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
if ms.LoadMessageInfo() == nil { |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
return ms |
|||
} |
|||
return mi.MessageOf(x) |
|||
} |
|||
|
|||
// Deprecated: Use CircuitRelay.ProtoReflect.Descriptor instead.
|
|||
func (*CircuitRelay) Descriptor() ([]byte, []int) { |
|||
return file_pb_relay_proto_rawDescGZIP(), []int{0} |
|||
} |
|||
|
|||
func (x *CircuitRelay) GetType() CircuitRelay_Type { |
|||
if x != nil && x.Type != nil { |
|||
return *x.Type |
|||
} |
|||
return CircuitRelay_HOP |
|||
} |
|||
|
|||
func (x *CircuitRelay) GetSrcPeer() *CircuitRelay_Peer { |
|||
if x != nil { |
|||
return x.SrcPeer |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *CircuitRelay) GetDstPeer() *CircuitRelay_Peer { |
|||
if x != nil { |
|||
return x.DstPeer |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *CircuitRelay) GetCode() CircuitRelay_Status { |
|||
if x != nil && x.Code != nil { |
|||
return *x.Code |
|||
} |
|||
return CircuitRelay_SUCCESS |
|||
} |
|||
|
|||
type CircuitRelay_Peer struct { |
|||
state protoimpl.MessageState |
|||
sizeCache protoimpl.SizeCache |
|||
unknownFields protoimpl.UnknownFields |
|||
|
|||
Id []byte `protobuf:"bytes,1,req,name=id" json:"id,omitempty"` // peer id
|
|||
Addrs [][]byte `protobuf:"bytes,2,rep,name=addrs" json:"addrs,omitempty"` // peer's known addresses
|
|||
} |
|||
|
|||
func (x *CircuitRelay_Peer) Reset() { |
|||
*x = CircuitRelay_Peer{} |
|||
if protoimpl.UnsafeEnabled { |
|||
mi := &file_pb_relay_proto_msgTypes[1] |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
} |
|||
|
|||
func (x *CircuitRelay_Peer) String() string { |
|||
return protoimpl.X.MessageStringOf(x) |
|||
} |
|||
|
|||
func (*CircuitRelay_Peer) ProtoMessage() {} |
|||
|
|||
func (x *CircuitRelay_Peer) ProtoReflect() protoreflect.Message { |
|||
mi := &file_pb_relay_proto_msgTypes[1] |
|||
if protoimpl.UnsafeEnabled && x != nil { |
|||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) |
|||
if ms.LoadMessageInfo() == nil { |
|||
ms.StoreMessageInfo(mi) |
|||
} |
|||
return ms |
|||
} |
|||
return mi.MessageOf(x) |
|||
} |
|||
|
|||
// Deprecated: Use CircuitRelay_Peer.ProtoReflect.Descriptor instead.
|
|||
func (*CircuitRelay_Peer) Descriptor() ([]byte, []int) { |
|||
return file_pb_relay_proto_rawDescGZIP(), []int{0, 0} |
|||
} |
|||
|
|||
func (x *CircuitRelay_Peer) GetId() []byte { |
|||
if x != nil { |
|||
return x.Id |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
func (x *CircuitRelay_Peer) GetAddrs() [][]byte { |
|||
if x != nil { |
|||
return x.Addrs |
|||
} |
|||
return nil |
|||
} |
|||
|
|||
var File_pb_relay_proto protoreflect.FileDescriptor |
|||
|
|||
var file_pb_relay_proto_rawDesc = []byte{ |
|||
0x0a, 0x0e, 0x70, 0x62, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, |
|||
0x12, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x22, 0x87, 0x06, 0x0a, 0x0c, 0x43, |
|||
0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x2f, 0x0a, 0x04, 0x74, |
|||
0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, |
|||
0x79, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x52, 0x65, 0x6c, 0x61, |
|||
0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x35, 0x0a, 0x07, |
|||
0x73, 0x72, 0x63, 0x50, 0x65, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, |
|||
0x72, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, |
|||
0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x07, 0x73, 0x72, 0x63, 0x50, |
|||
0x65, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x07, 0x64, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x18, 0x03, |
|||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, |
|||
0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x50, 0x65, 0x65, |
|||
0x72, 0x52, 0x07, 0x64, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x31, 0x0a, 0x04, 0x63, 0x6f, |
|||
0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, |
|||
0x2e, 0x70, 0x62, 0x2e, 0x43, 0x69, 0x72, 0x63, 0x75, 0x69, 0x74, 0x52, 0x65, 0x6c, 0x61, 0x79, |
|||
0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x1a, 0x2c, 0x0a, |
|||
0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, |
|||
0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x02, |
|||
0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, 0x73, 0x22, 0xc2, 0x03, 0x0a, 0x06, |
|||
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, |
|||
0x53, 0x10, 0x64, 0x12, 0x1a, 0x0a, 0x15, 0x48, 0x4f, 0x50, 0x5f, 0x53, 0x52, 0x43, 0x5f, 0x41, |
|||
0x44, 0x44, 0x52, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x4f, 0x4e, 0x47, 0x10, 0xdc, 0x01, 0x12, |
|||
0x1a, 0x0a, 0x15, 0x48, 0x4f, 0x50, 0x5f, 0x44, 0x53, 0x54, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, |
|||
0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x4f, 0x4e, 0x47, 0x10, 0xdd, 0x01, 0x12, 0x1e, 0x0a, 0x19, 0x48, |
|||
0x4f, 0x50, 0x5f, 0x53, 0x52, 0x43, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x41, 0x44, 0x44, 0x52, |
|||
0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0xfa, 0x01, 0x12, 0x1e, 0x0a, 0x19, 0x48, |
|||
0x4f, 0x50, 0x5f, 0x44, 0x53, 0x54, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x41, 0x44, 0x44, 0x52, |
|||
0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0xfb, 0x01, 0x12, 0x17, 0x0a, 0x12, 0x48, |
|||
0x4f, 0x50, 0x5f, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x5f, 0x54, 0x4f, 0x5f, 0x44, 0x53, |
|||
0x54, 0x10, 0x84, 0x02, 0x12, 0x16, 0x0a, 0x11, 0x48, 0x4f, 0x50, 0x5f, 0x43, 0x41, 0x4e, 0x54, |
|||
0x5f, 0x44, 0x49, 0x41, 0x4c, 0x5f, 0x44, 0x53, 0x54, 0x10, 0x85, 0x02, 0x12, 0x1d, 0x0a, 0x18, |
|||
0x48, 0x4f, 0x50, 0x5f, 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x44, 0x53, |
|||
0x54, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x10, 0x86, 0x02, 0x12, 0x19, 0x0a, 0x14, 0x48, |
|||
0x4f, 0x50, 0x5f, 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x53, 0x50, 0x45, 0x41, 0x4b, 0x5f, 0x52, 0x45, |
|||
0x4c, 0x41, 0x59, 0x10, 0x8e, 0x02, 0x12, 0x1b, 0x0a, 0x16, 0x48, 0x4f, 0x50, 0x5f, 0x43, 0x41, |
|||
0x4e, 0x54, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x5f, 0x54, 0x4f, 0x5f, 0x53, 0x45, 0x4c, 0x46, |
|||
0x10, 0x98, 0x02, 0x12, 0x1b, 0x0a, 0x16, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x53, 0x52, 0x43, 0x5f, |
|||
0x41, 0x44, 0x44, 0x52, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x4f, 0x4e, 0x47, 0x10, 0xc0, 0x02, |
|||
0x12, 0x1b, 0x0a, 0x16, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x44, 0x53, 0x54, 0x5f, 0x41, 0x44, 0x44, |
|||
0x52, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x4c, 0x4f, 0x4e, 0x47, 0x10, 0xc1, 0x02, 0x12, 0x1f, 0x0a, |
|||
0x1a, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x53, 0x52, 0x43, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x41, |
|||
0x44, 0x44, 0x52, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0xde, 0x02, 0x12, 0x1f, |
|||
0x0a, 0x1a, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x44, 0x53, 0x54, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, |
|||
0x41, 0x44, 0x44, 0x52, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0xdf, 0x02, 0x12, |
|||
0x17, 0x0a, 0x12, 0x53, 0x54, 0x4f, 0x50, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x59, 0x5f, 0x52, 0x45, |
|||
0x46, 0x55, 0x53, 0x45, 0x44, 0x10, 0x86, 0x03, 0x12, 0x16, 0x0a, 0x11, 0x4d, 0x41, 0x4c, 0x46, |
|||
0x4f, 0x52, 0x4d, 0x45, 0x44, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x90, 0x03, |
|||
0x22, 0x32, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x48, 0x4f, 0x50, 0x10, |
|||
0x01, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x53, |
|||
0x54, 0x41, 0x54, 0x55, 0x53, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x41, 0x4e, 0x5f, 0x48, |
|||
0x4f, 0x50, 0x10, 0x04, |
|||
} |
|||
|
|||
var ( |
|||
file_pb_relay_proto_rawDescOnce sync.Once |
|||
file_pb_relay_proto_rawDescData = file_pb_relay_proto_rawDesc |
|||
) |
|||
|
|||
func file_pb_relay_proto_rawDescGZIP() []byte { |
|||
file_pb_relay_proto_rawDescOnce.Do(func() { |
|||
file_pb_relay_proto_rawDescData = protoimpl.X.CompressGZIP(file_pb_relay_proto_rawDescData) |
|||
}) |
|||
return file_pb_relay_proto_rawDescData |
|||
} |
|||
|
|||
var file_pb_relay_proto_enumTypes = make([]protoimpl.EnumInfo, 2) |
|||
var file_pb_relay_proto_msgTypes = make([]protoimpl.MessageInfo, 2) |
|||
var file_pb_relay_proto_goTypes = []interface{}{ |
|||
(CircuitRelay_Status)(0), // 0: relay.pb.CircuitRelay.Status
|
|||
(CircuitRelay_Type)(0), // 1: relay.pb.CircuitRelay.Type
|
|||
(*CircuitRelay)(nil), // 2: relay.pb.CircuitRelay
|
|||
(*CircuitRelay_Peer)(nil), // 3: relay.pb.CircuitRelay.Peer
|
|||
} |
|||
var file_pb_relay_proto_depIdxs = []int32{ |
|||
1, // 0: relay.pb.CircuitRelay.type:type_name -> relay.pb.CircuitRelay.Type
|
|||
3, // 1: relay.pb.CircuitRelay.srcPeer:type_name -> relay.pb.CircuitRelay.Peer
|
|||
3, // 2: relay.pb.CircuitRelay.dstPeer:type_name -> relay.pb.CircuitRelay.Peer
|
|||
0, // 3: relay.pb.CircuitRelay.code:type_name -> relay.pb.CircuitRelay.Status
|
|||
4, // [4:4] is the sub-list for method output_type
|
|||
4, // [4:4] is the sub-list for method input_type
|
|||
4, // [4:4] is the sub-list for extension type_name
|
|||
4, // [4:4] is the sub-list for extension extendee
|
|||
0, // [0:4] is the sub-list for field type_name
|
|||
} |
|||
|
|||
func init() { file_pb_relay_proto_init() } |
|||
func file_pb_relay_proto_init() { |
|||
if File_pb_relay_proto != nil { |
|||
return |
|||
} |
|||
if !protoimpl.UnsafeEnabled { |
|||
file_pb_relay_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*CircuitRelay); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
file_pb_relay_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { |
|||
switch v := v.(*CircuitRelay_Peer); i { |
|||
case 0: |
|||
return &v.state |
|||
case 1: |
|||
return &v.sizeCache |
|||
case 2: |
|||
return &v.unknownFields |
|||
default: |
|||
return nil |
|||
} |
|||
} |
|||
} |
|||
type x struct{} |
|||
out := protoimpl.TypeBuilder{ |
|||
File: protoimpl.DescBuilder{ |
|||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), |
|||
RawDescriptor: file_pb_relay_proto_rawDesc, |
|||
NumEnums: 2, |
|||
NumMessages: 2, |
|||
NumExtensions: 0, |
|||
NumServices: 0, |
|||
}, |
|||
GoTypes: file_pb_relay_proto_goTypes, |
|||
DependencyIndexes: file_pb_relay_proto_depIdxs, |
|||
EnumInfos: file_pb_relay_proto_enumTypes, |
|||
MessageInfos: file_pb_relay_proto_msgTypes, |
|||
}.Build() |
|||
File_pb_relay_proto = out.File |
|||
file_pb_relay_proto_rawDesc = nil |
|||
file_pb_relay_proto_goTypes = nil |
|||
file_pb_relay_proto_depIdxs = nil |
|||
} |
@ -1,44 +0,0 @@ |
|||
syntax = "proto2"; |
|||
|
|||
package relay.pb; |
|||
|
|||
message CircuitRelay { |
|||
|
|||
enum Status { |
|||
SUCCESS = 100; |
|||
HOP_SRC_ADDR_TOO_LONG = 220; |
|||
HOP_DST_ADDR_TOO_LONG = 221; |
|||
HOP_SRC_MULTIADDR_INVALID = 250; |
|||
HOP_DST_MULTIADDR_INVALID = 251; |
|||
HOP_NO_CONN_TO_DST = 260; |
|||
HOP_CANT_DIAL_DST = 261; |
|||
HOP_CANT_OPEN_DST_STREAM = 262; |
|||
HOP_CANT_SPEAK_RELAY = 270; |
|||
HOP_CANT_RELAY_TO_SELF = 280; |
|||
STOP_SRC_ADDR_TOO_LONG = 320; |
|||
STOP_DST_ADDR_TOO_LONG = 321; |
|||
STOP_SRC_MULTIADDR_INVALID = 350; |
|||
STOP_DST_MULTIADDR_INVALID = 351; |
|||
STOP_RELAY_REFUSED = 390; |
|||
MALFORMED_MESSAGE = 400; |
|||
} |
|||
|
|||
enum Type { // RPC identifier, either HOP, STOP or STATUS |
|||
HOP = 1; |
|||
STOP = 2; |
|||
STATUS = 3; |
|||
CAN_HOP = 4; |
|||
} |
|||
|
|||
message Peer { |
|||
required bytes id = 1; // peer id |
|||
repeated bytes addrs = 2; // peer's known addresses |
|||
} |
|||
|
|||
optional Type type = 1; // Type of the message |
|||
|
|||
optional Peer srcPeer = 2; // srcPeer and dstPeer are used when Type is HOP or STOP |
|||
optional Peer dstPeer = 3; |
|||
|
|||
optional Status code = 4; // Status code, used when Type is STATUS |
|||
} |
@ -1,507 +0,0 @@ |
|||
package relay |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"io" |
|||
"sync" |
|||
"sync/atomic" |
|||
"time" |
|||
|
|||
pb "github.com/libp2p/go-libp2p/p2p/protocol/internal/circuitv1-deprecated/pb" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/host" |
|||
"github.com/libp2p/go-libp2p/core/network" |
|||
"github.com/libp2p/go-libp2p/core/peer" |
|||
"github.com/libp2p/go-libp2p/core/peerstore" |
|||
"github.com/libp2p/go-libp2p/core/transport" |
|||
|
|||
pool "github.com/libp2p/go-buffer-pool" |
|||
|
|||
logging "github.com/ipfs/go-log/v2" |
|||
|
|||
ma "github.com/multiformats/go-multiaddr" |
|||
) |
|||
|
|||
var log = logging.Logger("relay") |
|||
|
|||
const ProtoID = "/libp2p/circuit/relay/0.1.0" |
|||
|
|||
const maxMessageSize = 4096 |
|||
|
|||
var ( |
|||
RelayAcceptTimeout = 10 * time.Second |
|||
HopConnectTimeout = 30 * time.Second |
|||
StopHandshakeTimeout = 1 * time.Minute |
|||
|
|||
HopStreamBufferSize = 4096 |
|||
HopStreamLimit = 1 << 19 // 512K hops for 1M goroutines
|
|||
|
|||
streamTimeout = 1 * time.Minute |
|||
) |
|||
|
|||
// Relay is the relay transport and service.
|
|||
type Relay struct { |
|||
host host.Host |
|||
upgrader transport.Upgrader |
|||
ctx context.Context |
|||
ctxCancel context.CancelFunc |
|||
self peer.ID |
|||
|
|||
active bool |
|||
hop bool |
|||
|
|||
incoming chan *Conn |
|||
|
|||
// atomic counters
|
|||
streamCount atomic.Int32 |
|||
liveHopCount atomic.Int32 |
|||
|
|||
// per peer hop counters
|
|||
mx sync.Mutex |
|||
hopCount map[peer.ID]int |
|||
} |
|||
|
|||
// RelayOpts are options for configuring the relay transport.
|
|||
type RelayOpt int |
|||
|
|||
var ( |
|||
// OptActive configures the relay transport to actively establish
|
|||
// outbound connections on behalf of clients. You probably don't want to
|
|||
// enable this unless you know what you're doing.
|
|||
OptActive = RelayOpt(0) |
|||
// OptHop configures the relay transport to accept requests to relay
|
|||
// traffic on behalf of third-parties. Unless OptActive is specified,
|
|||
// this will only relay traffic between peers already connected to this
|
|||
// node.
|
|||
OptHop = RelayOpt(1) |
|||
// OptDiscovery is a no-op. It was introduced as a way to probe new
|
|||
// peers to see if they were willing to act as a relays. However, in
|
|||
// practice, it's useless. While it does test to see if these peers are
|
|||
// relays, it doesn't (and can't), check to see if these peers are
|
|||
// _active_ relays (i.e., will actively dial the target peer).
|
|||
//
|
|||
// This option may be re-enabled in the future but for now you shouldn't
|
|||
// use it.
|
|||
OptDiscovery = RelayOpt(2) |
|||
) |
|||
|
|||
type RelayError struct { |
|||
Code pb.CircuitRelay_Status |
|||
} |
|||
|
|||
func (e RelayError) Error() string { |
|||
return fmt.Sprintf("error opening relay circuit: %s (%d)", pb.CircuitRelay_Status_name[int32(e.Code)], e.Code) |
|||
} |
|||
|
|||
// NewRelay constructs a new relay.
|
|||
func NewRelay(h host.Host, upgrader transport.Upgrader, opts ...RelayOpt) (*Relay, error) { |
|||
r := &Relay{ |
|||
upgrader: upgrader, |
|||
host: h, |
|||
self: h.ID(), |
|||
incoming: make(chan *Conn), |
|||
hopCount: make(map[peer.ID]int), |
|||
} |
|||
r.ctx, r.ctxCancel = context.WithCancel(context.Background()) |
|||
|
|||
for _, opt := range opts { |
|||
switch opt { |
|||
case OptActive: |
|||
r.active = true |
|||
case OptHop: |
|||
r.hop = true |
|||
case OptDiscovery: |
|||
log.Errorf( |
|||
"circuit.OptDiscovery is now a no-op: %s", |
|||
"dialing peers with a random relay is no longer supported", |
|||
) |
|||
default: |
|||
return nil, fmt.Errorf("unrecognized option: %d", opt) |
|||
} |
|||
} |
|||
|
|||
h.SetStreamHandler(ProtoID, r.handleNewStream) |
|||
|
|||
return r, nil |
|||
} |
|||
|
|||
// Increment the live hop count and increment the connection manager tags by 1 for the two
|
|||
// sides of the hop stream. This ensures that connections with many hop streams will be protected
|
|||
// from pruning, thus minimizing disruption from connection trimming in a relay node.
|
|||
func (r *Relay) addLiveHop(from, to peer.ID) { |
|||
r.liveHopCount.Add(1) |
|||
r.host.ConnManager().UpsertTag(from, "relay-hop-stream", incrementTag) |
|||
r.host.ConnManager().UpsertTag(to, "relay-hop-stream", incrementTag) |
|||
} |
|||
|
|||
// Decrement the live hpo count and decrement the connection manager tags for the two sides
|
|||
// of the hop stream.
|
|||
func (r *Relay) rmLiveHop(from, to peer.ID) { |
|||
r.liveHopCount.Add(-1) |
|||
r.host.ConnManager().UpsertTag(from, "relay-hop-stream", decrementTag) |
|||
r.host.ConnManager().UpsertTag(to, "relay-hop-stream", decrementTag) |
|||
|
|||
} |
|||
|
|||
func (r *Relay) GetActiveHops() int32 { |
|||
return r.liveHopCount.Load() |
|||
} |
|||
|
|||
func (r *Relay) DialPeer(ctx context.Context, relay peer.AddrInfo, dest peer.AddrInfo) (*Conn, error) { |
|||
|
|||
log.Debugf("dialing peer %s through relay %s", dest.ID, relay.ID) |
|||
|
|||
if len(relay.Addrs) > 0 { |
|||
r.host.Peerstore().AddAddrs(relay.ID, relay.Addrs, peerstore.TempAddrTTL) |
|||
} |
|||
|
|||
s, err := r.host.NewStream(ctx, relay.ID, ProtoID) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
rd := newDelimitedReader(s, maxMessageSize) |
|||
wr := newDelimitedWriter(s) |
|||
defer rd.Close() |
|||
|
|||
var msg pb.CircuitRelay |
|||
|
|||
msg.Type = pb.CircuitRelay_HOP.Enum() |
|||
msg.SrcPeer = peerInfoToPeer(r.host.Peerstore().PeerInfo(r.self)) |
|||
msg.DstPeer = peerInfoToPeer(dest) |
|||
|
|||
err = wr.WriteMsg(&msg) |
|||
if err != nil { |
|||
s.Reset() |
|||
return nil, err |
|||
} |
|||
|
|||
msg.Reset() |
|||
|
|||
err = rd.ReadMsg(&msg) |
|||
if err != nil { |
|||
s.Reset() |
|||
return nil, err |
|||
} |
|||
|
|||
if msg.GetType() != pb.CircuitRelay_STATUS { |
|||
s.Reset() |
|||
return nil, fmt.Errorf("unexpected relay response; not a status message (%d)", msg.GetType()) |
|||
} |
|||
|
|||
if msg.GetCode() != pb.CircuitRelay_SUCCESS { |
|||
s.Reset() |
|||
return nil, RelayError{msg.GetCode()} |
|||
} |
|||
|
|||
return &Conn{stream: s, remote: dest, host: r.host, relay: r}, nil |
|||
} |
|||
|
|||
func (r *Relay) Matches(addr ma.Multiaddr) bool { |
|||
// TODO: Look at the prefix transport as well.
|
|||
_, err := addr.ValueForProtocol(ma.P_CIRCUIT) |
|||
return err == nil |
|||
} |
|||
|
|||
// Queries a peer for support of hop relay
|
|||
func CanHop(ctx context.Context, host host.Host, id peer.ID) (bool, error) { |
|||
s, err := host.NewStream(ctx, id, ProtoID) |
|||
if err != nil { |
|||
return false, err |
|||
} |
|||
defer s.Close() |
|||
|
|||
rd := newDelimitedReader(s, maxMessageSize) |
|||
wr := newDelimitedWriter(s) |
|||
defer rd.Close() |
|||
|
|||
var msg pb.CircuitRelay |
|||
|
|||
msg.Type = pb.CircuitRelay_CAN_HOP.Enum() |
|||
|
|||
if err := wr.WriteMsg(&msg); err != nil { |
|||
s.Reset() |
|||
return false, err |
|||
} |
|||
|
|||
msg.Reset() |
|||
|
|||
if err := rd.ReadMsg(&msg); err != nil { |
|||
s.Reset() |
|||
return false, err |
|||
} |
|||
|
|||
if msg.GetType() != pb.CircuitRelay_STATUS { |
|||
return false, fmt.Errorf("unexpected relay response; not a status message (%d)", msg.GetType()) |
|||
} |
|||
|
|||
return msg.GetCode() == pb.CircuitRelay_SUCCESS, nil |
|||
} |
|||
|
|||
func (r *Relay) CanHop(ctx context.Context, id peer.ID) (bool, error) { |
|||
return CanHop(ctx, r.host, id) |
|||
} |
|||
|
|||
func (r *Relay) handleNewStream(s network.Stream) { |
|||
s.SetReadDeadline(time.Now().Add(streamTimeout)) |
|||
|
|||
log.Infof("new relay stream from: %s", s.Conn().RemotePeer()) |
|||
|
|||
rd := newDelimitedReader(s, maxMessageSize) |
|||
defer rd.Close() |
|||
|
|||
var msg pb.CircuitRelay |
|||
|
|||
err := rd.ReadMsg(&msg) |
|||
if err != nil { |
|||
r.handleError(s, pb.CircuitRelay_MALFORMED_MESSAGE) |
|||
return |
|||
} |
|||
// reset stream deadline as message has been read
|
|||
s.SetReadDeadline(time.Time{}) |
|||
|
|||
switch msg.GetType() { |
|||
case pb.CircuitRelay_HOP: |
|||
r.handleHopStream(s, &msg) |
|||
case pb.CircuitRelay_STOP: |
|||
r.handleStopStream(s, &msg) |
|||
case pb.CircuitRelay_CAN_HOP: |
|||
r.handleCanHop(s, &msg) |
|||
default: |
|||
log.Warnf("unexpected relay handshake: %d", msg.GetType()) |
|||
r.handleError(s, pb.CircuitRelay_MALFORMED_MESSAGE) |
|||
} |
|||
} |
|||
|
|||
func (r *Relay) handleHopStream(s network.Stream, msg *pb.CircuitRelay) { |
|||
if !r.hop { |
|||
r.handleError(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
return |
|||
} |
|||
|
|||
streamCount := r.streamCount.Add(1) |
|||
liveHopCount := r.liveHopCount.Load() |
|||
defer r.streamCount.Add(-1) |
|||
|
|||
if (streamCount + liveHopCount) > int32(HopStreamLimit) { |
|||
log.Warn("hop stream limit exceeded; resetting stream") |
|||
s.Reset() |
|||
return |
|||
} |
|||
|
|||
src, err := peerToPeerInfo(msg.GetSrcPeer()) |
|||
if err != nil { |
|||
r.handleError(s, pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) |
|||
return |
|||
} |
|||
|
|||
if src.ID != s.Conn().RemotePeer() { |
|||
r.handleError(s, pb.CircuitRelay_HOP_SRC_MULTIADDR_INVALID) |
|||
return |
|||
} |
|||
|
|||
dst, err := peerToPeerInfo(msg.GetDstPeer()) |
|||
if err != nil { |
|||
r.handleError(s, pb.CircuitRelay_HOP_DST_MULTIADDR_INVALID) |
|||
return |
|||
} |
|||
|
|||
if dst.ID == r.self { |
|||
r.handleError(s, pb.CircuitRelay_HOP_CANT_RELAY_TO_SELF) |
|||
return |
|||
} |
|||
|
|||
// open stream
|
|||
ctx, cancel := context.WithTimeout(r.ctx, HopConnectTimeout) |
|||
defer cancel() |
|||
|
|||
if !r.active { |
|||
ctx = network.WithNoDial(ctx, "relay hop") |
|||
} else if len(dst.Addrs) > 0 { |
|||
r.host.Peerstore().AddAddrs(dst.ID, dst.Addrs, peerstore.TempAddrTTL) |
|||
} |
|||
|
|||
bs, err := r.host.NewStream(ctx, dst.ID, ProtoID) |
|||
if err != nil { |
|||
log.Debugf("error opening relay stream to %s: %s", dst.ID.Pretty(), err.Error()) |
|||
if err == network.ErrNoConn { |
|||
r.handleError(s, pb.CircuitRelay_HOP_NO_CONN_TO_DST) |
|||
} else { |
|||
r.handleError(s, pb.CircuitRelay_HOP_CANT_DIAL_DST) |
|||
} |
|||
return |
|||
} |
|||
|
|||
// stop handshake
|
|||
rd := newDelimitedReader(bs, maxMessageSize) |
|||
wr := newDelimitedWriter(bs) |
|||
defer rd.Close() |
|||
|
|||
// set handshake deadline
|
|||
bs.SetDeadline(time.Now().Add(StopHandshakeTimeout)) |
|||
|
|||
msg.Type = pb.CircuitRelay_STOP.Enum() |
|||
|
|||
err = wr.WriteMsg(msg) |
|||
if err != nil { |
|||
log.Debugf("error writing stop handshake: %s", err.Error()) |
|||
bs.Reset() |
|||
r.handleError(s, pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) |
|||
return |
|||
} |
|||
|
|||
msg.Reset() |
|||
|
|||
err = rd.ReadMsg(msg) |
|||
if err != nil { |
|||
log.Debugf("error reading stop response: %s", err.Error()) |
|||
bs.Reset() |
|||
r.handleError(s, pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) |
|||
return |
|||
} |
|||
|
|||
if msg.GetType() != pb.CircuitRelay_STATUS { |
|||
log.Debugf("unexpected relay stop response: not a status message (%d)", msg.GetType()) |
|||
bs.Reset() |
|||
r.handleError(s, pb.CircuitRelay_HOP_CANT_OPEN_DST_STREAM) |
|||
return |
|||
} |
|||
|
|||
if msg.GetCode() != pb.CircuitRelay_SUCCESS { |
|||
log.Debugf("relay stop failure: %d", msg.GetCode()) |
|||
bs.Reset() |
|||
r.handleError(s, msg.GetCode()) |
|||
return |
|||
} |
|||
|
|||
err = r.writeResponse(s, pb.CircuitRelay_SUCCESS) |
|||
if err != nil { |
|||
log.Debugf("error writing relay response: %s", err.Error()) |
|||
bs.Reset() |
|||
s.Reset() |
|||
return |
|||
} |
|||
|
|||
// relay connection
|
|||
log.Infof("relaying connection between %s and %s", src.ID.Pretty(), dst.ID.Pretty()) |
|||
|
|||
// reset deadline
|
|||
bs.SetDeadline(time.Time{}) |
|||
|
|||
r.addLiveHop(src.ID, dst.ID) |
|||
|
|||
var goroutines atomic.Int32 |
|||
goroutines.Store(2) |
|||
done := func() { |
|||
if goroutines.Add(-1) == 0 { |
|||
s.Close() |
|||
bs.Close() |
|||
r.rmLiveHop(src.ID, dst.ID) |
|||
} |
|||
} |
|||
|
|||
// Don't reset streams after finishing or the other side will get an
|
|||
// error, not an EOF.
|
|||
go func() { |
|||
defer done() |
|||
|
|||
buf := pool.Get(HopStreamBufferSize) |
|||
defer pool.Put(buf) |
|||
|
|||
count, err := io.CopyBuffer(s, bs, buf) |
|||
if err != nil { |
|||
log.Debugf("relay copy error: %s", err) |
|||
// Reset both.
|
|||
s.Reset() |
|||
bs.Reset() |
|||
} else { |
|||
// propagate the close
|
|||
s.CloseWrite() |
|||
} |
|||
log.Debugf("relayed %d bytes from %s to %s", count, dst.ID.Pretty(), src.ID.Pretty()) |
|||
}() |
|||
|
|||
go func() { |
|||
defer done() |
|||
|
|||
buf := pool.Get(HopStreamBufferSize) |
|||
defer pool.Put(buf) |
|||
|
|||
count, err := io.CopyBuffer(bs, s, buf) |
|||
if err != nil { |
|||
log.Debugf("relay copy error: %s", err) |
|||
// Reset both.
|
|||
bs.Reset() |
|||
s.Reset() |
|||
} else { |
|||
// propagate the close
|
|||
bs.CloseWrite() |
|||
} |
|||
log.Debugf("relayed %d bytes from %s to %s", count, src.ID.Pretty(), dst.ID.Pretty()) |
|||
}() |
|||
} |
|||
|
|||
func (r *Relay) handleStopStream(s network.Stream, msg *pb.CircuitRelay) { |
|||
src, err := peerToPeerInfo(msg.GetSrcPeer()) |
|||
if err != nil { |
|||
r.handleError(s, pb.CircuitRelay_STOP_SRC_MULTIADDR_INVALID) |
|||
return |
|||
} |
|||
|
|||
dst, err := peerToPeerInfo(msg.GetDstPeer()) |
|||
if err != nil || dst.ID != r.self { |
|||
r.handleError(s, pb.CircuitRelay_STOP_DST_MULTIADDR_INVALID) |
|||
return |
|||
} |
|||
|
|||
log.Infof("relay connection from: %s", src.ID) |
|||
|
|||
if len(src.Addrs) > 0 { |
|||
r.host.Peerstore().AddAddrs(src.ID, src.Addrs, peerstore.TempAddrTTL) |
|||
} |
|||
|
|||
select { |
|||
case r.incoming <- &Conn{stream: s, remote: src, host: r.host, relay: r}: |
|||
case <-time.After(RelayAcceptTimeout): |
|||
r.handleError(s, pb.CircuitRelay_STOP_RELAY_REFUSED) |
|||
} |
|||
} |
|||
|
|||
func (r *Relay) handleCanHop(s network.Stream, msg *pb.CircuitRelay) { |
|||
var err error |
|||
|
|||
if r.hop { |
|||
err = r.writeResponse(s, pb.CircuitRelay_SUCCESS) |
|||
} else { |
|||
err = r.writeResponse(s, pb.CircuitRelay_HOP_CANT_SPEAK_RELAY) |
|||
} |
|||
|
|||
if err != nil { |
|||
s.Reset() |
|||
log.Debugf("error writing relay response: %s", err.Error()) |
|||
} else { |
|||
s.Close() |
|||
} |
|||
} |
|||
|
|||
func (r *Relay) handleError(s network.Stream, code pb.CircuitRelay_Status) { |
|||
log.Warnf("relay error: %s (%d)", pb.CircuitRelay_Status_name[int32(code)], code) |
|||
err := r.writeResponse(s, code) |
|||
if err != nil { |
|||
s.Reset() |
|||
log.Debugf("error writing relay response: %s", err.Error()) |
|||
} else { |
|||
s.Close() |
|||
} |
|||
} |
|||
|
|||
func (r *Relay) writeResponse(s network.Stream, code pb.CircuitRelay_Status) error { |
|||
wr := newDelimitedWriter(s) |
|||
|
|||
var msg pb.CircuitRelay |
|||
msg.Type = pb.CircuitRelay_STATUS.Enum() |
|||
msg.Code = code.Enum() |
|||
|
|||
return wr.WriteMsg(&msg) |
|||
} |
@ -1,467 +0,0 @@ |
|||
//lint:file-ignore U1000 Ignore all unused code, we're not running any tests.
|
|||
package relay_test |
|||
|
|||
import ( |
|||
"bytes" |
|||
"context" |
|||
"fmt" |
|||
"io" |
|||
"net" |
|||
"testing" |
|||
"time" |
|||
|
|||
bhost "github.com/libp2p/go-libp2p/p2p/host/blank" |
|||
"github.com/libp2p/go-libp2p/p2p/net/swarm" |
|||
swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing" |
|||
. "github.com/libp2p/go-libp2p/p2p/protocol/internal/circuitv1-deprecated" |
|||
pb "github.com/libp2p/go-libp2p/p2p/protocol/internal/circuitv1-deprecated/pb" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/host" |
|||
|
|||
ma "github.com/multiformats/go-multiaddr" |
|||
manet "github.com/multiformats/go-multiaddr/net" |
|||
) |
|||
|
|||
/* TODO: add tests |
|||
- simple A -[R]-> B |
|||
- A tries to relay through R, R doesnt support relay |
|||
- A tries to relay through R to B, B doesnt support relay |
|||
- A sends too long multiaddr |
|||
- R drops stream mid-message |
|||
- A relays through R, R has no connection to B |
|||
*/ |
|||
|
|||
func getNetHosts(t *testing.T, n int) []host.Host { |
|||
var out []host.Host |
|||
|
|||
for i := 0; i < n; i++ { |
|||
netw := swarmt.GenSwarm(t) |
|||
h := bhost.NewBlankHost(netw) |
|||
out = append(out, h) |
|||
} |
|||
|
|||
return out |
|||
} |
|||
|
|||
func newTestRelay(t *testing.T, host host.Host, opts ...RelayOpt) *Relay { |
|||
r, err := NewRelay(host, swarmt.GenUpgrader(t, host.Network().(*swarm.Swarm), nil), opts...) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
return r |
|||
} |
|||
|
|||
func connect(t *testing.T, a, b host.Host) { |
|||
pinfo := a.Peerstore().PeerInfo(a.ID()) |
|||
err := b.Connect(context.Background(), pinfo) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
} |
|||
|
|||
func TestBasicRelay(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts := getNetHosts(t, 3) |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
connect(t, hosts[1], hosts[2]) |
|||
|
|||
time.Sleep(10 * time.Millisecond) |
|||
|
|||
r1 := newTestRelay(t, hosts[0]) |
|||
|
|||
newTestRelay(t, hosts[1], OptHop) |
|||
|
|||
r3 := newTestRelay(t, hosts[2]) |
|||
|
|||
var ( |
|||
conn1, conn2 net.Conn |
|||
done = make(chan struct{}) |
|||
) |
|||
|
|||
defer func() { |
|||
<-done |
|||
if conn1 != nil { |
|||
conn1.Close() |
|||
} |
|||
if conn2 != nil { |
|||
conn2.Close() |
|||
} |
|||
}() |
|||
|
|||
msg := []byte("relay works!") |
|||
go func() { |
|||
defer close(done) |
|||
list := r3.Listener() |
|||
|
|||
var err error |
|||
conn1, err = list.Accept() |
|||
if err != nil { |
|||
t.Error(err) |
|||
return |
|||
} |
|||
|
|||
_, err = conn1.Write(msg) |
|||
if err != nil { |
|||
t.Error(err) |
|||
return |
|||
} |
|||
}() |
|||
|
|||
rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) |
|||
dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) |
|||
|
|||
rctx, rcancel := context.WithTimeout(ctx, time.Second) |
|||
defer rcancel() |
|||
|
|||
var err error |
|||
conn2, err = r1.DialPeer(rctx, rinfo, dinfo) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
result := make([]byte, len(msg)) |
|||
_, err = io.ReadFull(conn2, result) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
if !bytes.Equal(result, msg) { |
|||
t.Fatal("message was incorrect:", string(result)) |
|||
} |
|||
} |
|||
|
|||
func TestRelayReset(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts := getNetHosts(t, 3) |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
connect(t, hosts[1], hosts[2]) |
|||
|
|||
time.Sleep(10 * time.Millisecond) |
|||
|
|||
r1 := newTestRelay(t, hosts[0]) |
|||
|
|||
newTestRelay(t, hosts[1], OptHop) |
|||
|
|||
r3 := newTestRelay(t, hosts[2]) |
|||
|
|||
ready := make(chan struct{}) |
|||
|
|||
msg := []byte("relay works!") |
|||
go func() { |
|||
list := r3.Listener() |
|||
|
|||
con, err := list.Accept() |
|||
if err != nil { |
|||
t.Error(err) |
|||
return |
|||
} |
|||
|
|||
<-ready |
|||
|
|||
_, err = con.Write(msg) |
|||
if err != nil { |
|||
t.Error(err) |
|||
return |
|||
} |
|||
|
|||
hosts[2].Network().ClosePeer(hosts[1].ID()) |
|||
}() |
|||
|
|||
rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) |
|||
dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) |
|||
|
|||
rctx, rcancel := context.WithTimeout(ctx, time.Second) |
|||
defer rcancel() |
|||
|
|||
con, err := r1.DialPeer(rctx, rinfo, dinfo) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
close(ready) |
|||
|
|||
_, err = io.ReadAll(con) |
|||
if err == nil { |
|||
t.Fatal("expected error for reset relayed connection") |
|||
} |
|||
} |
|||
|
|||
func TestBasicRelayDial(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
|
|||
hosts := getNetHosts(t, 3) |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
connect(t, hosts[1], hosts[2]) |
|||
|
|||
time.Sleep(10 * time.Millisecond) |
|||
|
|||
r1 := newTestRelay(t, hosts[0]) |
|||
|
|||
_ = newTestRelay(t, hosts[1], OptHop) |
|||
r3 := newTestRelay(t, hosts[2]) |
|||
|
|||
var ( |
|||
conn1, conn2 net.Conn |
|||
done = make(chan struct{}) |
|||
) |
|||
|
|||
defer func() { |
|||
cancel() |
|||
<-done |
|||
if conn1 != nil { |
|||
conn1.Close() |
|||
} |
|||
if conn2 != nil { |
|||
conn2.Close() |
|||
} |
|||
}() |
|||
|
|||
msg := []byte("relay works!") |
|||
go func() { |
|||
defer close(done) |
|||
list := r3.Listener() |
|||
|
|||
var err error |
|||
conn1, err = list.Accept() |
|||
if err != nil { |
|||
t.Error(err) |
|||
return |
|||
} |
|||
|
|||
_, err = conn1.Write(msg) |
|||
if err != nil { |
|||
t.Error(err) |
|||
return |
|||
} |
|||
}() |
|||
|
|||
addr := ma.StringCast(fmt.Sprintf("/ipfs/%s/p2p-circuit", hosts[1].ID().Pretty())) |
|||
|
|||
rctx, rcancel := context.WithTimeout(ctx, time.Second) |
|||
defer rcancel() |
|||
|
|||
var err error |
|||
conn2, err = r1.Dial(rctx, addr, hosts[2].ID()) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
data := make([]byte, len(msg)) |
|||
_, err = io.ReadFull(conn2, data) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
if !bytes.Equal(data, msg) { |
|||
t.Fatal("message was incorrect:", string(data)) |
|||
} |
|||
} |
|||
|
|||
func TestUnspecificRelayDialFails(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
hosts := getNetHosts(t, 3) |
|||
|
|||
r1 := newTestRelay(t, hosts[0]) |
|||
newTestRelay(t, hosts[1], OptHop) |
|||
r3 := newTestRelay(t, hosts[2]) |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
connect(t, hosts[1], hosts[2]) |
|||
|
|||
time.Sleep(100 * time.Millisecond) |
|||
|
|||
go func() { |
|||
if _, err := r3.Listener().Accept(); err == nil { |
|||
t.Error("should not have received relay connection") |
|||
} |
|||
}() |
|||
|
|||
addr := ma.StringCast("/p2p-circuit") |
|||
|
|||
ctx, cancel := context.WithTimeout(context.Background(), time.Second) |
|||
defer cancel() |
|||
if _, err := r1.Dial(ctx, addr, hosts[2].ID()); err == nil { |
|||
t.Fatal("expected dial with unspecified relay address to fail, even if we're connected to a relay") |
|||
} |
|||
} |
|||
|
|||
func TestRelayThroughNonHop(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts := getNetHosts(t, 3) |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
connect(t, hosts[1], hosts[2]) |
|||
|
|||
time.Sleep(10 * time.Millisecond) |
|||
|
|||
r1 := newTestRelay(t, hosts[0]) |
|||
|
|||
newTestRelay(t, hosts[1]) |
|||
|
|||
newTestRelay(t, hosts[2]) |
|||
|
|||
rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) |
|||
dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) |
|||
|
|||
rctx, rcancel := context.WithTimeout(ctx, time.Second) |
|||
defer rcancel() |
|||
|
|||
_, err := r1.DialPeer(rctx, rinfo, dinfo) |
|||
if err == nil { |
|||
t.Fatal("expected error") |
|||
} |
|||
|
|||
rerr, ok := err.(RelayError) |
|||
if !ok { |
|||
t.Fatalf("expected RelayError: %#v", err) |
|||
} |
|||
|
|||
if rerr.Code != pb.CircuitRelay_HOP_CANT_SPEAK_RELAY { |
|||
t.Fatal("expected 'HOP_CANT_SPEAK_RELAY' error") |
|||
} |
|||
} |
|||
|
|||
func TestRelayNoDestConnection(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts := getNetHosts(t, 3) |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
|
|||
time.Sleep(10 * time.Millisecond) |
|||
|
|||
r1 := newTestRelay(t, hosts[0]) |
|||
|
|||
newTestRelay(t, hosts[1], OptHop) |
|||
|
|||
rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) |
|||
dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) |
|||
|
|||
rctx, rcancel := context.WithTimeout(ctx, time.Second) |
|||
defer rcancel() |
|||
|
|||
_, err := r1.DialPeer(rctx, rinfo, dinfo) |
|||
if err == nil { |
|||
t.Fatal("expected error") |
|||
} |
|||
|
|||
rerr, ok := err.(RelayError) |
|||
if !ok { |
|||
t.Fatalf("expected RelayError: %#v", err) |
|||
} |
|||
|
|||
if rerr.Code != pb.CircuitRelay_HOP_NO_CONN_TO_DST { |
|||
t.Fatal("expected 'HOP_NO_CONN_TO_DST' error") |
|||
} |
|||
} |
|||
|
|||
func TestActiveRelay(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts := getNetHosts(t, 3) |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
|
|||
time.Sleep(10 * time.Millisecond) |
|||
|
|||
r1 := newTestRelay(t, hosts[0]) |
|||
newTestRelay(t, hosts[1], OptHop, OptActive) |
|||
r3 := newTestRelay(t, hosts[2]) |
|||
|
|||
connChan := make(chan manet.Conn) |
|||
|
|||
msg := []byte("relay works!") |
|||
go func() { |
|||
defer close(connChan) |
|||
list := r3.Listener() |
|||
|
|||
conn1, err := list.Accept() |
|||
if err != nil { |
|||
t.Error(err) |
|||
return |
|||
} |
|||
|
|||
if _, err := conn1.Write(msg); err != nil { |
|||
t.Error(err) |
|||
return |
|||
} |
|||
connChan <- conn1 |
|||
}() |
|||
|
|||
rinfo := hosts[1].Peerstore().PeerInfo(hosts[1].ID()) |
|||
dinfo := hosts[2].Peerstore().PeerInfo(hosts[2].ID()) |
|||
|
|||
rctx, rcancel := context.WithTimeout(ctx, time.Second) |
|||
defer rcancel() |
|||
|
|||
conn2, err := r1.DialPeer(rctx, rinfo, dinfo) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
defer conn2.Close() |
|||
|
|||
data := make([]byte, len(msg)) |
|||
_, err = io.ReadFull(conn2, data) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
if !bytes.Equal(data, msg) { |
|||
t.Fatal("message was incorrect:", string(data)) |
|||
} |
|||
conn1, ok := <-connChan |
|||
if !ok { |
|||
t.Fatal("listener didn't accept a connection") |
|||
} |
|||
conn1.Close() |
|||
} |
|||
|
|||
func TestRelayCanHop(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts := getNetHosts(t, 2) |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
|
|||
time.Sleep(10 * time.Millisecond) |
|||
|
|||
r1 := newTestRelay(t, hosts[0]) |
|||
|
|||
newTestRelay(t, hosts[1], OptHop) |
|||
|
|||
canhop, err := r1.CanHop(ctx, hosts[1].ID()) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
if !canhop { |
|||
t.Fatal("Relay can't hop") |
|||
} |
|||
} |
@ -1,74 +0,0 @@ |
|||
package relay |
|||
|
|||
import ( |
|||
"fmt" |
|||
"io" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/host" |
|||
"github.com/libp2p/go-libp2p/core/transport" |
|||
ma "github.com/multiformats/go-multiaddr" |
|||
) |
|||
|
|||
var circuitAddr = ma.Cast(ma.ProtocolWithCode(ma.P_CIRCUIT).VCode) |
|||
|
|||
var _ transport.Transport = (*RelayTransport)(nil) |
|||
var _ io.Closer = (*RelayTransport)(nil) |
|||
|
|||
type RelayTransport Relay |
|||
|
|||
func (t *RelayTransport) Relay() *Relay { |
|||
return (*Relay)(t) |
|||
} |
|||
|
|||
func (r *Relay) Transport() *RelayTransport { |
|||
return (*RelayTransport)(r) |
|||
} |
|||
|
|||
func (t *RelayTransport) Listen(laddr ma.Multiaddr) (transport.Listener, error) { |
|||
// TODO: Ensure we have a connection to the relay, if specified. Also,
|
|||
// make sure the multiaddr makes sense.
|
|||
if !t.Relay().Matches(laddr) { |
|||
return nil, fmt.Errorf("%s is not a relay address", laddr) |
|||
} |
|||
return t.upgrader.UpgradeListener(t, t.Relay().Listener()), nil |
|||
} |
|||
|
|||
func (t *RelayTransport) CanDial(raddr ma.Multiaddr) bool { |
|||
return t.Relay().Matches(raddr) |
|||
} |
|||
|
|||
func (t *RelayTransport) Proxy() bool { |
|||
return true |
|||
} |
|||
|
|||
func (t *RelayTransport) Protocols() []int { |
|||
return []int{ma.P_CIRCUIT} |
|||
} |
|||
|
|||
func (r *RelayTransport) Close() error { |
|||
r.ctxCancel() |
|||
return nil |
|||
} |
|||
|
|||
// AddRelayTransport constructs a relay and adds it as a transport to the host network.
|
|||
func AddRelayTransport(h host.Host, upgrader transport.Upgrader, opts ...RelayOpt) error { |
|||
n, ok := h.Network().(transport.TransportNetwork) |
|||
if !ok { |
|||
return fmt.Errorf("%v is not a transport network", h.Network()) |
|||
} |
|||
|
|||
r, err := NewRelay(h, upgrader, opts...) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
// There's no nice way to handle these errors as we have no way to tear
|
|||
// down the relay.
|
|||
// TODO
|
|||
if err := n.AddTransport(r.Transport()); err != nil { |
|||
log.Error("failed to add relay transport:", err) |
|||
} else if err := n.Listen(r.Listener().Multiaddr()); err != nil { |
|||
log.Error("failed to listen on relay transport:", err) |
|||
} |
|||
return nil |
|||
} |
@ -1,156 +0,0 @@ |
|||
//lint:file-ignore U1000 Ignore all unused code, we're not running any tests.
|
|||
package relay_test |
|||
|
|||
import ( |
|||
"bytes" |
|||
"context" |
|||
"fmt" |
|||
"io" |
|||
"testing" |
|||
"time" |
|||
|
|||
"github.com/libp2p/go-libp2p/p2p/net/swarm" |
|||
swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing" |
|||
. "github.com/libp2p/go-libp2p/p2p/protocol/internal/circuitv1-deprecated" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/host" |
|||
"github.com/libp2p/go-libp2p/core/network" |
|||
"github.com/libp2p/go-libp2p/core/peerstore" |
|||
|
|||
ma "github.com/multiformats/go-multiaddr" |
|||
) |
|||
|
|||
const TestProto = "test/relay-transport" |
|||
|
|||
var msg = []byte("relay works!") |
|||
|
|||
func testSetupRelay(t *testing.T) []host.Host { |
|||
hosts := getNetHosts(t, 3) |
|||
|
|||
err := AddRelayTransport(hosts[0], swarmt.GenUpgrader(t, hosts[0].Network().(*swarm.Swarm), nil)) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
err = AddRelayTransport(hosts[1], swarmt.GenUpgrader(t, hosts[1].Network().(*swarm.Swarm), nil), OptHop) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
err = AddRelayTransport(hosts[2], swarmt.GenUpgrader(t, hosts[2].Network().(*swarm.Swarm), nil)) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
connect(t, hosts[0], hosts[1]) |
|||
connect(t, hosts[1], hosts[2]) |
|||
|
|||
time.Sleep(100 * time.Millisecond) |
|||
|
|||
handler := func(s network.Stream) { |
|||
_, err := s.Write(msg) |
|||
if err != nil { |
|||
t.Error(err) |
|||
} |
|||
s.Close() |
|||
} |
|||
|
|||
hosts[2].SetStreamHandler(TestProto, handler) |
|||
|
|||
return hosts |
|||
} |
|||
|
|||
func TestFullAddressTransportDial(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
hosts := testSetupRelay(t) |
|||
|
|||
var relayAddr ma.Multiaddr |
|||
for _, addr := range hosts[1].Addrs() { |
|||
// skip relay addrs.
|
|||
if _, err := addr.ValueForProtocol(ma.P_CIRCUIT); err != nil { |
|||
relayAddr = addr |
|||
} |
|||
} |
|||
|
|||
addr, err := ma.NewMultiaddr(fmt.Sprintf("%s/p2p/%s/p2p-circuit/p2p/%s", relayAddr.String(), hosts[1].ID().Pretty(), hosts[2].ID().Pretty())) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
hosts[0].Peerstore().AddAddrs(hosts[2].ID(), []ma.Multiaddr{addr}, peerstore.TempAddrTTL) |
|||
|
|||
ctx, cancel := context.WithTimeout(context.Background(), time.Second) |
|||
defer cancel() |
|||
s, err := hosts[0].NewStream(ctx, hosts[2].ID(), TestProto) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
data, err := io.ReadAll(s) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
if !bytes.Equal(data, msg) { |
|||
t.Fatal("message was incorrect:", string(data)) |
|||
} |
|||
} |
|||
|
|||
func TestSpecificRelayTransportDial(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts := testSetupRelay(t) |
|||
|
|||
addr, err := ma.NewMultiaddr(fmt.Sprintf("/ipfs/%s/p2p-circuit/ipfs/%s", hosts[1].ID().Pretty(), hosts[2].ID().Pretty())) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
rctx, rcancel := context.WithTimeout(ctx, time.Second) |
|||
defer rcancel() |
|||
|
|||
hosts[0].Peerstore().AddAddrs(hosts[2].ID(), []ma.Multiaddr{addr}, peerstore.TempAddrTTL) |
|||
|
|||
s, err := hosts[0].NewStream(rctx, hosts[2].ID(), TestProto) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
data, err := io.ReadAll(s) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
if !bytes.Equal(data, msg) { |
|||
t.Fatal("message was incorrect:", string(data)) |
|||
} |
|||
} |
|||
|
|||
func TestUnspecificRelayTransportDialFails(t *testing.T) { |
|||
t.Skip("This package is legacy code we only keep around for testing purposes.") |
|||
|
|||
ctx, cancel := context.WithCancel(context.Background()) |
|||
defer cancel() |
|||
|
|||
hosts := testSetupRelay(t) |
|||
|
|||
addr, err := ma.NewMultiaddr(fmt.Sprintf("/p2p-circuit/ipfs/%s", hosts[2].ID().Pretty())) |
|||
if err != nil { |
|||
t.Fatal(err) |
|||
} |
|||
|
|||
rctx, rcancel := context.WithTimeout(ctx, time.Second) |
|||
defer rcancel() |
|||
|
|||
hosts[0].Peerstore().AddAddrs(hosts[2].ID(), []ma.Multiaddr{addr}, peerstore.TempAddrTTL) |
|||
|
|||
_, err = hosts[0].NewStream(rctx, hosts[2].ID(), TestProto) |
|||
if err == nil { |
|||
t.Fatal("dial to unspecified address should have failed") |
|||
} |
|||
|
|||
} |
@ -1,119 +0,0 @@ |
|||
package relay |
|||
|
|||
import ( |
|||
"errors" |
|||
"io" |
|||
|
|||
"github.com/libp2p/go-libp2p/core/peer" |
|||
"github.com/libp2p/go-libp2p/p2p/protocol/internal/circuitv1-deprecated/pb" |
|||
|
|||
pool "github.com/libp2p/go-buffer-pool" |
|||
"github.com/libp2p/go-msgio/pbio" |
|||
|
|||
ma "github.com/multiformats/go-multiaddr" |
|||
"github.com/multiformats/go-varint" |
|||
"google.golang.org/protobuf/proto" |
|||
) |
|||
|
|||
//go:generate protoc --proto_path=$PWD:$PWD/../../../.. --go_out=. --go_opt=Mpb/relay.proto=./pb pb/relay.proto
|
|||
|
|||
func peerToPeerInfo(p *pb.CircuitRelay_Peer) (peer.AddrInfo, error) { |
|||
if p == nil { |
|||
return peer.AddrInfo{}, errors.New("nil peer") |
|||
} |
|||
|
|||
id, err := peer.IDFromBytes(p.Id) |
|||
if err != nil { |
|||
return peer.AddrInfo{}, err |
|||
} |
|||
|
|||
addrs := make([]ma.Multiaddr, 0, len(p.Addrs)) |
|||
for _, addrBytes := range p.Addrs { |
|||
a, err := ma.NewMultiaddrBytes(addrBytes) |
|||
if err == nil { |
|||
addrs = append(addrs, a) |
|||
} |
|||
} |
|||
|
|||
return peer.AddrInfo{ID: id, Addrs: addrs}, nil |
|||
} |
|||
|
|||
func peerInfoToPeer(pi peer.AddrInfo) *pb.CircuitRelay_Peer { |
|||
addrs := make([][]byte, len(pi.Addrs)) |
|||
for i, addr := range pi.Addrs { |
|||
addrs[i] = addr.Bytes() |
|||
} |
|||
|
|||
p := new(pb.CircuitRelay_Peer) |
|||
p.Id = []byte(pi.ID) |
|||
p.Addrs = addrs |
|||
|
|||
return p |
|||
} |
|||
|
|||
func incrementTag(v int) int { |
|||
return v + 1 |
|||
} |
|||
|
|||
func decrementTag(v int) int { |
|||
if v > 0 { |
|||
return v - 1 |
|||
} else { |
|||
return v |
|||
} |
|||
} |
|||
|
|||
type delimitedReader struct { |
|||
r io.Reader |
|||
buf []byte |
|||
} |
|||
|
|||
// The protobuf NewDelimitedReader is buffered, which may eat up stream data.
|
|||
// So we need to implement a compatible delimited reader that reads unbuffered.
|
|||
// There is a slowdown from unbuffered reading: when reading the message
|
|||
// it can take multiple single byte Reads to read the length and another Read
|
|||
// to read the message payload.
|
|||
// However, this is not critical performance degradation as
|
|||
// - the reader is utilized to read one (dialer, stop) or two messages (hop) during
|
|||
// the handshake, so it's a drop in the water for the connection lifetime.
|
|||
// - messages are small (max 4k) and the length fits in a couple of bytes,
|
|||
// so overall we have at most three reads per message.
|
|||
func newDelimitedReader(r io.Reader, maxSize int) *delimitedReader { |
|||
return &delimitedReader{r: r, buf: pool.Get(maxSize)} |
|||
} |
|||
|
|||
func (d *delimitedReader) Close() { |
|||
if d.buf != nil { |
|||
pool.Put(d.buf) |
|||
d.buf = nil |
|||
} |
|||
} |
|||
|
|||
func (d *delimitedReader) ReadByte() (byte, error) { |
|||
buf := d.buf[:1] |
|||
_, err := d.r.Read(buf) |
|||
return buf[0], err |
|||
} |
|||
|
|||
func (d *delimitedReader) ReadMsg(msg proto.Message) error { |
|||
mlen, err := varint.ReadUvarint(d) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
if uint64(len(d.buf)) < mlen { |
|||
return errors.New("message too large") |
|||
} |
|||
|
|||
buf := d.buf[:mlen] |
|||
_, err = io.ReadFull(d.r, buf) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
return proto.Unmarshal(buf, msg) |
|||
} |
|||
|
|||
func newDelimitedWriter(w io.Writer) pbio.WriteCloser { |
|||
return pbio.NewDelimitedWriter(w) |
|||
} |
Loading…
Reference in new issue