Refactor ExampleDatagramSession to improve error handling and simplify datagram sending/receiving logic; enhance output messages for better clarity.

This commit is contained in:
eyedeekay
2025-10-06 12:46:01 -04:00
parent 984021c5cf
commit 2eebe2eb2f

View File

@@ -88,111 +88,74 @@ func Test_DatagramServerClient(t *testing.T) {
func ExampleDatagramSession() { func ExampleDatagramSession() {
// Creates a new DatagramSession, which behaves just like a net.PacketConn. // Creates a new DatagramSession, which behaves just like a net.PacketConn.
// Note: This example requires a running I2P router with SAM bridge enabled. // This example demonstrates I2P datagram communication by sending messages
// If no I2P router is available, the example will print an error and return. // and attempting to receive them through the I2P network.
//
// Requirements: This example requires a running I2P router with SAM bridge enabled.
const samBridge = "127.0.0.1:7656" const samBridge = "127.0.0.1:7656"
sam, err := NewSAM(samBridge) sam, err := NewSAM(samBridge)
if err != nil { if err != nil {
fmt.Println("Error creating SAM connection (I2P router may not be running):", err.Error()) fmt.Printf("Failed to connect to I2P SAM bridge at %s: %v\n", samBridge, err)
return return
} }
defer sam.Close()
keys, err := sam.NewKeys() keys, err := sam.NewKeys()
if err != nil { if err != nil {
fmt.Println("Error generating keys:", err.Error()) sam.Close()
fmt.Printf("Failed to generate I2P keys: %v\n", err)
return return
} }
myself := keys.Addr() myself := keys.Addr()
// See the example Option_* variables. // Create datagram session with small tunnel configuration for faster setup
dg, err := sam.NewDatagramSession("DGTUN", keys, Options_Small, 0) dg, err := sam.NewDatagramSession("DGTUN", keys, Options_Small, 0)
if err != nil { if err != nil {
fmt.Println("Error creating datagram session:", err.Error()) sam.Close()
fmt.Printf("Failed to create datagram session: %v\n", err)
return return
} }
defer dg.Close()
// Try to lookup a destination (this may fail if I2P is not fully started) // For this example, we'll send messages to ourselves to demonstrate functionality
someone, err := sam.Lookup("zzz.i2p")
if err != nil {
fmt.Println("Warning: Could not resolve zzz.i2p (I2P may still be starting up):", err.Error())
// Use a placeholder address for demonstration
someone = myself
}
// Send datagrams (these operations may timeout if I2P tunnels are not ready)
fmt.Println("Sending datagrams...") fmt.Println("Sending datagrams...")
// Use timeouts for I2P operations // Send a message to ourselves (this should work if I2P tunnels are established)
sendTimeout := make(chan bool, 1) _, err = dg.WriteTo([]byte("Hello myself!"), myself)
go func() { if err != nil {
defer func() { dg.Close()
if r := recover(); r != nil { sam.Close()
fmt.Printf("Error during send operation: %v\n", r) fmt.Printf("Failed to send datagram: %v\n", err)
}
sendTimeout <- true
}()
_, err1 := dg.WriteTo([]byte("Hello stranger!"), someone)
if err1 != nil {
fmt.Println("Warning: Could not send to destination:", err1.Error())
}
_, err2 := dg.WriteTo([]byte("Hello myself!"), myself)
if err2 != nil {
fmt.Println("Warning: Could not send to self:", err2.Error())
}
}()
// Wait for send operations with timeout
select {
case <-sendTimeout:
// Sends completed (successfully or with errors)
case <-time.After(30 * time.Second):
fmt.Println("Warning: Send operations timed out (I2P tunnels may not be ready)")
return return
} }
// Try to receive a datagram with reasonable timeout
fmt.Println("Attempting to receive datagram...") fmt.Println("Attempting to receive datagram...")
receiveTimeout := make(chan bool, 1)
var received bool
go func() { // Set a reasonable deadline for the receive operation (I2P operations need time)
defer func() { dg.SetReadDeadline(time.Now().Add(60 * time.Second))
if r := recover(); r != nil {
fmt.Printf("Error during receive operation: %v\n", r)
}
receiveTimeout <- true
}()
buf := make([]byte, 31*1024) buf := make([]byte, 31*1024)
n, _, err := dg.ReadFrom(buf) n, addr, err := dg.ReadFrom(buf)
if err != nil { if err != nil {
fmt.Println("Could not receive datagram:", err.Error()) dg.Close()
} else { sam.Close()
fmt.Printf("Got message: %s\n", string(buf[:n])) fmt.Printf("Failed to receive datagram within 60 seconds: %v\n", err)
received = true return
}
}()
// Wait for receive operation with timeout
select {
case <-receiveTimeout:
if !received {
fmt.Println("No datagram received (this is normal if I2P tunnels are not fully established)")
}
case <-time.After(30 * time.Second):
fmt.Println("Receive operation timed out (normal behavior when no messages are available)")
} }
fmt.Printf("Received message: %s\n", string(buf[:n]))
fmt.Printf("From address: %s\n", addr.String())
// Clean up resources
dg.Close()
sam.Close()
fmt.Println("DatagramSession example completed") fmt.Println("DatagramSession example completed")
return
// Output: // Output:
// Sending datagrams... // Sending datagrams...
// Attempting to receive datagram... // Attempting to receive datagram...
// Received message: Hello myself!
// From address: [I2P address]
// DatagramSession example completed // DatagramSession example completed
} }