mirror of https://github.com/poanetwork/gecko.git
142 lines
3.7 KiB
Go
142 lines
3.7 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package ipcs
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"nanomsg.org/go/mangos/v2/protocol/pub"
|
|
|
|
_ "nanomsg.org/go/mangos/v2/transport/ipc" // registers the IPC transport
|
|
|
|
"github.com/gorilla/rpc/v2"
|
|
|
|
"github.com/ava-labs/gecko/api"
|
|
"github.com/ava-labs/gecko/chains"
|
|
"github.com/ava-labs/gecko/snow/engine/common"
|
|
"github.com/ava-labs/gecko/snow/triggers"
|
|
"github.com/ava-labs/gecko/utils/json"
|
|
"github.com/ava-labs/gecko/utils/logging"
|
|
"github.com/ava-labs/gecko/utils/wrappers"
|
|
)
|
|
|
|
const baseURL = "ipc:///tmp/"
|
|
|
|
// IPCs maintains the IPCs
|
|
type IPCs struct {
|
|
log logging.Logger
|
|
chainManager chains.Manager
|
|
httpServer *api.Server
|
|
events *triggers.EventDispatcher
|
|
chains map[[32]byte]*ChainIPC
|
|
}
|
|
|
|
// NewService returns a new IPCs API service
|
|
func NewService(log logging.Logger, chainManager chains.Manager, events *triggers.EventDispatcher, httpServer *api.Server) *common.HTTPHandler {
|
|
newServer := rpc.NewServer()
|
|
codec := json.NewCodec()
|
|
newServer.RegisterCodec(codec, "application/json")
|
|
newServer.RegisterCodec(codec, "application/json;charset=UTF-8")
|
|
newServer.RegisterService(&IPCs{
|
|
log: log,
|
|
chainManager: chainManager,
|
|
httpServer: httpServer,
|
|
events: events,
|
|
chains: map[[32]byte]*ChainIPC{},
|
|
}, "ipcs")
|
|
return &common.HTTPHandler{Handler: newServer}
|
|
}
|
|
|
|
// PublishBlockchainArgs are the arguments for calling PublishBlockchain
|
|
type PublishBlockchainArgs struct {
|
|
BlockchainID string `json:"blockchainID"`
|
|
}
|
|
|
|
// PublishBlockchainReply are the results from calling PublishBlockchain
|
|
type PublishBlockchainReply struct {
|
|
URL string `json:"url"`
|
|
}
|
|
|
|
// PublishBlockchain publishes the finalized accepted transactions from the blockchainID over the IPC
|
|
func (ipc *IPCs) PublishBlockchain(r *http.Request, args *PublishBlockchainArgs, reply *PublishBlockchainReply) error {
|
|
chainID, err := ipc.chainManager.Lookup(args.BlockchainID)
|
|
if err != nil {
|
|
ipc.log.Error("unknown blockchainID: %s", err)
|
|
return err
|
|
}
|
|
|
|
chainIDKey := chainID.Key()
|
|
chainIDStr := chainID.String()
|
|
url := baseURL + chainIDStr + ".ipc"
|
|
|
|
reply.URL = url
|
|
|
|
if _, ok := ipc.chains[chainIDKey]; ok {
|
|
ipc.log.Info("returning existing blockchainID %s", chainIDStr)
|
|
return nil
|
|
}
|
|
|
|
sock, err := pub.NewSocket()
|
|
if err != nil {
|
|
ipc.log.Error("can't get new pub socket: %s", err)
|
|
return err
|
|
}
|
|
|
|
if err = sock.Listen(url); err != nil {
|
|
ipc.log.Error("can't listen on pub socket: %s", err)
|
|
sock.Close()
|
|
return err
|
|
}
|
|
|
|
chainIPC := &ChainIPC{
|
|
log: ipc.log,
|
|
socket: sock,
|
|
}
|
|
if err := ipc.events.RegisterChain(chainID, "ipc", chainIPC); err != nil {
|
|
ipc.log.Error("couldn't register event: %s", err)
|
|
sock.Close()
|
|
return err
|
|
}
|
|
|
|
ipc.chains[chainIDKey] = chainIPC
|
|
return nil
|
|
}
|
|
|
|
// UnpublishBlockchainArgs are the arguments for calling UnpublishBlockchain
|
|
type UnpublishBlockchainArgs struct {
|
|
BlockchainID string `json:"blockchainID"`
|
|
}
|
|
|
|
// UnpublishBlockchainReply are the results from calling UnpublishBlockchain
|
|
type UnpublishBlockchainReply struct {
|
|
Success bool `json:"success"`
|
|
}
|
|
|
|
// UnpublishBlockchain closes publishing of a blockchainID
|
|
func (ipc *IPCs) UnpublishBlockchain(r *http.Request, args *UnpublishBlockchainArgs, reply *UnpublishBlockchainReply) error {
|
|
chainID, err := ipc.chainManager.Lookup(args.BlockchainID)
|
|
if err != nil {
|
|
ipc.log.Error("unknown blockchainID %s: %s", args.BlockchainID, err)
|
|
return err
|
|
}
|
|
|
|
chainIDKey := chainID.Key()
|
|
|
|
chain, ok := ipc.chains[chainIDKey]
|
|
if !ok {
|
|
return fmt.Errorf("blockchainID not publishing: %s", chainID)
|
|
}
|
|
|
|
errs := wrappers.Errs{}
|
|
errs.Add(
|
|
chain.Stop(),
|
|
ipc.events.DeregisterChain(chainID, "ipc"),
|
|
)
|
|
delete(ipc.chains, chainIDKey)
|
|
|
|
reply.Success = true
|
|
return errs.Err
|
|
}
|