103 lines
2.8 KiB
Go
103 lines
2.8 KiB
Go
// Copyright 2021, Henrik Sölver henrik.solver@gmail.com
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"ippserver/packages/ipp"
|
|
"ippserver/packages/mdnsserver"
|
|
"net/http"
|
|
"net/url"
|
|
"sync"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var (
|
|
loglevel string
|
|
location string
|
|
port uint
|
|
printerURI string
|
|
printerName string
|
|
ippurl, httpurl *url.URL
|
|
)
|
|
|
|
func init() {
|
|
flag.StringVar(&loglevel, "loglevel", "info", "The wanted loglevel error/info/debug")
|
|
flag.StringVar(&location, "location", "somewhere", "locaton of the printer as shown in mDNS")
|
|
flag.UintVar(&port, "port", 1234, "tcp port")
|
|
flag.StringVar(&printerURI, "printer", "", "URL to the real printer, typical ipp://printername.local:631/ipp/print")
|
|
flag.StringVar(&printerName, "name", "ChroBroPrint", "Name of the printer advertised with mDNS")
|
|
}
|
|
|
|
func main() {
|
|
var err error
|
|
flag.Parse()
|
|
customFormatter := new(log.TextFormatter)
|
|
customFormatter.TimestampFormat = "2006-01-02 15:04:05"
|
|
log.SetFormatter(customFormatter)
|
|
customFormatter.FullTimestamp = true
|
|
log.SetLevel(log.InfoLevel)
|
|
|
|
ippurl, err = url.Parse(printerURI)
|
|
if err != nil {
|
|
fmt.Printf("Failed to parse printer URL %v", err.Error())
|
|
return
|
|
}
|
|
httpurl, _ = url.Parse(printerURI)
|
|
httpurl.Scheme = "http"
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
go mdnsserver.Run(ctx, location, uint16(port), printerName)
|
|
|
|
http.HandleFunc("/ipp/print", handle)
|
|
|
|
log.Infof("http server starting on :%v", port)
|
|
err = http.ListenAndServe(fmt.Sprintf(":%v", port), nil)
|
|
if err != nil {
|
|
log.Fatal("ListenAndServe: " + err.Error())
|
|
}
|
|
}
|
|
|
|
var mut sync.Mutex
|
|
var requestID uint32
|
|
|
|
func handle(w http.ResponseWriter, r *http.Request) {
|
|
mut.Lock()
|
|
requestID++
|
|
mut.Unlock()
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "Unsupported method", http.StatusMethodNotAllowed)
|
|
}
|
|
|
|
request := ipp.NewRequest(0, 0)
|
|
request.UnMarshal(r.Body)
|
|
log.Infof("Upstream Request: id: %v op: %v", request.RequestID(), request.Operation())
|
|
var response *ipp.Response
|
|
var err error
|
|
switch request.Operation() {
|
|
case ipp.GetPrinterAttributes:
|
|
response = handleGetPrinterAttributes(request)
|
|
case ipp.PrintJob:
|
|
response, err = handlePrintJob(request, r.Body, requestID)
|
|
case ipp.GetJobs:
|
|
response, err = handleGetJobs(request, requestID)
|
|
case ipp.ValidateJob:
|
|
response = handleValidateJob(request)
|
|
case ipp.GetJobAttributes:
|
|
response, err = handleGetJobAttributes(request, requestID)
|
|
default:
|
|
response = ipp.NewResponse(ipp.ClientErrorBadRequest, request.RequestID())
|
|
}
|
|
if err != nil {
|
|
log.Errorf("Failed to handle request: %v", err.Error())
|
|
response = ipp.NewResponse(ipp.ServerErrorServiceUnavailable, request.RequestID())
|
|
}
|
|
log.Infof("Upstream Response: %v", response.Header())
|
|
data := response.Marshal()
|
|
w.Write(data)
|
|
}
|