Skip to content

Commit

Permalink
Initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ameshkov committed Feb 2, 2024
1 parent f9ea21b commit d6093d4
Show file tree
Hide file tree
Showing 20 changed files with 1,412 additions and 0 deletions.
104 changes: 104 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: Build

'on':
'push':
'tags':
- 'v*'
'branches':
- '*'
'pull_request':

jobs:
tests:
runs-on: ${{ matrix.os }}
env:
GO111MODULE: "on"
strategy:
matrix:
os:
- windows-latest
- macos-latest
- ubuntu-latest

steps:
- uses: actions/checkout@master

- uses: actions/setup-go@v3
with:
go-version: 1.x

- name: Run tests
run: |-
go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
- name: Upload coverage
uses: codecov/codecov-action@v3
if: "success() && matrix.os == 'ubuntu-latest'"
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.txt

build:
needs:
- tests
runs-on: ubuntu-latest
env:
GO111MODULE: "on"
steps:
- uses: actions/checkout@master

- uses: actions/setup-go@v3
with:
go-version: 1.x

- name: Prepare environment
run: |-
RELEASE_VERSION="${GITHUB_REF##*/}"
if [[ "${RELEASE_VERSION}" != v* ]]; then RELEASE_VERSION='dev'; fi
echo "RELEASE_VERSION=\"${RELEASE_VERSION}\"" >> $GITHUB_ENV
# Win
- run: GOOS=windows GOARCH=386 VERSION=${RELEASE_VERSION} make release
- run: GOOS=windows GOARCH=amd64 VERSION=${RELEASE_VERSION} make release

# MacOS
- run: GOOS=darwin GOARCH=amd64 VERSION=${RELEASE_VERSION} make release

# MacOS ARM
- run: GOOS=darwin GOARCH=arm64 VERSION=${RELEASE_VERSION} make release

# Linux X86
- run: GOOS=linux GOARCH=386 VERSION=${RELEASE_VERSION} make release
- run: GOOS=linux GOARCH=amd64 VERSION=${RELEASE_VERSION} make release

# Linux ARM
- run: GOOS=linux GOARCH=arm GOARM=6 VERSION=${RELEASE_VERSION} make release
- run: GOOS=linux GOARCH=arm64 VERSION=${RELEASE_VERSION} make release

# Linux MIPS/MIPSLE
- run: GOOS=linux GOARCH=mips GOMIPS=softfloat VERSION=${RELEASE_VERSION} make release
- run: GOOS=linux GOARCH=mipsle GOMIPS=softfloat VERSION=${RELEASE_VERSION} make release

# FreeBSD X86
- run: GOOS=freebsd GOARCH=386 VERSION=${RELEASE_VERSION} make release
- run: GOOS=freebsd GOARCH=amd64 VERSION=${RELEASE_VERSION} make release

# FreeBSD ARM/ARM64
- run: GOOS=freebsd GOARCH=arm GOARM=6 VERSION=${RELEASE_VERSION} make release
- run: GOOS=freebsd GOARCH=arm64 VERSION=${RELEASE_VERSION} make release

- run: ls -l build/udptlspipe-*

- name: Create release
if: startsWith(github.ref, 'refs/tags/v')
id: create_release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
body: See [CHANGELOG.md](./CHANGELOG.md) for the list of changes.
draft: false
prerelease: false
files: |
build/udptlspipe-*.tar.gz
build/udptlspipe-*.zip
26 changes: 26 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: golangci-lint
'on':
'push':
'tags':
- 'v*'
'branches':
- '*'
'pull_request':

