matrix-capnproto-fed

What if Matrix was written using Cap'n'proto and a RPC federation API?
git clone git://archive.git.mtrnord.blog/MTRNord/matrix-capnproto-fed.git
Log | Files | Refs | README | LICENSE

main.go (3466B)


      1 package main
      2 
      3 import (
      4 	"context"
      5 	"errors"
      6 	"flag"
      7 	"fmt"
      8 	"log"
      9 	"log/slog"
     10 	"net"
     11 	"os"
     12 	"os/signal"
     13 	"runtime/pprof"
     14 	"syscall"
     15 
     16 	"capnproto.org/go/capnp/v3"
     17 	"capnproto.org/go/capnp/v3/flowcontrol"
     18 	"capnproto.org/go/capnp/v3/rpc"
     19 	"github.com/MTRNord/matrix_protobuf_fed/rpcserver"
     20 
     21 	protocol "github.com/MTRNord/matrix_protobuf_fed/proto/federation/v1"
     22 )
     23 
     24 // This implements a dummy server for testing purposes of the rough api design especially around signatures
     25 
     26 // Serve serves a Cap'n Proto RPC to incoming connections.
     27 //
     28 // Serve will take ownership of bootstrapClient and release it after the listener closes.
     29 //
     30 // Serve exits with the listener error if the listener is closed by the owner.
     31 func Serve(lis net.Listener, boot capnp.Client) error {
     32 	if !boot.IsValid() {
     33 		err := errors.New("bootstrap client is not valid")
     34 		return err
     35 	}
     36 	// Since we took ownership of the bootstrap client, release it after we're done.
     37 	defer boot.Release()
     38 	for {
     39 		// Accept incoming connections
     40 		conn, err := lis.Accept()
     41 		if err != nil {
     42 			conn.Close()
     43 			return err
     44 		}
     45 		defer conn.Close()
     46 
     47 		// the RPC connection takes ownership of the bootstrap interface and will release it when the connection
     48 		// exits, so use AddRef to avoid releasing the provided bootstrap client capability.
     49 		opts := rpc.Options{
     50 			BootstrapClient: boot.AddRef(),
     51 			Logger:          slog.Default(),
     52 		}
     53 		// For each new incoming connection, create a new RPC transport connection that will serve incoming RPC requests
     54 		transport := rpc.NewStreamTransport(conn)
     55 		defer transport.Close()
     56 		rpc_conn := rpc.NewConn(transport, &opts)
     57 		defer rpc_conn.Close()
     58 	}
     59 }
     60 
     61 // ListenAndServe opens a listener on the given address and serves a Cap'n Proto RPC to incoming connections
     62 //
     63 // network and address are passed to net.Listen. Use network "unix" for Unix Domain Sockets
     64 // and "tcp" for regular TCP IP4 or IP6 connections.
     65 //
     66 // ListenAndServe will take ownership of bootstrapClient and release it on exit.
     67 func ListenAndServe(ctx context.Context, network, addr string, bootstrapClient capnp.Client) error {
     68 	listener, err := net.Listen(network, addr)
     69 
     70 	if err == nil {
     71 		// to close this listener, close the context
     72 		go func() {
     73 			<-ctx.Done()
     74 			_ = listener.Close()
     75 		}()
     76 		err = Serve(listener, bootstrapClient)
     77 	}
     78 	return err
     79 }
     80 
     81 var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
     82 var memprofile = flag.String("memprofile", "", "write memory profile to this file")
     83 var f *os.File
     84 
     85 func main() {
     86 	flag.Parse()
     87 	if *cpuprofile != "" {
     88 		f, err := os.Create(*cpuprofile)
     89 		if err != nil {
     90 			log.Fatal(err)
     91 		}
     92 		pprof.StartCPUProfile(f)
     93 		defer pprof.StopCPUProfile()
     94 	}
     95 
     96 	c := make(chan os.Signal, 2)
     97 	signal.Notify(c, os.Interrupt, syscall.SIGTERM) // subscribe to system signals
     98 	onKill := func(c chan os.Signal) {
     99 		select {
    100 		case <-c:
    101 			fmt.Println("Got killed")
    102 			pprof.StopCPUProfile()
    103 			f.Close()
    104 			if *memprofile != "" {
    105 				f, err := os.Create(*memprofile)
    106 				if err != nil {
    107 					log.Fatal(err)
    108 				}
    109 				pprof.WriteHeapProfile(f)
    110 				f.Close()
    111 			}
    112 			os.Exit(0)
    113 		}
    114 	}
    115 
    116 	// try to handle os interrupt(signal terminated)
    117 	go onKill(c)
    118 
    119 	log.Println("Starting server on port localhost:8449")
    120 	server := rpcserver.NewServer()
    121 
    122 	client := protocol.MatrixFederation_ServerToClient(server)
    123 	client.SetFlowLimiter(flowcontrol.NewFixedLimiter(1 << 17))
    124 
    125 	ListenAndServe(context.Background(), "tcp", "localhost:8449", capnp.Client(client))
    126 }