all repos — honk @ 16d59f1a3bb26fe187f025437fac8caca1cd8d64

my fork of honk

backend.go (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
//
// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

package main

import (
	"bytes"
	"log"
	"net"
	"net/rpc"
	"os"
	"os/exec"

	"humungus.tedunangst.com/r/webs/gate"
	"humungus.tedunangst.com/r/webs/image"
)

type Shrinker struct {
}

type ShrinkerArgs struct {
	Buf    []byte
	Params image.Params
}

type ShrinkerResult struct {
	Image *image.Image
}

var shrinkgate = gate.NewLimiter(4)

func (s *Shrinker) Shrink(args *ShrinkerArgs, res *ShrinkerResult) error {
	shrinkgate.Start()
	defer shrinkgate.Finish()
	img, err := image.Vacuum(bytes.NewReader(args.Buf), args.Params)
	if err != nil {
		return err
	}
	res.Image = img
	return nil
}

func backendSockname() string {
	return dataDir + "/backend.sock"
}

func shrinkit(data []byte) (*image.Image, error) {
	cl, err := rpc.Dial("unix", backendSockname())
	if err != nil {
		return nil, err
	}
	defer cl.Close()
	var res ShrinkerResult
	err = cl.Call("Shrinker.Shrink", &ShrinkerArgs{
		Buf:    data,
		Params: image.Params{LimitSize: 4200 * 4200, MaxWidth: 2048, MaxHeight: 2048},
	}, &res)
	if err != nil {
		return nil, err
	}
	return res.Image, nil
}

var backendhooks []func()

func backendServer() {
	log.Printf("backend server running")
	shrinker := new(Shrinker)
	srv := rpc.NewServer()
	err := srv.Register(shrinker)
	if err != nil {
		log.Panicf("unable to register shrinker: %s", err)
	}

	sockname := backendSockname()
	err = os.Remove(sockname)
	if err != nil && !os.IsNotExist(err) {
		log.Panicf("unable to unlink socket: %s", err)
	}

	lis, err := net.Listen("unix", sockname)
	if err != nil {
		log.Panicf("unable to register shrinker: %s", err)
	}
	for _, h := range backendhooks {
		h()
	}
	srv.Accept(lis)
}

func startBackendServer() {
	proc := exec.Command(os.Args[0], "-datadir", dataDir, "backend")
	proc.Stdout = os.Stdout
	proc.Stderr = os.Stderr
	err := proc.Start()
	if err != nil {
		log.Panicf("can't exec backend: %s", err)
	}
}