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

View File

@@ -1,6 +1,7 @@
package ipp
import (
"bytes"
"encoding/binary"
"fmt"
"io"
@@ -10,16 +11,25 @@ import (
type ippRequestHeader struct {
versionNumber versionNumber
operationId operationId
operationId OperationId
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.operationId)
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 {
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
}
func NewRequest() *Request {
func NewRequest(op OperationId, requestId uint32) *Request {
r := new(Request)
r.header.operationId = op
r.header.requestId = requestId
r.header.versionNumber = 0x0200
r.operationAttributes = make(map[string]Attribute)
r.jobAttributes = 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) {
r.header.marshal(body)
r.header.unmarshal(body)
log.Debugf("Header %v", r.header)
var tag tag
err := binary.Read(body, binary.BigEndian, &tag)
@@ -75,95 +88,116 @@ func (r *Request) UnMarshal(body io.Reader) {
log.Error(err.Error())
}
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
nextoperationattr:
for tag != endOfAttributes {
err = binary.Read(body, binary.BigEndian, &tag)
if err != nil {
log.Error(err.Error())
}
log.Debugf("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.Debugf("got tag - %v", tag)
err = binary.Read(body, binary.BigEndian, &tag)
if err != nil {
log.Error(err.Error())
}
log.Debugf("got tag - %v", tag)
break nextoperationattr
case charsetValueTag:
c := NewCharSetValue("", "")
c.unmarshal(body)
r.operationAttributes[c.name] = c
log.Debugf("%v %v", c.name, c.value)
case uriValueTag:
u := NewUriValue("", "")
u.unmarshal(body)
r.operationAttributes[u.name] = u
log.Debugf("%v %v", u.name, u.value)
case naturalLanguageValueTag:
n := NewNaturalLanguage("", "")
n.unmarshal(body)
r.operationAttributes[n.name] = n
log.Debugf("%v %v", n.name, n.value)
case keyWordValueTag:
name, value := unmarshalSingleValue(body)
if name == "" {
lastAddValuer.addValue(value)
} else {
k := NewKeyWord(name, value)
r.operationAttributes[name] = k
lastAddValuer = k
}
log.Debugf("%v : %v", name, value)
case nameWithoutLanguageValueTag:
n := NewNameWithoutLanguage("", "")
n.unmarshal(body)
r.operationAttributes[n.name] = n
log.Debugf("%v %v", n.name, n.value)
case mimeMediaTypeValueTag:
name, value := unmarshalSingleValue(body)
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)
}
var lastAddValuer AddValuer
for {
err = binary.Read(body, binary.BigEndian, &tag)
if err != nil {
log.Errorf("End of input before end of attributes tag (%v)", err.Error())
}
log.Debugf("Value tag - %v", tag)
switch tag {
case endOfAttributes:
return
case charsetValueTag:
c := NewCharSetValue("", "")
c.unmarshal(body)
currentAttributeGroup[c.name] = c
log.Debugf("%v %v", c.name, c.value)
case uriValueTag:
u := NewUriValue("", "")
u.unmarshal(body)
currentAttributeGroup[u.name] = u
log.Debugf("%v %v", u.name, u.value)
case naturalLanguageValueTag:
n := NewNaturalLanguage("", "")
n.unmarshal(body)
currentAttributeGroup[n.name] = n
log.Debugf("%v %v", n.name, n.value)
case keyWordValueTag:
name, value := unmarshalSingleValue(body)
if name == "" {
lastAddValuer.addValue(value)
} else {
k := NewKeyWord(name, value)
currentAttributeGroup[name] = k
lastAddValuer = k
}
log.Debugf("%v : %v", name, value)
case nameWithoutLanguageValueTag:
n := NewNameWithoutLanguage("", "")
n.unmarshal(body)
currentAttributeGroup[n.name] = n
log.Debugf("%v %v", n.name, n.value)
case mimeMediaTypeValueTag:
name, value := unmarshalSingleValue(body)
if name == "" {
lastAddValuer.addValue(value)
} else {
m := NewMimeMediaType(name, value)
currentAttributeGroup[name] = m
lastAddValuer = m
}
log.Debugf("%v : %v", name, value)
case jobAttributes:
log.Debug("Start job attributes")
currentAttributeGroup = r.jobAttributes
case resolutionValueTag:
res := NewResolution("", 0, 0)
res.unmarshal(body)
currentAttributeGroup[res.name] = 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 {
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()
}