all repos — honk @ 92bacf5e7da1ccd7f80b61b0ca0e9611acea8f5c

my fork of honk

backend.go (view raw)

  1//
  2// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
  3//
  4// Permission to use, copy, modify, and distribute this software for any
  5// purpose with or without fee is hereby granted, provided that the above
  6// copyright notice and this permission notice appear in all copies.
  7//
  8// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 10// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 11// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 12// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 13// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 14// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 15
 16package main
 17
 18import (
 19	"bytes"
 20	"log"
 21	"net"
 22	"net/rpc"
 23	"os"
 24	"os/exec"
 25
 26	"humungus.tedunangst.com/r/webs/gate"
 27	"humungus.tedunangst.com/r/webs/image"
 28)
 29
 30type Shrinker struct {
 31}
 32
 33type ShrinkerArgs struct {
 34	Buf    []byte
 35	Params image.Params
 36}
 37
 38type ShrinkerResult struct {
 39	Image *image.Image
 40}
 41
 42var shrinkgate = gate.NewLimiter(4)
 43
 44func (s *Shrinker) Shrink(args *ShrinkerArgs, res *ShrinkerResult) error {
 45	shrinkgate.Start()
 46	defer shrinkgate.Finish()
 47	img, err := image.Vacuum(bytes.NewReader(args.Buf), args.Params)
 48	if err != nil {
 49		return err
 50	}
 51	res.Image = img
 52	return nil
 53}
 54
 55func backendSockname() string {
 56	return dataDir + "/backend.sock"
 57}
 58
 59func shrinkit(data []byte) (*image.Image, error) {
 60	cl, err := rpc.Dial("unix", backendSockname())
 61	if err != nil {
 62		return nil, err
 63	}
 64	defer cl.Close()
 65	var res ShrinkerResult
 66	err = cl.Call("Shrinker.Shrink", &ShrinkerArgs{
 67		Buf:    data,
 68		Params: image.Params{LimitSize: 4200 * 4200, MaxWidth: 2048, MaxHeight: 2048},
 69	}, &res)
 70	if err != nil {
 71		return nil, err
 72	}
 73	return res.Image, nil
 74}
 75
 76var backendhooks []func()
 77
 78func backendServer() {
 79	log.Printf("backend server running")
 80	shrinker := new(Shrinker)
 81	srv := rpc.NewServer()
 82	err := srv.Register(shrinker)
 83	if err != nil {
 84		log.Panicf("unable to register shrinker: %s", err)
 85	}
 86
 87	sockname := backendSockname()
 88	err = os.Remove(sockname)
 89	if err != nil && !os.IsNotExist(err) {
 90		log.Panicf("unable to unlink socket: %s", err)
 91	}
 92
 93	lis, err := net.Listen("unix", sockname)
 94	if err != nil {
 95		log.Panicf("unable to register shrinker: %s", err)
 96	}
 97	for _, h := range backendhooks {
 98		h()
 99	}
100	srv.Accept(lis)
101}
102
103func startBackendServer() {
104	proc := exec.Command(os.Args[0], "-datadir", dataDir, "backend")
105	proc.Stdout = os.Stdout
106	proc.Stderr = os.Stderr
107	err := proc.Start()
108	if err != nil {
109		log.Panicf("can't exec backend: %s", err)
110	}
111}