init v0.1.0

This commit is contained in:
Sudo-Ivan
2024-12-30 01:56:25 -06:00
commit 668d7c56b5
27 changed files with 3921 additions and 0 deletions

137
cmd/client/client.go Normal file
View File

@@ -0,0 +1,137 @@
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"os/signal"
"strings"
"syscall"
"github.com/Sudo-Ivan/reticulum-go/internal/config"
"github.com/Sudo-Ivan/reticulum-go/pkg/common"
"github.com/Sudo-Ivan/reticulum-go/pkg/identity"
"github.com/Sudo-Ivan/reticulum-go/pkg/transport"
"github.com/Sudo-Ivan/reticulum-go/pkg/destination"
)
var (
configPath = flag.String("config", "", "Path to config file")
targetHash = flag.String("target", "", "Target destination hash")
)
func main() {
flag.Parse()
var cfg *common.ReticulumConfig
var err error
if *configPath == "" {
cfg, err = config.InitConfig()
if err != nil {
log.Fatalf("Failed to initialize config: %v", err)
}
} else {
cfg, err = config.LoadConfig(*configPath)
if err != nil {
log.Fatalf("Failed to load config: %v", err)
}
}
// Enable transport by default for client
cfg.EnableTransport = true
// Initialize transport
transport, err := transport.NewTransport(cfg)
if err != nil {
log.Fatalf("Failed to initialize transport: %v", err)
}
defer transport.Close()
// If target specified, establish connection
if *targetHash != "" {
destHash, err := identity.HashFromHex(*targetHash)
if err != nil {
log.Fatalf("Invalid destination hash: %v", err)
}
// Request path if needed
if !transport.HasPath(destHash) {
fmt.Println("Requesting path to destination...")
if err := transport.RequestPath(destHash, "", nil, true); err != nil {
log.Fatalf("Failed to request path: %v", err)
}
}
// Get destination identity
destIdentity, err := identity.Recall(destHash)
if err != nil {
log.Fatalf("Failed to recall identity: %v", err)
}
// Create destination
dest, err := destination.New(
destIdentity,
destination.OUT,
destination.SINGLE,
"client",
"direct",
)
if err != nil {
log.Fatalf("Failed to create destination: %v", err)
}
// Enable and configure ratchets
dest.SetRetainedRatchets(destination.RATCHET_COUNT)
dest.SetRatchetInterval(destination.RATCHET_INTERVAL)
dest.EnforceRatchets()
// Create link
link := transport.NewLink(dest.Hash(), func() {
fmt.Println("Link established")
}, func() {
fmt.Println("Link closed")
})
defer link.Teardown()
// Set packet callback
link.SetPacketCallback(func(data []byte) {
fmt.Printf("Received: %s\n", string(data))
})
// Start interactive loop
go interactiveLoop(link)
} else {
fmt.Println("No target specified. Use -target <hash> to connect to a destination")
return
}
// Wait for interrupt
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
}
func interactiveLoop(link *transport.Link) {
reader := bufio.NewReader(os.Stdin)
for {
fmt.Print("> ")
input, err := reader.ReadString('\n')
if err != nil {
fmt.Printf("Error reading input: %v\n", err)
continue
}
input = strings.TrimSpace(input)
if input == "quit" || input == "exit" {
return
}
if err := link.Send([]byte(input)); err != nil {
fmt.Printf("Failed to send: %v\n", err)
}
}
}

117
cmd/reticulum/main.go Normal file
View File

@@ -0,0 +1,117 @@
package main
import (
"log"
"os"
"os/signal"
"syscall"
"github.com/Sudo-Ivan/reticulum-go/internal/config"
"github.com/Sudo-Ivan/reticulum-go/pkg/transport"
"github.com/Sudo-Ivan/reticulum-go/pkg/interfaces"
)
type Reticulum struct {
config *config.ReticulumConfig
transport *transport.Transport
}
func NewReticulum(cfg *config.ReticulumConfig) (*Reticulum, error) {
if cfg == nil {
cfg = config.DefaultConfig()
}
// Initialize transport
t, err := transport.NewTransport(cfg)
if err != nil {
return nil, err
}
return &Reticulum{
config: cfg,
transport: t,
}, nil
}
func (r *Reticulum) Start() error {
// Initialize interfaces based on config
for _, ifaceConfig := range r.config.Interfaces {
var iface interfaces.Interface
switch ifaceConfig.Type {
case "tcp":
client, err := interfaces.NewTCPClient(
ifaceConfig.Name,
ifaceConfig.Address,
ifaceConfig.Port,
ifaceConfig.KISSFraming,
ifaceConfig.I2PTunneled,
)
if err != nil {
log.Printf("Failed to create TCP interface %s: %v", ifaceConfig.Name, err)
continue
}
iface = client
case "tcpserver":
server, err := interfaces.NewTCPServer(
ifaceConfig.Name,
ifaceConfig.Address,
ifaceConfig.Port,
ifaceConfig.PreferIPv6,
ifaceConfig.I2PTunneled,
)
if err != nil {
log.Printf("Failed to create TCP server interface %s: %v", ifaceConfig.Name, err)
continue
}
iface = server
default:
log.Printf("Unknown interface type: %s", ifaceConfig.Type)
continue
}
// Set packet callback to transport
iface.SetPacketCallback(r.transport.HandlePacket)
}
log.Printf("Reticulum initialized with config at: %s", r.config.ConfigPath)
return nil
}
func (r *Reticulum) Stop() error {
if err := r.transport.Close(); err != nil {
return err
}
return nil
}
func main() {
// Initialize configuration
cfg, err := config.InitConfig()
if err != nil {
log.Fatalf("Failed to initialize config: %v", err)
}
// Create new reticulum instance
r, err := NewReticulum(cfg)
if err != nil {
log.Fatalf("Failed to create Reticulum instance: %v", err)
}
// Start reticulum
if err := r.Start(); err != nil {
log.Fatalf("Failed to start Reticulum: %v", err)
}
// Wait for interrupt signal
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
// Clean shutdown
if err := r.Stop(); err != nil {
log.Printf("Error during shutdown: %v", err)
}
}