func (c *client) PutBlock(ctx context.Context, ref torus.BlockRef, data []byte) error {
	_, err := c.handler.PutBlock(ctx, &models.PutBlockRequest{
		Refs: []*models.BlockRef{
			ref.ToProto(),
		},
		Blocks: [][]byte{
			data,
		},
	})
	return err
}
client (torusblk) calls this PutBlock.
package grpc
import (
	"net"
	"net/url"
	"strings"
	"time"
	"google.golang.org/grpc"
	"golang.org/x/net/context"
	"github.com/alternative-storage/torus"
	"github.com/alternative-storage/torus/distributor/protocols"
	"github.com/alternative-storage/torus/models"
	"github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
)
const defaultPort = "40000"
func init() {
	protocols.RegisterRPCListener("http", grpcRPCListener)
	protocols.RegisterRPCDialer("http", grpcRPCDialer)
}
func grpcRPCListener(url *url.URL, hdl protocols.RPC, gmd torus.GlobalMetadata) (protocols.RPCServer, error) {
	out := &handler{
		handle: hdl,
	}
	h := url.Host
	if !strings.Contains(h, ":") {
		h = net.JoinHostPort(h, defaultPort)
	}
	lis, err := net.Listen("tcp", h)
	if err != nil {
		return nil, err
	}
	uIntOpt := grpc.UnaryInterceptor(grpc_opentracing.UnaryServerInterceptor())
	out.grpc = grpc.NewServer(uIntOpt)
	models.RegisterTorusStorageServer(out.grpc, out)
	go out.grpc.Serve(lis)
	return out, nil
}
func grpcRPCDialer(url *url.URL, timeout time.Duration, gmd torus.GlobalMetadata) (protocols.RPC, error) {
	h := url.Host
	if !strings.Contains(h, ":") {
		h = net.JoinHostPort(h, defaultPort)
	}
	uIntOpt := grpc.WithUnaryInterceptor(grpc_opentracing.UnaryClientInterceptor())
	conn, err := grpc.Dial(h, grpc.WithInsecure(), grpc.WithTimeout(timeout), uIntOpt)
	if err != nil {
		return nil, err
	}
	return &client{
		conn:    conn,
		handler: models.NewTorusStorageClient(conn),
	}, nil
}
type client struct {
	conn    *grpc.ClientConn
	handler models.TorusStorageClient
}
func (c *client) Close() error {
	return c.conn.Close()
}