dsrpc

package module
v1.3.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2023 License: Apache-2.0 Imports: 14 Imported by: 0

README

dsrpc, Data RPC

DSRPC is easy and simple RPC framework over TCP socket.

Purpose

A very easy and open RPC framework with data streaming.

You can
  • Use own post and pre-execution middleware
  • Hash-based authentication in middleware
  • Test remote function without network

Socket encryption is not used at this time since framefork is oriented to transfer large amounts of data.

Style of the framework is similar of GIN framework.

Exec method example

Server
package main

import (
    "log"
    "github.com/kindsoldier/dsrpc"
    "netsrv/api"
)

func main() {
    err := server()
    if err != nil {
        log.Println(err)
    }
}

func server() error {
    var err error

    serv := dsrpc.NewService()

    cont := NewController()
    serv.Handle(api.HelloMethod, cont.HelloHandler)

    serv.PreMiddleware(dsrpc.LogRequest)
    serv.PostMiddleware(dsrpc.LogResponse)
    serv.PostMiddleware(dsrpc.LogAccess)

    err = serv.Listen(":8081")
    if err != nil {
        return err
    }
    return err
}


type Controller struct {
}

func NewController() *Controller {
    return &Controller{}
}

func (cont *Controller) HelloHandler(context *dsrpc.Context) error {
    var err error
    params := api.NewHelloParams()
    err = context.BindParams(params)
    if err != nil {
        return err
    }

    log.Println("hello message:", params.Message)

    result := api.NewHelloResult()
    result.Message = "hello!"

    err = context.SendResult(result, 0)
    if err != nil {
        return err
    }

    return err
}

Client
package main

import (
    "fmt"
    "github.com/kindsoldier/dsrpc"
    "netsrv/api"
)

func main() {

    err := exec()
    if err != nil {
        fmt.Println("exec err:", err)
    }
}

func exec() error {
    var err error

    params := api.NewHelloParams()
    params.Message = "hello, server!"

    result := api.NewHelloResult()

    err = dsrpc.Exec("127.0.0.1:8081", api.HelloMethod, params, result, nil)
    if err != nil {
        return err
    }

    fmt.Println("result:", result.Message)
    return err
}


Common api
package api

const HelloMethod string = "hello"

type HelloParams struct {
    Message string      `json:"message"`
}

func NewHelloParams() *HelloParams {
    return &HelloParams{}
}

type HelloResult struct {
    Message string      `json:"message"`
}

func NewHelloResult() *HelloResult {
    return &HelloResult{}
}

Authentication and authorization
Client side

func clientHello() error {
    var err error

    params := NewHelloParams()
    params.Message = "hello server!"
    result := NewHelloResult()

    auth := dsrpc.CreateAuth([]byte("login"), []byte("password"))

    err = dsrpc.Exec("127.0.0.1:8081", HelloMethod, params, result, auth)
    if err != nil {
        log.Println("method err:", err)
        return err
    }

    //...
}


Server side

func authMiddleware(context *dsrpc.Context) error {
    var err error
    reqIdent := context.AuthIdent()
    reqSalt := context.AuthSalt()
    reqHash := context.AuthHash()

    if reqIdent != "login" {
        err = errors.New("auth ident or pass mismatch")
        context.SendError(err)
        return err
    }

    ident := reqIdent
    pass := []byte("password")

    ok := dsrpc.CheckHash(ident, pass, reqSalt, reqHash)
    log.Println("auth is ok:", ok)
    if !ok {
        err = errors.New("auth ident or pass mismatch")
        context.SendError(err)
        return err
    }
    return err
}

func sampleServ(quiet bool) error {
    var err error

    if quiet {
        dsrpc.SetAccessWriter(io.Discard)
        dsrpc.SetMessageWriter(io.Discard)
    }
    serv := NewService()

    serv.PreMiddleware(authMiddleware)
    serv.PreMiddleware(dsrpc.LogRequest)

    serv.Handle(HelloMethod, helloHandler)
    serv.Handle(SaveMethod, saveHandler)
    serv.Handle(LoadMethod, loadHandler)

    serv.PostMiddleware(dsrpc.LogResponse)
    serv.PostMiddleware(dsrpc.LogAccess)

    err = serv.Listen(":8081")
    if err != nil {
        return err
    }
    return err
}

