<commit_before>package litrpc

import (
	"fmt"
	"log"
	"net"
	"net/rpc"
	"net/rpc/jsonrpc"
	"time"

	"github.com/mit-dci/lit/qln"
)

/*
Remote Procedure Calls
RPCs are how people tell the lit node what to do.
It ends up being the root of ~everything in the executable.


*/

// A LitRPC is the user I/O interface; it owns and initialized a SPVCon and LitNode
// and listens and responds on RPC
type LitRPC struct {
	Node      *qln.LitNode
	OffButton chan bool
}

func RpcListen(node *qln.LitNode, port uint16) {
	rpcl := new(LitRPC)
	rpcl.Node = node
	rpcl.OffButton = make(chan bool, 1)

	server := rpc.NewServer()
	server.Register(rpcl)
	server.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath)

	portString := fmt.Sprintf(":%d", port)
	listener, err := net.Listen("tcp", portString)
	if err != nil {
		fmt.Printf(err.Error())
		return
	}

	go func() {
		for {
			conn, err := listener.Accept()
			if err != nil {
				log.Printf("listener error: " + err.Error())
			} else {
				log.Printf("new connection from %s\n", conn.RemoteAddr().String())
				go server.ServeCodec(jsonrpc.NewServerCodec(conn))
			}
		}
	}()

	// ugly; add real synchronization here
	<-rpcl.OffButton
	fmt.Printf("Got stop request\n")
	time.Sleep(time.Second)
	return
}
<commit_msg>move from json-rpc over TCP to json-rpc over HTTP<commit_after>package litrpc

import (
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"net/rpc"
	"net/rpc/jsonrpc"
	"time"

	"github.com/mit-dci/lit/qln"
)

/*
Remote Procedure Calls
RPCs are how people tell the lit node what to do.
It ends up being the root of ~everything in the executable.


*/

// A LitRPC is the user I/O interface; it owns and initialized a SPVCon and LitNode
// and listens and responds on RPC

var GlobalServer *rpc.Server

type LitRPC struct {
	Node      *qln.LitNode
	OffButton chan bool
}

type HttpConn struct {
	in  io.Reader
	out io.Writer
}

func (c *HttpConn) Read(p []byte) (n int, err error)  { return c.in.Read(p) }
func (c *HttpConn) Write(d []byte) (n int, err error) { return c.out.Write(d) }
func (c *HttpConn) Close() error                      { return nil }

func JSONRPCoverHTTPHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/lit" { // all RPC calls have path /lit
		serverCodec :=
			jsonrpc.NewServerCodec(&HttpConn{in: r.Body, out: w})
		w.Header().Set("Content-type", "application/json")
		w.WriteHeader(200)
		// this is super ugly; find a better way to do this.
		// maybe try a different struct with a ServeHTTP method.
		err := GlobalServer.ServeRequest(serverCodec)
		if err != nil {
			log.Printf("JSON-RPC request serving error: %v", err)
			http.Error(w, "JSON-RPC request error", 500)
			return
		}
	}
}

func RpcListen(node *qln.LitNode, port uint16) {
	rpcl := new(LitRPC)
	rpcl.Node = node
	rpcl.OffButton = make(chan bool, 1)

	GlobalServer = rpc.NewServer()
	GlobalServer.Register(rpcl)

	//	server.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath)

	portString := fmt.Sprintf(":%d", port)
	listener, err := net.Listen("tcp", portString)
	if err != nil {
		fmt.Printf(err.Error())
		return
	}
	defer listener.Close()

	http.Serve(listener, http.HandlerFunc(JSONRPCoverHTTPHandler))

	/*
		go func() {
			for {
				conn, err := listener.Accept()
				if err != nil {
					log.Printf("listener error: " + err.Error())
				} else {
					log.Printf("new connection from %s\n", conn.RemoteAddr().String())
					go server.ServeCodec(jsonrpc.NewServerCodec(conn))
				}
			}
		}()

	*/

	// ugly; add real synchronization here
	<-rpcl.OffButton
	fmt.Printf("Got stop request\n")
	time.Sleep(time.Second)
	return
}

{'fraction_non_alphanumeric': 0.13630041724617525, 'fraction_numerical': 0.003337969401947149, 'mean_word_length': 3.406862745098039, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3053837', 'n_tokens_mistral': 1397, 'n_tokens_neox': 1295, 'n_words': 362}