mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
whisper: grouped variables, added a server stub
This commit is contained in:
parent
556992d503
commit
fab165ead9
1 changed files with 239 additions and 59 deletions
|
|
@ -1,21 +1,21 @@
|
||||||
// Copyright 2016 The go-ethereum Authors
|
// Copyright 2016 The go-ethereum Authors
|
||||||
// This file is part of the go-ethereum library.
|
// This file is part of go-ethereum.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
// go-ethereum is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (at your option) any later version.
|
||||||
//
|
//
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
// go-ethereum is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU Lesser General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// This is a simple Whisper node.
|
// This is a simple Whisper node. It could be used as a stand-alone bootstrap node.
|
||||||
// It also implements a command line chat between the peers sharing the same credentials.
|
// Also, could be used for different test and diagnostics purposes.
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -41,35 +42,62 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
whisper "github.com/ethereum/go-ethereum/whisper/whisperv5"
|
whisper "github.com/ethereum/go-ethereum/whisper/whisperv5"
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var done chan struct{}
|
const sizeOfInt = 4
|
||||||
var server *p2p.Server
|
|
||||||
var shh *whisper.Whisper
|
|
||||||
var asymKey, nodeid *ecdsa.PrivateKey // used for asymmetric decryption and signing
|
|
||||||
var pub *ecdsa.PublicKey // used for asymmetric encryption
|
|
||||||
var symKey []byte // used for symmetric encryption
|
|
||||||
var filterID uint32
|
|
||||||
var topic whisper.TopicType
|
|
||||||
var pow float64 = whisper.MinimumPoW
|
|
||||||
var ttl uint32 = 30
|
|
||||||
var workTime uint32 = 5
|
|
||||||
var ipAddress, enode, salt, topicStr, pubStr, NodeIdFile string
|
|
||||||
var input *bufio.Reader = bufio.NewReader(os.Stdin)
|
|
||||||
|
|
||||||
var bootstrapNode bool // does not actively connect to peers, wait for incoming connections
|
// singletons
|
||||||
var daemonMode bool // only forward messages, neither send nor track
|
var (
|
||||||
var testMode bool // predefined password, topic, ip and port
|
server *p2p.Server
|
||||||
var echoMode bool // shows params, etc.
|
shh *whisper.Whisper
|
||||||
var isAsymmetric bool
|
mailServer WMailServer
|
||||||
|
|
||||||
|
done chan struct{}
|
||||||
|
input *bufio.Reader = bufio.NewReader(os.Stdin)
|
||||||
|
)
|
||||||
|
|
||||||
|
// encryption/decryption
|
||||||
|
var (
|
||||||
|
pub *ecdsa.PublicKey
|
||||||
|
asymKey *ecdsa.PrivateKey
|
||||||
|
nodeid *ecdsa.PrivateKey
|
||||||
|
symKey []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
// parameters
|
||||||
|
var (
|
||||||
|
filterID uint32
|
||||||
|
topic whisper.TopicType
|
||||||
|
ttl uint32 = 30
|
||||||
|
workTime uint32 = 5
|
||||||
|
msPoW float64
|
||||||
|
timeLow uint32
|
||||||
|
timeUpp uint32
|
||||||
|
pow float64 = whisper.MinimumPoW
|
||||||
|
|
||||||
|
ipAddress, enode, salt, topicStr, pubStr, NodeIdFile, dbPath, msPassword string
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
bootstrapMode bool // does not actively connect to peers, wait for incoming connections
|
||||||
|
forwarderMode bool // only forward messages, neither send nor track
|
||||||
|
mailServerMode bool // delivers expired messages on demand
|
||||||
|
testMode bool // predefined password, topic, ip and port
|
||||||
|
echoMode bool // shows params, etc.
|
||||||
|
isAsymmetric bool
|
||||||
|
requestMail bool
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
argNameHelp = "-h"
|
argNameHelp = "-h"
|
||||||
argNameBootstrap = "-b"
|
argBootstrapMode = "-b"
|
||||||
argNameDaemon = "-d"
|
argNameForwarder = "-f"
|
||||||
argNameAsymmetric = "-a"
|
argNameAsymmetric = "-a"
|
||||||
|
argMailServerMode = "-m"
|
||||||
|
argRequestMail = "-r"
|
||||||
argNameTest = "-test"
|
argNameTest = "-test"
|
||||||
argNameEcho = "-echo"
|
argNameEcho = "-echo"
|
||||||
argNameWorkTime = "-work"
|
argNameWorkTime = "-work"
|
||||||
|
|
@ -79,11 +107,23 @@ var (
|
||||||
argNamePoW = "-pow"
|
argNamePoW = "-pow"
|
||||||
argNameSalt = "-salt"
|
argNameSalt = "-salt"
|
||||||
argNamePub = "-pub"
|
argNamePub = "-pub"
|
||||||
argNameEnode = "-enode"
|
argNameBoot = "-boot"
|
||||||
argNameIdSrc = "-idfile"
|
argNameIdSrc = "-idfile"
|
||||||
|
argNameDbPath = "-dbpath"
|
||||||
|
argNameMSPoW = "-mspow"
|
||||||
|
|
||||||
quitCommand = "~Q"
|
quitCommand = "~Q"
|
||||||
|
enodePrefix = "enode://"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// this is a temporary stub, will be expanded later
|
||||||
|
type WMailServer struct{}
|
||||||
|
|
||||||
|
func (s *WMailServer) Archive(env *whisper.Envelope) {}
|
||||||
|
func (s *WMailServer) DeliverMail(peer *whisper.Peer, data []byte) {}
|
||||||
|
func (s *WMailServer) Init(w *whisper.Whisper, path string, password string, pow float64) {}
|
||||||
|
func (s *WMailServer) Close() {}
|
||||||
|
|
||||||
func padRight(str string) string {
|
func padRight(str string) string {
|
||||||
res := str
|
res := str
|
||||||
for len(res) < 9 {
|
for len(res) < 9 {
|
||||||
|
|
@ -93,14 +133,14 @@ func padRight(str string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func printHelp() {
|
func printHelp() {
|
||||||
fmt.Println("wchat is a stand-alone whisper node with command-line interface.")
|
fmt.Println("wnode is a stand-alone whisper node with command-line interface.")
|
||||||
fmt.Println("wchat also allows to set up a chat using either symmetric or asymmetric encryption.")
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("usage: wchat [arguments]")
|
fmt.Println("usage: wnode [arguments]")
|
||||||
fmt.Printf(" %s print this help and exit \n", padRight(argNameHelp))
|
fmt.Printf(" %s print this help and exit \n", padRight(argNameHelp))
|
||||||
fmt.Printf(" %s boostrap node: don't actively connect to peers, wait for incoming connections\n", padRight(argNameBootstrap))
|
fmt.Printf(" %s boostrap node: don't actively connect to peers, wait for incoming connections\n", padRight(argBootstrapMode))
|
||||||
fmt.Printf(" %s daemon mode: only forward messages, neither send nor decrypt messages \n", padRight(argNameDaemon))
|
fmt.Printf(" %s forwarder mode: only forward messages, neither send nor decrypt messages \n", padRight(argNameForwarder))
|
||||||
fmt.Printf(" %s use asymmetric encryption \n", padRight(argNameAsymmetric))
|
fmt.Printf(" %s use asymmetric encryption \n", padRight(argNameAsymmetric))
|
||||||
|
fmt.Printf(" %s mail server mode: delivers expired messages on demand \n", padRight(argMailServerMode))
|
||||||
fmt.Printf(" %s test mode: predefined password, salt, topic, ip and port \n", padRight(argNameTest))
|
fmt.Printf(" %s test mode: predefined password, salt, topic, ip and port \n", padRight(argNameTest))
|
||||||
fmt.Printf(" %s echo mode: prints arguments (diagnostic) \n", padRight(argNameEcho))
|
fmt.Printf(" %s echo mode: prints arguments (diagnostic) \n", padRight(argNameEcho))
|
||||||
fmt.Printf(" %s IP address and port of this node (e.g. %s=127.0.0.1:30303) \n", padRight(argNameIP), argNameIP)
|
fmt.Printf(" %s IP address and port of this node (e.g. %s=127.0.0.1:30303) \n", padRight(argNameIP), argNameIP)
|
||||||
|
|
@ -111,7 +151,10 @@ func printHelp() {
|
||||||
fmt.Printf(" %s topic in hexadecimal format (e.g. %s=70a4beef) \n", padRight(argNameTopic), argNameTopic)
|
fmt.Printf(" %s topic in hexadecimal format (e.g. %s=70a4beef) \n", padRight(argNameTopic), argNameTopic)
|
||||||
fmt.Printf(" %s public key for asymmetric encryption \n", padRight(argNamePub))
|
fmt.Printf(" %s public key for asymmetric encryption \n", padRight(argNamePub))
|
||||||
fmt.Printf(" %s file name with node id (private key) \n", padRight(argNameIdSrc))
|
fmt.Printf(" %s file name with node id (private key) \n", padRight(argNameIdSrc))
|
||||||
fmt.Printf(" %s enode \n", padRight(argNameEnode))
|
fmt.Printf(" %s path to the DB directory \n", padRight(argNameDbPath))
|
||||||
|
fmt.Printf(" %s PoW requirement for Mail Server (int) \n", padRight(argNameMSPoW))
|
||||||
|
fmt.Printf(" %s request old (expired) messages from the bootstrap server \n", padRight(argRequestMail))
|
||||||
|
fmt.Printf(" %s bootstrap node you want to connect to (e.g. %s=enode://e454......08d50@52.176.211.200:16428) \n", padRight(argNameBoot), argNameBoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -122,7 +165,7 @@ func main() {
|
||||||
|
|
||||||
func parseArgs() {
|
func parseArgs() {
|
||||||
var err error
|
var err error
|
||||||
var p uint32
|
var p, x uint32
|
||||||
help1 := checkMode(argNameHelp)
|
help1 := checkMode(argNameHelp)
|
||||||
help2 := checkMode("-help")
|
help2 := checkMode("-help")
|
||||||
help3 := checkMode("--help")
|
help3 := checkMode("--help")
|
||||||
|
|
@ -132,21 +175,25 @@ func parseArgs() {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
bootstrapNode = checkMode(argNameBootstrap)
|
bootstrapMode = checkMode(argBootstrapMode)
|
||||||
daemonMode = checkMode(argNameDaemon)
|
forwarderMode = checkMode(argNameForwarder)
|
||||||
|
mailServerMode = checkMode(argMailServerMode)
|
||||||
testMode = checkMode(argNameTest)
|
testMode = checkMode(argNameTest)
|
||||||
echoMode = checkMode(argNameEcho)
|
echoMode = checkMode(argNameEcho)
|
||||||
isAsymmetric = checkMode(argNameAsymmetric)
|
isAsymmetric = checkMode(argNameAsymmetric)
|
||||||
|
requestMail = checkMode(argRequestMail)
|
||||||
|
|
||||||
checkIntArg(argNameTTL, &ttl)
|
checkIntArg(argNameTTL, &ttl)
|
||||||
checkIntArg(argNameWorkTime, &workTime)
|
checkIntArg(argNameWorkTime, &workTime)
|
||||||
checkIntArg(argNamePoW, &p)
|
checkIntArg(argNamePoW, &p)
|
||||||
|
checkIntArg(argNameMSPoW, &x)
|
||||||
checkStringArg(argNameIP, &ipAddress)
|
checkStringArg(argNameIP, &ipAddress)
|
||||||
checkStringArg(argNameEnode, &enode)
|
checkStringArg(argNameBoot, &enode)
|
||||||
checkStringArg(argNameSalt, &salt)
|
checkStringArg(argNameSalt, &salt)
|
||||||
checkStringArg(argNameTopic, &topicStr)
|
checkStringArg(argNameTopic, &topicStr)
|
||||||
checkStringArg(argNamePub, &pubStr)
|
checkStringArg(argNamePub, &pubStr)
|
||||||
checkStringArg(argNameIdSrc, &NodeIdFile)
|
checkStringArg(argNameIdSrc, &NodeIdFile)
|
||||||
|
checkStringArg(argNameDbPath, &dbPath)
|
||||||
|
|
||||||
if len(NodeIdFile) > 0 {
|
if len(NodeIdFile) > 0 {
|
||||||
nodeid, err = crypto.LoadECDSA(NodeIdFile)
|
nodeid, err = crypto.LoadECDSA(NodeIdFile)
|
||||||
|
|
@ -156,9 +203,8 @@ func parseArgs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(enode) > 0 {
|
if len(enode) > 0 {
|
||||||
prefix := "enode://"
|
if enode[:len(enodePrefix)] != enodePrefix {
|
||||||
if enode[:len(prefix)] != prefix {
|
enode = enodePrefix + enode
|
||||||
enode = prefix + enode
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,6 +212,10 @@ func parseArgs() {
|
||||||
pow = float64(p)
|
pow = float64(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if x > 0 {
|
||||||
|
msPoW = float64(x)
|
||||||
|
}
|
||||||
|
|
||||||
if len(topicStr) > 0 {
|
if len(topicStr) > 0 {
|
||||||
var x []byte
|
var x []byte
|
||||||
x, err := hex.DecodeString(topicStr)
|
x, err := hex.DecodeString(topicStr)
|
||||||
|
|
@ -190,7 +240,7 @@ func parseArgs() {
|
||||||
fmt.Printf("salt = %s \n", salt)
|
fmt.Printf("salt = %s \n", salt)
|
||||||
fmt.Printf("topic = %x \n", topic)
|
fmt.Printf("topic = %x \n", topic)
|
||||||
fmt.Printf("pub = %s \n", common.ToHex(crypto.FromECDSAPub(pub)))
|
fmt.Printf("pub = %s \n", common.ToHex(crypto.FromECDSAPub(pub)))
|
||||||
fmt.Printf("enode = %s \n", enode)
|
fmt.Printf("boot = %s \n", enode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -251,6 +301,7 @@ func initialize() {
|
||||||
|
|
||||||
done = make(chan struct{})
|
done = make(chan struct{})
|
||||||
var peers []*discover.Node
|
var peers []*discover.Node
|
||||||
|
var err error
|
||||||
|
|
||||||
if testMode {
|
if testMode {
|
||||||
password := []byte("this is a test password for symmetric encryption")
|
password := []byte("this is a test password for symmetric encryption")
|
||||||
|
|
@ -259,7 +310,7 @@ func initialize() {
|
||||||
topic = whisper.TopicType{0xFF, 0xFF, 0xFF, 0xFF}
|
topic = whisper.TopicType{0xFF, 0xFF, 0xFF, 0xFF}
|
||||||
}
|
}
|
||||||
|
|
||||||
if bootstrapNode {
|
if bootstrapMode {
|
||||||
if len(ipAddress) == 0 {
|
if len(ipAddress) == 0 {
|
||||||
if testMode {
|
if testMode {
|
||||||
ipAddress = "127.0.0.1:30303"
|
ipAddress = "127.0.0.1:30303"
|
||||||
|
|
@ -277,7 +328,18 @@ func initialize() {
|
||||||
peers = append(peers, peer)
|
peers = append(peers, peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mailServerMode {
|
||||||
|
msPassword, err = console.Stdin.PromptPassword("Please enter the Mail Server password: ")
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to read Mail Server password: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
shh = whisper.NewWhisper(&mailServer)
|
||||||
|
mailServer.Init(shh, dbPath, msPassword, msPoW)
|
||||||
|
} else {
|
||||||
shh = whisper.NewWhisper(nil)
|
shh = whisper.NewWhisper(nil)
|
||||||
|
}
|
||||||
|
|
||||||
asymKey = shh.NewIdentity()
|
asymKey = shh.NewIdentity()
|
||||||
if nodeid == nil {
|
if nodeid == nil {
|
||||||
nodeid = shh.NewIdentity()
|
nodeid = shh.NewIdentity()
|
||||||
|
|
@ -307,19 +369,19 @@ func startServer() {
|
||||||
fmt.Printf("my public key: %s \n", common.ToHex(crypto.FromECDSAPub(&asymKey.PublicKey)))
|
fmt.Printf("my public key: %s \n", common.ToHex(crypto.FromECDSAPub(&asymKey.PublicKey)))
|
||||||
fmt.Println(server.NodeInfo().Enode)
|
fmt.Println(server.NodeInfo().Enode)
|
||||||
|
|
||||||
if bootstrapNode {
|
if bootstrapMode {
|
||||||
configureChat()
|
configureNode()
|
||||||
fmt.Println("Bootstrap Whisper node started")
|
fmt.Println("Bootstrap Whisper node started")
|
||||||
waitForConnection(false)
|
//waitForConnection(false) // todo: review
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Whisper node started")
|
fmt.Println("Whisper node started")
|
||||||
// first see if we can establish connection, then require futher user input
|
// first see if we can establish connection, then require futher user input
|
||||||
waitForConnection(true)
|
waitForConnection(true)
|
||||||
configureChat()
|
configureNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !daemonMode {
|
if !forwarderMode {
|
||||||
fmt.Printf("Chat is enabled. Please type the message. To quit type: '%s'\n", quitCommand)
|
fmt.Printf("Connection is established. Please type the message. To quit type: '%s'\n", quitCommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -327,8 +389,12 @@ func isKeyValid(k *ecdsa.PublicKey) bool {
|
||||||
return k.X != nil && k.Y != nil
|
return k.X != nil && k.Y != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureChat() {
|
func configureNode() {
|
||||||
if daemonMode {
|
var i int
|
||||||
|
var s string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if forwarderMode {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,7 +406,7 @@ func configureChat() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isAsymmetric && !testMode {
|
if !isAsymmetric && !testMode && !forwarderMode {
|
||||||
pass, err := console.Stdin.PromptPassword("Please enter the password: ")
|
pass, err := console.Stdin.PromptPassword("Please enter the password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read passphrase: %v", err)
|
utils.Fatalf("Failed to read passphrase: %v", err)
|
||||||
|
|
@ -357,6 +423,28 @@ func configureChat() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mailServerMode {
|
||||||
|
if len(dbPath) == 0 {
|
||||||
|
dbPath = scanLine("Please enter the path to DB file: ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if msPoW == 0.0 {
|
||||||
|
s = scanLine("Please enter the PoW requirement for the Mail Server (int): ")
|
||||||
|
i, err = strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Fail to parse the PoW: %s", err)
|
||||||
|
}
|
||||||
|
msPoW = float64(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestMail {
|
||||||
|
msPassword, err = console.Stdin.PromptPassword("Please enter the Mail Server password: ")
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to read Mail Server password: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
filter := &whisper.Filter{KeySym: symKey, KeyAsym: asymKey, Topics: []whisper.TopicType{topic}}
|
filter := &whisper.Filter{KeySym: symKey, KeyAsym: asymKey, Topics: []whisper.TopicType{topic}}
|
||||||
filterID = shh.Watch(filter)
|
filterID = shh.Watch(filter)
|
||||||
}
|
}
|
||||||
|
|
@ -391,15 +479,24 @@ func waitForConnection(timeout bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func run() {
|
func run() {
|
||||||
|
defer mailServer.Close()
|
||||||
startServer()
|
startServer()
|
||||||
defer server.Stop()
|
defer server.Stop()
|
||||||
shh.Start(nil)
|
shh.Start(nil)
|
||||||
defer shh.Stop()
|
defer shh.Stop()
|
||||||
|
|
||||||
if !daemonMode {
|
if !forwarderMode {
|
||||||
go messageLoop()
|
go messageLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if requestMail {
|
||||||
|
requestExpiredMessagesLoop()
|
||||||
|
} else {
|
||||||
|
sendLoop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendLoop() {
|
||||||
for {
|
for {
|
||||||
s := scanLine("")
|
s := scanLine("")
|
||||||
if s == quitCommand {
|
if s == quitCommand {
|
||||||
|
|
@ -478,8 +575,7 @@ func messageLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func printMessageInfo(msg *whisper.ReceivedMessage) {
|
func printMessageInfo(msg *whisper.ReceivedMessage) {
|
||||||
hour, min, sec := time.Now().Clock()
|
timestamp := fmt.Sprintf("%d", msg.Sent) // unix timestamp for diagnostics
|
||||||
timestamp := fmt.Sprintf("%02d:%02d:%02d", hour, min, sec)
|
|
||||||
text := string(msg.Payload)
|
text := string(msg.Payload)
|
||||||
|
|
||||||
var address common.Address
|
var address common.Address
|
||||||
|
|
@ -493,3 +589,87 @@ func printMessageInfo(msg *whisper.ReceivedMessage) {
|
||||||
fmt.Printf("\n%s [%x]: %s\n", timestamp, address, text) // message from a peer
|
fmt.Printf("\n%s [%x]: %s\n", timestamp, address, text) // message from a peer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func requestExpiredMessagesLoop() {
|
||||||
|
var key, peerID []byte
|
||||||
|
err := shh.AddSymKey(argRequestMail, []byte(msPassword))
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to create symmetric key for mail request: %s", err)
|
||||||
|
}
|
||||||
|
key = shh.GetSymKey(argRequestMail)
|
||||||
|
peerID = extractIdFromEnode(enode)
|
||||||
|
shh.MarkPeerTrusted(peerID)
|
||||||
|
|
||||||
|
for {
|
||||||
|
s := scanLine("Please enter the lower limit for the time range (unix timestamp): ")
|
||||||
|
i, err := strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Fail to parse the lower time limit: %s", err)
|
||||||
|
}
|
||||||
|
timeLow = uint32(i)
|
||||||
|
|
||||||
|
s = scanLine("Please enter the upper limit for the time range (unix timestamp): ")
|
||||||
|
i, err = strconv.Atoi(s)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Fail to parse the upper time limit: %s", err)
|
||||||
|
}
|
||||||
|
timeUpp = uint32(i)
|
||||||
|
if timeUpp == 0 {
|
||||||
|
timeUpp = 0xFFFFFFFF
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make([]byte, sizeOfInt*2)
|
||||||
|
binary.BigEndian.PutUint32(data, timeLow)
|
||||||
|
binary.BigEndian.PutUint32(data[sizeOfInt:], timeUpp)
|
||||||
|
// todo: add topic
|
||||||
|
|
||||||
|
var params whisper.MessageParams
|
||||||
|
params.PoW = msPoW
|
||||||
|
params.Payload = data
|
||||||
|
params.KeySym = key
|
||||||
|
params.Src = nodeid
|
||||||
|
params.WorkTime = 5
|
||||||
|
|
||||||
|
msg := whisper.NewSentMessage(¶ms)
|
||||||
|
env, err := msg.Wrap(¶ms)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Wrap failed: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
encoded, err := rlp.EncodeToBytes(env)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("RLP encoding failed: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = shh.RequestHistoricMessages(peerID, encoded)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to send P2P message: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractIdFromEnode(s string) []byte {
|
||||||
|
if len(s) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
p := len(enodePrefix)
|
||||||
|
if s[:p] == enodePrefix {
|
||||||
|
s = s[p:]
|
||||||
|
}
|
||||||
|
|
||||||
|
i := strings.Index(s, "@")
|
||||||
|
if i > 0 {
|
||||||
|
s = s[:i]
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Failed to decode enode: %s", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue