27 Commits

Author SHA1 Message Date
decentral1se 412c2f48ea feat: better error handling 2026-07-23 17:57:42 +02:00
decentral1se b60f37f85e fix: build examples from local HEAD 2026-07-17 13:50:57 +02:00
decentral1se 68ad06fe2a feat: v1.1.0 bindings
See https://github.com/n0-computer/iroh-ffi/releases/tag/v1.1.0
2026-07-17 13:08:20 +02:00
decentral1se 14a1ebf8d8 docs(README): more known issues 2026-07-03 10:59:14 +02:00
decentral1se c4522df071 docs(iroh-relay): how to use own relay 2026-07-03 10:30:33 +02:00
decentral1se 0858f533fa docs: point to iroh-tracker 2026-07-02 08:46:50 +02:00
decentral1se b2c2f9363c feat: apache2 & mit licenses 2026-06-28 00:11:53 +02:00
decentral1se c668dd01d8 docs: add godocs 2026-06-26 15:42:01 +02:00
decentral1se d8668c7949 chore: ignore timeserve and sort 2026-06-26 06:53:38 +02:00
decentral1se f3c78b79ff docs(README): bindings 2026-06-26 06:43:08 +02:00
decentral1se 0da4eb7dd2 chore: update libs 2026-06-26 06:41:22 +02:00
decentral1se e7f90ff4f6 feat: add aarch64-unknown-linux-musl 2026-06-26 06:40:52 +02:00
decentral1se c151d398bc docs(README): share known state 2026-06-26 06:31:43 +02:00
decentral1se 7162741cb0 fix: use forked iroh-ffi for now 2026-06-26 06:03:22 +02:00
decentral1se 6be98f24b7 chore: remove unused file 2026-06-26 06:03:03 +02:00
decentral1se fcd131a0e4 chore: formatting and minor typos 2026-06-26 06:02:41 +02:00
cblgh a2494e624c examples(connect-desktop): update title 2026-06-25 17:26:14 +02:00
cblgh a163d5bf07 examples(connect-desktop): improve description 2026-06-25 17:24:48 +02:00
cblgh d63e45f746 Merge branch 'main' of ssh://git.coopcloud.tech:2222/decentral1se/iroh-go 2026-06-25 17:18:10 +02:00
cblgh 1affee6df6 add connect-desktop example 2026-06-25 17:17:46 +02:00
decentral1se caf52e915d Merge pull request 'Add timeserve example to demonstrate writing to multiple live peers' (#3) from cblgh/iroh-go:main into main
Reviewed-on: decentral1se/iroh-go#3
2026-06-25 14:05:05 +00:00
cblgh 186f3ac9aa fmt 2026-06-25 15:18:55 +02:00
cblgh 931465c83e examples: add timeserve to demonstrate writing to multiple live peers 2026-06-25 15:13:36 +02:00
decentral1se 1a469c4ae9 fix(connect): title 2026-06-23 22:49:24 +02:00
decentral1se 23211c0ba6 docs(examples): clarifying purposes 2026-06-23 22:48:47 +02:00
decentral1se 1c18b9265f fix: ignore bins, sort 2026-06-23 22:41:59 +02:00
decentral1se e9a0e0be63 Merge pull request 'Add pairchat example' (#2) from cblgh/iroh-go:examples-round-two into main
Reviewed-on: decentral1se/iroh-go#2
Reviewed-by: decentral1se <2+decentral1se@noreply.git.coopcloud.tech>
2026-06-23 20:36:16 +00:00
41 changed files with 1838 additions and 60 deletions
+8 -1
View File
@@ -1,2 +1,9 @@
iroh-go/target/
.*.sw[a-z]
examples/connect-desktop/build
examples/connect-desktop/frontend/dist
examples/connect-desktop/frontend/wailsjs
examples/connect/connect
examples/errors/errors
examples/pairchat/pairchat
examples/timeserve/timeserve
iroh-go/target/
+84 -10
View File
@@ -1,18 +1,92 @@
# iroh-go
# `iroh-go`
> **WARNING** Extremely Experimental ™️
> **WARNING** Highly Experimental ™️
Go bindings for [`iroh-ffi`](https://github.com/n0-computer/iroh-ffi). They're
ready for testing but due to [this
issue](https://github.com/n0-computer/iroh-ffi/issues/248#issuecomment-4777541073),
there are surely unknown horrors awaiting you deep inside the `staticlib`. It's
a work in progress but you can yeet some bytes across the interwebz Right Now
Go FFI bindings for [`iroh`](https://iroh.computer) via
[`iroh-ffi`](https://github.com/n0-computer/iroh-ffi).
## Motivation
The goal is to provide, as far as possible, seamless "just `go build` it"
support for Go iroh hackers without requiring them to deal with shared
libraries, the Rust toolchain or a deepdive in how FFI works. The current
approach is to embed `libiroh` as a `staticlib` built with Rust for each
platform. We use [`musl`](https://musl.libc.org) to avoid `glibc`
incompatibilities on different linux systems. It's then possible to build a
static binary with `go build` or [with
Zig](https://dev.to/kristoff/zig-makes-go-cross-compilation-just-work-29ho).
`iroh-go` does require `CGO_ENABLED=1`.
## Platform support
* `x86_64-unknown-linux-musl`
* `aarch64-unknown-linux-musl`
## Documentation
See [`docs.rs`](https://docs.rs/iroh/1.0.0/iroh/) for the original Rust API
documentation. The exposed Go API is 1:1. Here's the Go bindings documentation
on [`godocs.io`](https://godocs.io/git.coopcloud.tech/decentral1se/iroh-go).
## Examples
See [`examples`](./examples).
## Rebuild `iroh-ffi`
## Run your own `iroh-relay`
`./scripts/generate.sh`
See [`iroh-relay`](https://git.coopcloud.tech/decentral1se/iroh-relay) if you
want more small footprint static binary goodness. You can also make use of the
upstream provided docker image: `n0computer/iroh-relay`.
### Local hacking
First, run `iroh-relay` in development mode with noisy logging.
```
RUST_LOG=info,iroh_relay=debug ./iroh-relay --dev
```
You can then use `http://localhost:3340` as the default location of your own
relay in the construction of your endpoint as follows. Once you create an
endpoint, you should see your relay respond locally with corresponding logs.
```go
preset := iroh.PresetN0DisableRelay()
relay, _ := iroh.RelayModeCustomFromUrls([]string{"http://localhost:3340"})
opts := iroh.EndpointOptions{
Preset: &preset,
RelayMode: &relay,
// ...moar config...
}
```
## Generate bindings
See [`iroh-go`](./iroh-go) for the Rust toolchain configuration. Run
`./scripts/generate.sh` to build a new set of libraries which end up vendored
in [`libs`](./libs).
## Who is using it?
* [`iroh-tracker`](https://git.coopcloud.tech/cblgh/iroh-tracker)
## Known issues
* We need to patch the upstream `iroh-ffi` `endpoint.rs` to fix an
incompatibility with
[`uniffi-bindgen-go`](https://github.com/NordSecurity/uniffi-bindgen-go). See
[this
commit](https://github.com/decentral1se/iroh-ffi/commit/3e102569e1c348480416a9b05cf020760f607dfe)
for more.
* We need to patch the upstream `iroh-ffi` `Cargo.toml` to remove the
`crate-type` configuration when runnings builds here. See [this
commit](https://github.com/decentral1se/iroh-ffi/commit/207e5d7cd7dee6eab350d3aad85029431a63ca3f)
for more.
* Error handling is extremely inconvenient due to
[`iroh-ffi#263`](https://github.com/n0-computer/iroh-ffi/issues/263).
Proposals for improvement are very welcome.
## Licenses
Apache 2.0 & MIT, following the upstream licensing choices in
[`iroh-ffi`](https://github.com/n0-computer/iroh-ffi).
+107
View File
@@ -0,0 +1,107 @@
package iroh_ffi
import (
"errors"
"fmt"
)
// As casts an error to IrohError and back, extracting relevant error message
// information. It is a single argument variant of the typical errors.As API
// because we always expect an IrohError back from the iroh FFI bindings. The
// bindings do not return an IrohError for reasons and will not for the
// forseeable future due to API stability guarantees.
func As(err error) error {
if err, ok := errors.AsType[IrohError](err); ok {
return errors.New(fmt.Sprintf("%s: %s", err.Message(), err.DebugMessage()))
}
return err
}
// Is suports matching against the stable iroh error taxonomy using the error
// sentinel construction below. The caller must pass in a valid error sentinel
// specified by this library, e.g. iroh.BindError.
func (e *IrohError) Is(target error) bool {
if err, ok := errors.AsType[sentinel](target); ok {
return uint(e.Kind()) == err.kind
}
return false
}
type sentinel struct {
kind uint
message string
}
func (s sentinel) Error() string {
return s.message
}
var InvalidInputError error = sentinel{
kind: uint(IrohErrorKindInvalidInput),
message: "iroh: invalid input supplied by the caller",
}
var BindError error = sentinel{
kind: uint(IrohErrorKindBind),
message: "iroh: failure while initiating or completing an outgoing connection",
}
var ConnectError error = sentinel{
kind: uint(IrohErrorKindConnect),
message: "iroh: failure while initiating or completing an outgoing connectio",
}
var ConnectionError error = sentinel{
kind: uint(IrohErrorKindConnection),
message: "iroh: an established connection failed or closed unexpectedly",
}
var AlpnError error = sentinel{
kind: uint(IrohErrorKindAlpn),
message: "iroh: ALPN negotiation or lookup failed",
}
var KeyParsingError error = sentinel{
kind: uint(IrohErrorKindKeyParsing),
message: "iroh: endpoint id / public key parsing failed",
}
var TicketParsingError error = sentinel{
kind: uint(IrohErrorKindKeyParsing),
message: "iroh: ticket parsing failed",
}
var RelayError error = sentinel{
kind: uint(IrohErrorKindRelay),
message: "iroh: stream read/write/control operation failed",
}
var StreamError error = sentinel{
kind: uint(IrohErrorKindStream),
message: "iroh: datagram send/receive operation failed",
}
var DatagramError error = sentinel{
kind: uint(IrohErrorKindDatagram),
message: "iroh: datagram send/receive operation failed",
}
var FCallbackError error = sentinel{
kind: uint(IrohErrorKindCallback),
message: "iroh: foreign callback failed",
}
var ClosedError error = sentinel{
kind: uint(IrohErrorKindClosed),
message: "iroh: operation was attempted on a closed stream/connection/resource",
}
var TimeoutError error = sentinel{
kind: uint(IrohErrorKindTimeout),
message: "iroh: operation timed out",
}
var InternalError error = sentinel{
kind: uint(IrohErrorKindInternal),
message: "iroh: unclassified internal error",
}
+3
View File
@@ -0,0 +1,3 @@
build/bin
node_modules
frontend/dist
+61
View File
@@ -0,0 +1,61 @@
# connect-desktop
A version of [`../connect`](../connect) as a desktop application. On running
the desktop application, an Iroh endpoint id will be displayed. This id can be
plugged into a terminal running the [`../connect`](../connect) example as a
sender. What the sender types in the terminal will appear in the
connect-desktop application window.
## Dependencies
* Wails v2.10.2 (old version, haven't tried on a newer yet - hopefully works there too!)
* Vite v3.0.7
* Go v1.18
* npm v10.2+
* node v20.11+
**Getting setup**
* Install node and golang
Install Wails:
```
go install github.com/wailsapp/wails/v2/cmd/wails@v2.10.2 // for tested version
// OR: go install github.com/wailsapp/wails/v2/cmd/wails@latest // for latest
// then install frontend dependency
cd frontend
npm i
```
## Running in development mode
```
wails dev
```
## Build a binary
```
wails build .
```
## Listener (this example)
```
./connect-desktop
```
## Terminal 2 (sender)
Run [`../connect`](../connect) in a terminal and connect to the endpoint id
displayed by the listener.
```
./connect -endpoint <endpoint-id>
```
You'll see a connection notice if the two endpoints manage to connect to each
other. You can type messages in the sender terminal and they will be shown on
the screen of the desktop app.
+94
View File
@@ -0,0 +1,94 @@
package main
import (
"context"
"fmt"
"strings"
iroh "git.coopcloud.tech/decentral1se/iroh-go"
"github.com/wailsapp/wails/v2/pkg/runtime"
)
var (
alpn = []byte("iroh-go-hello-world/0")
frameSize uint32 = 256
endpointPeer *string
)
func check(err error) {
if err != nil {
irohErr := err.(*iroh.IrohError)
panic(irohErr.Message())
}
}
// App struct
type App struct {
ctx context.Context
endpoint *iroh.Endpoint
}
// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
}
// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
preset := iroh.PresetN0()
opts := iroh.EndpointOptions{
Preset: &preset,
Alpns: &[][]byte{alpn},
}
endpoint, err := iroh.EndpointBind(opts)
check(err)
endpoint.Online()
a.endpoint = endpoint
listen(a.ctx, a.endpoint)
}
func (a *App) GetEndpointIDString() string {
return a.endpoint.Id().String()
}
func listen(ctx context.Context, e *iroh.Endpoint) {
for {
incoming := *e.AcceptNext()
go handleIncoming(ctx, incoming)
}
}
func handleIncoming (ctx context.Context, incoming *iroh.Incoming) {
accepting, err := incoming.Accept()
check(err)
conn, err := accepting.Connect()
check(err)
stream, err := conn.AcceptBi()
check(err)
recv := stream.Recv()
for {
frame, err := recv.Read(frameSize)
// handle timeout
if err != nil {
irohErr := err.(*iroh.IrohError)
errMsg := irohErr.Message()
if strings.HasPrefix(errMsg, "ConnectionLost") {
fmt.Println("lost connection")
break
} else {
check(err)
}
}
runtime.EventsEmit(ctx, "data", map[string]interface{}{
"data": string(frame),
})
}
}
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>go-iroh-desktop-example</title>
</head>
<body>
<div id="app"></div>
<script src="./src/main.js" type="module"></script>
</body>
</html>
+627
View File
@@ -0,0 +1,627 @@
{
"name": "frontend",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "frontend",
"version": "0.0.0",
"devDependencies": {
"vite": "^3.0.7"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
"integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
"integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
"cpu": [
"loong64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/esbuild": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
"integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
"dev": true,
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/android-arm": "0.15.18",
"@esbuild/linux-loong64": "0.15.18",
"esbuild-android-64": "0.15.18",
"esbuild-android-arm64": "0.15.18",
"esbuild-darwin-64": "0.15.18",
"esbuild-darwin-arm64": "0.15.18",
"esbuild-freebsd-64": "0.15.18",
"esbuild-freebsd-arm64": "0.15.18",
"esbuild-linux-32": "0.15.18",
"esbuild-linux-64": "0.15.18",
"esbuild-linux-arm": "0.15.18",
"esbuild-linux-arm64": "0.15.18",
"esbuild-linux-mips64le": "0.15.18",
"esbuild-linux-ppc64le": "0.15.18",
"esbuild-linux-riscv64": "0.15.18",
"esbuild-linux-s390x": "0.15.18",
"esbuild-netbsd-64": "0.15.18",
"esbuild-openbsd-64": "0.15.18",
"esbuild-sunos-64": "0.15.18",
"esbuild-windows-32": "0.15.18",
"esbuild-windows-64": "0.15.18",
"esbuild-windows-arm64": "0.15.18"
}
},
"node_modules/esbuild-android-64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
"integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-android-arm64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
"integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-darwin-64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
"integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-darwin-arm64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
"integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-freebsd-64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
"integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-freebsd-arm64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
"integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-linux-32": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
"integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-linux-64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
"integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-linux-arm": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
"integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
"cpu": [
"arm"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-linux-arm64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
"integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-linux-mips64le": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
"integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
"cpu": [
"mips64el"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-linux-ppc64le": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
"integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
"cpu": [
"ppc64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-linux-riscv64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
"integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
"cpu": [
"riscv64"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-linux-s390x": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
"integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
"cpu": [
"s390x"
],
"dev": true,
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-netbsd-64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
"integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-openbsd-64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
"integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-sunos-64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
"integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-windows-32": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
"integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
"cpu": [
"ia32"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-windows-64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
"integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
"cpu": [
"x64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/esbuild-windows-arm64": {
"version": "0.15.18",
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
"integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
"cpu": [
"arm64"
],
"dev": true,
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/is-core-module": {
"version": "2.16.2",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
"integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
"dev": true,
"dependencies": {
"hasown": "^2.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/nanoid": {
"version": "3.3.15",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
"integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true
},
"node_modules/postcss": {
"version": "8.5.15",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
"integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"nanoid": "^3.3.12",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/resolve": {
"version": "1.22.12",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
"integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
"dev": true,
"dependencies": {
"es-errors": "^1.3.0",
"is-core-module": "^2.16.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/rollup": {
"version": "2.80.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.80.0.tgz",
"integrity": "sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=10.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/vite": {
"version": "3.2.11",
"resolved": "https://registry.npmjs.org/vite/-/vite-3.2.11.tgz",
"integrity": "sha512-K/jGKL/PgbIgKCiJo5QbASQhFiV02X9Jh+Qq0AKCRCRKZtOTVi4t6wh75FDpGf2N9rYOnzH87OEFQNaFy6pdxQ==",
"dev": true,
"dependencies": {
"esbuild": "^0.15.9",
"postcss": "^8.4.18",
"resolve": "^1.22.1",
"rollup": "^2.79.1"
},
"bin": {
"vite": "bin/vite.js"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
},
"peerDependencies": {
"@types/node": ">= 14",
"less": "*",
"sass": "*",
"stylus": "*",
"sugarss": "*",
"terser": "^5.4.0"
},
"peerDependenciesMeta": {
"@types/node": {
"optional": true
},
"less": {
"optional": true
},
"sass": {
"optional": true
},
"stylus": {
"optional": true
},
"sugarss": {
"optional": true
},
"terser": {
"optional": true
}
}
}
}
}
@@ -0,0 +1,13 @@
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^3.0.7"
}
}
+1
View File
@@ -0,0 +1 @@
5fbf12469d224a93954efecb5886e8a6
@@ -0,0 +1,41 @@
import './style.css';
import { GetEndpointIDString } from '../wailsjs/go/main/App';
import { EventsOn } from "../wailsjs/runtime/runtime";
document.querySelector('#app').innerHTML = `
<div class="result" id="result">loading endpoint id...</div>
<div class="messages" id="messages"></div>
`;
let resultElement = document.getElementById("result");
EventsOn("data", ({ data }) => {
const m = document.getElementById("messages")
// append to previous output
m.innerText = m.innerText + data + "\n"
})
function init () {
// checky little 1s wait just to let the iroh bits properly initialize
setTimeout(() => {
try {
GetEndpointIDString()
.then((result) => {
resultElement.innerText = `endpoint id is ${result}`;
})
.catch((err) => {
console.error(err);
});
} catch (err) {
console.error(err);
}
}, 1000)
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init)
} else {
init()
}
@@ -0,0 +1,20 @@
html {
text-align: center;
background: black;
color: white;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
}
#app {
display: grid;
grid-template-rows: 5rem 1fr;
justify-items: center;
align-items: center;
height: 100vh;
}
+40
View File
@@ -0,0 +1,40 @@
module go-iroh-desktop-example
go 1.26.1
require (
git.coopcloud.tech/decentral1se/iroh-go v0.0.0-20260623204924-1a469c4ae933
github.com/wailsapp/wails/v2 v2.10.2
)
require (
github.com/bep/debounce v1.2.1 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
github.com/labstack/echo/v4 v4.13.3 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/leaanthony/go-ansi-parser v1.6.1 // indirect
github.com/leaanthony/gosod v1.0.4 // indirect
github.com/leaanthony/slicer v1.6.0 // indirect
github.com/leaanthony/u v1.1.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/samber/lo v1.49.1 // indirect
github.com/tkrajina/go-reflector v0.5.8 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/wailsapp/go-webview2 v1.0.19 // indirect
github.com/wailsapp/mimetype v1.4.1 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
)
replace git.coopcloud.tech/decentral1se/iroh-go => ../../
+81
View File
@@ -0,0 +1,81 @@
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
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/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc=
github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA=
github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A=
github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU=
github.com/leaanthony/gosod v1.0.4 h1:YLAbVyd591MRffDgxUOU1NwLhT9T1/YiwjKZpkNFeaI=
github.com/leaanthony/gosod v1.0.4/go.mod h1:GKuIL0zzPj3O1SdWQOdgURSuhkF+Urizzxh26t9f1cw=
github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js=
github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8=
github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M=
github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tkrajina/go-reflector v0.5.8 h1:yPADHrwmUbMq4RGEyaOUpz2H90sRsETNVpjzo3DLVQQ=
github.com/tkrajina/go-reflector v0.5.8/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyTImA6NU=
github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
github.com/wailsapp/wails/v2 v2.10.2 h1:29U+c5PI4K4hbx8yFbFvwpCuvqK9VgNv8WGobIlKlXk=
github.com/wailsapp/wails/v2 v2.10.2/go.mod h1:XuN4IUOPpzBrHUkEd7sCU5ln4T/p1wQedfxP7fKik+4=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+36
View File
@@ -0,0 +1,36 @@
package main
import (
"embed"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
var assets embed.FS
func main() {
// Create an instance of the app structure
app := NewApp()
// Create application with options
err := wails.Run(&options.App{
Title: "go-iroh-desktop-example",
Width: 1024,
Height: 768,
AssetServer: &assetserver.Options{
Assets: assets,
},
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
app,
},
})
if err != nil {
println("Error:", err.Error())
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"$schema": "https://wails.io/schemas/config.v2.json",
"name": "connect-desktop-example",
"outputfilename": "connect-desktop-example",
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
"frontend:dev:serverUrl": "auto",
"author": {
"name": "cblgh",
"email": "source-code@cblgh.org"
}
}
+4 -1
View File
@@ -1,4 +1,7 @@
t connect
# connect
A simple connection test where one peer can send and the other can receive. See
[`../pairchat`](../pairchat) for a more complete bidirectional example.
## Build a binary
+2 -2
View File
@@ -4,9 +4,9 @@ import (
"bufio"
"flag"
"fmt"
"strings"
"os"
"os/signal"
"strings"
"syscall"
iroh "git.coopcloud.tech/decentral1se/iroh-go"
@@ -70,7 +70,7 @@ func listen(e *iroh.Endpoint) {
}
}
func handleIncoming (incoming *iroh.Incoming) {
func handleIncoming(incoming *iroh.Incoming) {
accepting, err := incoming.Accept()
check(err)
+7
View File
@@ -0,0 +1,7 @@
module git.coopcloud.tech/decentral1se/iroh-go/examples/connect
go 1.26.1
require git.coopcloud.tech/decentral1se/iroh-go v0.0.0-20260717110820-68ad06fe2a25
replace git.coopcloud.tech/decentral1se/iroh-go => ../../
View File
+5
View File
@@ -0,0 +1,5 @@
# errors
How to deal with error handling in a convenient way. See
[`#263`](https://github.com/n0-computer/iroh-ffi/issues/263) for the juicy
details.
+37
View File
@@ -0,0 +1,37 @@
package main
import (
"errors"
iroh "git.coopcloud.tech/decentral1se/iroh-go"
)
func main() {
preset := iroh.PresetN0DisableRelay()
opts := iroh.EndpointOptions{
Preset: &preset,
Alpns: &[][]byte{[]byte("iroh-go-errors/0")},
}
endpoint, err := iroh.EndpointBind(opts)
// BEGIN API PREVIEW ZONE
// 1. convert error to IrohError with As
// bring IrohError.Message/DebugMessage back
// maintain `err != nil` compatibility
if err := iroh.As(err); err != nil {
panic(err)
}
// 1. no As machinery required
// sentinel check with errors.Is support
// works like usual `err`
if err != nil && errors.Is(err, iroh.BindError) {
panic(err)
}
// END API PREVIEW ZONE
endpoint.Online()
}
+7
View File
@@ -0,0 +1,7 @@
module git.coopcloud.tech/decentral1se/iroh-go/examples/errors
go 1.26.1
require git.coopcloud.tech/decentral1se/iroh-go v0.0.0-20260717110820-68ad06fe2a25
replace git.coopcloud.tech/decentral1se/iroh-go => ../../
View File
+3 -3
View File
@@ -1,8 +1,8 @@
# pairchat
This is a more complicated version of `examples/connect` which allows the listener to also
write back to the sender. The result is a basic pairwise (only 2 peers can connect at once)
chat program.
This is a more complicated version of [`../connect`](../connect) which allows
the listener to also write back to the sender. The result is a basic pairwise
(only 2 peers can connect at once) chat program.
## Build a binary
+7
View File
@@ -0,0 +1,7 @@
module git.coopcloud.tech/decentral1se/iroh-go/examples/pairchat
go 1.26.1
require git.coopcloud.tech/decentral1se/iroh-go v0.0.0-20260717110820-68ad06fe2a25
replace git.coopcloud.tech/decentral1se/iroh-go => ../../
+3 -4
View File
@@ -4,9 +4,9 @@ import (
"bufio"
"flag"
"fmt"
"strings"
"os"
"os/signal"
"strings"
"syscall"
iroh "git.coopcloud.tech/decentral1se/iroh-go"
@@ -61,7 +61,7 @@ func listen(e *iroh.Endpoint) {
}
}
func handleIncoming (incoming *iroh.Incoming) {
func handleIncoming(incoming *iroh.Incoming) {
accepting, err := incoming.Accept()
check(err)
@@ -77,7 +77,7 @@ func handleIncoming (incoming *iroh.Incoming) {
go handleReading(recv, done)
}
func handleInput (stream *iroh.BiStream, done chan struct{}) {
func handleInput(stream *iroh.BiStream, done chan struct{}) {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
if line := scanner.Text(); line != "" {
@@ -118,7 +118,6 @@ func handleReading(recv *iroh.RecvStream, done chan struct{}) {
close(done)
}
func main() {
parseFlags()
+43
View File
@@ -0,0 +1,43 @@
# timeserve
This example demonstrates that an endpoint can support multiple live connections at once. The
endpoint aka listener writes the time, once every 2 seconds, to every connected peer.
Try connecting to a running listener with 3 (or more!) receiver peers at once.
## Build a binary
```
go build --ldflags '-linkmode external -extldflags=-static -s -w' ./timeserve.go
```
If you run into `glibc` incompatibility, you can compile with `zig`/`musl`.
```
CC="zig cc -target x86_64-linux-musl -lunwind" \
CGO_ENABLED=1 \
CGO_LDFLAGS="-static" \
GOOS=linux GOARCH=amd64 \
go build -v -a -ldflags '-extldflags "-static"' ./timeserve.go
```
## Terminal 1 (listener)
```
./timeserve
```
## Terminal 2 (receiver)
```
./timeserve -endpoint <endpoint-id>
```
## Terminal 3 (receiver)
```
./timeserve -endpoint <endpoint-id>
```
You'll see a connection notice if a receiver peer manages to connect to the listener.
Receivers (Terminal 2 and Terminal 3) will display the time sent by the listener (Terminal 1).
+7
View File
@@ -0,0 +1,7 @@
module git.coopcloud.tech/decentral1se/iroh-go/examples/timeserve
go 1.26.1
require git.coopcloud.tech/decentral1se/iroh-go v0.0.0-20260717110820-68ad06fe2a25
replace git.coopcloud.tech/decentral1se/iroh-go => ../../
+139
View File
@@ -0,0 +1,139 @@
package main
import (
"flag"
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"time"
iroh "git.coopcloud.tech/decentral1se/iroh-go"
)
var (
alpn = []byte("iroh-go-timeserve/0")
frameSize uint32 = 256
endpointPeer *string
)
func check(err error) {
if err != nil {
irohErr := err.(*iroh.IrohError)
panic(irohErr.Message())
}
}
func awaitInterrupt() {
done := make(chan os.Signal, 1)
signal.Notify(done, syscall.SIGINT, syscall.SIGTERM)
<-done
os.Exit(0)
}
func parseFlags() {
endpointPeer = flag.String("endpoint", "", "endpoint id of peer")
flag.Parse()
}
func receiver(e *iroh.Endpoint, id string) {
remote, err := iroh.EndpointIdFromString(id)
check(err)
addr := iroh.NewEndpointAddr(remote, nil, nil)
conn, err := e.Connect(addr, alpn)
check(err)
// from docs:
// "The peer that calls open_bi must write to its SendStream before the peer Connection is able to accept the stream
// using accept_bi()"
// https://docs.rs/iroh/latest/iroh/endpoint/struct.Connection.html#method.accept_bi
stream, err := conn.OpenBi()
check(err)
// NOTE: for the other peer to realize the bidi stream is open, you have to send some data! the data sent cannot be
// the empty string ""; empty string == no data
err = stream.Send().WriteAll([]byte{1})
check(err)
handleReading(stream.Recv())
}
func handleReading(recv *iroh.RecvStream) {
for {
frame, err := recv.Read(frameSize)
if checkForTimeout(err) {
break
}
fmt.Println(string(frame))
check(err)
}
}
func checkForTimeout(err error) bool {
// handle timeout
if err != nil {
irohErr := err.(*iroh.IrohError)
errMsg := irohErr.Message()
if strings.HasPrefix(errMsg, "ConnectionLost") {
fmt.Println("lost connection")
return true
} else {
// panics and exits bc unhandled err
check(err)
}
}
return false
}
func listen(e *iroh.Endpoint) {
for {
incoming := *e.AcceptNext()
fmt.Println("new connection")
go handleIncoming(incoming)
}
}
func handleIncoming(incoming *iroh.Incoming) {
accepting, err := incoming.Accept()
check(err)
conn, err := accepting.Connect()
check(err)
stream, err := conn.AcceptBi()
check(err)
for {
err := stream.Send().WriteAll([]byte(time.Now().Format(time.DateTime)))
if checkForTimeout(err) {
break
}
// prints every two seconds (not for any technical reason, 1/sec just feels hectic!)
<-time.After(2 * time.Second)
}
}
func main() {
parseFlags()
preset := iroh.PresetN0()
opts := iroh.EndpointOptions{
Preset: &preset,
Alpns: &[][]byte{alpn},
}
endpoint, err := iroh.EndpointBind(opts)
check(err)
endpoint.Online()
if *endpointPeer == "" {
fmt.Println("this endpoint is online and listening! use this id to connect via a peer:")
fmt.Printf("timeserve\n -endpoint %s\n", endpoint.Id())
go func() { listen(endpoint) }()
} else {
go func() { receiver(endpoint, *endpointPeer) }()
}
awaitInterrupt()
}
+20 -19
View File
@@ -432,9 +432,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chacha20"
version = "0.10.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601"
checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
@@ -1787,7 +1787,8 @@ dependencies = [
[[package]]
name = "iroh-ffi"
version = "1.0.0"
version = "1.1.0"
source = "git+https://github.com/decentral1se/iroh-ffi?rev=455ba0df43d07b1a28890a70f325b71b05ddeb88#455ba0df43d07b1a28890a70f325b71b05ddeb88"
dependencies = [
"anyhow",
"async-trait",
@@ -2074,9 +2075,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.102"
version = "0.3.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
dependencies = [
"cfg-if",
"futures-util",
@@ -4221,9 +4222,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "uuid"
version = "1.23.3"
version = "1.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7"
checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53"
dependencies = [
"getrandom 0.4.3",
"js-sys",
@@ -4316,9 +4317,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.125"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
dependencies = [
"cfg-if",
"once_cell",
@@ -4329,9 +4330,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.75"
version = "0.4.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "503b14d284f2c8dac03b819967e155ea753f573586193b2b2c95990cb5d69280"
checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -4339,9 +4340,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.125"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -4349,9 +4350,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.125"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -4362,9 +4363,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.125"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
dependencies = [
"unicode-ident",
]
@@ -4384,9 +4385,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.102"
version = "0.3.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6430a72df5eb332242960fe84b3002a241163998241eb596d4f739b9757061d"
checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141"
dependencies = [
"js-sys",
"wasm-bindgen",
+1 -10
View File
@@ -8,17 +8,8 @@ publish = false
name = "iroh"
crate-type = ["staticlib"]
[[bin]]
name = "uniffi-bindgen"
path = "src/uniffi-bindgen.rs"
[dependencies]
# NOTE(d1): locally patched with https://github.com/n0-computer/iroh-ffi/pull/254
# iroh-ffi = { git = "https://github.com/n0-computer/iroh-ffi" }
iroh-ffi = { path = "../../iroh-ffi" }
# [build-dependencies]
# uniffi = { version = "0.31.1", features = ["build"] }
iroh-ffi = { git = "https://github.com/decentral1se/iroh-ffi", rev = "455ba0df43d07b1a28890a70f325b71b05ddeb88" }
[profile.release]
codegen-units = 1
-3
View File
@@ -1,3 +0,0 @@
fn main() {
uniffi::uniffi_bindgen_main()
}
+212 -1
View File
@@ -975,6 +975,15 @@ func uniffiCheckChecksums() {
panic("iroh_ffi: uniffi_iroh_ffi_checksum_method_endpointbuilder_apply_n0_disable_relay: UniFFI API checksum mismatch")
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iroh_ffi_checksum_method_endpointbuilder_bind()
})
if checksum != 5850 {
// If this happens try cleaning and rebuilding your project
panic("iroh_ffi: uniffi_iroh_ffi_checksum_method_endpointbuilder_bind: UniFFI API checksum mismatch")
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iroh_ffi_checksum_method_endpointbuilder_bind_addr()
@@ -1173,11 +1182,38 @@ func uniffiCheckChecksums() {
panic("iroh_ffi: uniffi_iroh_ffi_checksum_method_sendstream_write_all: UniFFI API checksum mismatch")
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iroh_ffi_checksum_method_iroherror_debug_message()
})
if checksum != 33751 {
// If this happens try cleaning and rebuilding your project
panic("iroh_ffi: uniffi_iroh_ffi_checksum_method_iroherror_debug_message: UniFFI API checksum mismatch")
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iroh_ffi_checksum_method_iroherror_is_kind()
})
if checksum != 10479 {
// If this happens try cleaning and rebuilding your project
panic("iroh_ffi: uniffi_iroh_ffi_checksum_method_iroherror_is_kind: UniFFI API checksum mismatch")
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iroh_ffi_checksum_method_iroherror_kind()
})
if checksum != 11512 {
// If this happens try cleaning and rebuilding your project
panic("iroh_ffi: uniffi_iroh_ffi_checksum_method_iroherror_kind: UniFFI API checksum mismatch")
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iroh_ffi_checksum_method_iroherror_message()
})
if checksum != 64767 {
if checksum != 60838 {
// If this happens try cleaning and rebuilding your project
panic("iroh_ffi: uniffi_iroh_ffi_checksum_method_iroherror_message: UniFFI API checksum mismatch")
}
@@ -1461,6 +1497,15 @@ func uniffiCheckChecksums() {
panic("iroh_ffi: uniffi_iroh_ffi_checksum_constructor_endpoint_bind: UniFFI API checksum mismatch")
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iroh_ffi_checksum_constructor_endpointbuilder_new()
})
if checksum != 16347 {
// If this happens try cleaning and rebuilding your project
panic("iroh_ffi: uniffi_iroh_ffi_checksum_constructor_endpointbuilder_new: UniFFI API checksum mismatch")
}
}
{
checksum := rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint16_t {
return C.uniffi_iroh_ffi_checksum_constructor_endpointid_from_bytes()
@@ -3906,6 +3951,13 @@ type EndpointBuilderInterface interface {
ApplyN0()
// Replay the n0 preset with relays disabled.
ApplyN0DisableRelay()
// Consume the builder and bind a new [`Endpoint`].
//
// The returned `Endpoint` has no protocol handlers — use
// [`Endpoint::bind`] with [`EndpointOptions::protocols`] to attach them.
// The builder is single-use; a second `bind` returns
// `EndpointBuilder already consumed`.
Bind() (*Endpoint, error)
// Set the address the endpoint binds to (`host:port`).
BindAddr(addr string) error
// Set the relay mode.
@@ -3925,6 +3977,15 @@ type EndpointBuilder struct {
ffiObject FfiObject
}
// Create a fresh empty endpoint builder. Apply a preset (`apply_n0`,
// `apply_minimal`, `apply_n0_disable_relay`) before [`bind`](Self::bind);
// the preset installs the crypto provider, without one `bind` will error.
func NewEndpointBuilder() *EndpointBuilder {
return FfiConverterEndpointBuilderINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) C.uint64_t {
return C.uniffi_iroh_ffi_fn_constructor_endpointbuilder_new(_uniffiStatus)
}))
}
// Set the advertised ALPNs.
func (_self *EndpointBuilder) Alpns(alpns [][]byte) {
_pointer := _self.ffiObject.incrementPointer("*EndpointBuilder")
@@ -3969,6 +4030,45 @@ func (_self *EndpointBuilder) ApplyN0DisableRelay() {
})
}
// Consume the builder and bind a new [`Endpoint`].
//
// The returned `Endpoint` has no protocol handlers — use
// [`Endpoint::bind`] with [`EndpointOptions::protocols`] to attach them.
// The builder is single-use; a second `bind` returns
// `EndpointBuilder already consumed`.
func (_self *EndpointBuilder) Bind() (*Endpoint, error) {
_pointer := _self.ffiObject.incrementPointer("*EndpointBuilder")
defer _self.ffiObject.decrementPointer()
res, err := uniffiRustCallAsync[*IrohError](
FfiConverterIrohErrorINSTANCE,
// completeFn
func(handle C.uint64_t, status *C.RustCallStatus) C.uint64_t {
res := C.ffi_iroh_ffi_rust_future_complete_u64(handle, status)
return res
},
// liftFn
func(ffi C.uint64_t) *Endpoint {
return FfiConverterEndpointINSTANCE.Lift(ffi)
},
C.uniffi_iroh_ffi_fn_method_endpointbuilder_bind(
_pointer),
// pollFn
func(handle C.uint64_t, continuation C.UniffiRustFutureContinuationCallback, data C.uint64_t) {
C.ffi_iroh_ffi_rust_future_poll_u64(handle, continuation, data)
},
// freeFn
func(handle C.uint64_t) {
C.ffi_iroh_ffi_rust_future_free_u64(handle)
},
)
if err == nil {
return res, nil
}
return res, err
}
// Set the address the endpoint binds to (`host:port`).
func (_self *EndpointBuilder) BindAddr(addr string) error {
_pointer := _self.ffiObject.incrementPointer("*EndpointBuilder")
@@ -4886,6 +4986,14 @@ func (_ FfiDestroyerIncoming) Destroy(value *Incoming) {
// An Error.
type IrohErrorInterface interface {
// Detailed debug representation of the original Rust error.
DebugMessage() string
// Convenience helper for bindings that do not expose enum comparison
// ergonomically.
IsKind(kind IrohErrorKind) bool
// Stable high-level error category.
Kind() IrohErrorKind
// Human-readable error message.
Message() string
}
@@ -4894,6 +5002,42 @@ type IrohError struct {
ffiObject FfiObject
}
// Detailed debug representation of the original Rust error.
func (_self *IrohError) DebugMessage() string {
_pointer := _self.ffiObject.incrementPointer("*IrohError")
defer _self.ffiObject.decrementPointer()
return FfiConverterStringINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) RustBufferI {
return GoRustBuffer{
inner: C.uniffi_iroh_ffi_fn_method_iroherror_debug_message(
_pointer, _uniffiStatus),
}
}))
}
// Convenience helper for bindings that do not expose enum comparison
// ergonomically.
func (_self *IrohError) IsKind(kind IrohErrorKind) bool {
_pointer := _self.ffiObject.incrementPointer("*IrohError")
defer _self.ffiObject.decrementPointer()
return FfiConverterBoolINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) C.int8_t {
return C.uniffi_iroh_ffi_fn_method_iroherror_is_kind(
_pointer, FfiConverterIrohErrorKindINSTANCE.Lower(kind), _uniffiStatus)
}))
}
// Stable high-level error category.
func (_self *IrohError) Kind() IrohErrorKind {
_pointer := _self.ffiObject.incrementPointer("*IrohError")
defer _self.ffiObject.decrementPointer()
return FfiConverterIrohErrorKindINSTANCE.Lift(rustCall(func(_uniffiStatus *C.RustCallStatus) RustBufferI {
return GoRustBuffer{
inner: C.uniffi_iroh_ffi_fn_method_iroherror_kind(
_pointer, _uniffiStatus),
}
}))
}
// Human-readable error message.
func (_self *IrohError) Message() string {
_pointer := _self.ffiObject.incrementPointer("*IrohError")
defer _self.ffiObject.decrementPointer()
@@ -8601,6 +8745,73 @@ func (_ FfiDestroyerIncomingLocalAddr) Destroy(value IncomingLocalAddr) {
value.Destroy()
}
// Stable high-level error categories exposed across the FFI boundary.
//
// These are intentionally coarser than the upstream Rust error types. They
// give foreign bindings a stable taxonomy for `errors.Is`-style handling
// without leaking the internal `iroh` / `n0-error` error hierarchy.
type IrohErrorKind uint
const (
// Invalid input supplied by the caller.
IrohErrorKindInvalidInput IrohErrorKind = 1
// Failure while binding an endpoint.
IrohErrorKindBind IrohErrorKind = 2
// Failure while initiating or completing an outgoing connection.
IrohErrorKindConnect IrohErrorKind = 3
// An established connection failed or closed unexpectedly.
IrohErrorKindConnection IrohErrorKind = 4
// ALPN negotiation or lookup failed.
IrohErrorKindAlpn IrohErrorKind = 5
// Endpoint id / public key parsing failed.
IrohErrorKindKeyParsing IrohErrorKind = 6
// Ticket parsing failed.
IrohErrorKindTicketParsing IrohErrorKind = 7
// Relay configuration or relay operation failed.
IrohErrorKindRelay IrohErrorKind = 8
// Stream read/write/control operation failed.
IrohErrorKindStream IrohErrorKind = 9
// Datagram send/receive operation failed.
IrohErrorKindDatagram IrohErrorKind = 10
// Foreign callback failed.
IrohErrorKindCallback IrohErrorKind = 11
// Operation was attempted on a closed stream/connection/resource.
IrohErrorKindClosed IrohErrorKind = 12
// Operation timed out.
IrohErrorKindTimeout IrohErrorKind = 13
// Unclassified internal error.
IrohErrorKindInternal IrohErrorKind = 14
)
type FfiConverterIrohErrorKind struct{}
var FfiConverterIrohErrorKindINSTANCE = FfiConverterIrohErrorKind{}
func (c FfiConverterIrohErrorKind) Lift(rb RustBufferI) IrohErrorKind {
return LiftFromRustBuffer[IrohErrorKind](c, rb)
}
func (c FfiConverterIrohErrorKind) Lower(value IrohErrorKind) C.RustBuffer {
return LowerIntoRustBuffer[IrohErrorKind](c, value)
}
func (c FfiConverterIrohErrorKind) LowerExternal(value IrohErrorKind) ExternalCRustBuffer {
return RustBufferFromC(LowerIntoRustBuffer[IrohErrorKind](c, value))
}
func (FfiConverterIrohErrorKind) Read(reader io.Reader) IrohErrorKind {
id := readInt32(reader)
return IrohErrorKind(id)
}
func (FfiConverterIrohErrorKind) Write(writer io.Writer, value IrohErrorKind) {
writeInt32(writer, int32(value))
}
type FfiDestroyerIrohErrorKind struct{}
func (_ FfiDestroyerIrohErrorKind) Destroy(value IrohErrorKind) {
}
// The logging level. See the rust (log crate)[https://docs.rs/log] for more information.
type LogLevel uint
+56
View File
@@ -932,6 +932,12 @@ uint64_t uniffi_iroh_ffi_fn_clone_endpointbuilder(uint64_t handle, RustCallStatu
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_FREE_ENDPOINTBUILDER
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_FREE_ENDPOINTBUILDER
void uniffi_iroh_ffi_fn_free_endpointbuilder(uint64_t handle, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_CONSTRUCTOR_ENDPOINTBUILDER_NEW
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_CONSTRUCTOR_ENDPOINTBUILDER_NEW
uint64_t uniffi_iroh_ffi_fn_constructor_endpointbuilder_new(RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_ENDPOINTBUILDER_ALPNS
@@ -954,6 +960,11 @@ void uniffi_iroh_ffi_fn_method_endpointbuilder_apply_n0(uint64_t ptr, RustCallSt
void uniffi_iroh_ffi_fn_method_endpointbuilder_apply_n0_disable_relay(uint64_t ptr, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_ENDPOINTBUILDER_BIND
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_ENDPOINTBUILDER_BIND
uint64_t uniffi_iroh_ffi_fn_method_endpointbuilder_bind(uint64_t ptr
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_ENDPOINTBUILDER_BIND_ADDR
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_ENDPOINTBUILDER_BIND_ADDR
void uniffi_iroh_ffi_fn_method_endpointbuilder_bind_addr(uint64_t ptr, RustBuffer addr, RustCallStatus *out_status
@@ -1139,6 +1150,21 @@ uint64_t uniffi_iroh_ffi_fn_clone_iroherror(uint64_t handle, RustCallStatus *out
void uniffi_iroh_ffi_fn_free_iroherror(uint64_t handle, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_IROHERROR_DEBUG_MESSAGE
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_IROHERROR_DEBUG_MESSAGE
RustBuffer uniffi_iroh_ffi_fn_method_iroherror_debug_message(uint64_t ptr, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_IROHERROR_IS_KIND
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_IROHERROR_IS_KIND
int8_t uniffi_iroh_ffi_fn_method_iroherror_is_kind(uint64_t ptr, RustBuffer kind, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_IROHERROR_KIND
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_IROHERROR_KIND
RustBuffer uniffi_iroh_ffi_fn_method_iroherror_kind(uint64_t ptr, RustCallStatus *out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_IROHERROR_MESSAGE
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_FN_METHOD_IROHERROR_MESSAGE
RustBuffer uniffi_iroh_ffi_fn_method_iroherror_message(uint64_t ptr, RustCallStatus *out_status
@@ -2301,6 +2327,12 @@ uint16_t uniffi_iroh_ffi_checksum_method_endpointbuilder_apply_n0(void
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_ENDPOINTBUILDER_APPLY_N0_DISABLE_RELAY
uint16_t uniffi_iroh_ffi_checksum_method_endpointbuilder_apply_n0_disable_relay(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_ENDPOINTBUILDER_BIND
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_ENDPOINTBUILDER_BIND
uint16_t uniffi_iroh_ffi_checksum_method_endpointbuilder_bind(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_ENDPOINTBUILDER_BIND_ADDR
@@ -2433,6 +2465,24 @@ uint16_t uniffi_iroh_ffi_checksum_method_sendstream_write(void
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_SENDSTREAM_WRITE_ALL
uint16_t uniffi_iroh_ffi_checksum_method_sendstream_write_all(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_IROHERROR_DEBUG_MESSAGE
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_IROHERROR_DEBUG_MESSAGE
uint16_t uniffi_iroh_ffi_checksum_method_iroherror_debug_message(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_IROHERROR_IS_KIND
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_IROHERROR_IS_KIND
uint16_t uniffi_iroh_ffi_checksum_method_iroherror_is_kind(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_IROHERROR_KIND
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_IROHERROR_KIND
uint16_t uniffi_iroh_ffi_checksum_method_iroherror_kind(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_METHOD_IROHERROR_MESSAGE
@@ -2625,6 +2675,12 @@ uint16_t uniffi_iroh_ffi_checksum_method_watchhandle_stop(void
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_CONSTRUCTOR_ENDPOINT_BIND
uint16_t uniffi_iroh_ffi_checksum_constructor_endpoint_bind(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_CONSTRUCTOR_ENDPOINTBUILDER_NEW
#define UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_CONSTRUCTOR_ENDPOINTBUILDER_NEW
uint16_t uniffi_iroh_ffi_checksum_constructor_endpointbuilder_new(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_IROH_FFI_CHECKSUM_CONSTRUCTOR_ENDPOINTID_FROM_BYTES
+1
View File
@@ -1,4 +1,5 @@
package iroh_ffi
// #cgo linux,amd64 LDFLAGS: -L${SRCDIR}/libs/x86_64-unknown-linux-musl -liroh -lm
// #cgo linux,arm64 LDFLAGS: -L${SRCDIR}/libs/aarch64-unknown-linux-musl -liroh -lm
import "C"
Binary file not shown.
Binary file not shown.
+12
View File
@@ -0,0 +1,12 @@
Copyright (c) 2026 iroh-go contributors
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 iroh-go contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+10 -6
View File
@@ -9,8 +9,7 @@ RUST_FOLDER="$THIS_SCRIPT_DIR/../iroh-go"
FFI_FOLDER="$THIS_SCRIPT_DIR/../iroh-ffi"
GO_FOLDER="$THIS_SCRIPT_DIR/../"
# TARGETS="x86_64-unknown-linux-musl aarch64-unknown-linux-musl aarch64-apple-darwin x86_64-apple-darwin"
TARGETS="x86_64-unknown-linux-musl"
TARGETS="x86_64-unknown-linux-musl aarch64-unknown-linux-musl"
if ! command -v cross &> /dev/null; then
echo "▸ cross tool not found, installing"
@@ -21,7 +20,9 @@ if ! command -v rustup &> /dev/null; then
echo "▸ rustup not found, please install it"
exit 1
else
rustup target add $TARGETS
for TARGET in $TARGETS; do
rustup target add $TARGET
done
fi
export RUSTFLAGS="-C target-feature=+crt-static"
@@ -32,11 +33,11 @@ for TARGET in $TARGETS; do
cp "${RUST_FOLDER}/target/${TARGET}/release/${LIB_NAME}" "${GO_FOLDER}/libs/${TARGET}/${LIB_NAME}"
done
TARGET="x86_64-unknown-linux-musl"
echo "▸ Generate Go bindings"
BINDGEN_TARGET="x86_64-unknown-linux-musl"
echo "▸ generate Go bindings"
cd "$RUST_FOLDER"
uniffi-bindgen-go \
"${GO_FOLDER}/libs/${TARGET}/${LIB_NAME}" \
"${GO_FOLDER}/libs/${BINDGEN_TARGET}/${LIB_NAME}" \
--library \
--out-dir "${RUST_FOLDER}/target/go"
@@ -45,3 +46,6 @@ cp -r "${RUST_FOLDER}/target/go/iroh_ffi/iroh_ffi.go" "${GO_FOLDER}"
test -f "${RUST_FOLDER}/target/go/iroh_ffi/iroh_ffi.h"
cp -r "${RUST_FOLDER}/target/go/iroh_ffi/iroh_ffi.h" "${GO_FOLDER}"
go -C "${GO_FOLDER}" fmt ./...
go -C "${GO_FOLDER}" build -v iroh_ffi.go