Skip to content
Snippets Groups Projects
Commit 58f7fee6 authored by Jake Taylor's avatar Jake Taylor :lips:
Browse files

Merge branch 'ConnectionServer' into 'master'

Connection server

See merge request !1
parents 0d2448c3 fc4b63db
Branches
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
# xxdk Connection Server Example
module gitlab.com/elixxir/xxdk-examples/connectServer
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/badoux/checkmail v1.2.1 // indirect
github.com/cloudflare/circl v1.1.0 // indirect
github.com/elliotchance/orderedmap v1.4.0 // indirect
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // 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
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
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
)
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 will allow clients to start connections with you
connectionListParams := connect.DefaultConnectionListParams()
_, err = connect.StartServer(
identity, cb, baseClient, params, 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
e2eClient.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