| // Copyright 2020 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package jsonrpc2 |
| |
| import ( |
| "context" |
| "log" |
| "net" |
| "os" |
| ) |
| |
| // NOTE: This file provides an experimental API for serving multiple remote |
| // jsonrpc2 clients over the network. For now, it is intentionally similar to |
| // net/http, but that may change in the future as we figure out the correct |
| // semantics. |
| |
| // A StreamServer is used to serve incoming jsonrpc2 clients communicating over |
| // a newly created stream. |
| type StreamServer interface { |
| ServeStream(context.Context, Stream) error |
| } |
| |
| // The ServerFunc type is an adapter that implements the StreamServer interface |
| // using an ordinary function. |
| type ServerFunc func(context.Context, Stream) error |
| |
| // ServeStream calls f(ctx, s). |
| func (f ServerFunc) ServeStream(ctx context.Context, s Stream) error { |
| return f(ctx, s) |
| } |
| |
| // HandlerServer returns a StreamServer that handles incoming streams using the |
| // provided handler. |
| func HandlerServer(h Handler) StreamServer { |
| return ServerFunc(func(ctx context.Context, s Stream) error { |
| conn := NewConn(s) |
| conn.AddHandler(h) |
| return conn.Run(ctx) |
| }) |
| } |
| |
| // ListenAndServe starts an jsonrpc2 server on the given address. It exits only |
| // on error. |
| func ListenAndServe(ctx context.Context, network, addr string, server StreamServer) error { |
| ln, err := net.Listen(network, addr) |
| if err != nil { |
| return err |
| } |
| if network == "unix" { |
| defer os.Remove(addr) |
| } |
| return Serve(ctx, ln, server) |
| } |
| |
| // Serve accepts incoming connections from the network, and handles them using |
| // the provided server. It exits only on error. |
| func Serve(ctx context.Context, ln net.Listener, server StreamServer) error { |
| for { |
| netConn, err := ln.Accept() |
| if err != nil { |
| return err |
| } |
| stream := NewHeaderStream(netConn, netConn) |
| go func() { |
| if err := server.ServeStream(ctx, stream); err != nil { |
| log.Printf("serving stream: %v", err) |
| } |
| }() |
| } |
| } |