Put method
Client side sample
    var binSize int64 = 16
    rand.Seed(time.Now().UnixNano())
    binBytes := make([]byte, binSize)
    rand.Read(binBytes)

    reader := bytes.NewReader(binBytes)

    err = dsrpc.Put("127.0.0.1:8081", SaveMethod, reader, binSize, params, result, auth)

Server side
func saveHandler(context *dsrpc.Context) error {
    var err error
    params := NewSaveParams()

    err = context.BindParams(params)
    if err != nil {
        return err
    }

    bufferBytes := make([]byte, 0, 1024)
    binWriter := bytes.NewBuffer(bufferBytes)

    err = context.ReadBin(binWriter)
    if err != nil {
        context.SendError(err)
        return err
    }

    result := NewSaveResult()
    result.Message = "saved successfully!"

    err = context.SendResult(result, 0)
    if err != nil {
        return err
    }
    return err
}

Get method
Client side
    params := NewLoadParams()
    params.Message = "load data!"
    result := NewHelloResult()
    auth := CreateAuth([]byte("qwert"), []byte("12345"))

    binBytes := make([]byte, 0)
    writer := bytes.NewBuffer(binBytes)

    err = dsrpc.Get("127.0.0.1:8081", LoadMethod, writer, params, result, auth)
    if err != nil {
        return err
    }

    //...

Server side

func getHandler(context *dsrpc.Context) error {
    var err error
    params := NewSaveParams()

    err = context.BindParams(params)
    if err != nil {
        return err
    }

    var binSize int64 = 1024

    rand.Seed(time.Now().UnixNano())
    binBytes := make([]byte, binSize)
    rand.Read(binBytes)

    binReader := bytes.NewReader(binBytes)

    result := NewSaveResult()
    result.Message = "load successfully!"

    err = context.SendResult(result, binSize)
    if err != nil {
        return err
    }
    binWriter := context.BinWriter()
    _, err = dsrpc.CopyBytes(binReader, binWriter, binSize)
    if err != nil {
        return err
    }

    return err
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckHash

func CheckHash(ident, pass, reqSalt, reqHash []byte) bool

func ConnExec

func ConnExec(ctx context.Context, conn net.Conn, method string, param any, result any, auth *Auth) error

func ConnGet

func ConnGet(ctx context.Context, conn net.Conn, method string, writer io.Writer, param, result any, auth *Auth) error

func ConnPut

func ConnPut(ctx context.Context, conn net.Conn, method string, reader io.Reader, binSize int64, param, result any, auth *Auth) error

func CopyBytes

func CopyBytes(ctx context.Context, reader io.Reader, writer io.Writer, dataSize int64) (int64, error)

func CreateHash

func CreateHash(ident, pass, salt []byte) []byte

func CreateSalt

func CreateSalt() []byte

func DecoderI64 added in v1.2.0

func DecoderI64(b []byte) int64

func EncoderI64 added in v1.2.0

func EncoderI64(i int64) []byte

func Exec

func Exec(ctx context.Context, address, method string, param any, result any, auth *Auth) error

func ExecTLS added in v1.3.0

func ExecTLS(ctx context.Context, tlsConfig *tls.Config, address, method string, param any, result any, auth *Auth) error

func Get

func Get(ctx context.Context, address string, method string, writer io.Writer, param, result any, auth *Auth) error

func GetTLS added in v1.3.0

func GetTLS(ctx context.Context, tlsConfig *tls.Config, address string, method string, writer io.Writer, param, result any, auth *Auth) error

func LocalExec

func LocalExec(method string, param, result any, auth *Auth, handler HandlerFunc) error

func LocalGet

func LocalGet(ctx context.Context, method string, writer io.Writer, param, result any, auth *Auth, handler HandlerFunc) error

func LocalPut

func LocalPut(ctx context.Context, method string, reader io.Reader, size int64, param, result any, auth *Auth, handler HandlerFunc) error

func LocalService

func LocalService(conn net.Conn, handler HandlerFunc) error

func LogAccess

func LogAccess(content *Content) error

func LogRequest

func LogRequest(content *Content) error

func LogResponse

func LogResponse(content *Content) error

func NewFConn

func NewFConn() (*FConn, *FConn)

func Put

func Put(ctx context.Context, address string, method string, reader io.Reader, binSize int64, param, result any, auth *Auth) error

func PutTLS added in v1.3.0

func PutTLS(ctx context.Context, tlsConfig *tls.Config, address string, method string, reader io.Reader, binSize int64, param, result any, auth *Auth) error

func ReadBytes

func ReadBytes(reader io.Reader, size int64) ([]byte, error)

func SetAccessWriter

func SetAccessWriter(writer io.Writer)

func SetMessageWriter

func SetMessageWriter(writer io.Writer)

Types

type Auth

type Auth struct {
	Ident []byte `msgpack:"ident"    json:"ident"`
	Salt  []byte `msgpack:"salt"     json:"salt"`
	Hash  []byte `msgpack:"hash"     json:"hash"`
}

func CreateAuth

func CreateAuth(ident, pass []byte) *Auth

func NewAuth

func NewAuth() *Auth

func (*Auth) Json added in v1.1.3

func (this *Auth) Json() []byte

type Content added in v1.1.2

type Content struct {
	// contains filtered or unexported fields
}

func CreateContent added in v1.1.2

func CreateContent(conn net.Conn) *Content

func (*Content) Auth added in v1.1.2

func (context *Content) Auth() *Auth

func (*Content) AuthHash added in v1.1.2

func (context *Content) AuthHash() []byte

func (*Content) AuthIdent added in v1.1.2

func (context *Content) AuthIdent() []byte

func (*Content) AuthSalt added in v1.1.2

func (context *Content) AuthSalt() []byte

func (*Content) BinReader added in v1.1.2

func (content *Content) BinReader() io.Reader

func (*Content) BinSize added in v1.1.2

func (content *Content) BinSize() int64

func (*Content) BinWriter added in v1.1.2

func (content *Content) BinWriter() io.Writer

func (*Content) BindMethod added in v1.1.2

func (content *Content) BindMethod() error

func (*Content) BindParams added in v1.1.2

func (content *Content) BindParams(params any) error

func (*Content) Method added in v1.1.2

func (context *Content) Method() string

func (*Content) ReadBin added in v1.1.2

func (content *Content) ReadBin(ctx context.Context, writer io.Writer) error

func (*Content) ReadRequest added in v1.1.2

func (content *Content) ReadRequest() error

func (*Content) RemoteHost added in v1.1.2

func (context *Content) RemoteHost() string

func (*Content) ReqBinSize added in v1.1.2

func (context *Content) ReqBinSize() int64

func (*Content) ReqRpcSize added in v1.1.2

func (context *Content) ReqRpcSize() int64

func (*Content) ReqSize added in v1.1.2

func (context *Content) ReqSize() int64

func (*Content) Request added in v1.1.2

func (context *Content) Request() *Request

func (*Content) ResBinSize added in v1.1.2

func (context *Content) ResBinSize() int64

func (*Content) ResRpcSize added in v1.1.2

func (context *Content) ResRpcSize() int64

func (*Content) ResSize added in v1.1.2

func (context *Content) ResSize() int64

func (*Content) SendError added in v1.1.2

func (content *Content) SendError(execErr error) error

func (*Content) SendResult added in v1.1.2

func (content *Content) SendResult(result any, binSize int64) error

func (*Content) SetAuthHash added in v1.1.2

func (context *Content) SetAuthHash(hash []byte)

func (*Content) SetAuthIdent added in v1.1.2

func (context *Content) SetAuthIdent(ident []byte)

func (*Content) SetAuthSalt added in v1.1.2

func (context *Content) SetAuthSalt(salt []byte)

func (*Content) Start added in v1.1.2

func (context *Content) Start() time.Time

type EmptyParams added in v1.1.1

type EmptyParams struct{}

func NewEmptyParams added in v1.1.1

func NewEmptyParams() *EmptyParams

type EmptyResult added in v1.1.1

type EmptyResult struct{}

func NewEmptyResult added in v1.1.1

func NewEmptyResult() *EmptyResult

type FAddr

type FAddr struct {
	// contains filtered or unexported fields
}

func NewFAddr

func NewFAddr() *FAddr

func (*FAddr) Network

func (addr *FAddr) Network() string

func (*FAddr) String

func (addr *FAddr) String() string

type FConn

type FConn struct {
	// contains filtered or unexported fields
}

func (FConn) Close

func (conn FConn) Close() error

func (FConn) LocalAddr

func (conn FConn) LocalAddr() net.Addr

func (FConn) Read

func (conn FConn) Read(data []byte) (int, error)

func (FConn) RemoteAddr

func (conn FConn) RemoteAddr() net.Addr

func (FConn) SetDeadline

func (conn FConn) SetDeadline(t time.Time) error

func (FConn) SetReadDeadline

func (conn FConn) SetReadDeadline(t time.Time) error

func (FConn) SetWriteDeadline

func (conn FConn) SetWriteDeadline(t time.Time) error

func (FConn) Write

func (conn FConn) Write(data []byte) (int, error)

type HandlerFunc

type HandlerFunc = func(*Content) error
type Header struct {
	// contains filtered or unexported fields
}

func NewEmptyHeader added in v1.1.1

func NewEmptyHeader() *Header

func UnpackHeader

func UnpackHeader(headerBytes []byte) (*Header, error)

func (*Header) Pack

func (hdr *Header) Pack() ([]byte, error)

func (*Header) ToJson added in v1.1.1

func (hdr *Header) ToJson() []byte

type Packet

type Packet struct {
	// contains filtered or unexported fields
}

func NewEmptyPacket added in v1.1.1

func NewEmptyPacket() *Packet

type Request

type Request struct {
	Method string `json:"method"            msgpack:"method"`
	Params any    `json:"params,omitempty"  msgpack:"params"`
	Auth   *Auth  `json:"auth,omitempty"    msgpack:"auth"`
}

func NewEmptyRequest added in v1.1.1

func NewEmptyRequest() *Request

func (*Request) Pack

func (req *Request) Pack() ([]byte, error)

func (*Request) ToJson added in v1.1.1

func (req *Request) ToJson() []byte

type Response

type Response struct {
	Error  string `json:"error"   msgpack:"error"`
	Result any    `json:"result"  msgpack:"result"`
}

func NewEmptyResponse added in v1.1.1

func NewEmptyResponse() *Response

func (*Response) Pack

func (resp *Response) Pack() ([]byte, error)

func (*Response) ToJson added in v1.1.1

func (resp *Response) ToJson() []byte

type Service

type Service struct {
	// contains filtered or unexported fields
}

func NewService

func NewService() *Service

func (*Service) Handle added in v1.2.2

func (svc *Service) Handle(method string, handler HandlerFunc)

func (*Service) Listen

func (svc *Service) Listen(address string) error

func (*Service) ListenTLS added in v1.3.0

func (svc *Service) ListenTLS(address string, tlsConfig *tls.Config) error

func (*Service) PostMiddleware

func (svc *Service) PostMiddleware(mw HandlerFunc)

func (*Service) PreMiddleware

func (svc *Service) PreMiddleware(mw HandlerFunc)

func (*Service) Route

func (svc *Service) Route(content *Content) error

func (*Service) SetKeepAlive added in v1.1.0

func (svc *Service) SetKeepAlive(flag bool)

func (*Service) SetKeepAlivePeriod added in v1.1.0

func (svc *Service) SetKeepAlivePeriod(interval time.Duration)

func (*Service) Stop

func (svc *Service) Stop() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL