2-add-keyword-support (#6)
More development. More types. Fixed attribute groups in requests. Started on client. Saving data to file. More types. Printing from chromeos works a little bit. More types. Spelling corrections. WIP: Fix keyword handling Move request to a separate file and add test. Co-authored-by: Henrik Sölver <henrik.solver@gmail.com> Reviewed-on: #6 Co-Authored-By: henrik <henrik.solver@gmail.com> Co-Committed-By: henrik <henrik.solver@gmail.com>
This commit was merged in pull request #6.
This commit is contained in:
@@ -4,8 +4,6 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// References
|
||||
@@ -45,37 +43,45 @@ const (
|
||||
endCollectionValueTag tag = 0x37
|
||||
|
||||
// Character string values
|
||||
textWithoutLanguagageValueTag tag = 0x41
|
||||
nameWithoutLanguagageValueTag tag = 0x42
|
||||
keyWordValueTag tag = 0x44
|
||||
uriValueTag tag = 0x45
|
||||
uriSchemeValueTag tag = 0x46
|
||||
charsetValueTag tag = 0x47
|
||||
naturalLanguagageValueTag tag = 0x48
|
||||
mimeMediaTypeValueTag tag = 0x49
|
||||
memberAttrNameValueTag tag = 0x4a
|
||||
textWithoutLanguageValueTag tag = 0x41
|
||||
nameWithoutLanguageValueTag tag = 0x42
|
||||
keyWordValueTag tag = 0x44
|
||||
uriValueTag tag = 0x45
|
||||
uriSchemeValueTag tag = 0x46
|
||||
charsetValueTag tag = 0x47
|
||||
naturalLanguageValueTag tag = 0x48
|
||||
mimeMediaTypeValueTag tag = 0x49
|
||||
memberAttrNameValueTag tag = 0x4a
|
||||
)
|
||||
|
||||
// Operation-id, defined in rfc8011
|
||||
type operationId uint16
|
||||
type OperationId uint16
|
||||
|
||||
const (
|
||||
PrintJob operationId = 0x0002
|
||||
PrintURI operationId = 0x0003
|
||||
ValidateJob operationId = 0x0004
|
||||
CreateJob operationId = 0x0005
|
||||
SendDocument operationId = 0x0006
|
||||
SendURI operationId = 0x0007
|
||||
CancelJob operationId = 0x0008
|
||||
GetJobAttributes operationId = 0x0009
|
||||
GetJobs operationId = 0x000a
|
||||
GetPrinterAttributes operationId = 0x000b
|
||||
HoldJob operationId = 0x000c
|
||||
ReleaseJob operationId = 0x000d
|
||||
RestartJob operationId = 0x000e
|
||||
PausePrinter operationId = 0x0010
|
||||
ResumePrinter operationId = 0x0011
|
||||
PurgeJobs operationId = 0x0012
|
||||
PrintJob OperationId = 0x0002
|
||||
PrintURI OperationId = 0x0003
|
||||
ValidateJob OperationId = 0x0004
|
||||
CreateJob OperationId = 0x0005
|
||||
SendDocument OperationId = 0x0006
|
||||
SendURI OperationId = 0x0007
|
||||
CancelJob OperationId = 0x0008
|
||||
GetJobAttributes OperationId = 0x0009
|
||||
GetJobs OperationId = 0x000a
|
||||
GetPrinterAttributes OperationId = 0x000b
|
||||
HoldJob OperationId = 0x000c
|
||||
ReleaseJob OperationId = 0x000d
|
||||
RestartJob OperationId = 0x000e
|
||||
PausePrinter OperationId = 0x0010
|
||||
ResumePrinter OperationId = 0x0011
|
||||
PurgeJobs OperationId = 0x0012
|
||||
)
|
||||
|
||||
type printerState int32
|
||||
|
||||
const (
|
||||
Idle printerState = 3
|
||||
Processing printerState = 4
|
||||
Stopped printerState = 5
|
||||
)
|
||||
|
||||
type statusCode uint16
|
||||
@@ -92,151 +98,16 @@ func (v versionNumber) String() string {
|
||||
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) {
|
||||
var length uint16
|
||||
binary.Read(byteStream, binary.BigEndian, &length)
|
||||
//log.Infof("Length %v", length)
|
||||
attributeName := make([]byte, length)
|
||||
if length > 0 {
|
||||
binary.Read(byteStream, binary.BigEndian, attributeName)
|
||||
//log.Infof("Valuename %v", string(attributeName))
|
||||
}
|
||||
binary.Read(byteStream, binary.BigEndian, &length)
|
||||
//log.Infof("Length %v", length)
|
||||
attributeValue := make([]byte, length)
|
||||
binary.Read(byteStream, binary.BigEndian, attributeValue)
|
||||
//log.Infof("Value %v", string(attributeValue))
|
||||
return string(attributeName), string(attributeValue)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user