~sbaildon/blocky

d778218f639c50a2a5a8d9cb73af9bd247979365 — Sean Baildon 1 year, 7 months ago c3616d0
super hacky launchd integration
1 files changed, 72 insertions(+), 44 deletions(-)

M server/server.go
M server/server.go => server/server.go +72 -44
@@ 1,5 1,11 @@
package server

/*
#include <stdlib.h>
int launch_activate_socket(const char *name, int **fds, size_t *cnt);
*/
import "C"

import (
	"bytes"
	"crypto/rand"


@@ 11,11 17,13 @@ import (
	"math/big"
	mrand "math/rand"
	"net"
	"net/http"
	"os"
	"runtime"
	"runtime/debug"
	"strings"
	"sync"
	"time"
	"unsafe"

	"github.com/0xERR0R/blocky/api"
	"github.com/0xERR0R/blocky/config"


@@ 200,12 208,11 @@ func createServers(cfg *config.Config, cert tls.Certificate) ([]*dns.Server, err
		return nil
	}

	err = multierror.Append(err,
		addServers(createUDPServer, cfg.DNSPorts),
		addServers(createTCPServer, cfg.DNSPorts),
		addServers(func(address string) (*dns.Server, error) {
			return createTLSServer(address, cert)
		}, cfg.TLSPorts))
	err = multierror.Append(err, addServers(createUDPServer, cfg.DNSPorts))
	// addServers(createTCPServer, cfg.DNSPorts),
	// addServers(func(address string) (*dns.Server, error) {
	// 	return createTLSServer(address, cert)
	// }, cfg.TLSPorts))

	return dnsServers, err.ErrorOrNil()
}


@@ 280,10 287,20 @@ func createTCPServer(address string) (*dns.Server, error) {
}

func createUDPServer(address string) (*dns.Server, error) {
	logger().Infof("Creating UDP server with %s\n", address)
	pktConn, _ := launchdSocket("Listeners")

	if pktConn == nil {
		logger().Info("got nil from launchd")
	} else {
		logger().Info("good to go")
	}

	return &dns.Server{
		Addr:    address,
		Net:     "udp",
		Handler: dns.NewServeMux(),
		Addr:       "127.0.0.1:53",
		Net:        "udp",
		PacketConn: pktConn,
		Handler:    dns.NewServeMux(),
		NotifyStartedFunc: func() {
			logger().Infof("UDP server is up and running on address %s", address)
		},


@@ 468,52 485,63 @@ func toMB(b uint64) uint64 {
	return b / bytesInKB / bytesInKB
}

// Start starts the server
func (s *Server) Start(errCh chan<- error) {
	logger().Info("Starting server")
func unlockOnce(l sync.Locker) func() {
	var once sync.Once
	return func() { once.Do(l.Unlock) }
}

	for _, srv := range s.dnsServers {
		srv := srv
func launchdSocket(address string) (net.PacketConn, error) {
	c_name := C.CString(address)
	var c_fds *C.int
	c_cnt := C.size_t(0)

		go func() {
			if err := srv.ListenAndServe(); err != nil {
				errCh <- fmt.Errorf("start %s listener failed: %w", srv.Net, err)
			}
		}()
	err := C.launch_activate_socket(c_name, &c_fds, &c_cnt)
	if err != 0 {
		return nil, fmt.Errorf("couldn't activate launchd socket: %v", err)
	}

	for i, listener := range s.httpListeners {
		listener := listener
		address := s.cfg.HTTPPorts[i]
	length := int(c_cnt)
	if length != 1 {
		return nil, fmt.Errorf("expected exactly one socket to be configured in launchd for '%s', found %d", address, length)
	}
	ptr := unsafe.Pointer(c_fds)
	defer C.free(ptr)

		go func() {
			logger().Infof("http server is up and running on addr/port %s", address)
	fds := (*[1]C.int)(ptr)
	file := os.NewFile(uintptr(fds[0]), "")

			if err := http.Serve(listener, s.httpMux); err != nil {
				errCh <- fmt.Errorf("start http listener failed: %w", err)
			}
		}()
	l, e := net.FilePacketConn(file)

	if _, ok := l.(*net.UDPConn); !ok {
		logger().Info("typecast not okay")
	} else {
		logger().Info("typecast is okay?")
	}

	for i, listener := range s.httpsListeners {
		listener := listener
		address := s.cfg.HTTPSPorts[i]
	return l, e
	// return net.FileListener(file)
}

// Start starts the server
func (s *Server) Start(errCh chan<- error) {
	logger().Info("Starting server")

	for i, _ := range s.dnsServers {
		srv := s.dnsServers[i]

		// if err != nil {
		// 	errCh <- fmt.Errorf("got err: %w", err)
		// }

		go func() {
			logger().Infof("https server is up and running on addr/port %s", address)

			server := http.Server{
				Handler: s.httpsMux,
				//nolint:gosec
				TLSConfig: &tls.Config{
					MinVersion:   minTLSVersion(),
					CipherSuites: tlsCipherSuites(),
					Certificates: []tls.Certificate{s.cert},
				},
			if srv.PacketConn == nil {
				logger().Info("packetconn is nill")
			} else {
				logger().Info("packetconn should be good")
			}

			if err := server.ServeTLS(listener, "", ""); err != nil {
				errCh <- fmt.Errorf("start https listener failed: %w", err)
			if err := srv.ActivateAndServe(); err != nil {
				errCh <- fmt.Errorf("start %s listener failed: %w", srv.Net, err)
			}
		}()
	}