Support for socket.io interface, initial commit
parent
ec87f4ed8d
commit
b0f163e21c
|
@ -37,9 +37,10 @@ Install Go interface to ZeroMQ:
|
|||
go get github.com/pebbe/zmq4
|
||||
```
|
||||
|
||||
Install glog logging:
|
||||
Install additional go libraries - glog logging, socket.io:
|
||||
```
|
||||
go get github.com/golang/glog
|
||||
go get github.com/graarh/golang-socketio
|
||||
```
|
||||
|
||||
Install blockbook:
|
||||
|
@ -112,7 +113,7 @@ The data are separated to different column families:
|
|||
- stream results to REST and websocket interfaces
|
||||
- parallel sync - rewrite - it is not possible to gracefully stop it now, can leave holes in the block
|
||||
- ~~parallel sync - let rocksdb to compact itself from time to time, otherwise it consumes too much disk space~~
|
||||
- disconnect blocks - optimize - full range scan is too slow and takes too much disk space (creates snapshot of the whole outputs), split to multiple iterators
|
||||
- ~~disconnect blocks - optimize - full range scan is too slow and takes too much disk space (creates snapshot of the whole outputs), split to multiple iterators~~
|
||||
- disconnect blocks - keep map of transactions in the last 100 blocks
|
||||
- xpub index
|
||||
- tests
|
||||
|
|
34
blockbook.go
34
blockbook.go
|
@ -56,6 +56,8 @@ var (
|
|||
|
||||
httpServerBinding = flag.String("httpserver", "", "http server binding [address]:port, if missing no http server")
|
||||
|
||||
socketIoBinding = flag.String("socketio", "", "socketio server binding [address]:port[/path], if missing no socketio server")
|
||||
|
||||
zeroMQBinding = flag.String("zeromq", "", "binding to zeromq, if missing no zeromq connection")
|
||||
)
|
||||
|
||||
|
@ -152,6 +154,24 @@ func main() {
|
|||
}()
|
||||
}
|
||||
|
||||
var socketIoServer *server.SocketIoServer
|
||||
if *socketIoBinding != "" {
|
||||
socketIoServer, err = server.NewSocketIoServer(*socketIoBinding, index, mempool)
|
||||
if err != nil {
|
||||
glog.Fatal("socketio: ", err)
|
||||
}
|
||||
go func() {
|
||||
err = socketIoServer.Run()
|
||||
if err != nil {
|
||||
if err.Error() == "http: Server closed" {
|
||||
glog.Info(err)
|
||||
} else {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
var mq *bchain.MQ
|
||||
if *zeroMQBinding != "" {
|
||||
if !*synchronize {
|
||||
|
@ -193,7 +213,7 @@ func main() {
|
|||
}
|
||||
|
||||
if httpServer != nil || mq != nil {
|
||||
waitForSignalAndShutdown(httpServer, mq, 5*time.Second)
|
||||
waitForSignalAndShutdown(httpServer, socketIoServer, mq, 5*time.Second)
|
||||
}
|
||||
|
||||
if *synchronize {
|
||||
|
@ -263,7 +283,7 @@ func mqHandler(m *bchain.MQMessage) {
|
|||
}
|
||||
}
|
||||
|
||||
func waitForSignalAndShutdown(s *server.HTTPServer, mq *bchain.MQ, timeout time.Duration) {
|
||||
func waitForSignalAndShutdown(https *server.HTTPServer, socketio *server.SocketIoServer, mq *bchain.MQ, timeout time.Duration) {
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
|
||||
|
||||
|
@ -280,11 +300,17 @@ func waitForSignalAndShutdown(s *server.HTTPServer, mq *bchain.MQ, timeout time.
|
|||
}
|
||||
}
|
||||
|
||||
if s != nil {
|
||||
if err := s.Shutdown(ctx); err != nil {
|
||||
if https != nil {
|
||||
if err := https.Shutdown(ctx); err != nil {
|
||||
glog.Error("HttpServer.Shutdown error: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
if socketio != nil {
|
||||
if err := socketio.Shutdown(ctx); err != nil {
|
||||
glog.Error("SocketIo.Shutdown error: ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printResult(txid string, vout uint32, isOutput bool) error {
|
||||
|
|
|
@ -42,6 +42,9 @@ func NewHTTPServer(httpServerBinding string, db *db.RocksDB, mempool *bchain.Mem
|
|||
r.HandleFunc("/confirmedTransactions/{address}/{lower}/{higher}", s.confirmedTransactions)
|
||||
r.HandleFunc("/unconfirmedTransactions/{address}", s.unconfirmedTransactions)
|
||||
|
||||
// support for testing of socket.io interface
|
||||
r.PathPrefix("/socket.io/").Handler(http.StripPrefix("/socket.io/", http.FileServer(http.Dir("./server/static/"))))
|
||||
|
||||
var h http.Handler = r
|
||||
h = handlers.LoggingHandler(os.Stderr, h)
|
||||
https.Handler = h
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/db"
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/graarh/golang-socketio"
|
||||
"github.com/graarh/golang-socketio/transport"
|
||||
)
|
||||
|
||||
// SocketIoServer is handle to SocketIoServer
|
||||
type SocketIoServer struct {
|
||||
binding string
|
||||
server *gosocketio.Server
|
||||
https *http.Server
|
||||
db *db.RocksDB
|
||||
mempool *bchain.Mempool
|
||||
}
|
||||
|
||||
// NewSocketIoServer creates new SocketIo interface to blockbook and returns its handle
|
||||
func NewSocketIoServer(binding string, db *db.RocksDB, mempool *bchain.Mempool) (*SocketIoServer, error) {
|
||||
server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport())
|
||||
|
||||
server.On(gosocketio.OnConnection, func(c *gosocketio.Channel) {
|
||||
glog.Info("Client connected ", c.Id())
|
||||
c.Join("chat")
|
||||
})
|
||||
|
||||
server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) {
|
||||
glog.Info("Client disconnected ", c.Id())
|
||||
})
|
||||
|
||||
type Message struct {
|
||||
Name string `json:"name"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
server.On("send", func(c *gosocketio.Channel, msg Message) string {
|
||||
c.BroadcastTo("chat", "message", msg)
|
||||
return "OK"
|
||||
})
|
||||
|
||||
addr, path := splitBinding(binding)
|
||||
serveMux := http.NewServeMux()
|
||||
serveMux.Handle(path, server)
|
||||
https := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: serveMux,
|
||||
}
|
||||
|
||||
s := &SocketIoServer{
|
||||
binding: binding,
|
||||
https: https,
|
||||
server: server,
|
||||
db: db,
|
||||
mempool: mempool,
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func splitBinding(binding string) (addr string, path string) {
|
||||
i := strings.Index(binding, "/")
|
||||
if i >= 0 {
|
||||
return binding[0:i], binding[i:]
|
||||
}
|
||||
return binding, "/"
|
||||
}
|
||||
|
||||
// Run starts the server
|
||||
func (s *SocketIoServer) Run() error {
|
||||
glog.Info("socketio server starting to listen on ", s.https.Addr)
|
||||
return s.https.ListenAndServe()
|
||||
}
|
||||
|
||||
// Close closes the server
|
||||
func (s *SocketIoServer) Close() error {
|
||||
glog.Infof("socketio server closing")
|
||||
return s.https.Close()
|
||||
}
|
||||
|
||||
// Shutdown shuts down the server
|
||||
func (s *SocketIoServer) Shutdown(ctx context.Context) error {
|
||||
glog.Infof("socketio server shutdown")
|
||||
return s.https.Shutdown(ctx)
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
|
||||
crossorigin="anonymous">
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.4/socket.io.js"></script>
|
||||
<title>Test socket.io</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<h1>Socket.io tester</h1>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
var socket = io('ws://127.0.0.1:8334', { transports: ['websocket'] });
|
||||
socket.on('message', function (message) {
|
||||
console.log('new message');
|
||||
console.log(message);
|
||||
});
|
||||
socket.on('connect', function () {
|
||||
console.log('socket connected');
|
||||
socket.emit('send', { name: "my name", message: "hello" }, function (result) {
|
||||
console.log('sent successfully');
|
||||
console.log(result);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
Loading…
Reference in New Issue