More development.

More types.
Fixed attribute groups in requests.
Started on client.
Saving data to file.
This commit is contained in:
2020-12-26 20:58:38 +01:00
parent 8b5f69cb52
commit 77ef627fe2
15 changed files with 307 additions and 207 deletions

77
main.go
View File

@@ -1,77 +0,0 @@
package main
import (
"context"
"fmt"
"ippserver/packages/ipp"
"ippserver/packages/mdnsserver"
"net/http"
log "github.com/sirupsen/logrus"
)
func main() {
customFormatter := new(log.TextFormatter)
customFormatter.TimestampFormat = "2006-01-02 15:04:05"
log.SetFormatter(customFormatter)
customFormatter.FullTimestamp = true
log.SetLevel(log.DebugLevel)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go mdnsserver.Run(ctx)
http.HandleFunc("/ipp/print", handle)
log.Info("http server started on :1234")
err := http.ListenAndServe(":1234", nil)
if err != nil {
log.Fatal("ListenAndServe: " + err.Error())
}
}
func handle(w http.ResponseWriter, r *http.Request) {
log.Infoln("handle")
if r.Method != http.MethodPost {
http.Error(w, "Unsupported method", http.StatusMethodNotAllowed)
}
//body := make([]byte, r.ContentLength)
//io.ReadFull(r.Body, body)
//log.Infof("Body %x", body)
request := ipp.NewRequest()
//rdata := make([]byte, r.ContentLength)
//io.ReadFull(r.Body, rdata)
//log.Printf("Data %x", rdata)
//fmt.Printf("data % #0x", rdata)
//buf := bytes.NewBuffer(rdata)
request.UnMarshal(r.Body)
fmt.Printf("Request: \n%v\n", request)
response := ipp.NewResponse(ipp.SuccessfulOk, request.RequestId())
var a ipp.Attribute
a = ipp.NewCharSetValue("attributes-charset", "utf-8")
response.AddOperatonAttribute(a)
a = ipp.NewNaturalLanguage("attributes-natural-language", "en")
response.AddOperatonAttribute(a)
a = ipp.NewUriValue("printer-uri", "ipp://drpork:1234/ipp/print")
response.AddOperatonAttribute(a)
a = ipp.NewtextWithoutLanguage("printer-make-and-model", "ChroBro 001")
response.AddOperatonAttribute(a)
a = ipp.NewEnum("printer-state", int32(ipp.Idle))
response.AddOperatonAttribute(a)
a = ipp.NewKeyWord("ipp-versions-supported", "1.0", "1.1", "2.0")
response.AddOperatonAttribute(a)
response.AddOperatonAttribute(ipp.NewKeyWord("ipp-features-supported", "wfds-print-1.0"))
response.AddOperatonAttribute(ipp.NewMimeMediaType("document-format-supported", "image/pwg-raster"))
response.AddOperatonAttribute(ipp.NewKeyWord("media-supported", "iso_a4_210x297mm"))
response.AddOperatonAttribute(ipp.NewKeyWord("sides-supported", "one-sided", "two-sided-long-edge", "two-sided-short-edge"))
response.AddOperatonAttribute(ipp.NewKeyWord("print-color-mode-supported", "auto", "color", "monochrome"))
fmt.Printf("Response:\n%v\n", response)
data := response.Marshal()
log.Debugf("% x", data)
w.Write(data)
}

View File

