Skip to content
Snippets Groups Projects
Commit 2c2426f3 authored by Josh Brooks's avatar Josh Brooks
Browse files

Merge branch 'XX-3134/GwHostPool' of gitlab.com:elixxir/client into XX-3134/GwHostPoolTest

parents fc621725 74fc8e65
Branches
Tags
No related merge requests found
...@@ -32,6 +32,7 @@ func init() { ...@@ -32,6 +32,7 @@ func init() {
// to support the gomobile Client interface // to support the gomobile Client interface
type Client struct { type Client struct {
api api.Client api api.Client
waitForNetwork chan bool
} }
// NewClient creates client storage, generates keys, connects, and registers // NewClient creates client storage, generates keys, connects, and registers
...@@ -84,7 +85,7 @@ func Login(storageDir string, password []byte, parameters string) (*Client, erro ...@@ -84,7 +85,7 @@ func Login(storageDir string, password []byte, parameters string) (*Client, erro
if err != nil { if err != nil {
return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err)) return nil, errors.New(fmt.Sprintf("Failed to login: %+v", err))
} }
return &Client{*client}, nil return &Client{api: *client}, nil
} }
// sets level of logging. All logs the set level and above will be displayed // sets level of logging. All logs the set level and above will be displayed
...@@ -203,6 +204,46 @@ func (c *Client) StopNetworkFollower(timeoutMS int) error { ...@@ -203,6 +204,46 @@ func (c *Client) StopNetworkFollower(timeoutMS int) error {
return nil return nil
} }
// WaitForNewtwork will block until either the network is healthy or the
// passed timeout. It will return true if the network is healthy
func (c *Client) WaitForNetwork(timeoutMS int) bool {
timeout := time.NewTimer(time.Duration(timeoutMS) * time.Millisecond)
if c.waitForNetwork == nil{
c.waitForNetwork = make(chan bool, 1)
c.api.GetHealth().AddChannel(c.waitForNetwork)
}
//flush the channel if it is already full
select{
case <- c.waitForNetwork:
default:
}
// start a thread to check if healthy in a second in order to handle
// race conditions
go func() {
time.Sleep(1*time.Second)
if c.api.GetHealth().IsHealthy() {
select{
case c.waitForNetwork<-true:
default:
}
}
}()
//wait for network to be healthy or the timer to time out
for {
select{
case result := <- c.waitForNetwork:
if result {
return true
}
case <-timeout.C:
return false
}
}
}
// Gets the state of the network follower. Returns: // Gets the state of the network follower. Returns:
// Stopped - 0 // Stopped - 0
// Starting - 1000 // Starting - 1000
...@@ -348,9 +389,9 @@ func (c *Client) GetUser() *User { ...@@ -348,9 +389,9 @@ func (c *Client) GetUser() *User {
// GetNodeRegistrationStatus returns a struct with the number of nodes the // GetNodeRegistrationStatus returns a struct with the number of nodes the
// client is registered with and the number total. // client is registered with and the number total.
func (c *Client) GetNodeRegistrationStatus() (*NodeRegistrationsStatus, error) { func (c *Client) GetNodeRegistrationStatus() (*NodeRegistrationsStatus, error) {
registered, inProgress, err := c.api.GetNodeRegistrationStatus() registered, total, err := c.api.GetNodeRegistrationStatus()
return &NodeRegistrationsStatus{registered, inProgress}, err return &NodeRegistrationsStatus{registered, total}, err
} }
/* /*
......
...@@ -99,8 +99,8 @@ func (fl *FactList) Num() int { ...@@ -99,8 +99,8 @@ func (fl *FactList) Num() int {
return len(fl.c.Facts) return len(fl.c.Facts)
} }
func (fl *FactList) Get(i int) Fact { func (fl *FactList) Get(i int) *Fact {
return Fact{f: &(fl.c.Facts)[i]} return &Fact{f: &(fl.c.Facts)[i]}
} }
func (fl *FactList) Add(factData string, factType int) error { func (fl *FactList) Add(factData string, factType int) error {
......
...@@ -6,10 +6,12 @@ require ( ...@@ -6,10 +6,12 @@ require (
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
github.com/golang/protobuf v1.4.3 github.com/golang/protobuf v1.4.3
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
github.com/liyue201/goqr v0.0.0-20200803022322-df443203d4ea // indirect
github.com/magiconair/properties v1.8.4 // indirect github.com/magiconair/properties v1.8.4 // indirect
github.com/mitchellh/mapstructure v1.4.0 // indirect github.com/mitchellh/mapstructure v1.4.0 // indirect
github.com/pelletier/go-toml v1.8.1 // indirect github.com/pelletier/go-toml v1.8.1 // indirect
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/smartystreets/assertions v1.0.1 // indirect github.com/smartystreets/assertions v1.0.1 // indirect
github.com/spf13/afero v1.5.1 // indirect github.com/spf13/afero v1.5.1 // indirect
github.com/spf13/cast v1.3.1 // indirect github.com/spf13/cast v1.3.1 // indirect
......
...@@ -144,6 +144,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= ...@@ -144,6 +144,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/liyue201/goqr v0.0.0-20200803022322-df443203d4ea h1:uyJ13zfy6l79CM3HnVhDalIyZ4RJAyVfDrbnfFeJoC4=
github.com/liyue201/goqr v0.0.0-20200803022322-df443203d4ea/go.mod h1:w4pGU9PkiX2hAWyF0yuHEHmYTQFAd6WHzp6+IY7JVjE=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
...@@ -201,6 +203,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb ...@@ -201,6 +203,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
...@@ -266,6 +270,8 @@ gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp0 ...@@ -266,6 +270,8 @@ gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp0
gitlab.com/elixxir/crypto v0.0.4/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= gitlab.com/elixxir/crypto v0.0.4/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA=
gitlab.com/elixxir/crypto v0.0.7-0.20210319231554-b73b6e62ddbc h1:r2nJ1opPnvaY/46nqOHxBEh/QlbNH3O7hurfDtJC0Wk= gitlab.com/elixxir/crypto v0.0.7-0.20210319231554-b73b6e62ddbc h1:r2nJ1opPnvaY/46nqOHxBEh/QlbNH3O7hurfDtJC0Wk=
gitlab.com/elixxir/crypto v0.0.7-0.20210319231554-b73b6e62ddbc/go.mod h1:Th9bJRvEQecOFW0coD21AzzIBoNDOXcP3+hIGXELCXE= gitlab.com/elixxir/crypto v0.0.7-0.20210319231554-b73b6e62ddbc/go.mod h1:Th9bJRvEQecOFW0coD21AzzIBoNDOXcP3+hIGXELCXE=
gitlab.com/elixxir/crypto v0.0.7-0.20210326171146-c137bd7b0c6e h1:+zoFtqHyHUflsF1DPf+vty8o1hur5gQyBy6FERmPKyg=
gitlab.com/elixxir/crypto v0.0.7-0.20210326171146-c137bd7b0c6e/go.mod h1:bmCiS3OH4BGWL6Y/hnvA3jsNYd736UERL4UU9ScdbZQ=
gitlab.com/elixxir/ekv v0.1.4 h1:NLVMwsFEKArWcsDHu2DbXlm9374iSgn7oIA3rVSsvjc= gitlab.com/elixxir/ekv v0.1.4 h1:NLVMwsFEKArWcsDHu2DbXlm9374iSgn7oIA3rVSsvjc=
gitlab.com/elixxir/ekv v0.1.4/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4= gitlab.com/elixxir/ekv v0.1.4/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4=
gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg= gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
...@@ -276,6 +282,8 @@ gitlab.com/elixxir/primitives v0.0.1/go.mod h1:kNp47yPqja2lHSiS4DddTvFpB/4D9dB2Y ...@@ -276,6 +282,8 @@ gitlab.com/elixxir/primitives v0.0.1/go.mod h1:kNp47yPqja2lHSiS4DddTvFpB/4D9dB2Y
gitlab.com/elixxir/primitives v0.0.2/go.mod h1:3fxFHSlQhkV4vs+S0dZEz3Om3m+40WX8L806yvSnNFc= gitlab.com/elixxir/primitives v0.0.2/go.mod h1:3fxFHSlQhkV4vs+S0dZEz3Om3m+40WX8L806yvSnNFc=
gitlab.com/elixxir/primitives v0.0.3-0.20210309193003-ef42ebb4800b h1:TswWfqiZqsdPLeWsfe7VJHMlV01W792kRHGYfYwb2Lk= gitlab.com/elixxir/primitives v0.0.3-0.20210309193003-ef42ebb4800b h1:TswWfqiZqsdPLeWsfe7VJHMlV01W792kRHGYfYwb2Lk=
gitlab.com/elixxir/primitives v0.0.3-0.20210309193003-ef42ebb4800b/go.mod h1:/e3a4KPqmA9V22qKSZ9prfYYNzIzvLI8xh7noVV091w= gitlab.com/elixxir/primitives v0.0.3-0.20210309193003-ef42ebb4800b/go.mod h1:/e3a4KPqmA9V22qKSZ9prfYYNzIzvLI8xh7noVV091w=
gitlab.com/elixxir/primitives v0.0.3-0.20210326022836-1143187bd2fe h1:fOZONg2RIiMtJoXdQHBSAdhv8/fm03VGEnZWcF9DJ8Q=
gitlab.com/elixxir/primitives v0.0.3-0.20210326022836-1143187bd2fe/go.mod h1:/e3a4KPqmA9V22qKSZ9prfYYNzIzvLI8xh7noVV091w=
gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw= gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw=
gitlab.com/xx_network/comms v0.0.3/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8= gitlab.com/xx_network/comms v0.0.3/go.mod h1:YViGbRj7FjJYoaO4NpALGEd9dK/l8uUT000FEBbUTL8=
gitlab.com/xx_network/comms v0.0.4-0.20210322201806-b35c5f0dc6e0 h1:j+Ky4+RstnRQVWIXssUImo6X9aNCgbIOOWJOpcpflak= gitlab.com/xx_network/comms v0.0.4-0.20210322201806-b35c5f0dc6e0 h1:j+Ky4+RstnRQVWIXssUImo6X9aNCgbIOOWJOpcpflak=
......
...@@ -13,17 +13,27 @@ import ( ...@@ -13,17 +13,27 @@ import (
"encoding/base64" "encoding/base64"
"encoding/binary" "encoding/binary"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/skip2/go-qrcode"
"gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/primitives/fact" "gitlab.com/elixxir/primitives/fact"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
"strings"
) )
const sizeByteLength = 2 const (
const fingerprintLength = 15 version = "0"
headTag = "<xxc"
footTag = "xxc>"
openVerTag = "("
closeVerTag = ")"
sizeLength = 2
minLength = (sizeLength * 3) + len(headTag) + len(footTag) + id.ArrIDLen
fingerprintLength = 15
)
// Contact implements the Contact interface defined in interface/contact.go, // Contact implements the Contact interface defined in interface/contact.go,
// in go, the structure is meant to be edited directly, the functions are for // in go, the structure is meant to be edited directly, the functions are for
// bindings compatibility // bindings compatibility.
type Contact struct { type Contact struct {
ID *id.ID ID *id.ID
DhPubKey *cyclic.Int DhPubKey *cyclic.Int
...@@ -31,17 +41,23 @@ type Contact struct { ...@@ -31,17 +41,23 @@ type Contact struct {
Facts fact.FactList Facts fact.FactList
} }
// Marshal saves the Contact in a compact byte slice. The byte slice has // Marshal saves the Contact in a compact binary format with base 64 encoding.
// the following structure (not to scale). // The data has a header and footer that specify the format version and allow
// the data to be recognized in a stream of data. The format has the following
// structure.
// //
// +----------+----------------+---------+----------+----------+----------------+----------+ // +----------------+---------------------------------------------------------------------------------------+--------+
// | DhPubKey | OwnershipProof | Facts | ID | | | | // | header | contact data | footer |
// | size | size | size | | DhPubKey | OwnershipProof | FactList | // +------+---------+----------+----------------+---------+----------+----------+----------------+----------+--------+
// | 2 bytes | 2 bytes | 2 bytes | 33 bytes | | | | // | Open | | DhPubKey | OwnershipProof | Facts | ID | | | | Close |
// +----------+----------------+---------+----------+----------+----------------+----------+ // | Tag | Version | size | size | size | | DhPubKey | OwnershipProof | FactList | Tag |
// | | | 2 bytes | 2 bytes | 2 bytes | 33 bytes | | | | |
// +------+---------+----------+----------------+---------+----------+----------+----------------+----------+--------+
// | string | base 64 encoded | string |
// +----------------+---------------------------------------------------------------------------------------+--------+
func (c Contact) Marshal() []byte { func (c Contact) Marshal() []byte {
var buff bytes.Buffer var buff bytes.Buffer
b := make([]byte, sizeByteLength) b := make([]byte, sizeLength)
// Write size of DhPubKey // Write size of DhPubKey
var dhPubKey []byte var dhPubKey []byte
...@@ -77,30 +93,65 @@ func (c Contact) Marshal() []byte { ...@@ -77,30 +93,65 @@ func (c Contact) Marshal() []byte {
// Write fact list // Write fact list
buff.Write([]byte(factList)) buff.Write([]byte(factList))
return buff.Bytes() // Base 64 encode buffer
encodedBuff := make([]byte, base64.StdEncoding.EncodedLen(buff.Len()))
base64.StdEncoding.Encode(encodedBuff, buff.Bytes())
// Add header tag, version number, and footer tag
encodedBuff = append([]byte(headTag+openVerTag+version+closeVerTag), encodedBuff...)
encodedBuff = append(encodedBuff, []byte(footTag)...)
return encodedBuff
} }
// Unmarshal decodes the byte slice produced by Contact.Marshal into a Contact. // Unmarshal decodes the byte slice produced by Contact.Marshal into a Contact.
func Unmarshal(b []byte) (Contact, error) { func Unmarshal(b []byte) (Contact, error) {
if len(b) < sizeByteLength*3+id.ArrIDLen { if len(b) < minLength {
return Contact{}, errors.Errorf("Length of provided buffer (%d) too "+ return Contact{}, errors.Errorf("Length of provided buffer (%d) too "+
"short; length must be at least %d.", "short; length must be at least %d.",
len(b), sizeByteLength*3+id.ArrIDLen) len(b), minLength)
} }
c := Contact{DhPubKey: &cyclic.Int{}}
var err error var err error
buff := bytes.NewBuffer(b)
// Get data from between the header and footer tags
b, err = getTagContents(b, headTag, footTag)
if err != nil {
return Contact{}, errors.Errorf("data not found: %+v", err)
}
// Check that the version matches
currentVersion, err := getTagContents(b, openVerTag, closeVerTag)
if string(currentVersion) != version {
return Contact{}, errors.Errorf("found version %s incomptible, "+
"requires version %s", string(currentVersion), version)
}
// Strip version number
b = b[len(currentVersion)+len(openVerTag)+len(closeVerTag):]
// Create new decoder
decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewReader(b))
// Create a new buffer from the data found between the open and close tags
var buff bytes.Buffer
_, err = buff.ReadFrom(decoder)
if err != nil {
return Contact{}, errors.Errorf("failed to read from decoder: %+v", err)
}
// Get size of each field // Get size of each field
dhPubKeySize, _ := binary.Varint(buff.Next(sizeByteLength)) dhPubKeySize, _ := binary.Varint(buff.Next(sizeLength))
ownershipProofSize, _ := binary.Varint(buff.Next(sizeByteLength)) ownershipProofSize, _ := binary.Varint(buff.Next(sizeLength))
factsSize, _ := binary.Varint(buff.Next(sizeByteLength)) factsSize, _ := binary.Varint(buff.Next(sizeLength))
// Create empty client
c := Contact{DhPubKey: &cyclic.Int{}}
// Get and unmarshal ID // Get and unmarshal ID
c.ID, err = id.Unmarshal(buff.Next(id.ArrIDLen)) c.ID, err = id.Unmarshal(buff.Next(id.ArrIDLen))
if err != nil { if err != nil {
return Contact{}, errors.Errorf("Failed to unmarshal Contact ID: %+v", err) return Contact{}, errors.Errorf("failed to unmarshal Contact ID: %+v", err)
} }
// Handle nil ID // Handle nil ID
...@@ -114,7 +165,7 @@ func Unmarshal(b []byte) (Contact, error) { ...@@ -114,7 +165,7 @@ func Unmarshal(b []byte) (Contact, error) {
c.DhPubKey = nil c.DhPubKey = nil
} else { } else {
if err = c.DhPubKey.BinaryDecode(buff.Next(int(dhPubKeySize))); err != nil { if err = c.DhPubKey.BinaryDecode(buff.Next(int(dhPubKeySize))); err != nil {
return Contact{}, errors.Errorf("Failed to binary decode Contact DhPubKey: %+v", err) return Contact{}, errors.Errorf("failed to binary decode Contact DhPubKey: %+v", err)
} }
} }
...@@ -129,7 +180,7 @@ func Unmarshal(b []byte) (Contact, error) { ...@@ -129,7 +180,7 @@ func Unmarshal(b []byte) (Contact, error) {
// Get and unstringify fact list // Get and unstringify fact list
c.Facts, _, err = fact.UnstringifyFactList(string(buff.Next(int(factsSize)))) c.Facts, _, err = fact.UnstringifyFactList(string(buff.Next(int(factsSize))))
if err != nil { if err != nil {
return Contact{}, errors.Errorf("Failed to unstringify Contact fact list: %+v", err) return Contact{}, errors.Errorf("failed to unstringify Contact fact list: %+v", err)
} }
return c, nil return c, nil
...@@ -151,6 +202,23 @@ func (c Contact) GetFingerprint() string { ...@@ -151,6 +202,23 @@ func (c Contact) GetFingerprint() string {
return base64.StdEncoding.EncodeToString(data)[:fingerprintLength] return base64.StdEncoding.EncodeToString(data)[:fingerprintLength]
} }
// MakeQR generates a QR code PNG of the Contact.
func (c Contact) MakeQR(size int, level qrcode.RecoveryLevel) ([]byte, error) {
qrCode, err := qrcode.Encode(string(c.Marshal()), level, size)
if err != nil {
return nil, errors.Errorf("failed to encode contact to QR code: %v", err)
}
return qrCode, nil
}
func (c Contact) String() string {
return "ID: " + c.ID.String() +
" DhPubKey: " + c.DhPubKey.Text(10) +
" OwnershipProof: " + base64.StdEncoding.EncodeToString(c.OwnershipProof) +
" Facts: " + c.Facts.Stringify()
}
// Equal determines if the two contacts have the same values. // Equal determines if the two contacts have the same values.
func Equal(a, b Contact) bool { func Equal(a, b Contact) bool {
return a.ID.Cmp(b.ID) && return a.ID.Cmp(b.ID) &&
...@@ -158,3 +226,26 @@ func Equal(a, b Contact) bool { ...@@ -158,3 +226,26 @@ func Equal(a, b Contact) bool {
bytes.Equal(a.OwnershipProof, b.OwnershipProof) && bytes.Equal(a.OwnershipProof, b.OwnershipProof) &&
a.Facts.Stringify() == b.Facts.Stringify() a.Facts.Stringify() == b.Facts.Stringify()
} }
// getTagContents returns the bytes between the two tags. An error is returned
// if one ore more tags cannot be found or closing tag precedes the opening tag.
func getTagContents(b []byte, openTag, closeTag string) ([]byte, error) {
// Search for opening tag
openIndex := strings.Index(string(b), openTag)
if openIndex < 0 {
return nil, errors.New("missing opening tag")
}
// Search for closing tag
closeIndex := strings.Index(string(b), closeTag)
if closeIndex < 0 {
return nil, errors.New("missing closing tag")
}
// Return an error if the closing tag comes first
if openIndex > closeIndex {
return nil, errors.New("tags in wrong order")
}
return b[openIndex+len(openTag) : closeIndex], nil
}
This diff is collapsed.
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
// LICENSE file // // LICENSE file //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Handles functionality related to providing Gateway connect.Host objects
// for message sending to the rest of the client repo
package gateway package gateway
import ( import (
...@@ -106,8 +109,13 @@ func (h *HostPool) UpdateNdf(ndf *ndf.NetworkDefinition) { ...@@ -106,8 +109,13 @@ func (h *HostPool) UpdateNdf(ndf *ndf.NetworkDefinition) {
} }
// Obtain a random, unique list of Hosts of the given length from the HostPool // Obtain a random, unique list of Hosts of the given length from the HostPool
func (h *HostPool) GetAnyList(length int) []*connect.Host { func (h *HostPool) GetAny(length int) []*connect.Host {
checked := make(map[uint32]interface{}) checked := make(map[uint32]interface{}) // Keep track of Hosts already selected to avoid duplicates
if length > int(h.poolParams.poolSize) {
length = int(h.poolParams.poolSize)
}
result := make([]*connect.Host, length)
h.hostMux.RLock() h.hostMux.RLock()
if len(h.hostList) <= length { if len(h.hostList) <= length {
length = len(h.hostList) length = len(h.hostList)
...@@ -128,23 +136,23 @@ func (h *HostPool) GetAnyList(length int) []*connect.Host { ...@@ -128,23 +136,23 @@ func (h *HostPool) GetAnyList(length int) []*connect.Host {
return result return result
} }
// Obtain a specific list of Hosts from the manager, irrespective of the HostPool // Obtain a specific connect.Host from the manager, irrespective of the HostPool
func (h *HostPool) GetSpecific(targets []*id.ID) []*connect.Host { func (h *HostPool) GetSpecific(target *id.ID) (*connect.Host, bool) {
result := make([]*connect.Host, len(targets)) return h.manager.GetHost(target)
for i := 0; i < len(targets); i++ {
result[i], _ = h.manager.GetHost(targets[i])
}
return result
} }
// Try to obtain the given targets from the HostPool // Try to obtain the given targets from the HostPool
// If each is not present, obtain a random replacement from the HostPool // If each is not present, obtain a random replacement from the HostPool
func (h *HostPool) GetPreferred(targets []*id.ID) []*connect.Host { func (h *HostPool) GetPreferred(targets []*id.ID) []*connect.Host {
checked := make(map[uint32]interface{}) // Keep track of Hosts already selected to avoid duplicates checked := make(map[uint32]interface{}) // Keep track of Hosts already selected to avoid duplicates
result := make([]*connect.Host, len(targets)) length := len(targets)
if length > int(h.poolParams.poolSize) {
length = int(h.poolParams.poolSize)
}
result := make([]*connect.Host, length)
h.hostMux.RLock() h.hostMux.RLock()
for i := 0; i < len(targets); i++ { for i := 0; i < length; {
if hostIdx, ok := h.hostMap[*targets[i]]; ok { if hostIdx, ok := h.hostMap[*targets[i]]; ok {
result[i] = h.hostList[hostIdx] result[i] = h.hostList[hostIdx]
i++ i++
......
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2021 Privategrity Corporation /
// /
// All rights reserved. /
////////////////////////////////////////////////////////////////////////////////
// Contains gateway message sending wrappers
package gateway
import (
"github.com/pkg/errors"
"gitlab.com/xx_network/comms/connect"
"gitlab.com/xx_network/primitives/id"
)
// Object used for sending that wraps the HostPool for providing destinations
type Mesh struct {
HostPool
}
// Call given sendFunc to a specific Host in the HostPool,
// attempting with up to numProxies destinations in case of failure
func (m *Mesh) SendToSpecific(target *id.ID, numProxies int,
sendFunc func(host *connect.Host) (interface{}, error)) (interface{}, error) {
host, ok := m.GetSpecific(target)
if ok {
result, err := sendFunc(host)
if err == nil {
return result, m.ForceAdd([]*id.ID{host.GetId()})
}
}
return m.SendToAny(numProxies, sendFunc)
}
// Call given sendFunc to any Host in the HostPool, attempting with up to numProxies destinations
func (m *Mesh) SendToAny(numProxies int,
sendFunc func(host *connect.Host) (interface{}, error)) (interface{}, error) {
proxies := m.GetAny(numProxies)
for _, proxy := range proxies {
result, err := sendFunc(proxy)
if err == nil {
return result, nil
}
}
return nil, errors.Errorf("Unable to send to any proxies")
}
...@@ -32,7 +32,8 @@ type sendCmixCommsInterface interface { ...@@ -32,7 +32,8 @@ type sendCmixCommsInterface interface {
SendPutMessage(host *connect.Host, message *pb.GatewaySlot) (*pb.GatewaySlotResponse, error) SendPutMessage(host *connect.Host, message *pb.GatewaySlot) (*pb.GatewaySlotResponse, error)
} }
const sendTimeBuffer = 500 * time.Millisecond // 1.5 seconds
const sendTimeBuffer = 1500 * time.Millisecond
// WARNING: Potentially Unsafe // WARNING: Potentially Unsafe
// Public manager function to send a message over CMIX // Public manager function to send a message over CMIX
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment