whisper: final update

This commit is contained in:
Vlad 2017-03-14 23:59:54 +01:00
parent b26af42b63
commit c6e0e93672
5 changed files with 94 additions and 18 deletions

View file

@ -32,6 +32,10 @@ import (
"strings" "strings"
"time" "time"
"io/ioutil"
"path/filepath"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/console" "github.com/ethereum/go-ethereum/console"
@ -80,6 +84,7 @@ var (
asymmetricMode = flag.Bool("a", false, "use asymmetric encryption") asymmetricMode = flag.Bool("a", false, "use asymmetric encryption")
testMode = flag.Bool("t", false, "use of predefined parameters for diagnostics") testMode = flag.Bool("t", false, "use of predefined parameters for diagnostics")
generateKey = flag.Bool("k", false, "generate and show the private key") generateKey = flag.Bool("k", false, "generate and show the private key")
fileExMode = flag.Bool("x", false, "file exchange mode")
argVerbosity = flag.Int("verbosity", int(log.LvlWarn), "log verbosity level") argVerbosity = flag.Int("verbosity", int(log.LvlWarn), "log verbosity level")
argTTL = flag.Uint("ttl", 30, "time-to-live for messages in seconds") argTTL = flag.Uint("ttl", 30, "time-to-live for messages in seconds")
@ -93,6 +98,7 @@ var (
argIDFile = flag.String("idfile", "", "file name with node id (private key)") argIDFile = flag.String("idfile", "", "file name with node id (private key)")
argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://e454......08d50@52.176.211.200:16428)") argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://e454......08d50@52.176.211.200:16428)")
argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)") argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)")
argSaveDir = flag.String("savedir", "", "directory where incoming messages will be saved as files")
) )
func main() { func main() {
@ -134,6 +140,14 @@ func processArgs() {
} }
} }
if len(*argSaveDir) > 0 {
if _, err := os.Stat(*argSaveDir); os.IsNotExist(err) {
utils.Fatalf("Download directory '%s' does not exist", *argSaveDir)
}
} else if *fileExMode {
utils.Fatalf("Parameter 'savedir' is mandatory for file exchange mode")
}
if *echoMode { if *echoMode {
echo() echo()
} }
@ -374,6 +388,8 @@ func run() {
if *requestMail { if *requestMail {
requestExpiredMessagesLoop() requestExpiredMessagesLoop()
} else if *fileExMode {
sendFilesLoop()
} else { } else {
sendLoop() sendLoop()
} }
@ -399,6 +415,31 @@ func sendLoop() {
} }
} }
func sendFilesLoop() {
for {
s := scanLine("")
if s == quitCommand {
fmt.Println("Quit command received")
close(done)
break
}
b, err := ioutil.ReadFile(s)
if err != nil {
fmt.Printf(">>> Error: %s \n", err)
continue
} else {
h := sendMsg(b)
if (h == common.Hash{}) {
fmt.Printf(">>> Error: message was not sent \n")
} else {
timestamp := time.Now().Unix()
from := crypto.PubkeyToAddress(asymKey.PublicKey)
fmt.Printf("\n%d <%x>: sent message with hash %x\n", timestamp, from, h)
}
}
}
}
func scanLine(prompt string) string { func scanLine(prompt string) string {
if len(prompt) > 0 { if len(prompt) > 0 {
fmt.Print(prompt) fmt.Print(prompt)
@ -425,7 +466,7 @@ func scanUint(prompt string) uint32 {
return uint32(i) return uint32(i)
} }
func sendMsg(payload []byte) { func sendMsg(payload []byte) common.Hash {
params := whisper.MessageParams{ params := whisper.MessageParams{
Src: asymKey, Src: asymKey,
Dst: pub, Dst: pub,
@ -441,13 +482,16 @@ func sendMsg(payload []byte) {
envelope, err := msg.Wrap(&params) envelope, err := msg.Wrap(&params)
if err != nil { if err != nil {
fmt.Printf("failed to seal message: %v \n", err) fmt.Printf("failed to seal message: %v \n", err)
return return common.Hash{}
} }
err = shh.Send(envelope) err = shh.Send(envelope)
if err != nil { if err != nil {
fmt.Printf("failed to send message: %v \n", err) fmt.Printf("failed to send message: %v \n", err)
return common.Hash{}
} }
return envelope.Hash()
} }
func messageLoop() { func messageLoop() {
@ -463,8 +507,12 @@ func messageLoop() {
case <-ticker.C: case <-ticker.C:
messages := f.Retrieve() messages := f.Retrieve()
for _, msg := range messages { for _, msg := range messages {
if *fileExMode {
saveMessageInFile(msg)
} else {
printMessageInfo(msg) printMessageInfo(msg)
} }
}
case <-done: case <-done:
return return
} }
@ -487,6 +535,29 @@ func printMessageInfo(msg *whisper.ReceivedMessage) {
} }
} }
func saveMessageInFile(msg *whisper.ReceivedMessage) {
timestamp := fmt.Sprintf("%d", msg.Sent)
name := fmt.Sprintf("%x", msg.EnvelopeHash)
var address common.Address
if msg.Src != nil {
address = crypto.PubkeyToAddress(*msg.Src)
}
if whisper.IsPubKeyEqual(msg.Src, &asymKey.PublicKey) {
// message from myself: don't save, only report
fmt.Printf("\n%s <%x>: message received: '%s'\n", timestamp, address, name)
} else {
fullpath := filepath.Join(*argSaveDir, name)
err := ioutil.WriteFile(fullpath, msg.Payload, 0644)
if err != nil {
fmt.Printf("\n%s [%x]: message received but not saved: %s\n", timestamp, address, err)
} else {
fmt.Printf("\n%s [%x]: message received and saved as '%s'\n", timestamp, address, name)
}
}
}
func requestExpiredMessagesLoop() { func requestExpiredMessagesLoop() {
var key, peerID []byte var key, peerID []byte
var timeLow, timeUpp uint32 var timeLow, timeUpp uint32
@ -502,7 +573,7 @@ func requestExpiredMessagesLoop() {
utils.Fatalf("Failed to save symmetric key for mail request: %s", err) utils.Fatalf("Failed to save symmetric key for mail request: %s", err)
} }
peerID = extractIdFromEnode(*argEnode) peerID = extractIdFromEnode(*argEnode)
shh.MarkPeerTrusted(peerID) shh.AllowP2PMessagesFromPeer(peerID)
for { for {
timeLow = scanUint("Please enter the lower limit of the time range (unix timestamp): ") timeLow = scanUint("Please enter the lower limit of the time range (unix timestamp): ")

View file

@ -86,13 +86,19 @@ func (api *PublicWhisperAPI) SetMinimumPoW(val float64) error {
return api.whisper.SetMinimumPoW(val) return api.whisper.SetMinimumPoW(val)
} }
// MarkPeerTrusted marks specific peer trusted, which will allow it // AllowP2PMessagesFromPeer marks specific peer trusted, which will allow it
// to send historic (expired) messages. // to send historic (expired) messages.
func (api *PublicWhisperAPI) MarkPeerTrusted(peerID hexutil.Bytes) error { func (api *PublicWhisperAPI) AllowP2PMessagesFromPeer(enode string) error {
if api.whisper == nil { if api.whisper == nil {
return whisperOffLineErr return whisperOffLineErr
} }
return api.whisper.MarkPeerTrusted(peerID) n, err := discover.ParseNode(enode)
if err != nil {
info := "Failed to parse enode of trusted peer: " + err.Error()
log.Error(info)
return errors.New(info)
}
return api.whisper.AllowP2PMessagesFromPeer(n.ID[:])
} }
// RequestHistoricMessages requests the peer to deliver the old (expired) messages. // RequestHistoricMessages requests the peer to deliver the old (expired) messages.

View file

@ -57,7 +57,7 @@ const (
keyIdSize = 32 keyIdSize = 32
DefaultMaxMessageLength = 1024 * 1024 DefaultMaxMessageLength = 1024 * 1024
DefaultMinimumPoW = 10.0 // todo: review after testing. DefaultMinimumPoW = 2.0 // todo: review after testing.
padSizeLimitLower = 128 // it can not be less - we don't want to reveal the absence of signature padSizeLimitLower = 128 // it can not be less - we don't want to reveal the absence of signature
padSizeLimitUpper = 256 // just an arbitrary number, could be changed without losing compatibility padSizeLimitUpper = 256 // just an arbitrary number, could be changed without losing compatibility

View file

@ -78,7 +78,6 @@ type Whisper struct {
func New() *Whisper { func New() *Whisper {
whisper := &Whisper{ whisper := &Whisper{
privateKeys: make(map[string]*ecdsa.PrivateKey), privateKeys: make(map[string]*ecdsa.PrivateKey),
//identities: make(map[string]*ecdsa.PrivateKey),
symKeys: make(map[string][]byte), symKeys: make(map[string][]byte),
envelopes: make(map[common.Hash]*Envelope), envelopes: make(map[common.Hash]*Envelope),
expirations: make(map[uint32]*set.SetNonTS), expirations: make(map[uint32]*set.SetNonTS),
@ -158,7 +157,7 @@ func (w *Whisper) getPeer(peerID []byte) (*Peer, error) {
// MarkPeerTrusted marks specific peer trusted, which will allow it // MarkPeerTrusted marks specific peer trusted, which will allow it
// to send historic (expired) messages. // to send historic (expired) messages.
func (w *Whisper) MarkPeerTrusted(peerID []byte) error { func (w *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error {
p, err := w.getPeer(peerID) p, err := w.getPeer(peerID)
if err != nil { if err != nil {
return err return err

View file

@ -52,7 +52,7 @@ func TestWhisperBasic(t *testing.T) {
if peer != nil { if peer != nil {
t.Fatal("found peer for random key.") t.Fatal("found peer for random key.")
} }
if err := w.MarkPeerTrusted(peerID); err == nil { if err := w.AllowP2PMessagesFromPeer(peerID); err == nil {
t.Fatalf("failed MarkPeerTrusted.") t.Fatalf("failed MarkPeerTrusted.")
} }
exist := w.HasSymKey("non-existing") exist := w.HasSymKey("non-existing")