@@ -5,6 +5,8 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
log "github.com/sirupsen/logrus"
) )
type enum struct { type enum struct {
@@ -27,8 +29,7 @@ func (e *enum) valueTag() tag {
} }
func (e *enum) unmarshal(byteStream io.Reader) { func (e *enum) unmarshal(byteStream io.Reader) {
//e.name, e.value = unmarshalSingleValue(byteStream) log.Warn("Unmarshal of enum is not implemented yet")
} }
func (e *enum) marshal() []byte { func (e *enum) marshal() []byte {

View File

@@ -55,33 +55,33 @@ const (
) )
// Operation-id, defined in rfc8011 // Operation-id, defined in rfc8011
type operationId uint16 type OperationId uint16
const ( const (
PrintJob operationId = 0x0002 PrintJob OperationId = 0x0002
PrintURI operationId = 0x0003 PrintURI OperationId = 0x0003
ValidateJob operationId = 0x0004 ValidateJob OperationId = 0x0004
CreateJob operationId = 0x0005 CreateJob OperationId = 0x0005
SendDocument operationId = 0x0006 SendDocument OperationId = 0x0006
SendURI operationId = 0x0007 SendURI OperationId = 0x0007
CancelJob operationId = 0x0008 CancelJob OperationId = 0x0008
GetJobAttributes operationId = 0x0009 GetJobAttributes OperationId = 0x0009
GetJobs operationId = 0x000a GetJobs OperationId = 0x000a
GetPrinterAttributes operationId = 0x000b GetPrinterAttributes OperationId = 0x000b
HoldJob operationId = 0x000c HoldJob OperationId = 0x000c
ReleaseJob operationId = 0x000d ReleaseJob OperationId = 0x000d
RestartJob operationId = 0x000e RestartJob OperationId = 0x000e
PausePrinter operationId = 0x0010 PausePrinter OperationId = 0x0010
ResumePrinter operationId = 0x0011 ResumePrinter OperationId = 0x0011
PurgeJobs operationId = 0x0012 PurgeJobs OperationId = 0x0012
) )
type printerState int32 type printerState int32
const ( const (
Idle printerState = 3 Idle printerState = 3
Preocessing printerState = 4 Processing printerState = 4
Stopped printerState = 5 Stopped printerState = 5
) )
type statusCode uint16 type statusCode uint16
@@ -101,17 +101,13 @@ func (v versionNumber) String() string {
func unmarshalSingleValue(byteStream io.Reader) (string, string) { func unmarshalSingleValue(byteStream io.Reader) (string, string) {
var length uint16 var length uint16
binary.Read(byteStream, binary.BigEndian, &length) binary.Read(byteStream, binary.BigEndian, &length)
//log.Infof("Length %v", length)
attributeName := make([]byte, length) attributeName := make([]byte, length)
if length > 0 { if length > 0 {
binary.Read(byteStream, binary.BigEndian, attributeName) binary.Read(byteStream, binary.BigEndian, attributeName)
//log.Infof("Valuename %v", string(attributeName))
} }
binary.Read(byteStream, binary.BigEndian, &length) binary.Read(byteStream, binary.BigEndian, &length)
//log.Infof("Length %v", length)
attributeValue := make([]byte, length) attributeValue := make([]byte, length)
binary.Read(byteStream, binary.BigEndian, attributeValue) binary.Read(byteStream, binary.BigEndian, attributeValue)
//log.Infof("Value %v", string(attributeValue))
return string(attributeName), string(attributeValue) return string(attributeName), string(attributeValue)
} }

View File

@@ -2,30 +2,30 @@ package ipp
import "io" import "io"
type nameWithoutLanguage struct { type NameWithoutLanguage struct {
name string name string
value string value string
} }
func NewNameWithoutLanguage(name, value string) *nameWithoutLanguage { func NewNameWithoutLanguage(name, value string) *NameWithoutLanguage {
c := new(nameWithoutLanguage) c := new(NameWithoutLanguage)
c.name = name c.name = name
c.value = value c.value = value
return c return c
} }
func (c nameWithoutLanguage) String() string { func (c NameWithoutLanguage) String() string {
return c.name + ":" + c.value return c.name + ":" + c.value
} }
func (c *nameWithoutLanguage) valueTag() tag { func (c *NameWithoutLanguage) valueTag() tag {
return nameWithoutLanguageValueTag return nameWithoutLanguageValueTag
} }
func (c *nameWithoutLanguage) unmarshal(byteStream io.Reader) { func (c *NameWithoutLanguage) unmarshal(byteStream io.Reader) {
c.name, c.value = unmarshalSingleValue(byteStream) c.name, c.value = unmarshalSingleValue(byteStream)
} }
func (c *nameWithoutLanguage) marshal() []byte { func (c *NameWithoutLanguage) marshal() []byte {
l := 5 + len(c.name) + len(c.value) l := 5 + len(c.name) + len(c.value)
b := make([]byte, l, l) b := make([]byte, l, l)
b[0] = byte(nameWithoutLanguageValueTag) b[0] = byte(nameWithoutLanguageValueTag)
@@ -33,9 +33,13 @@ func (c *nameWithoutLanguage) marshal() []byte {
return b return b
} }
func (c *nameWithoutLanguage) size() int { func (c *NameWithoutLanguage) size() int {
l := 1 + 4 // The attribute tag + 2 lengths l := 1 + 4 // The attribute tag + 2 lengths
l += len(c.name) l += len(c.name)
l += len(c.value) l += len(c.value)
return l return l
} }
func (n NameWithoutLanguage) Value() string {
return n.value
}

View File

@@ -36,7 +36,7 @@ var (
_operationId_index_1 = [...]uint8{0, 12, 25, 34} _operationId_index_1 = [...]uint8{0, 12, 25, 34}
) )
func (i operationId) String() string { func (i OperationId) String() string {
switch { switch {
case 2 <= i && i <= 14: case 2 <= i && i <= 14:
i -= 2 i -= 2

View File

@@ -9,7 +9,7 @@ func _() {
// Re-run the stringer command to generate them again. // Re-run the stringer command to generate them again.
var x [1]struct{} var x [1]struct{}
_ = x[Idle-3] _ = x[Idle-3]
_ = x[Preocessing-4] _ = x[Processing-4]
_ = x[Stopped-5] _ = x[Stopped-5]
} }

View File

@@ -1,6 +1,7 @@
package ipp package ipp
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
@@ -10,16 +11,25 @@ import (
type ippRequestHeader struct { type ippRequestHeader struct {
versionNumber versionNumber versionNumber versionNumber
operationId operationId operationId OperationId
requestId uint32 requestId uint32
} }
func (h *ippRequestHeader) marshal(byteStream io.Reader) { func (h *ippRequestHeader) unmarshal(byteStream io.Reader) {
binary.Read(byteStream, binary.BigEndian, &h.versionNumber) binary.Read(byteStream, binary.BigEndian, &h.versionNumber)
binary.Read(byteStream, binary.BigEndian, &h.operationId) binary.Read(byteStream, binary.BigEndian, &h.operationId)
binary.Read(byteStream, binary.BigEndian, &h.requestId) binary.Read(byteStream, binary.BigEndian, &h.requestId)
} }
func (h *ippRequestHeader) marshal() []byte {
b := make([]byte, 0, 8)
buf := bytes.NewBuffer(b)
binary.Write(buf, binary.BigEndian, h.versionNumber)
binary.Write(buf, binary.BigEndian, h.operationId)
binary.Write(buf, binary.BigEndian, h.requestId)
return buf.Bytes()
}
func (h ippRequestHeader) String() string { func (h ippRequestHeader) String() string {
return fmt.Sprintf("Version number: %v Operation Id: %v Request Id: %v", h.versionNumber, h.operationId, h.requestId) return fmt.Sprintf("Version number: %v Operation Id: %v Request Id: %v", h.versionNumber, h.operationId, h.requestId)
} }
@@ -41,8 +51,11 @@ type Request struct {
header ippRequestHeader header ippRequestHeader
} }
func NewRequest() *Request { func NewRequest(op OperationId, requestId uint32) *Request {
r := new(Request) r := new(Request)
r.header.operationId = op
r.header.requestId = requestId
r.header.versionNumber = 0x0200
r.operationAttributes = make(map[string]Attribute) r.operationAttributes = make(map[string]Attribute)
r.jobAttributes = make(map[string]Attribute) r.jobAttributes = make(map[string]Attribute)
r.printerAttributes = make(map[string]Attribute) r.printerAttributes = make(map[string]Attribute)
@@ -67,7 +80,7 @@ func (r Request) String() string {
} }
func (r *Request) UnMarshal(body io.Reader) { func (r *Request) UnMarshal(body io.Reader) {
r.header.marshal(body) r.header.unmarshal(body)
log.Debugf("Header %v", r.header) log.Debugf("Header %v", r.header)
var tag tag var tag tag
err := binary.Read(body, binary.BigEndian, &tag) err := binary.Read(body, binary.BigEndian, &tag)
@@ -75,95 +88,116 @@ func (r *Request) UnMarshal(body io.Reader) {
log.Error(err.Error()) log.Error(err.Error())
} }
log.Debugf("got tag - %v", tag) log.Debugf("got tag - %v", tag)
var currentAttributeGroup map[string]Attribute
switch tag {
case operationAttributes:
currentAttributeGroup = r.operationAttributes
case jobAttributes:
currentAttributeGroup = r.jobAttributes
case printerAttributes:
currentAttributeGroup = r.printerAttributes
default:
log.Errorf("Unknown tag %v", tag)
}
if tag == operationAttributes { var lastAddValuer AddValuer
var lastAddValuer AddValuer for {
nextoperationattr: err = binary.Read(body, binary.BigEndian, &tag)
for tag != endOfAttributes { if err != nil {
log.Errorf("End of input before end of attributes tag (%v)", err.Error())
err = binary.Read(body, binary.BigEndian, &tag) }
if err != nil { log.Debugf("Value tag - %v", tag)
log.Error(err.Error()) switch tag {
} case endOfAttributes:
log.Debugf("Value tag - %v", tag) return
switch tag { case charsetValueTag:
case endOfAttributes: c := NewCharSetValue("", "")
err = binary.Read(body, binary.BigEndian, &tag) c.unmarshal(body)
if err == io.EOF { currentAttributeGroup[c.name] = c
// No more data log.Debugf("%v %v", c.name, c.value)
return case uriValueTag:
} u := NewUriValue("", "")
if err != nil { u.unmarshal(body)
log.Error(err.Error()) currentAttributeGroup[u.name] = u
} log.Debugf("%v %v", u.name, u.value)
log.Debugf("got tag - %v", tag) case naturalLanguageValueTag:
err = binary.Read(body, binary.BigEndian, &tag) n := NewNaturalLanguage("", "")
if err != nil { n.unmarshal(body)
log.Error(err.Error()) currentAttributeGroup[n.name] = n
} log.Debugf("%v %v", n.name, n.value)
log.Debugf("got tag - %v", tag) case keyWordValueTag:
name, value := unmarshalSingleValue(body)
break nextoperationattr if name == "" {
case charsetValueTag: lastAddValuer.addValue(value)
c := NewCharSetValue("", "") } else {
c.unmarshal(body) k := NewKeyWord(name, value)
r.operationAttributes[c.name] = c currentAttributeGroup[name] = k
log.Debugf("%v %v", c.name, c.value) lastAddValuer = k
case uriValueTag: }
u := NewUriValue("", "") log.Debugf("%v : %v", name, value)
u.unmarshal(body) case nameWithoutLanguageValueTag:
r.operationAttributes[u.name] = u n := NewNameWithoutLanguage("", "")
log.Debugf("%v %v", u.name, u.value) n.unmarshal(body)
case naturalLanguageValueTag: currentAttributeGroup[n.name] = n
n := NewNaturalLanguage("", "") log.Debugf("%v %v", n.name, n.value)
n.unmarshal(body) case mimeMediaTypeValueTag:
r.operationAttributes[n.name] = n name, value := unmarshalSingleValue(body)
log.Debugf("%v %v", n.name, n.value) if name == "" {
case keyWordValueTag: lastAddValuer.addValue(value)
name, value := unmarshalSingleValue(body) } else {
if name == "" { m := NewMimeMediaType(name, value)
lastAddValuer.addValue(value) currentAttributeGroup[name] = m
} else { lastAddValuer = m
k := NewKeyWord(name, value) }
r.operationAttributes[name] = k log.Debugf("%v : %v", name, value)
lastAddValuer = k case jobAttributes:
} log.Debug("Start job attributes")
log.Debugf("%v : %v", name, value) currentAttributeGroup = r.jobAttributes
case nameWithoutLanguageValueTag: case resolutionValueTag:
n := NewNameWithoutLanguage("", "") res := NewResolution("", 0, 0)
n.unmarshal(body) res.unmarshal(body)
r.operationAttributes[n.name] = n currentAttributeGroup[res.name] = res
log.Debugf("%v %v", n.name, n.value) log.Debugf("Resolution %v", res)
case mimeMediaTypeValueTag: default:
name, value := unmarshalSingleValue(body) log.Errorf("Unsupported tag %v", tag)
if name == "" {
lastAddValuer.addValue(value)
} else {
m := NewMimeMediaType(name, value)
r.operationAttributes[name] = m
lastAddValuer = m
}
case jobAttributes:
log.Debug("Start job attributes")
case resolutionValueTag:
res := NewResolution()
res.unmarshal(body)
r.operationAttributes["resolution"] = res
log.Debugf("Resolution %v", res)
default:
log.Errorf("Unsupported tag %v", tag)
}
} }
log.Infof("Value tag %v", tag)
} else {
log.Error("unexpected tag")
// TODO Return something sensible here
} }
} }
func (r *Request) RequestId() uint32 { func (r *Request) RequestId() uint32 {
return r.header.requestId return r.header.requestId
} }
func (r *Request) Operation() OperationId {
return r.header.operationId
}
func (r *Request) GetAttribute(name string) Attribute {
return r.operationAttributes[name]
}
func (r *Request) Marshal() []byte {
// //s = r.size
var buf bytes.Buffer
buf.Write(r.header.marshal())
if len(r.operationAttributes) > 0 {
buf.WriteByte(byte(operationAttributes))
for _, e := range r.operationAttributes {
buf.Write(e.marshal())
}
}
if len(r.jobAttributes) > 0 {
buf.WriteByte(byte(jobAttributes))
for _, e := range r.jobAttributes {
buf.Write(e.marshal())
}
}
if len(r.printerAttributes) > 0 {
buf.WriteByte(byte(printerAttributes))
for _, e := range r.printerAttributes {
buf.Write(e.marshal())
}
}
buf.WriteByte(byte(endOfAttributes))
return buf.Bytes()
}

View File

@@ -59,7 +59,7 @@ var testRequest = []byte{0x01, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x11,
func TestUnmarshalRequestPrinterAttributes(T *testing.T) { func TestUnmarshalRequestPrinterAttributes(T *testing.T) {
buf := bytes.NewBuffer(testRequest) buf := bytes.NewBuffer(testRequest)
req := NewRequest() req := NewRequest(GetPrinterAttributes, 17)
req.UnMarshal(buf) req.UnMarshal(buf)
fmt.Print(req) fmt.Print(req)

View File

@@ -1,6 +1,7 @@
package ipp package ipp
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
@@ -13,8 +14,12 @@ type resolution struct {
units int8 units int8
} }
func NewResolution() *resolution { func NewResolution(name string, xfres int32, fres int32) *resolution {
r := new(resolution) r := new(resolution)
r.name = name
r.crossFeedResolution = xfres
r.feedResolution = fres
r.units = 3 // 3 seems to mean dpi (rfc3805)
return r return r
} }
@@ -36,11 +41,21 @@ func (r *resolution) unmarshal(byteStream io.Reader) {
} }
func (r resolution) String() string { func (r resolution) String() string {
return fmt.Sprintf("%v:%v:%v", r.crossFeedResolution, r.feedResolution, r.units) return fmt.Sprintf("%v:%v,%v,%v", r.name, r.crossFeedResolution, r.feedResolution, r.units)
} }
func (r *resolution) marshal() []byte { func (r *resolution) marshal() []byte {
return []byte{}
b := make([]byte, 0, 14+len(r.name))
buf := bytes.NewBuffer(b)
buf.WriteByte(byte(resolutionValueTag))
binary.Write(buf, binary.BigEndian, uint16(len(r.name)))
buf.WriteString(r.name)
binary.Write(buf, binary.BigEndian, uint16(9))
binary.Write(buf, binary.BigEndian, int32(r.crossFeedResolution))
binary.Write(buf, binary.BigEndian, int32(r.feedResolution))
buf.WriteByte(byte(r.units))
return buf.Bytes()
} }
func (r *resolution) valueTag() tag { func (r *resolution) valueTag() tag {

View File

@@ -25,10 +25,10 @@ func (h *ippResponseHeader) marshal() []byte {
} }
type Response struct { type Response struct {
header ippResponseHeader
operationAttributes []Attribute operationAttributes []Attribute
jobAttributes []Attribute jobAttributes []Attribute
printerAttributes []Attribute printerAttributes []Attribute
header ippResponseHeader
} }
func NewResponse(code statusCode, requestId uint32) *Response { func NewResponse(code statusCode, requestId uint32) *Response {

View File

@@ -3,9 +3,9 @@ package ipp
import "encoding/binary" import "encoding/binary"
type setOfStrings struct { type setOfStrings struct {
vTag tag
name string name string
values []string values []string
vTag tag
} }
func NewSetOfStrings(name string, t tag, values []string) *setOfStrings { func NewSetOfStrings(name string, t tag, values []string) *setOfStrings {

8
server/handlegetjobs.go Normal file
View File

@@ -0,0 +1,8 @@
package main
import "ippserver/packages/ipp"
func handleGetJobs(r *ipp.Request) *ipp.Response {
response := ipp.NewResponse(ipp.SuccessfulOk, r.RequestId())
return response
}

View File

@@ -0,0 +1,28 @@
package main
import "ippserver/packages/ipp"
func handleGetPrinterAttributes(r *ipp.Request) *ipp.Response {
response := ipp.NewResponse(ipp.SuccessfulOk, r.RequestId())
var a ipp.Attribute
a = ipp.NewCharSetValue("attributes-charset", "utf-8")
response.AddOperatonAttribute(a)
a = ipp.NewNaturalLanguage("attributes-natural-language", "en")
response.AddOperatonAttribute(a)
a = ipp.NewUriValue("printer-uri", "ipp://drpork:1234/ipp/print")
response.AddOperatonAttribute(a)
a = ipp.NewtextWithoutLanguage("printer-make-and-model", "ChroBro 001")
response.AddOperatonAttribute(a)
a = ipp.NewEnum("printer-state", int32(ipp.Idle))
response.AddOperatonAttribute(a)
a = ipp.NewKeyWord("ipp-versions-supported", "1.0", "1.1", "2.0")
response.AddOperatonAttribute(a)
response.AddOperatonAttribute(ipp.NewKeyWord("ipp-features-supported", "wfds-print-1.0"))
response.AddOperatonAttribute(ipp.NewMimeMediaType("document-format-supported", "image/pwg-raster"))
response.AddOperatonAttribute(ipp.NewKeyWord("media-supported", "iso_a4_210x297mm"))
response.AddOperatonAttribute(ipp.NewKeyWord("sides-supported", "one-sided", "two-sided-long-edge", "two-sided-short-edge"))
response.AddOperatonAttribute(ipp.NewKeyWord("print-color-mode-supported", "auto", "color", "monochrome"))
response.AddOperatonAttribute(ipp.NewResolution("printer-resolution-default", 600, 600))
response.AddOperatonAttribute(ipp.NewBoolean("printer-is-accepting-jobs", true))
return response
}

22
server/handleprintjob.go Normal file
View File

@@ -0,0 +1,22 @@
package main
import (
"io"
"ippserver/packages/ipp"
"os"
)
func handlePrintJob(r *ipp.Request, byteStream io.Reader) *ipp.Response {
a := r.GetAttribute("job-name")
//a.(nameWithoutLanguage).Value
f, err := os.Create(a.(*ipp.NameWithoutLanguage).Value())
if err != nil {
panic("fail")
}
defer f.Close()
io.Copy(f, byteStream)
response := ipp.NewResponse(ipp.SuccessfulOk, r.RequestId())
return response
}

69
server/main.go Normal file
View File

@@ -0,0 +1,69 @@
package main
import (
"context"
"ippserver/packages/ipp"
"ippserver/packages/mdnsserver"
"net/http"
log "github.com/sirupsen/logrus"
)
func main() {
customFormatter := new(log.TextFormatter)
customFormatter.TimestampFormat = "2006-01-02 15:04:05"
log.SetFormatter(customFormatter)
customFormatter.FullTimestamp = true
log.SetLevel(log.InfoLevel)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go mdnsserver.Run(ctx)
http.HandleFunc("/ipp/print", handle)
log.Info("http server started on :1234")
err := http.ListenAndServe(":1234", nil)
if err != nil {
log.Fatal("ListenAndServe: " + err.Error())
}
}
func handle(w http.ResponseWriter, r *http.Request) {
log.Infoln("handle")
if r.Method != http.MethodPost {
http.Error(w, "Unsupported method", http.StatusMethodNotAllowed)
}
log.Info(r.Header)
//body := make([]byte, r.ContentLength)
//io.ReadFull(r.Body, body)
//log.Infof("Body %x", body)
request := ipp.NewRequest(0, 0)
//rdata := make([]byte, r.ContentLength)
//io.ReadFull(r.Body, rdata)
//log.Printf("Data %x", rdata)
//fmt.Printf("data % #0x", rdata)
//buf := bytes.NewBuffer(rdata)
request.UnMarshal(r.Body)
log.Infof("Request: \n%v\n", request)
var response *ipp.Response
switch request.Operation() {
case ipp.GetPrinterAttributes:
response = handleGetPrinterAttributes(request)
case ipp.PrintJob:
response = handlePrintJob(request, r.Body)
case ipp.GetJobs:
response = handleGetJobs(request)
default:
response = ipp.NewResponse(ipp.ClientErrorBadRequest, request.RequestId())
}
log.Infof("Response:\n%v\n", response)
data := response.Marshal()
//log.Debugf("% x", data)
w.Write(data)
}