112 lines
3.3 KiB
Go
112 lines
3.3 KiB
Go
package tokenboard
|
|
|
|
import (
|
|
"cwtch.im/tapir"
|
|
"cwtch.im/tapir/applications"
|
|
"cwtch.im/tapir/primitives/auditable"
|
|
"cwtch.im/tapir/primitives/privacypass"
|
|
"encoding/json"
|
|
"git.openprivacy.ca/openprivacy/log"
|
|
)
|
|
|
|
// NewTokenBoardClient generates a new Client for Token Board
|
|
func NewTokenBoardClient(store *auditable.Store, handler AppHandler, paymentHandler privacypass.TokenPaymentHandler) tapir.Application {
|
|
tba := new(Client)
|
|
tba.AuditableStore = store
|
|
tba.handler = handler
|
|
tba.paymentHandler = paymentHandler
|
|
return tba
|
|
}
|
|
|
|
// Client defines a client for the TokenBoard server
|
|
type Client struct {
|
|
applications.AuthApp
|
|
connection tapir.Connection
|
|
AuditableStore *auditable.Store
|
|
paymentHandler privacypass.TokenPaymentHandler
|
|
handler AppHandler
|
|
}
|
|
|
|
// NewInstance Client a new TokenBoardApp
|
|
func (ta *Client) NewInstance() tapir.Application {
|
|
tba := new(Client)
|
|
tba.AuditableStore = ta.AuditableStore
|
|
tba.handler = ta.handler
|
|
tba.paymentHandler = ta.paymentHandler
|
|
return tba
|
|
}
|
|
|
|
// Init initializes the cryptographic TokenBoardApp
|
|
func (ta *Client) Init(connection tapir.Connection) {
|
|
ta.AuthApp.Init(connection)
|
|
|
|
if connection.HasCapability(applications.AuthCapability) {
|
|
ta.connection = connection
|
|
go ta.Listen()
|
|
return
|
|
}
|
|
connection.Close()
|
|
}
|
|
|
|
// Listen processes the messages for this application
|
|
func (ta *Client) Listen() {
|
|
for {
|
|
log.Debugf("Client waiting...")
|
|
data := ta.connection.Expect()
|
|
if len(data) == 0 {
|
|
log.Debugf("Server closed the connection...")
|
|
return // connection is closed
|
|
}
|
|
|
|
var message Message
|
|
json.Unmarshal(data, &message)
|
|
switch message.MessageType {
|
|
case postResultMessage:
|
|
log.Debugf("Post result: %x", message.PostResult.Proof)
|
|
case replayResultMessage:
|
|
var state auditable.State
|
|
log.Debugf("Replaying %v Messages...", message.ReplayResult.NumMessages)
|
|
lastCommit := ta.AuditableStore.LatestCommit
|
|
for i := 0; i < message.ReplayResult.NumMessages; i++ {
|
|
message := ta.connection.Expect()
|
|
state.Messages = append(state.Messages, message)
|
|
}
|
|
data := ta.connection.Expect()
|
|
var signedProof auditable.SignedProof
|
|
json.Unmarshal(data, &signedProof)
|
|
state.SignedProof = signedProof
|
|
err := ta.AuditableStore.AppendState(state)
|
|
if err == nil {
|
|
log.Debugf("Successfully updated Auditable Store %v", ta.AuditableStore.LatestCommit)
|
|
ta.handler.HandleNewMessages(lastCommit)
|
|
} else {
|
|
log.Debugf("Error updating Auditable Store %v", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Replay posts a Replay Message to the server.
|
|
func (ta *Client) Replay() {
|
|
log.Debugf("Sending replay request for %v", ta.AuditableStore.LatestCommit)
|
|
data, _ := json.Marshal(Message{MessageType: replayRequestMessage, ReplayRequest: replayRequest{LastCommit: ta.AuditableStore.LatestCommit}})
|
|
ta.connection.Send(data)
|
|
}
|
|
|
|
// PurchaseTokens purchases the given number of tokens from the server (using the provided payment handler)
|
|
func (ta *Client) PurchaseTokens() {
|
|
ta.paymentHandler.MakePayment()
|
|
}
|
|
|
|
// Post sends a Post Request to the server
|
|
func (ta *Client) Post(message auditable.Message) bool {
|
|
token, err := ta.paymentHandler.NextToken(message, ta.connection.Hostname())
|
|
if err == nil {
|
|
data, _ := json.Marshal(Message{MessageType: postRequestMessage, PostRequest: postRequest{Token: token, Message: message}})
|
|
ta.connection.Send(data)
|
|
return true
|
|
}
|
|
log.Debugf("No Valid Tokens: %v", err)
|
|
return false
|
|
}
|