Skip to content

Commit 8c93d85

Browse files
committed
project initialization
0 parents  commit 8c93d85

10 files changed

Lines changed: 372 additions & 0 deletions

File tree

CONTRIBUTING.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Contributing to VX6
2+
3+
VX6 is being developed as a networking project with a narrow initial scope and a long technical runway. Contributions should improve correctness, clarity, and operational confidence.
4+
5+
## Project Priorities
6+
7+
- Keep IPv6 behavior explicit.
8+
- Prefer simple designs over speculative abstraction.
9+
- Build stable transport primitives before layering discovery or routing features.
10+
- Document behavioral changes in the same change set as the code.
11+
12+
## Development Baseline
13+
14+
- Go 1.22 or newer
15+
- Linux-first workflow
16+
- An environment where IPv6 can be tested directly
17+
18+
## Repository Conventions
19+
20+
- `cmd/` contains executable entrypoints.
21+
- `internal/` contains implementation packages.
22+
- `docs/` contains architecture, roadmap, and protocol notes.
23+
24+
## Pull Requests
25+
26+
Keep pull requests focused. A good change set should:
27+
28+
- solve one clearly defined problem
29+
- include tests when behavior can be exercised automatically
30+
- update documentation when commands, structure, or semantics change
31+
- explain operational impact in plain language
32+
33+
## Coding Standards
34+
35+
- Run `gofmt` on all Go changes.
36+
- Keep exported APIs minimal.
37+
- Return contextual errors.
38+
- Do not silently fall back from IPv6 to IPv4.
39+
- Avoid introducing dependencies without a clear payoff.
40+
41+
## Design Changes
42+
43+
Open an issue or short design note before changing:
44+
45+
- wire formats
46+
- identity semantics
47+
- routing behavior
48+
- discovery models
49+
- configuration layout
50+
51+
## Security
52+
53+
Do not commit private keys, captured traffic, credentials, or lab secrets. If a change affects trust boundaries or transport guarantees, document the assumptions directly in the pull request.

README.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# VX6
2+
3+
VX6 is an IPv6-first transport and service fabric for direct, host-to-host connectivity without central tunnel infrastructure.
4+
5+
This repository currently ships the first executable building block: a small Go CLI that opens a `tcp6` connection and streams a file to a remote IPv6 listener. The long-term project direction is larger than that, but the codebase starts with a narrow, working transport primitive.
6+
7+
## Current Scope
8+
9+
- IPv6-only file transfer over `tcp6`
10+
- Simple CLI with no external dependencies
11+
- Linux-first development baseline
12+
- Clean repository structure for future networking components
13+
14+
## Repository Layout
15+
16+
```text
17+
VX6/
18+
├── cmd/vx6/ # CLI entrypoint
19+
├── docs/ # Architecture and roadmap documents
20+
├── internal/ # Non-exported application packages
21+
├── .gitignore
22+
├── CONTRIBUTING.md
23+
├── go.mod
24+
└── README.md
25+
```
26+
27+
## Quick Start
28+
29+
Build the binary:
30+
31+
```bash
32+
go build ./cmd/vx6
33+
```
34+
35+
Start a receiver on another machine with an IPv6 listener on port `4242`:
36+
37+
```bash
38+
nc -6 -l 4242 > received.bin
39+
```
40+
41+
Send a file:
42+
43+
```bash
44+
./vx6 send --file ./example.bin --addr [2001:db8::10]:4242
45+
```
46+
47+
The current sender writes raw file bytes to the socket. The receiving side can be any IPv6-capable TCP listener that reads from standard input.
48+
49+
## Design Principles
50+
51+
- IPv6 is a first-class constraint, not an optional fallback.
52+
- The codebase should stay small, inspectable, and easy to reason about.
53+
- Initial transport primitives should be reliable before higher-level discovery and routing layers are added.
54+
- Documentation should describe the system plainly and precisely.
55+
56+
## Status
57+
58+
VX6 is at an early bootstrap stage. The present milestone establishes repository conventions and a working IPv6 transfer command that the larger system can build on.
59+
60+
## Contributing
61+
62+
Contribution guidelines are in [CONTRIBUTING.md](./CONTRIBUTING.md).