jobs:
golangci:
runs-on:
${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
- macos-latest
steps:
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/[email protected]
with:
# This field is required. Dont set the patch version to always use
# the latest patch version.
version: v1.54.1
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.DS_Store
.idea
.vscode
build
udptlspipe
66 changes: 66 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# options for analysis running
run:
# default concurrency is a available CPU number
concurrency: 4

# timeout for analysis, e.g. 30s, 5m, default is 1m
deadline: 2m

# which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize
# autogenerated files. If it's not please let us know.
skip-files:
- ".*generated.*"
- ".*_test.go"

# all available settings of specific linters
linters-settings:
gocyclo:
min-complexity: 20
lll:
line-length: 200

linters:
enable:
- errcheck
- govet
- ineffassign
- staticcheck
- unused
- dupl
- gocyclo
- goimports
- revive
- gosec
- misspell
- stylecheck
- unconvert
disable-all: true
fast: true

issues:
exclude-use-default: false

# List of regexps of issue texts to exclude, empty list by default.
# But independently from this option we use default exclude patterns,
# it can be disabled by `exclude-use-default: false`. To list all
# excluded by default patterns execute `golangci-lint run --help`
exclude:
# errcheck defer Close
- error return value not checked \(defer .*\.Close()\)
# errcheck: Almost all programs ignore errors on these functions and in most cases it's ok
- Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked
# gosec: Duplicated errcheck checks
- G104
# gosec: Expect file permissions to be 0600 or less
- G302
# errcheck defer Close
- error return value not checked \(defer .*\.Close()\)
# gosec: False positive is triggered by 'src, err := os.ReadFile(filename)'
- Potential file inclusion via variable
# gosec: TLS InsecureSkipVerify may be true
# We have a configuration option that allows to do this
- G402
# gosec: Use of weak random number generator
- G404
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# udptlspipe changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog][keepachangelog], and this project
adheres to [Semantic Versioning][semver].

[keepachangelog]: https://keepachangelog.com/en/1.0.0/

[semver]: https://semver.org/spec/v2.0.0.html

## [Unreleased]

[unreleased]: https://github.com/ameshkov/udptlspipe/compare/v1.0.0...HEAD

## [1.0.0] - 2024-02-02

### Added

* The first version with base functionality.

[1.0.0]: https://github.com/ameshkov/udptlspipe/releases/tag/v1.0.0
44 changes: 44 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
NAME=udptlspipe
BASE_BUILDDIR=build
BUILDNAME=$(GOOS)-$(GOARCH)
BUILDDIR=$(BASE_BUILDDIR)/$(BUILDNAME)
VERSION?=v0.0-dev
VERSIONPKG=github.com/ameshkov/udptlspipe/internal/version

ifeq ($(GOOS),windows)
ext=.exe
archiveCmd=zip -9 -r $(NAME)-$(BUILDNAME)-$(VERSION).zip $(BUILDNAME)
else
ext=
archiveCmd=tar czpvf $(NAME)-$(BUILDNAME)-$(VERSION).tar.gz $(BUILDNAME)
endif

.PHONY: default
default: build

build: clean
go build -ldflags "-X $(VERSIONPKG).version=$(VERSION)"

release: check-env-release
mkdir -p $(BUILDDIR)
cp LICENSE $(BUILDDIR)/
cp README.md $(BUILDDIR)/
CGO_ENABLED=0 GOOS=$(GOOS) GOARCH=$(GOARCH) go build -ldflags "-X $(VERSIONPKG).version=$(VERSION)" -o $(BUILDDIR)/$(NAME)$(ext)
cd $(BASE_BUILDDIR) ; $(archiveCmd)

test:
go test -race -v -bench=. ./...

clean:
go clean
rm -rf $(BASE_BUILDDIR)

check-env-release:
@ if [ "$(GOOS)" = "" ]; then \
echo "Environment variable GOOS not set"; \
exit 1; \
fi
@ if [ "$(GOARCH)" = "" ]; then \
echo "Environment variable GOARCH not set"; \
exit 1; \
fi
16 changes: 16 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module github.com/ameshkov/udptlspipe

go 1.21.6

require (
github.com/AdguardTeam/golibs v0.20.0
github.com/jessevdk/go-flags v1.5.0
github.com/stretchr/testify v1.8.4
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.15.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
17 changes: 17 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
github.com/AdguardTeam/golibs v0.20.0 h1:A9FIdYq7wUKhFYy3z+YZ/Aw5oFUYgW+xgaVAJ0pnnPY=
github.com/AdguardTeam/golibs v0.20.0/go.mod h1:3WunclLLfrVAq7fYQRhd6f168FHOEMssnipVXCxDL/w=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
39 changes: 39 additions & 0 deletions internal/cmd/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Package cmd is the entry point of the tool.
package cmd

import (
"errors"
"fmt"
"os"

"github.com/AdguardTeam/golibs/log"
"github.com/ameshkov/udptlspipe/internal/version"
goFlags "github.com/jessevdk/go-flags"
)

// Main is the entry point for the command-line tool.
func Main() {
if len(os.Args) == 2 && (os.Args[1] == "--version" || os.Args[1] == "-v") {
fmt.Printf("udptlspipe version: %s\n", version.Version())

os.Exit(0)
}

o, err := parseOptions()
var flagErr *goFlags.Error
if errors.As(err, &flagErr) && flagErr.Type == goFlags.ErrHelp {
// This is a special case when we exit process here as we received
// --help.
os.Exit(0)
}

if err != nil {
log.Error("Failed to parse args: %v", err)

os.Exit(1)
}

if o.Verbose {
log.SetLevel(log.DEBUG)
}
}
45 changes: 45 additions & 0 deletions internal/cmd/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cmd

import (
"fmt"
"os"

goFlags "github.com/jessevdk/go-flags"
)

// Options represents command-line arguments.
type Options struct {
// ServerMode controls whether the tool works in the server mode.
// By default, the tool will work in the client mode.
ServerMode bool `short:"s" long:"pipe" description:"Enables pipe mode." optional:"yes" optional-value:"true"`

// ListenAddr is the address the tool will be listening to. If it's in the
// pipe mode, it will listen to tcp://, if it's in the client mode, it
// will listen to udp://.
ListenAddr string `short:"l" long:"listen" description:"Address the tool will be listening to." value-name:"<IP>:<Port>"`

// DestinationAddr is the address the tool will connect to. Depending on the
// mode (pipe or client) this address has different semantics. In the
// client mode this is the address of the udptlspipe pipe. In the pipe
// mode this is the address where the received traffic will be passed.
DestinationAddr string `short:"d" long:"destination" description:"Address the tool will connect to." value-name:"<IP>:<Port>"`

// Verbose defines whether we should write the DEBUG-level log or not.
Verbose bool `short:"v" long:"verbose" description:"Verbose output (optional)." optional:"yes" optional-value:"true"`
}

// parseOptions parses os.Args and creates the Options struct.
func parseOptions() (o *Options, err error) {
opts := &Options{}
parser := goFlags.NewParser(opts, goFlags.Default|goFlags.IgnoreUnknown)
remainingArgs, err := parser.ParseArgs(os.Args[1:])
if err != nil {
return nil, err
}

if len(remainingArgs) > 0 {
return nil, fmt.Errorf("unknown arguments: %v", remainingArgs)
}

return opts, nil
}
Loading

0 comments on commit d6093d4

Please sign in to comment.