mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00
[NOD-286] Implement API-Server base structure (#379)
* [NOD-286] Implement API-Server base structure * [NOD-286] Add rpc user and password as command line arguments * [NOD-286] Make log directory a CLI argument * [NOD-286] Add db login details as CLI arguments
This commit is contained in:
parent
c73113a12e
commit
ed9165f533
63
apiserver/client.go
Normal file
63
apiserver/client.go
Normal file
@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/daglabs/btcd/btcjson"
|
||||
"github.com/daglabs/btcd/util/daghash"
|
||||
|
||||
"github.com/daglabs/btcd/rpcclient"
|
||||
"github.com/daglabs/btcd/util"
|
||||
"github.com/daglabs/btcd/wire"
|
||||
)
|
||||
|
||||
type apiServerClient struct {
|
||||
*rpcclient.Client
|
||||
onBlockAdded chan *blockAddedMsg
|
||||
onChainChanged chan *chainChangedMsg
|
||||
}
|
||||
|
||||
type blockAddedMsg struct {
|
||||
chainHeight uint64
|
||||
header *wire.BlockHeader
|
||||
}
|
||||
|
||||
type chainChangedMsg struct {
|
||||
removedChainBlockHashes []*daghash.Hash
|
||||
addedChainBlocks []*btcjson.ChainBlock
|
||||
}
|
||||
|
||||
func newAPIServerClient(connCfg *rpcclient.ConnConfig) (*apiServerClient, error) {
|
||||
client := &apiServerClient{
|
||||
onBlockAdded: make(chan *blockAddedMsg),
|
||||
onChainChanged: make(chan *chainChangedMsg),
|
||||
}
|
||||
notificationHandlers := &rpcclient.NotificationHandlers{
|
||||
OnFilteredBlockAdded: func(height uint64, header *wire.BlockHeader,
|
||||
txs []*util.Tx) {
|
||||
client.onBlockAdded <- &blockAddedMsg{
|
||||
chainHeight: height,
|
||||
header: header,
|
||||
}
|
||||
},
|
||||
OnChainChanged: func(removedChainBlockHashes []*daghash.Hash,
|
||||
addedChainBlocks []*btcjson.ChainBlock) {
|
||||
client.onChainChanged <- &chainChangedMsg{
|
||||
removedChainBlockHashes: removedChainBlockHashes,
|
||||
addedChainBlocks: addedChainBlocks,
|
||||
}
|
||||
},
|
||||
}
|
||||
var err error
|
||||
client.Client, err = rpcclient.New(connCfg, notificationHandlers)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error connecting to address %s: %s", connCfg.Host, err)
|
||||
}
|
||||
|
||||
if err = client.NotifyBlocks(); err != nil {
|
||||
return nil, fmt.Errorf("Error while registering client %s for block notifications: %s", client.Host(), err)
|
||||
}
|
||||
if err = client.NotifyChainChanges(); err != nil {
|
||||
return nil, fmt.Errorf("Error while registering client %s for chain changes notifications: %s", client.Host(), err)
|
||||
}
|
||||
return client, nil
|
||||
}
|
58
apiserver/config.go
Normal file
58
apiserver/config.go
Normal file
@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/daglabs/btcd/util"
|
||||
"github.com/jessevdk/go-flags"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultLogFilename = "apiserver.log"
|
||||
defaultErrLogFilename = "apiserver_err.log"
|
||||
)
|
||||
|
||||
var (
|
||||
// Default configuration options
|
||||
defaultLogDir = util.AppDataDir("apiserver", false)
|
||||
defaultDBHost = "localhost:3306"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
LogDir string `long:"logdir" description:"Directory to log output."`
|
||||
RPCUser string `short:"u" long:"rpcuser" description:"RPC username" required:"true"`
|
||||
RPCPassword string `short:"P" long:"rpcpass" default-mask:"-" description:"RPC password" required:"true"`
|
||||
RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to" required:"true"`
|
||||
RPCCert string `short:"c" long:"rpccert" description:"RPC server certificate chain for validation"`
|
||||
DisableTLS bool `long:"notls" description:"Disable TLS"`
|
||||
DBHost string `long:"dbhost" description:"Database host"`
|
||||
DBUser string `long:"dbuser" description:"Database user" required:"true"`
|
||||
DBPassword string `long:"dbpass" description:"Database password" required:"true"`
|
||||
}
|
||||
|
||||
func parseConfig() (*config, error) {
|
||||
cfg := &config{
|
||||
LogDir: defaultLogDir,
|
||||
DBHost: defaultDBHost,
|
||||
}
|
||||
parser := flags.NewParser(cfg, flags.PrintErrors|flags.HelpFlag)
|
||||
_, err := parser.Parse()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg.RPCCert == "" && !cfg.DisableTLS {
|
||||
return nil, errors.New("--notls has to be disabled if --cert is used")
|
||||
}
|
||||
|
||||
if cfg.RPCCert != "" && cfg.DisableTLS {
|
||||
return nil, errors.New("--cert should be omitted if --notls is used")
|
||||
}
|
||||
|
||||
logFile := filepath.Join(cfg.LogDir, defaultLogFilename)
|
||||
errLogFile := filepath.Join(cfg.LogDir, defaultErrLogFilename)
|
||||
initLog(logFile, errLogFile)
|
||||
|
||||
return cfg, nil
|
||||
}
|
39
apiserver/connect.go
Normal file
39
apiserver/connect.go
Normal file
@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/daglabs/btcd/rpcclient"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func connectToServer(cfg *config) (*apiServerClient, error) {
|
||||
var cert []byte
|
||||
if !cfg.DisableTLS {
|
||||
var err error
|
||||
cert, err = ioutil.ReadFile(cfg.RPCCert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error reading certificates file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
connCfg := &rpcclient.ConnConfig{
|
||||
Host: cfg.RPCServer,
|
||||
Endpoint: "ws",
|
||||
User: cfg.RPCUser,
|
||||
Pass: cfg.RPCPassword,
|
||||
DisableTLS: cfg.DisableTLS,
|
||||
}
|
||||
|
||||
if !cfg.DisableTLS {
|
||||
connCfg.Certificates = cert
|
||||
}
|
||||
|
||||
client, err := newAPIServerClient(connCfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error connecting to address %s: %s", cfg.RPCServer, err)
|
||||
}
|
||||
|
||||
log.Infof("Connected to server %s", cfg.RPCServer)
|
||||
|
||||
return client, nil
|
||||
}
|
27
apiserver/log.go
Normal file
27
apiserver/log.go
Normal file
@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/daglabs/btcd/logs"
|
||||
"github.com/daglabs/btcd/util/panics"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
backendLog = logs.NewBackend()
|
||||
log = backendLog.Logger("APIS")
|
||||
spawn = panics.GoroutineWrapperFunc(log, backendLog)
|
||||
)
|
||||
|
||||
func initLog(logFile, errLogFile string) {
|
||||
err := backendLog.AddLogFile(logFile, logs.LevelTrace)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding log file %s as log rotator for level %s: %s", logFile, logs.LevelTrace, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = backendLog.AddLogFile(errLogFile, logs.LevelWarn)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding log file %s as log rotator for level %s: %s", errLogFile, logs.LevelWarn, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
30
apiserver/main.go
Normal file
30
apiserver/main.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/daglabs/btcd/signal"
|
||||
"github.com/daglabs/btcd/util/panics"
|
||||
)
|
||||
|
||||
func main() {
|
||||
defer panics.HandlePanic(log, backendLog)
|
||||
|
||||
cfg, err := parseConfig()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("Error parsing command-line arguments: %s", err))
|
||||
}
|
||||
|
||||
client, err := connectToServer(cfg)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("Error connecting to servers: %s", err))
|
||||
}
|
||||
defer disconnect(client)
|
||||
|
||||
interrupt := signal.InterruptListener()
|
||||
<-interrupt
|
||||
}
|
||||
|
||||
func disconnect(client *apiServerClient) {
|
||||
log.Infof("Disconnecting client")
|
||||
client.Disconnect()
|
||||
}
|
@ -7,7 +7,6 @@ import (
|
||||
)
|
||||
|
||||
func connectToServer(cfg *config) (*txgenClient, error) {
|
||||
|
||||
var cert []byte
|
||||
if !cfg.DisableTLS {
|
||||
var err error
|
||||
|
Loading…
x
Reference in New Issue
Block a user