Move request to a separate file and add test.
This commit is contained in:
@@ -4,8 +4,6 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// References
|
// References
|
||||||
@@ -92,137 +90,6 @@ func (v versionNumber) String() string {
|
|||||||
return fmt.Sprintf("%x.%x", vn&0xff00>>8, vn&0x00ff)
|
return fmt.Sprintf("%x.%x", vn&0xff00>>8, vn&0x00ff)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ippRequestHeader struct {
|
|
||||||
versionNumber versionNumber
|
|
||||||
operationId operationId
|
|
||||||
requestId uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *ippRequestHeader) marshal(byteStream io.Reader) {
|
|
||||||
binary.Read(byteStream, binary.BigEndian, &h.versionNumber)
|
|
||||||
binary.Read(byteStream, binary.BigEndian, &h.operationId)
|
|
||||||
binary.Read(byteStream, binary.BigEndian, &h.requestId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h ippRequestHeader) String() string {
|
|
||||||
return fmt.Sprintf("Version number: %v Operation Id: %v Request Id: %v", h.versionNumber, h.operationId, h.requestId)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Attribute interface {
|
|
||||||
valueTag() tag
|
|
||||||
unmarshal(io.Reader)
|
|
||||||
marshal() []byte
|
|
||||||
size() int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Request struct {
|
|
||||||
header ippRequestHeader
|
|
||||||
operationAttributes map[string]Attribute
|
|
||||||
jobAttributes map[string]Attribute
|
|
||||||
printerAttributes map[string]Attribute
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRequest() *Request {
|
|
||||||
r := new(Request)
|
|
||||||
r.operationAttributes = make(map[string]Attribute)
|
|
||||||
r.jobAttributes = make(map[string]Attribute)
|
|
||||||
r.printerAttributes = make(map[string]Attribute)
|
|
||||||
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r Request) String() string {
|
|
||||||
s := r.header.String() + "\n" + " OperationAttributes" + "\n"
|
|
||||||
for _, a := range r.operationAttributes {
|
|
||||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// log.Info(r.Header)
|
|
||||||
// log.Info(r.ContentLength)
|
|
||||||
|
|
||||||
//body := make([]byte, r.ContentLength)
|
|
||||||
//body.Read(body)
|
|
||||||
|
|
||||||
func (r *Request) UnMarshal(body io.Reader) {
|
|
||||||
r.header.marshal(body)
|
|
||||||
log.Infof("Header %v", r.header)
|
|
||||||
var tag tag
|
|
||||||
err := binary.Read(body, binary.BigEndian, &tag)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err.Error())
|
|
||||||
}
|
|
||||||
log.Infof("got tag - %v", tag)
|
|
||||||
|
|
||||||
if tag == operationAttributes {
|
|
||||||
nextoperationattr:
|
|
||||||
for tag != endOfAttributes {
|
|
||||||
var lastKeyword *keyWord
|
|
||||||
err = binary.Read(body, binary.BigEndian, &tag)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err.Error())
|
|
||||||
}
|
|
||||||
log.Infof("Value tag - %v", tag)
|
|
||||||
switch tag {
|
|
||||||
case endOfAttributes:
|
|
||||||
err = binary.Read(body, binary.BigEndian, &tag)
|
|
||||||
if err == io.EOF {
|
|
||||||
// No more data
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err.Error())
|
|
||||||
}
|
|
||||||
log.Infof("got tag - %v", tag)
|
|
||||||
err = binary.Read(body, binary.BigEndian, &tag)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err.Error())
|
|
||||||
}
|
|
||||||
log.Infof("got tag - %v", tag)
|
|
||||||
|
|
||||||
break nextoperationattr
|
|
||||||
case charsetValueTag:
|
|
||||||
c := NewCharSetValue("", "")
|
|
||||||
c.unmarshal(body)
|
|
||||||
r.operationAttributes[c.name] = c
|
|
||||||
log.Infof("%v %v", c.name, c.value)
|
|
||||||
case uriValueTag:
|
|
||||||
u := newUriValue("", "")
|
|
||||||
u.unmarshal(body)
|
|
||||||
r.operationAttributes[u.name] = u
|
|
||||||
log.Infof("%v %v", u.name, u.value)
|
|
||||||
case naturalLanguagageValueTag:
|
|
||||||
n := newNaturalLanguagage("", "")
|
|
||||||
n.unmarshal(body)
|
|
||||||
r.operationAttributes[n.name] = n
|
|
||||||
log.Infof("%v %v", n.name, n.value)
|
|
||||||
case keyWordValueTag:
|
|
||||||
k := newKeyWord()
|
|
||||||
k.unmarshal(body)
|
|
||||||
r.operationAttributes[k.name] = k
|
|
||||||
if k.name == "" {
|
|
||||||
lastKeyword.addValue(k.values[0])
|
|
||||||
} else {
|
|
||||||
lastKeyword = k
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
return r.header.requestId
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
137
packages/ipp/request.go
Normal file
137
packages/ipp/request.go
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package ipp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ippRequestHeader struct {
|
||||||
|
versionNumber versionNumber
|
||||||
|
operationId operationId
|
||||||
|
requestId uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ippRequestHeader) marshal(byteStream io.Reader) {
|
||||||
|
binary.Read(byteStream, binary.BigEndian, &h.versionNumber)
|
||||||
|
binary.Read(byteStream, binary.BigEndian, &h.operationId)
|
||||||
|
binary.Read(byteStream, binary.BigEndian, &h.requestId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ippRequestHeader) String() string {
|
||||||
|
return fmt.Sprintf("Version number: %v Operation Id: %v Request Id: %v", h.versionNumber, h.operationId, h.requestId)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Attribute interface {
|
||||||
|
valueTag() tag
|
||||||
|
//unmarshal(io.Reader)
|
||||||
|
marshal() []byte
|
||||||
|
size() int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
header ippRequestHeader
|
||||||
|
operationAttributes map[string]Attribute
|
||||||
|
jobAttributes map[string]Attribute
|
||||||
|
printerAttributes map[string]Attribute
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRequest() *Request {
|
||||||
|
r := new(Request)
|
||||||
|
r.operationAttributes = make(map[string]Attribute)
|
||||||
|
r.jobAttributes = make(map[string]Attribute)
|
||||||
|
r.printerAttributes = make(map[string]Attribute)
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Request) String() string {
|
||||||
|
s := r.header.String() + "\n" + " OperationAttributes" + "\n"
|
||||||
|
for _, a := range r.operationAttributes {
|
||||||
|
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Request) UnMarshal(body io.Reader) {
|
||||||
|
r.header.marshal(body)
|
||||||
|
log.Infof("Header %v", r.header)
|
||||||
|
var tag tag
|
||||||
|
err := binary.Read(body, binary.BigEndian, &tag)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
}
|
||||||
|
log.Infof("got tag - %v", tag)
|
||||||
|
|
||||||
|
if tag == operationAttributes {
|
||||||
|
var lastKeyword *keyWord
|
||||||
|
nextoperationattr:
|
||||||
|
for tag != endOfAttributes {
|
||||||
|
|
||||||
|
err = binary.Read(body, binary.BigEndian, &tag)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
}
|
||||||
|
log.Infof("Value tag - %v", tag)
|
||||||
|
switch tag {
|
||||||
|
case endOfAttributes:
|
||||||
|
err = binary.Read(body, binary.BigEndian, &tag)
|
||||||
|
if err == io.EOF {
|
||||||
|
// No more data
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
}
|
||||||
|
log.Infof("got tag - %v", tag)
|
||||||
|
err = binary.Read(body, binary.BigEndian, &tag)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
}
|
||||||
|
log.Infof("got tag - %v", tag)
|
||||||
|
|
||||||
|
break nextoperationattr
|
||||||
|
case charsetValueTag:
|
||||||
|
c := NewCharSetValue("", "")
|
||||||
|
c.unmarshal(body)
|
||||||
|
r.operationAttributes[c.name] = c
|
||||||
|
log.Infof("%v %v", c.name, c.value)
|
||||||
|
case uriValueTag:
|
||||||
|
u := newUriValue("", "")
|
||||||
|
u.unmarshal(body)
|
||||||
|
r.operationAttributes[u.name] = u
|
||||||
|
log.Infof("%v %v", u.name, u.value)
|
||||||
|
case naturalLanguagageValueTag:
|
||||||
|
n := newNaturalLanguagage("", "")
|
||||||
|
n.unmarshal(body)
|
||||||
|
r.operationAttributes[n.name] = n
|
||||||
|
log.Infof("%v %v", n.name, n.value)
|
||||||
|
case keyWordValueTag:
|
||||||
|
name, value := unmarshalSingleValue(body)
|
||||||
|
if name == "" {
|
||||||
|
lastKeyword.addValue(value)
|
||||||
|
} else {
|
||||||
|
k := newKeyWord()
|
||||||
|
k.name = name
|
||||||
|
k.addValue(value)
|
||||||
|
r.operationAttributes[k.name] = k
|
||||||
|
lastKeyword = k
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
return r.header.requestId
|
||||||
|
}
|
||||||
79
packages/ipp/request_test.go
Normal file
79
packages/ipp/request_test.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package ipp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testRequest = []byte{0x01, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x11,
|
||||||
|
0x01,
|
||||||
|
0x47,
|
||||||
|
0x00, 0x12,
|
||||||
|
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, 0x74,
|
||||||
|
0x00, 0x05,
|
||||||
|
0x75, 0x74, 0x66, 0x2d, 0x38,
|
||||||
|
0x48,
|
||||||
|
0x00, 0x1b,
|
||||||
|
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2d, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x2d, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65,
|
||||||
|
0x00, 0x05,
|
||||||
|
0x65, 0x6e, 0x2d, 0x75, 0x73,
|
||||||
|
0x45, // uriValueTag
|
||||||
|
0x00, 0x0b,
|
||||||
|
0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x75, 0x72, 0x69,
|
||||||
|
0x00, 0x20,
|
||||||
|
0x69, 0x70, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x30, 0x2e, 0x32, 0x3a, 0x31, 0x32, 0x33, 0x34, 0x2f, 0x69, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x69, 0x6e, 0x74,
|
||||||
|
0x44, // keywordValueTag
|
||||||
|
0x00, 0x14,
|
||||||
|
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||||
|
0x00, 0x16,
|
||||||
|
0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6d, 0x61, 0x6b, 0x65, 0x2d, 0x61, 0x6e, 0x64, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
|
||||||
|
0x44, // keywordValueTag
|
||||||
|
0x00, 0x00,
|
||||||
|
0x00, 0x16,
|
||||||
|
0x69, 0x70, 0x70, 0x2d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64,
|
||||||
|
0x44, // keywordValueTag
|
||||||
|
0x00, 0x00,
|
||||||
|
0x00, 0x16,
|
||||||
|
0x69, 0x70, 0x70, 0x2d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64,
|
||||||
|
0x44, // keywordValueTag
|
||||||
|
0x00, 0x00,
|
||||||
|
0x00, 0x19,
|
||||||
|
0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x2d, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64,
|
||||||
|
0x44,
|
||||||
|
0x00, 0x00,
|
||||||
|
0x00, 0x0d,
|
||||||
|
0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65,
|
||||||
|
0x44,
|
||||||
|
0x00, 0x00,
|
||||||
|
0x00, 0x15,
|
||||||
|
0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x73,
|
||||||
|
0x44,
|
||||||
|
0x00, 0x00,
|
||||||
|
0x00, 0x15,
|
||||||
|
0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||||
|
0x03}
|
||||||
|
|
||||||
|
func TestUnmarshalRequestPrinterAttributes(T *testing.T) {
|
||||||
|
buf := bytes.NewBuffer(testRequest)
|
||||||
|
|
||||||
|
req := NewRequest()
|
||||||
|
|
||||||
|
req.UnMarshal(buf)
|
||||||
|
fmt.Print(req)
|
||||||
|
assert.Equal(T, versionNumber(0x0101), req.header.versionNumber, "Wrong version number")
|
||||||
|
assert.Equal(T, GetPrinterAttributes, req.header.operationId, "Wrong Operation")
|
||||||
|
assert.Equal(T, uint32(17), req.header.requestId, "Wrong request id")
|
||||||
|
assert.Len(T, req.operationAttributes, 4)
|
||||||
|
v := req.operationAttributes["requested-attributes"].(*keyWord).values
|
||||||
|
assert.Len(T, v, 7)
|
||||||
|
assert.Contains(T, v, "printer-make-and-model")
|
||||||
|
assert.Contains(T, v, "ipp-versions-supported")
|
||||||
|
assert.Contains(T, v, "ipp-features-supported")
|
||||||
|
assert.Contains(T, v, "document-format-supported")
|
||||||
|
assert.Contains(T, v, "printer-state-reasons")
|
||||||
|
assert.Contains(T, v, "printer-state-message")
|
||||||
|
assert.Contains(T, v, "printer-state")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user