-
-
Notifications
You must be signed in to change notification settings - Fork 108
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The support is modeled on azure.go under tlvparse. The GCP spec is similar but encodes uint64. There's no subtype. Since zero value of uint64 is technically a valid header value, I've opted for an extra boolean to indicate if it was found (same as with Azure).
- Loading branch information
1 parent
3aa7ea9
commit 9f25ec7
Showing
2 changed files
with
129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package tlvparse | ||
|
||
import ( | ||
"encoding/binary" | ||
|
||
"github.com/pires/go-proxyproto" | ||
) | ||
|
||
const ( | ||
// PP2_TYPE_GCP indicates a Google Cloud Platform header | ||
PP2_TYPE_GCP proxyproto.PP2Type = 0xE0 | ||
) | ||
|
||
// ExtractPSCConnectionID returns the first PSC Connection ID in the TLV if it exists and is well-formed and | ||
// a bool indicating one was found. | ||
func ExtractPSCConnectionID(tlvs []proxyproto.TLV) (uint64, bool) { | ||
for _, tlv := range tlvs { | ||
if linkID, err := pscConnectionID(tlv); err == nil { | ||
return linkID, true | ||
} | ||
} | ||
return 0, false | ||
} | ||
|
||
// pscConnectionID returns the ID of a GCP PSC extension TLV or errors with ErrIncompatibleTLV or | ||
// ErrMalformedTLV if it's the wrong TLV type or is malformed. | ||
// | ||
// Field Length (bytes) Description | ||
// Type 1 PP2_TYPE_GCP (0xE0) | ||
// Length 2 Length of value (always 0x0008) | ||
// Value 8 The 8-byte PSC Connection ID (decode to uint64; big endian) | ||
// | ||
// For example proxyproto.TLV{Type:0xea, Length:8, Value:[]byte{0xff, 0xff, 0xff, 0xff, 0xc0, 0xa8, 0x64, 0x02}} | ||
// will be decoded as 18446744072646845442. | ||
// | ||
// See https://cloud.google.com/vpc/docs/configure-private-service-connect-producer | ||
func pscConnectionID(t proxyproto.TLV) (uint64, error) { | ||
if !isPSCConnectionID(t) { | ||
return 0, proxyproto.ErrIncompatibleTLV | ||
} | ||
linkID := binary.BigEndian.Uint64(t.Value) | ||
return linkID, nil | ||
} | ||
|
||
func isPSCConnectionID(t proxyproto.TLV) bool { | ||
return t.Type == PP2_TYPE_GCP && len(t.Value) == 8 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package tlvparse | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/pires/go-proxyproto" | ||
) | ||
|
||
func TestExtractPSCConnectionID(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
tlvs []proxyproto.TLV | ||
wantPSCConnectionID uint64 | ||
wantFound bool | ||
}{ | ||
{ | ||
name: "nil TLVs", | ||
tlvs: nil, | ||
wantFound: false, | ||
}, | ||
{ | ||
name: "empty TLVs", | ||
tlvs: []proxyproto.TLV{}, | ||
wantFound: false, | ||
}, | ||
{ | ||
name: "AWS VPC endpoint ID", | ||
tlvs: []proxyproto.TLV{ | ||
{ | ||
Type: 0xEA, | ||
Value: []byte{0x01, 0x76, 0x70, 0x63, 0x65, 0x2d, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33}, | ||
}, | ||
}, | ||
wantFound: false, | ||
}, | ||
{ | ||
name: "GCP link ID", | ||
tlvs: []proxyproto.TLV{ | ||
{ | ||
Type: PP2_TYPE_GCP, | ||
Value: []byte{'\xff', '\xff', '\xff', '\xff', '\xc0', '\xa8', '\x64', '\x02'}, | ||
}, | ||
}, | ||
wantPSCConnectionID: 18446744072646845442, | ||
wantFound: true, | ||
}, | ||
{ | ||
name: "Multiple TLVs", | ||
tlvs: []proxyproto.TLV{ | ||
{ // AWS | ||
Type: 0xEA, | ||
Value: []byte{0x01, 0x76, 0x70, 0x63, 0x65, 0x2d, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33}, | ||
}, | ||
{ // Azure | ||
Type: 0xEE, | ||
Value: []byte{0x02, 0x01, 0x01, 0x01, 0x01}, | ||
}, | ||
{ // GCP but wrong length | ||
Type: 0xE0, | ||
Value: []byte{0xff, 0xff, 0xff}, | ||
}, | ||
{ // Correct | ||
Type: 0xE0, | ||
Value: []byte{'\xff', '\xff', '\xff', '\xff', '\xc0', '\xa8', '\x64', '\x02'}, | ||
}, | ||
}, | ||
wantPSCConnectionID: 18446744072646845442, | ||
wantFound: true, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
linkID, hasLinkID := ExtractPSCConnectionID(tt.tlvs) | ||
if hasLinkID != tt.wantFound { | ||
t.Errorf("ExtractPSCConnectionID() got1 = %v, want %v", hasLinkID, tt.wantFound) | ||
} | ||
if linkID != tt.wantPSCConnectionID { | ||
t.Errorf("ExtractPSCConnectionID() got = %v, want %v", linkID, tt.wantPSCConnectionID) | ||
} | ||
}) | ||
} | ||
} |