cmd/vx6/main.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
8+
"github.com/vx6/vx6/internal/cli"
9+
)
10+
11+
func main() {
12+
if err := cli.Run(context.Background(), os.Args[1:]); err != nil {
13+
fmt.Fprintln(os.Stderr, "vx6:", err)
14+
os.Exit(1)
15+
}
16+
}

docs/architecture.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# VX6 Architecture
2+
3+
## Current Baseline
4+
5+
The repository starts with a single transport primitive:
6+
7+
1. Open a `tcp6` connection to a remote IPv6 endpoint.
8+
2. Stream file bytes over that connection.
9+
3. Close cleanly after transfer completion or surface the error.
10+
11+
This is intentionally narrow. VX6 should earn complexity rather than declare it.
12+
13+
## Near-Term Direction
14+
15+
The transport primitive in this repository is expected to evolve into a larger IPv6-first system with the following layers:
16+
17+
- endpoint handling
18+
- node identity
19+
- service publication
20+
- discovery
21+
- forwarding and routing
22+
23+
Each layer should remain independently testable. Direct connectivity is the default path; any relay or proxy behavior should be an explicit extension, not an implicit fallback.
24+
25+
## Implementation Rules
26+
27+
- Keep IPv6-only behavior explicit in code and documentation.
28+
- Prefer streaming interfaces over whole-file buffering.
29+
- Keep package boundaries small and responsibility-driven.
30+
- Add protocol surface gradually and document it as it appears.

docs/roadmap.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# VX6 Roadmap
2+
3+
## Phase 0
4+
5+
- establish repository structure
6+
- provide a working Go CLI
7+
- implement IPv6 file streaming over `tcp6`
8+
- define documentation and contribution standards
9+
10+
## Phase 1
11+
12+
- add receiver-side protocol support in Go
13+
- define transfer metadata framing
14+
- add checksums and transfer diagnostics
15+
- add tests for IPv6 parsing and stream handling
16+
17+
## Phase 2
18+
19+
- introduce node identity
20+
- persist local configuration
21+
- formalize peer connection handling
22+
23+
## Phase 3
24+
25+
- add service advertisement primitives
26+
- define discovery records
27+
- document bootstrap and lookup strategy
28+
29+
## Phase 4
30+
31+
- evaluate forwarding, proxying, and policy controls
32+
- add observability for routing and transfer paths
33+
- prepare for multi-node integration testing

docs/vision.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# VX6 Vision
2+
3+
VX6 is intended to grow from a transport tool into a broader IPv6-native connectivity layer for direct service exposure and peer-to-peer operation.
4+
5+
The project direction is guided by a few constraints:
6+
7+
- direct IPv6 paths should be preferred over managed tunnel infrastructure
8+
- endpoint identity should eventually be separable from a changing address
9+
- service publication and discovery should be designed as composable layers
10+
- operational simplicity matters as much as protocol ambition
11+
12+
The current repository does not claim that full system yet. It establishes the code, structure, and standards needed to build toward it without overstating present capabilities.

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/vx6/vx6
2+
3+
go 1.22.0

internal/cli/app.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package cli
2+
3+
import (
4+
"context"
5+
"errors"
6+
"flag"
7+
"fmt"
8+
"io"
9+
"os"
10+
11+
"github.com/vx6/vx6/internal/transfer"
12+
)
13+
14+
func Run(ctx context.Context, args []string) error {
15+
if len(args) == 0 {
16+
printUsage(os.Stderr)
17+
return errors.New("missing command")
18+
}
19+
20+
switch args[0] {
21+
case "send":
22+
return runSend(ctx, args[1:])
23+
case "-h", "--help", "help":
24+
printUsage(os.Stdout)
25+
return nil
26+
default:
27+
printUsage(os.Stderr)
28+
return fmt.Errorf("unknown command %q", args[0])
29+
}
30+
}
31+
32+
func runSend(ctx context.Context, args []string) error {
33+
fs := flag.NewFlagSet("send", flag.ContinueOnError)
34+
fs.SetOutput(io.Discard)
35+
36+
filePath := fs.String("file", "", "path to the file to send")
37+
address := fs.String("addr", "", "remote IPv6 address in [addr]:port form")
38+
39+
if err := fs.Parse(args); err != nil {
40+
return err
41+
}
42+
43+
if *filePath == "" {
44+
return errors.New("send requires --file")
45+
}
46+
if *address == "" {
47+
return errors.New("send requires --addr")
48+
}
49+
50+
result, err := transfer.SendFile(ctx, *filePath, *address)
51+
if err != nil {
52+
return err
53+
}
54+
55+
fmt.Fprintf(os.Stdout, "sent %d bytes to %s\n", result.BytesSent, result.RemoteAddr)
56+
return nil
57+
}
58+
59+
func printUsage(w io.Writer) {
60+
fmt.Fprintln(w, "VX6")
61+
fmt.Fprintln(w)
62+
fmt.Fprintln(w, "Usage:")
63+
fmt.Fprintln(w, " vx6 send --file <path> --addr [ipv6]:port")
64+
}

internal/transfer/send.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package transfer
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net"
7+
"os"
8+
)
9+
10+
type SendResult struct {
11+
BytesSent int64
12+
RemoteAddr string
13+
}
14+
15+
func SendFile(ctx context.Context, filePath, address string) (SendResult, error) {
16+
if err := validateIPv6Address(address); err != nil {
17+
return SendResult{}, err
18+
}
19+
20+
file, err := os.Open(filePath)
21+
if err != nil {
22+
return SendResult{}, fmt.Errorf("open file: %w", err)
23+
}
24+
defer file.Close()
25+
26+
var dialer net.Dialer
27+
conn, err := dialer.DialContext(ctx, "tcp6", address)
28+
if err != nil {
29+
return SendResult{}, fmt.Errorf("dial tcp6 %s: %w", address, err)
30+
}
31+
defer conn.Close()
32+
33+
written, err := file.WriteTo(conn)
34+
if err != nil {
35+
return SendResult{}, fmt.Errorf("stream file to %s: %w", address, err)
36+
}
37+
38+
return SendResult{
39+
BytesSent: written,
40+
RemoteAddr: conn.RemoteAddr().String(),
41+
}, nil
42+
}
43+
44+
func validateIPv6Address(address string) error {
45+
host, _, err := net.SplitHostPort(address)
46+
if err != nil {
47+
return fmt.Errorf("invalid address %q: %w", address, err)
48+
}
49+
50+
ip := net.ParseIP(host)
51+
if ip == nil || ip.To4() != nil {
52+
return fmt.Errorf("address %q is not an IPv6 endpoint", address)
53+
}
54+
55+
return nil
56+
}

internal/transfer/send_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package transfer
2+
3+
import "testing"
4+
5+
func TestValidateIPv6Address(t *testing.T) {
6+
t.Parallel()
7+
8+
tests := []struct {
9+
name string
10+
address string
11+
wantErr bool
12+
}{
13+
{
14+
name: "valid ipv6",
15+
address: "[2001:db8::1]:4242",
16+
},
17+
{
18+
name: "ipv4 rejected",
19+
address: "127.0.0.1:4242",
20+
wantErr: true,
21+
},
22+
{
23+
name: "missing brackets rejected",
24+
address: "2001:db8::1:4242",
25+
wantErr: true,
26+
},
27+
}
28+
29+
for _, tc := range tests {
30+
tc := tc
31+
t.Run(tc.name, func(t *testing.T) {
32+
t.Parallel()
33+
34+
err := validateIPv6Address(tc.address)
35+
if tc.wantErr && err == nil {
36+
t.Fatal("expected error, got nil")
37+
}
38+
if !tc.wantErr && err != nil {
39+
t.Fatalf("expected nil error, got %v", err)
40+
}
41+
})
42+
}
43+
}

0 commit comments

Comments
 (0)