Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
fionera committed Sep 1, 2023
0 parents commit 9278ccf
Show file tree
Hide file tree
Showing 31 changed files with 2,004 additions and 0 deletions.
64 changes: 64 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Go

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dominikh/[email protected]

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20'

- name: Build
run: go build -v ./...

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20'

- name: Test
run: go test -v ./...

e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20'

- name: setup environment
run: |
sudo apt-get install -y software-properties-common
sudo add-apt-repository -y ppa:vbernat/haproxy-2.8
sudo apt-get update
sudo apt-get install -y haproxy
haproxy -vv
- name: Test E2E
run: go test -v ./... --tags=e2e
40 changes: 40 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Created by https://www.toptal.com/developers/gitignore/api/go,direnv
# Edit at https://www.toptal.com/developers/gitignore?templates=go,direnv

### direnv ###
.direnv
.envrc

### Go ###
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work

### Go Patch ###
/vendor/
/Godeps/

# End of https://www.toptal.com/developers/gitignore/api/go,direnv

### Intellij ###

.idea
*.iml
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# HAProxy Protocols in Go

3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/fionera/haproxy-go

go 1.20
Empty file added go.sum
Empty file.
48 changes: 48 additions & 0 deletions pkg/buffer/slicebuf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package buffer

type SliceBuffer struct {
readOffset int
writeOffset int
buf []byte
}

func NewSliceBuffer(size int) *SliceBuffer {
return &SliceBuffer{
buf: make([]byte, size),
}
}

func (s *SliceBuffer) Reset() {
s.readOffset = 0
s.writeOffset = 0
}

func (s *SliceBuffer) ReadBytes() []byte {
return s.buf[s.readOffset:s.writeOffset]
}

func (s *SliceBuffer) WriteBytes() []byte {
return s.buf[s.writeOffset:]
}

func (s *SliceBuffer) AdvanceR(n int) {
s.readOffset += n
}

func (s *SliceBuffer) AdvanceW(n int) {
s.writeOffset += n
}

func (s *SliceBuffer) WriteNBytes(n int) []byte {
s.writeOffset += n
return s.buf[s.writeOffset-n : s.writeOffset]
}

func (s *SliceBuffer) ReadNBytes(n int) []byte {
s.readOffset += n
return s.buf[s.readOffset-n : s.readOffset]
}

func (s *SliceBuffer) Len() int {
return s.writeOffset - s.readOffset
}
30 changes: 30 additions & 0 deletions pkg/encoding/other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package encoding

import (
"net/netip"
)

func PutBytes(b []byte, v []byte) (int, error) {
l := len(v)
n, err := PutVarint(b, int64(l))
if err != nil {
return 0, err
}

if l+n > len(b) {
return 0, ErrInsufficientSpace
}

copy(b[n:], v)
return n + l, nil
}

func PutAddr(b []byte, ip netip.Addr) (int, error) {
s := ip.AsSlice()
if len(b) < len(s) {
return 0, ErrInsufficientSpace
}

copy(b, s)
return len(s), nil
}
76 changes: 76 additions & 0 deletions pkg/encoding/varint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package encoding

import (
"fmt"
)

var (
ErrUnterminatedSequence = fmt.Errorf("unterminated sequence")
ErrInsufficientSpace = fmt.Errorf("insufficient space in buffer")
)

// Source: https://github.com/criteo/haproxy-spoe-go/blob/master/encoding.go
func PutVarint(b []byte, i int64) (int, error) {
if len(b) == 0 {
return 0, ErrInsufficientSpace
}

if i < 240 {
b[0] = byte(i)
return 1, nil
}

n := 0
b[n] = byte(i) | 240
n++
i = (i - 240) >> 4
for i >= 128 {
if n > len(b)-1 {
return 0, ErrInsufficientSpace
}

b[n] = byte(i) | 128
n++
i = (i - 128) >> 7
}

if n > len(b)-1 {
return 0, ErrInsufficientSpace
}

b[n] = byte(i)
n++

return n, nil
}

// Source: https://github.com/criteo/haproxy-spoe-go/blob/master/encoding.go
func Varint(b []byte) (int64, int, error) {
if len(b) == 0 {
return 0, 0, ErrUnterminatedSequence
}
val := int64(b[0])
off := 1

if val < 240 {
return val, 1, nil
}

r := uint(4)
for {
if off > len(b)-1 {
return 0, 0, ErrUnterminatedSequence
}

v := int64(b[off])
val += v << r
off++
r += 7

if v < 128 {
break
}
}

return val, off, nil
}
37 changes: 37 additions & 0 deletions pkg/encoding/varint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package encoding

import (
"reflect"
"testing"
)

func Test_encode(t *testing.T) {
type args struct {
val int64
}
tests := []struct {
name string
args args
want []byte
}{
{
name: "",
args: args{
val: 0x1234,
},
want: []byte{0xf4, 0x94, 0x01},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b := make([]byte, 4)
if n, _ := PutVarint(b, tt.args.val); !reflect.DeepEqual(b[:n], tt.want) {
t.Errorf("encode() = %v, want %v", b[:n], tt.want)
}

if got, _, _ := Varint(tt.want); !reflect.DeepEqual(got, tt.args.val) {
t.Errorf("decode() = %v, want %v", got, tt.args.val)
}
})
}
}
Loading

0 comments on commit 9278ccf

Please sign in to comment.