Skip to content
Snippets Groups Projects
Commit 99541248 authored by Jono Wenger's avatar Jono Wenger
Browse files

Implement connection server example

parent ece1b708
No related branches found
No related tags found
1 merge request!1Connection server
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Ignore Jetbrains IDE folder
.idea/*
# Dependency directories (remove the comment below to include it)
vendor/
# File from testing
session*/
*.darwin64
*.linux64
*.win64
*.xxchan
*.pem
*.log
\ No newline at end of file
module gitlab.com/elixxir/xxdk-examples/connection
go 1.17
require (
github.com/spf13/jwalterweatherman v1.1.0
gitlab.com/elixxir/client v1.5.1-0.20220705214402-3ebd3c1fcfec
gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea
gitlab.com/xx_network/primitives v0.0.4-0.20220630163313-7890038258c6
)
require (
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/badoux/checkmail v1.2.1 // indirect
github.com/cloudflare/circl v1.1.0 // indirect
github.com/elliotchance/orderedmap v1.4.0 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/magiconair/properties v1.8.4 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.4.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/pelletier/go-toml v1.8.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
github.com/spf13/afero v1.5.1 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/cobra v1.1.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.7.1 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/ttacon/builder v0.0.0-20170518171403-c099f663e1c2 // indirect
github.com/ttacon/libphonenumber v1.2.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/zeebo/blake3 v0.1.1 // indirect
gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f // indirect
gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326 // indirect
gitlab.com/elixxir/ekv v0.1.7 // indirect
gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f // indirect
gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd // indirect
gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81 // indirect
gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect
golang.org/x/text v0.3.6 // indirect
google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect
google.golang.org/grpc v1.42.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
This diff is collapsed.
package main
import (
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/e2e/receive"
)
// listener adheres to the receive.Listener interface.
type listener struct {
name string
}
// Hear will be called whenever a message matching the RegisterListener call is
// received.
//
// User-defined message handling logic goes here.
func (l *listener) Hear(item receive.Message) {
jww.INFO.Printf("Message received: %v", item)
}
// Name is used for debugging purposes.
func (l *listener) Name() string {
return l.name
}
\ No newline at end of file
// Starting connection server
package main
import (
"errors"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/catalog"
"gitlab.com/elixxir/client/xxdk"
"io/fs"
"io/ioutil"
"os"
"time"
"gitlab.com/elixxir/client/connect"
)
func main() {
// Logging
initLog(1, "client.log")
// Create a new client object-------------------------------------------------------
// You would ideally use a configuration tool to acquire these parameters
statePath := "statePath"
statePass := "password"
// The following connects to mainnet. For historical reasons it is called a json file
// but it is actually a marshalled file with a cryptographic signature attached.
// This may change in the future.
ndfURL := "https://elixxir-bins.s3.us-west-1.amazonaws.com/ndf/mainnet.json"
certificatePath := "../mainnet.crt"
ndfPath := "ndf.json"
// Check if state exists
if _, err := os.Stat(statePath); errors.Is(err, fs.ErrNotExist) {
// Attempt to read the NDF
var ndfJSON []byte
ndfJSON, err = ioutil.ReadFile(ndfPath)
if err != nil {
jww.INFO.Printf("NDF does not exist: %+v", err)
}
// If NDF can't be read, retrieve it remotely
if ndfJSON == nil {
cert, err := ioutil.ReadFile(certificatePath)
if err != nil {
jww.FATAL.Panicf("Failed to read certificate: %v", err)
}
ndfJSON, err = xxdk.DownloadAndVerifySignedNdfWithUrl(ndfURL, string(cert))
if err != nil {
jww.FATAL.Panicf("Failed to download NDF: %+v", err)
}
}
// Initialize the state
err = xxdk.NewCmix(string(ndfJSON), statePath, []byte(statePass), "")
if err != nil {
jww.FATAL.Panicf("Failed to initialize state: %+v", err)
}
}
// Login to your client session-----------------------------------------------------
// Login with the same sessionPath and sessionPass used to call NewClient()
baseClient, err := xxdk.LoadCmix(statePath, []byte(statePass), xxdk.GetDefaultCMixParams())
if err != nil {
jww.FATAL.Panicf("Failed to load state: %+v", err)
}
// Get reception identity (automatically created if one does not exist)
identityStorageKey := "identityStorageKey"
identity, err := xxdk.LoadReceptionIdentity(identityStorageKey, baseClient)
if err != nil {
// If no extant xxdk.ReceptionIdentity, generate and store a new one
identity, err = xxdk.MakeReceptionIdentity(baseClient)
if err != nil {
jww.FATAL.Panicf("Failed to generate reception identity: %+v", err)
}
err = xxdk.StoreReceptionIdentity(identityStorageKey, identity, baseClient)
if err != nil {
jww.FATAL.Panicf("Failed to store new reception identity: %+v", err)
}
}
// Create an E2E client
// The connect packages handles AuthCallbacks, xxdk.DefaultAuthCallbacks is fine here
params := xxdk.GetDefaultE2EParams()
jww.INFO.Printf("Using E2E parameters: %+v", params)
e2eClient, err := xxdk.Login(baseClient, xxdk.DefaultAuthCallbacks{}, identity, params)
if err != nil {
jww.FATAL.Panicf("Unable to Login: %+v", err)
}
// Save contact file----------------------------------------------------------------
// Get the contact file path
contactFilePath := "connectServer.xxc"
// Save the contact file so that client can connect to this server
writeContact(contactFilePath, identity.GetContact())
// Handle incoming connections------------------------------------------------------
// Create callback for incoming connections
cb := func(connection connect.Connection) {
// Listen for all types of messages using catalog.NoType
// User-defined behavior for message reception goes in the listener
_, err = connection.RegisterListener(
catalog.NoType, &listener{"connection server listener"})
if err != nil {
jww.FATAL.Panicf("Failed to register listener: %+v", err)
}
}
// Start connection server----------------------------------------------------------
// Start the connection server, which
e2eParams := xxdk.GetDefaultE2EParams()
connectionListParams := connect.DefaultConnectionListParams()
_, err = connect.StartServer(
identity, cb, baseClient, e2eParams, connectionListParams)
if err != nil {
jww.FATAL.Panicf("Unable to start connection server: %+v", err)
}
// Start network threads------------------------------------------------------------
// Set networkFollowerTimeout to a value of your choice (seconds)
networkFollowerTimeout := 5 * time.Second
err = e2eClient.StartNetworkFollower(networkFollowerTimeout)
if err != nil {
jww.FATAL.Panicf("Failed to start network follower: %+v", err)
}
// Set up a wait for the network to be connected
waitUntilConnected := func(connected chan bool) {
waitTimeout := 30 * time.Second
timeoutTimer := time.NewTimer(waitTimeout)
isConnected := false
// Wait until we connect or panic if we cannot before the timeout
for !isConnected {
select {
case isConnected = <-connected:
jww.INFO.Printf("Network Status: %v", isConnected)
break
case <-timeoutTimer.C:
jww.FATAL.Panicf("Timeout on starting network follower")
}
}
}
// Create a tracker channel to be notified of network changes
connected := make(chan bool, 10)
// Provide a callback that will be signalled when network health status changes
baseClient.GetCmix().AddHealthCallback(
func(isConnected bool) {
connected <- isConnected
})
// Wait until connected or crash on timeout
waitUntilConnected(connected)
// Keep app running to receive messages-----------------------------------------------
select {}
}
package main
import (
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/crypto/contact"
"gitlab.com/xx_network/primitives/utils"
"io/ioutil"
"log"
"os"
)
func initLog(threshold uint, logPath string) {
if logPath != "-" && logPath != "" {
// Disable stdout output
jww.SetStdoutOutput(ioutil.Discard)
// Use log file
logOutput, err := os.OpenFile(logPath,
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err.Error())
}
jww.SetLogOutput(logOutput)
}
if threshold > 1 {
jww.INFO.Printf("log level set to: TRACE")
jww.SetStdoutThreshold(jww.LevelTrace)
jww.SetLogThreshold(jww.LevelTrace)
jww.SetFlags(log.LstdFlags | log.Lmicroseconds)
} else if threshold == 1 {
jww.INFO.Printf("log level set to: DEBUG")
jww.SetStdoutThreshold(jww.LevelDebug)
jww.SetLogThreshold(jww.LevelDebug)
jww.SetFlags(log.LstdFlags | log.Lmicroseconds)
} else {
jww.INFO.Printf("log level set to: INFO")
jww.SetStdoutThreshold(jww.LevelInfo)
jww.SetLogThreshold(jww.LevelInfo)
}
}
func writeContact(outfilePath string, c contact.Contact) {
err := utils.WriteFileDef(outfilePath, c.Marshal())
if err != nil {
jww.ERROR.Printf("could not write contact file: %+v", err)
} else {
jww.INFO.Printf("contact written to %s successfully", outfilePath)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment