A working proxy exists.
This commit is contained in:
@@ -4,35 +4,35 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type charSetValue struct {
|
||||
type CharSetValue struct {
|
||||
name string
|
||||
value string
|
||||
}
|
||||
|
||||
func NewCharSetValue(name string, value string) *charSetValue {
|
||||
c := new(charSetValue)
|
||||
func NewCharSetValue(name string, value string) *CharSetValue {
|
||||
c := new(CharSetValue)
|
||||
c.name = name
|
||||
c.value = value
|
||||
return c
|
||||
}
|
||||
|
||||
func (c charSetValue) Name() string {
|
||||
func (c CharSetValue) Name() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c charSetValue) String() string {
|
||||
func (c CharSetValue) String() string {
|
||||
return c.name + ":" + c.value
|
||||
}
|
||||
|
||||
func (c *charSetValue) valueTag() tag {
|
||||
func (c *CharSetValue) valueTag() tag {
|
||||
return charsetValueTag
|
||||
}
|
||||
|
||||
func (c *charSetValue) unmarshal(byteStream io.Reader) {
|
||||
func (c *CharSetValue) unmarshal(byteStream io.Reader) {
|
||||
c.name, c.value = unmarshalSingleValue(byteStream)
|
||||
}
|
||||
|
||||
func (c *charSetValue) marshal() []byte {
|
||||
func (c *CharSetValue) marshal() []byte {
|
||||
l := 5 + len(c.name) + len(c.value)
|
||||
b := make([]byte, l)
|
||||
b[0] = byte(charsetValueTag)
|
||||
@@ -40,11 +40,11 @@ func (c *charSetValue) marshal() []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
func (c *charSetValue) marshalInto([]byte) int {
|
||||
func (c *CharSetValue) marshalInto([]byte) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *charSetValue) size() int {
|
||||
func (c *CharSetValue) size() int {
|
||||
l := 1 + 4 // The attribute tag + 2 lengths
|
||||
l += len(c.name)
|
||||
l += len(c.value)
|
||||
|
||||
@@ -4,38 +4,38 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type enum struct {
|
||||
type Enum struct {
|
||||
name string
|
||||
values []int32
|
||||
}
|
||||
|
||||
func NewEnum(name string, values ...int32) *enum {
|
||||
e := new(enum)
|
||||
func NewEnum(name string, values ...int32) *Enum {
|
||||
e := new(Enum)
|
||||
e.name = name
|
||||
e.values = values
|
||||
return e
|
||||
}
|
||||
|
||||
func (e enum) Name() string {
|
||||
func (e Enum) Name() string {
|
||||
return e.name
|
||||
}
|
||||
|
||||
func (e enum) String() string {
|
||||
func (e Enum) String() string {
|
||||
return e.name + ":" + fmt.Sprint(e.values)
|
||||
}
|
||||
|
||||
func (e *enum) valueTag() tag {
|
||||
func (e *Enum) valueTag() tag {
|
||||
return enumValueTag
|
||||
}
|
||||
|
||||
func (e *enum) size() int {
|
||||
return 9 + len(e.name)
|
||||
func (e *Enum) size() int {
|
||||
return 9 + len(e.name)
|
||||
}
|
||||
|
||||
func (e *enum) addValue(v interface{}) {
|
||||
func (e *Enum) addValue(v interface{}) {
|
||||
e.values = append(e.values, v.(int32))
|
||||
}
|
||||
|
||||
func (e *enum) marshal() []byte {
|
||||
func (e *Enum) marshal() []byte {
|
||||
return marshalInteger(enumValueTag, e.name, e.values)
|
||||
}
|
||||
|
||||
@@ -7,53 +7,53 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type integer struct {
|
||||
type Integer struct {
|
||||
name string
|
||||
values []int32
|
||||
}
|
||||
|
||||
func NewInteger(name string, values ...int32) *integer {
|
||||
e := new(integer)
|
||||
func NewInteger(name string, values ...int32) *Integer {
|
||||
e := new(Integer)
|
||||
e.name = name
|
||||
e.values = values
|
||||
return e
|
||||
}
|
||||
|
||||
func (i integer) Name() string {
|
||||
func (i Integer) Name() string {
|
||||
return i.name
|
||||
}
|
||||
|
||||
func (i integer) String() string {
|
||||
func (i Integer) String() string {
|
||||
return i.name + ":" + fmt.Sprint(i.values)
|
||||
}
|
||||
|
||||
func (i *integer) valueTag() tag {
|
||||
func (i *Integer) valueTag() tag {
|
||||
return integerValueTag
|
||||
}
|
||||
|
||||
func (i *integer) size() int {
|
||||
func (i *Integer) size() int {
|
||||
return 9 + len(i.name) // The attribute tag + 2 lengths
|
||||
}
|
||||
|
||||
func (i *integer) addValue(v interface{}) {
|
||||
func (i *Integer) addValue(v interface{}) {
|
||||
i.values = append(i.values, v.(int32))
|
||||
}
|
||||
|
||||
func (i *integer) marshal() []byte {
|
||||
func (i *Integer) marshal() []byte {
|
||||
return marshalInteger(integerValueTag, i.name, i.values)
|
||||
}
|
||||
|
||||
func marshalInteger(t tag, name string, values []int32) []byte {
|
||||
l := 9 + len(name)
|
||||
l := 9 + len(name) + 9*(len(values)-1)
|
||||
b := make([]byte, 0, l)
|
||||
buf := bytes.NewBuffer(b)
|
||||
buf.WriteByte(byte(integerValueTag))
|
||||
buf.WriteByte(byte(t))
|
||||
binary.Write(buf, binary.BigEndian, uint16(len(name)))
|
||||
buf.WriteString(name)
|
||||
binary.Write(buf, binary.BigEndian, uint16(4))
|
||||
binary.Write(buf, binary.BigEndian, values[0])
|
||||
for _, v := range values[1:] {
|
||||
buf.WriteByte(byte(integerValueTag))
|
||||
buf.WriteByte(byte(t))
|
||||
binary.Write(buf, binary.BigEndian, uint16(0))
|
||||
binary.Write(buf, binary.BigEndian, uint16(4))
|
||||
binary.Write(buf, binary.BigEndian, v)
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
package ipp
|
||||
|
||||
type keyWord struct {
|
||||
sos *setOfStrings
|
||||
type KeyWord struct {
|
||||
sos *SetOfStrings
|
||||
}
|
||||
|
||||
func NewKeyWord(name string, values ...string) *keyWord {
|
||||
func NewKeyWord(name string, values ...string) *KeyWord {
|
||||
|
||||
k := new(keyWord)
|
||||
k := new(KeyWord)
|
||||
k.sos = NewSetOfStrings(name, keyWordValueTag, values)
|
||||
return k
|
||||
}
|
||||
|
||||
func (k keyWord) Name() string {
|
||||
func (k KeyWord) Name() string {
|
||||
return k.sos.name
|
||||
}
|
||||
|
||||
func (k keyWord) String() string {
|
||||
func (k KeyWord) String() string {
|
||||
return k.sos.String()
|
||||
}
|
||||
|
||||
func (k *keyWord) size() int {
|
||||
func (k *KeyWord) size() int {
|
||||
return k.sos.size()
|
||||
}
|
||||
|
||||
func (k *keyWord) valueTag() tag {
|
||||
func (k *KeyWord) valueTag() tag {
|
||||
return k.sos.valueTag()
|
||||
}
|
||||
|
||||
func (k *keyWord) marshal() []byte {
|
||||
func (k *KeyWord) marshal() []byte {
|
||||
return k.sos.marshal()
|
||||
}
|
||||
|
||||
func (k *keyWord) addValue(v interface{}) {
|
||||
func (k *KeyWord) addValue(v interface{}) {
|
||||
k.sos.AddValue(v.(string))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
//Package ipp provides functonality to handle ipp messages
|
||||
//go:generate stringer -type jobState -type printerState
|
||||
package ipp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
@@ -14,6 +16,9 @@ import (
|
||||
// https://tools.ietf.org/html/rfc8010
|
||||
// https://tools.ietf.org/html/rfc8011
|
||||
|
||||
// ErrNilAttribute is returned when an attempt to use nil as a attribute
|
||||
var ErrNilAttribute = errors.New("can not add use nil as attribute")
|
||||
|
||||
// Defined value tags
|
||||
// from rfc8010
|
||||
type tag uint8
|
||||
@@ -89,12 +94,27 @@ const (
|
||||
Stopped printerState = 5
|
||||
)
|
||||
|
||||
// jobstate defined in rfc8011 ch 5.3.7
|
||||
type jobState uint16
|
||||
|
||||
const (
|
||||
pending jobState = 3
|
||||
pendingHeld jobState = 4
|
||||
processing jobState = 5
|
||||
processingStoppped jobState = 6
|
||||
cancelled jobState = 7
|
||||
aborted jobState = 8
|
||||
completed jobState = 9
|
||||
)
|
||||
|
||||
type statusCode uint16
|
||||
|
||||
// status code defenitions
|
||||
const (
|
||||
SuccessfulOk statusCode = 0x0000
|
||||
ClientErrorBadRequest statusCode = 0x0400
|
||||
SuccessfulOk statusCode = 0x0000
|
||||
SuccessfulOkIgnoredOrSubstitutedAttributes statusCode = 0x0001
|
||||
SuccessfulOkConflictingAttributes statusCode = 0x0002
|
||||
ClientErrorBadRequest statusCode = 0x0400
|
||||
)
|
||||
|
||||
type versionNumber uint16
|
||||
@@ -148,13 +168,14 @@ type Attribute interface {
|
||||
//size() int
|
||||
}
|
||||
|
||||
type attributes struct {
|
||||
operation []Attribute
|
||||
printer []Attribute
|
||||
job []Attribute
|
||||
type Attributes struct {
|
||||
operation []Attribute
|
||||
printer []Attribute
|
||||
job []Attribute
|
||||
unsupported []Attribute
|
||||
}
|
||||
|
||||
func (a *attributes) String() string {
|
||||
func (a *Attributes) String() string {
|
||||
s := " OperationAttributes" + "\n"
|
||||
for _, a := range a.operation {
|
||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||
@@ -167,10 +188,15 @@ func (a *attributes) String() string {
|
||||
for _, a := range a.job {
|
||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||
}
|
||||
s = s + " Unsupported" + "\n"
|
||||
for _, a := range a.unsupported {
|
||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (a *attributes) addAttribute(group tag, attr Attribute) {
|
||||
func (a *Attributes) addAttribute(group tag, attr Attribute) {
|
||||
switch group {
|
||||
case operationAttributes:
|
||||
a.operation = append(a.operation, attr)
|
||||
@@ -178,13 +204,15 @@ func (a *attributes) addAttribute(group tag, attr Attribute) {
|
||||
a.job = append(a.job, attr)
|
||||
case printerAttributes:
|
||||
a.printer = append(a.printer, attr)
|
||||
case unsupportedAttributes:
|
||||
a.unsupported = append(a.unsupported, attr)
|
||||
default:
|
||||
log.Error("Unknown attribute group")
|
||||
log.Errorf("Unknown attribute group %v", group)
|
||||
}
|
||||
}
|
||||
|
||||
func UnMarshalAttributes(bytestream *bufio.Reader) *attributes {
|
||||
a := new(attributes)
|
||||
func UnMarshalAttributes(bytestream *bufio.Reader) *Attributes {
|
||||
a := new(Attributes)
|
||||
|
||||
var t tag
|
||||
err := binary.Read(bytestream, binary.BigEndian, &t)
|
||||
@@ -290,6 +318,11 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *attributes {
|
||||
case begCollectionValueTag:
|
||||
// For now just consume the collection
|
||||
consumeCollection(bytestream)
|
||||
case unsupportedValueTag:
|
||||
attr := NewUnsupportedValue()
|
||||
attr.unmarshal(bytestream)
|
||||
a.addAttribute(currentAttributeGroup, attr)
|
||||
|
||||
case jobAttributes:
|
||||
log.Debug("Start job attributes")
|
||||
currentAttributeGroup = jobAttributes
|
||||
@@ -299,8 +332,11 @@ func UnMarshalAttributes(bytestream *bufio.Reader) *attributes {
|
||||
case operationAttributes:
|
||||
log.Debug("Start operation attributes")
|
||||
currentAttributeGroup = operationAttributes
|
||||
case unsupportedAttributes:
|
||||
log.Debug("Start unsupported attributes")
|
||||
currentAttributeGroup = unsupportedAttributes
|
||||
case resolutionValueTag:
|
||||
res := NewResolution("", 0, 0)
|
||||
res := NewSetOfResolution("")
|
||||
res.unmarshal(bytestream)
|
||||
a.addAttribute(currentAttributeGroup, res)
|
||||
log.Debugf("Resolution %v", res)
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
package ipp
|
||||
|
||||
type mimeMediaType struct {
|
||||
sos *setOfStrings
|
||||
type MimeMediaType struct {
|
||||
sos *SetOfStrings
|
||||
}
|
||||
|
||||
func NewMimeMediaType(name string, values ...string) *mimeMediaType {
|
||||
func NewMimeMediaType(name string, values ...string) *MimeMediaType {
|
||||
|
||||
m := new(mimeMediaType)
|
||||
m := new(MimeMediaType)
|
||||
m.sos = NewSetOfStrings(name, mimeMediaTypeValueTag, values)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m mimeMediaType) Name() string {
|
||||
func (m MimeMediaType) Name() string {
|
||||
return m.sos.name
|
||||
}
|
||||
|
||||
func (m mimeMediaType) String() string {
|
||||
func (m MimeMediaType) String() string {
|
||||
return m.sos.String()
|
||||
}
|
||||
|
||||
func (m *mimeMediaType) size() int {
|
||||
func (m *MimeMediaType) size() int {
|
||||
return m.sos.size()
|
||||
}
|
||||
|
||||
func (m *mimeMediaType) valueTag() tag {
|
||||
func (m *MimeMediaType) valueTag() tag {
|
||||
return m.sos.valueTag()
|
||||
}
|
||||
|
||||
func (m *mimeMediaType) marshal() []byte {
|
||||
func (m *MimeMediaType) marshal() []byte {
|
||||
return m.sos.marshal()
|
||||
}
|
||||
|
||||
func (m *mimeMediaType) addValue(v interface{}) {
|
||||
func (m *MimeMediaType) addValue(v interface{}) {
|
||||
m.sos.AddValue(v.(string))
|
||||
}
|
||||
|
||||
@@ -4,35 +4,35 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type naturalLanguage struct {
|
||||
type NaturalLanguage struct {
|
||||
name string
|
||||
value string
|
||||
}
|
||||
|
||||
func NewNaturalLanguage(name, value string) *naturalLanguage {
|
||||
c := new(naturalLanguage)
|
||||
func NewNaturalLanguage(name, value string) *NaturalLanguage {
|
||||
c := new(NaturalLanguage)
|
||||
c.name = name
|
||||
c.value = value
|
||||
return c
|
||||
}
|
||||
|
||||
func (c naturalLanguage) Name() string {
|
||||
func (c NaturalLanguage) Name() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c naturalLanguage) String() string {
|
||||
func (c NaturalLanguage) String() string {
|
||||
return c.name + ":" + c.value
|
||||
}
|
||||
|
||||
func (c *naturalLanguage) valueTag() tag {
|
||||
func (c *NaturalLanguage) valueTag() tag {
|
||||
return naturalLanguageValueTag
|
||||
}
|
||||
|
||||
func (c *naturalLanguage) unmarshal(byteStream io.Reader) {
|
||||
func (c *NaturalLanguage) unmarshal(byteStream io.Reader) {
|
||||
c.name, c.value = unmarshalSingleValue(byteStream)
|
||||
}
|
||||
|
||||
func (c *naturalLanguage) marshal() []byte {
|
||||
func (c *NaturalLanguage) marshal() []byte {
|
||||
l := 5 + len(c.name) + len(c.value)
|
||||
b := make([]byte, l)
|
||||
b[0] = byte(naturalLanguageValueTag)
|
||||
@@ -40,7 +40,7 @@ func (c *naturalLanguage) marshal() []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
func (c *naturalLanguage) size() int {
|
||||
func (c *NaturalLanguage) size() int {
|
||||
l := 1 + 4 // The attribute tag + 2 lengths
|
||||
l += len(c.name)
|
||||
l += len(c.value)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by "stringer -type printerState ."; DO NOT EDIT.
|
||||
// Code generated by "stringer -type jobState -type printerState"; DO NOT EDIT.
|
||||
|
||||
package ipp
|
||||
|
||||
@@ -13,9 +13,9 @@ func _() {
|
||||
_ = x[Stopped-5]
|
||||
}
|
||||
|
||||
const _printerState_name = "IdlePreocessingStopped"
|
||||
const _printerState_name = "IdleProcessingStopped"
|
||||
|
||||
var _printerState_index = [...]uint8{0, 4, 15, 22}
|
||||
var _printerState_index = [...]uint8{0, 4, 14, 21}
|
||||
|
||||
func (i printerState) String() string {
|
||||
i -= 3
|
||||
|
||||
@@ -13,36 +13,36 @@ type IRange struct {
|
||||
upper int32
|
||||
}
|
||||
|
||||
type rangeOfInteger struct {
|
||||
type RangeOfInteger struct {
|
||||
name string
|
||||
values []IRange
|
||||
}
|
||||
|
||||
func NewRangeOfInteger(name string, values ...IRange) *rangeOfInteger {
|
||||
r := new(rangeOfInteger)
|
||||
func NewRangeOfInteger(name string, values ...IRange) *RangeOfInteger {
|
||||
r := new(RangeOfInteger)
|
||||
r.name = name
|
||||
r.values = values
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *rangeOfInteger) Name() string {
|
||||
func (r *RangeOfInteger) Name() string {
|
||||
return r.name
|
||||
}
|
||||
|
||||
func (r rangeOfInteger) String() string {
|
||||
func (r RangeOfInteger) String() string {
|
||||
return r.name + ":" + fmt.Sprint(r.values)
|
||||
}
|
||||
|
||||
func (r *rangeOfInteger) valueTag() tag {
|
||||
func (r *RangeOfInteger) valueTag() tag {
|
||||
return rangeOfIntegerValueTag
|
||||
}
|
||||
|
||||
func (r *rangeOfInteger) marshal() []byte {
|
||||
func (r *RangeOfInteger) marshal() []byte {
|
||||
log.Error("marshal rangeOfInteger is not implemented yet")
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func (r *rangeOfInteger) addValue(v interface{}) {
|
||||
func (r *RangeOfInteger) addValue(v interface{}) {
|
||||
r.values = append(r.values, v.(IRange))
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ type AddValuer interface {
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
a *attributes
|
||||
a *Attributes
|
||||
header ippMessageHeader
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func NewRequest(op OperationID, requestID uint32) *Request {
|
||||
r.header.operationID = op
|
||||
r.header.requestID = requestID
|
||||
r.header.versionNumber = 0x0200
|
||||
r.a = new(attributes)
|
||||
r.a = new(Attributes)
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -58,7 +58,6 @@ func (r Request) String() string {
|
||||
func (r *Request) UnMarshal(body io.Reader) {
|
||||
buffbody := bufio.NewReader(body)
|
||||
r.header.unmarshal(buffbody)
|
||||
//log.Printf("Header %v", r.header)
|
||||
r.a = UnMarshalAttributes(buffbody)
|
||||
}
|
||||
|
||||
@@ -76,9 +75,25 @@ func (r *Request) GetAttribute(name string) Attribute {
|
||||
return a
|
||||
}
|
||||
}
|
||||
for _, a := range r.a.job {
|
||||
if a.Name() == name {
|
||||
return a
|
||||
}
|
||||
}
|
||||
for _, a := range r.a.printer {
|
||||
if a.Name() == name {
|
||||
return a
|
||||
}
|
||||
}
|
||||
for _, a := range r.a.unsupported {
|
||||
if a.Name() == name {
|
||||
return a
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal converts the request object to a ipp request
|
||||
func (r *Request) Marshal() []byte {
|
||||
|
||||
var buf bytes.Buffer
|
||||
@@ -105,14 +120,29 @@ func (r *Request) Marshal() []byte {
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (r *Request) AddPrinterAttribute(a Attribute) {
|
||||
r.a.addAttribute(printerAttributes, a)
|
||||
// AddPrinterAttribute adds a printer attribute to the request object
|
||||
func (r *Request) AddPrinterAttribute(a Attribute) error {
|
||||
if a != nil {
|
||||
r.a.addAttribute(printerAttributes, a)
|
||||
return nil
|
||||
}
|
||||
return ErrNilAttribute
|
||||
}
|
||||
|
||||
func (r *Request) AddOperatonAttribute(a Attribute) {
|
||||
r.a.addAttribute(operationAttributes, a)
|
||||
// AddOperatonAttribute adds a operation attribute to the request object
|
||||
func (r *Request) AddOperatonAttribute(a Attribute) error {
|
||||
if a != nil {
|
||||
r.a.addAttribute(operationAttributes, a)
|
||||
return nil
|
||||
}
|
||||
return ErrNilAttribute
|
||||
}
|
||||
|
||||
func (r *Request) AddJobAttribute(a Attribute) {
|
||||
r.a.addAttribute(jobAttributes, a)
|
||||
// AddJobAttribute adds a job attribute to the request object
|
||||
func (r *Request) AddJobAttribute(a Attribute) error {
|
||||
if a != nil {
|
||||
r.a.addAttribute(jobAttributes, a)
|
||||
return nil
|
||||
}
|
||||
return ErrNilAttribute
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ func TestUnmarshalRequestPrinterAttributes(T *testing.T) {
|
||||
assert.Equal(T, GetPrinterAttributes, req.header.operationID, "Wrong Operation")
|
||||
assert.Equal(T, uint32(17), req.header.requestID, "Wrong request id")
|
||||
assert.Len(T, req.a.operation, 4)
|
||||
v := req.GetAttribute("requested-attributes").(*keyWord).sos.values
|
||||
v := req.GetAttribute("requested-attributes").(*KeyWord).sos.values
|
||||
assert.Len(T, v, 7)
|
||||
assert.Contains(T, v, "printer-make-and-model")
|
||||
assert.Contains(T, v, "ipp-versions-supported")
|
||||
|
||||
@@ -1,67 +1,95 @@
|
||||
package ipp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type resolution struct {
|
||||
name string
|
||||
crossFeedResolution int32
|
||||
feedResolution int32
|
||||
units int8
|
||||
// Resolution represents a ipp resolution attribute
|
||||
type Resolution struct {
|
||||
CrossFeedResolution int32
|
||||
FeedResolution int32
|
||||
Unit int8 // 3 seems to mean dpi (rfc3805)
|
||||
}
|
||||
|
||||
func NewResolution(name string, xfres int32, fres int32) *resolution {
|
||||
r := new(resolution)
|
||||
// SetOfResolutions represents a set ipp resolution attributes
|
||||
type SetOfResolutions struct {
|
||||
name string
|
||||
sor []Resolution
|
||||
}
|
||||
|
||||
// NewSetOfResolution creats a new set of ipp resolution attributes
|
||||
func NewSetOfResolution(name string, resSet ...Resolution) *SetOfResolutions {
|
||||
r := new(SetOfResolutions)
|
||||
r.name = name
|
||||
r.crossFeedResolution = xfres
|
||||
r.feedResolution = fres
|
||||
r.units = 3 // 3 seems to mean dpi (rfc3805)
|
||||
r.sor = resSet
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *resolution) unmarshal(byteStream io.Reader) {
|
||||
func (r *SetOfResolutions) unmarshal(byteStream *bufio.Reader) {
|
||||
var length uint16
|
||||
binary.Read(byteStream, binary.BigEndian, &length)
|
||||
attributeName := make([]byte, length)
|
||||
if length > 0 {
|
||||
binary.Read(byteStream, binary.BigEndian, attributeName)
|
||||
var res Resolution
|
||||
for {
|
||||
binary.Read(byteStream, binary.BigEndian, &length)
|
||||
attributeName := make([]byte, length)
|
||||
if length > 0 {
|
||||
binary.Read(byteStream, binary.BigEndian, attributeName)
|
||||
r.name = string(attributeName)
|
||||
}
|
||||
binary.Read(byteStream, binary.BigEndian, &length)
|
||||
if length != 9 {
|
||||
panic("Wrong length in resolution")
|
||||
}
|
||||
binary.Read(byteStream, binary.BigEndian, &res.CrossFeedResolution)
|
||||
binary.Read(byteStream, binary.BigEndian, &res.FeedResolution)
|
||||
binary.Read(byteStream, binary.BigEndian, &res.Unit)
|
||||
r.sor = append(r.sor, res)
|
||||
var t tag
|
||||
err := binary.Read(byteStream, binary.BigEndian, &t)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
if t != resolutionValueTag {
|
||||
byteStream.UnreadByte()
|
||||
return
|
||||
}
|
||||
}
|
||||
r.name = string(attributeName)
|
||||
binary.Read(byteStream, binary.BigEndian, &length)
|
||||
if length != 9 {
|
||||
panic("Wrong length in resolution")
|
||||
}
|
||||
binary.Read(byteStream, binary.BigEndian, &r.crossFeedResolution)
|
||||
binary.Read(byteStream, binary.BigEndian, &r.feedResolution)
|
||||
binary.Read(byteStream, binary.BigEndian, &r.units)
|
||||
}
|
||||
|
||||
func (r resolution) Name() string {
|
||||
// Name returns the name of the attribute
|
||||
func (r SetOfResolutions) Name() string {
|
||||
return r.name
|
||||
}
|
||||
|
||||
func (r resolution) String() string {
|
||||
return fmt.Sprintf("%v:%v,%v,%v", r.name, r.crossFeedResolution, r.feedResolution, r.units)
|
||||
func (r SetOfResolutions) String() string {
|
||||
return fmt.Sprintf("%v:%v", r.name, r.sor)
|
||||
}
|
||||
|
||||
func (r *resolution) marshal() []byte {
|
||||
func (r *SetOfResolutions) marshal() []byte {
|
||||
|
||||
b := make([]byte, 0, 14+len(r.name))
|
||||
b := make([]byte, 0, 14+len(r.name)+14*(len(r.sor)-1))
|
||||
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))
|
||||
|
||||
for i, res := range r.sor {
|
||||
buf.WriteByte(byte(resolutionValueTag))
|
||||
if i == 0 {
|
||||
binary.Write(buf, binary.BigEndian, uint16(len(r.name)))
|
||||
buf.WriteString(r.name)
|
||||
} else {
|
||||
binary.Write(buf, binary.BigEndian, uint16(0))
|
||||
}
|
||||
binary.Write(buf, binary.BigEndian, uint16(9))
|
||||
binary.Write(buf, binary.BigEndian, int32(res.CrossFeedResolution))
|
||||
binary.Write(buf, binary.BigEndian, int32(res.FeedResolution))
|
||||
buf.WriteByte(byte(res.Unit))
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (r *resolution) valueTag() tag {
|
||||
func (r *SetOfResolutions) valueTag() tag {
|
||||
return resolutionValueTag
|
||||
}
|
||||
|
||||
@@ -32,14 +32,16 @@ func (h *ippResponseHeader) unmarshal(byteStream io.Reader) {
|
||||
binary.Read(byteStream, binary.BigEndian, &h.requestID)
|
||||
}
|
||||
|
||||
// Response represens a ipp response object
|
||||
type Response struct {
|
||||
a *attributes
|
||||
a *Attributes
|
||||
header ippResponseHeader
|
||||
}
|
||||
|
||||
// NewResponse creates a new ipp response object
|
||||
func NewResponse(code statusCode, requestID uint32) *Response {
|
||||
r := new(Response)
|
||||
r.a = new(attributes)
|
||||
r.a = new(Attributes)
|
||||
r.header.versionNumber = 0x0101
|
||||
r.header.requestID = requestID
|
||||
r.header.statusCode = code
|
||||
@@ -50,6 +52,7 @@ func (r Response) String() string {
|
||||
return r.header.String() + "\n" + r.a.String()
|
||||
}
|
||||
|
||||
// Marshal converts the response object to a wire formatted byte stream.
|
||||
func (r *Response) Marshal() []byte {
|
||||
a := make([]byte, 0, 20)
|
||||
a = append(a, r.header.marshal()...)
|
||||
@@ -75,21 +78,63 @@ func (r *Response) Marshal() []byte {
|
||||
return a
|
||||
}
|
||||
|
||||
// UnMarshal unmarshals a ipp response into a response object
|
||||
func (r *Response) UnMarshal(body io.Reader) {
|
||||
buffbody := bufio.NewReader(body)
|
||||
r.header.unmarshal(buffbody)
|
||||
//log.Printf("Header %v", r.header)
|
||||
r.a = UnMarshalAttributes(buffbody)
|
||||
}
|
||||
|
||||
func (r *Response) AddPrinterAttribute(a Attribute) {
|
||||
r.a.addAttribute(printerAttributes, a)
|
||||
// AddPrinterAttribute adds a printer attribute to the response object
|
||||
func (r *Response) AddPrinterAttribute(a Attribute) error {
|
||||
if a != nil {
|
||||
r.a.addAttribute(printerAttributes, a)
|
||||
return nil
|
||||
}
|
||||
return ErrNilAttribute
|
||||
}
|
||||
|
||||
func (r *Response) AddOperatonAttribute(a Attribute) {
|
||||
r.a.addAttribute(operationAttributes, a)
|
||||
// AddOperatonAttribute adds a printer attribute to the response object
|
||||
func (r *Response) AddOperatonAttribute(a Attribute) error {
|
||||
|
||||
if a != nil {
|
||||
r.a.addAttribute(operationAttributes, a)
|
||||
return nil
|
||||
}
|
||||
return ErrNilAttribute
|
||||
}
|
||||
|
||||
func (r *Response) AddJobAttribute(a Attribute) {
|
||||
r.a.addAttribute(jobAttributes, a)
|
||||
// AddJobAttribute adds a printer attribute to the response object
|
||||
func (r *Response) AddJobAttribute(a Attribute) error {
|
||||
if a != nil {
|
||||
r.a.addAttribute(jobAttributes, a)
|
||||
return nil
|
||||
}
|
||||
return ErrNilAttribute
|
||||
}
|
||||
|
||||
// GetAttribute retreives a attribute by name from the response object
|
||||
// returns nil a atribute with the provided name can be found.
|
||||
func (r *Response) GetAttribute(name string) Attribute {
|
||||
for _, a := range r.a.operation {
|
||||
if a.Name() == name {
|
||||
return a
|
||||
}
|
||||
}
|
||||
for _, a := range r.a.job {
|
||||
if a.Name() == name {
|
||||
return a
|
||||
}
|
||||
}
|
||||
for _, a := range r.a.printer {
|
||||
if a.Name() == name {
|
||||
return a
|
||||
}
|
||||
}
|
||||
for _, a := range r.a.unsupported {
|
||||
if a.Name() == name {
|
||||
return a
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,28 +2,31 @@ package ipp
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
type setOfStrings struct {
|
||||
// SetOfStrings is the strings attribute
|
||||
type SetOfStrings struct {
|
||||
name string
|
||||
values []string
|
||||
vTag tag
|
||||
}
|
||||
|
||||
func NewSetOfStrings(name string, t tag, values []string) *setOfStrings {
|
||||
s := new(setOfStrings)
|
||||
// NewSetOfStrings creates a new strings attribute
|
||||
func NewSetOfStrings(name string, t tag, values []string) *SetOfStrings {
|
||||
s := new(SetOfStrings)
|
||||
s.name = name
|
||||
s.vTag = t
|
||||
s.values = values //make([]string, 0)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s setOfStrings) String() string {
|
||||
func (s SetOfStrings) String() string {
|
||||
r := s.name + " :"
|
||||
for _, v := range s.values {
|
||||
r = r + " " + v
|
||||
}
|
||||
return r
|
||||
}
|
||||
func (s *setOfStrings) valueTag() tag {
|
||||
|
||||
func (s *SetOfStrings) valueTag() tag {
|
||||
return s.vTag
|
||||
}
|
||||
|
||||
@@ -39,7 +42,7 @@ func (s *setOfStrings) valueTag() tag {
|
||||
// }
|
||||
// }
|
||||
|
||||
func (s *setOfStrings) marshal() []byte {
|
||||
func (s *SetOfStrings) marshal() []byte {
|
||||
l := 5 + len(s.name) + len(s.values[0])
|
||||
for i := range s.values[1:] {
|
||||
l += 5 + len(s.values[i+1])
|
||||
@@ -47,7 +50,7 @@ func (s *setOfStrings) marshal() []byte {
|
||||
res := make([]byte, l)
|
||||
p := 0
|
||||
res[p] = byte(s.vTag)
|
||||
p += 1
|
||||
p++
|
||||
binary.BigEndian.PutUint16(res[p:p+2], uint16(len(s.name)))
|
||||
p += 2
|
||||
copy(res[p:], []byte(s.name))
|
||||
@@ -58,7 +61,7 @@ func (s *setOfStrings) marshal() []byte {
|
||||
p += len(s.values[0])
|
||||
for i := range s.values[1:] {
|
||||
res[p] = byte(s.vTag)
|
||||
p += 1
|
||||
p++
|
||||
binary.BigEndian.PutUint16(res[p:p+2], uint16(0))
|
||||
p = p + 2
|
||||
binary.BigEndian.PutUint16(res[p:p+2], uint16(len(s.values[i+1])))
|
||||
@@ -70,11 +73,12 @@ func (s *setOfStrings) marshal() []byte {
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *setOfStrings) AddValue(v string) {
|
||||
// AddValue adds a new sring to the set
|
||||
func (s *SetOfStrings) AddValue(v string) {
|
||||
s.values = append(s.values, v)
|
||||
}
|
||||
|
||||
func (s *setOfStrings) size() int {
|
||||
func (s *SetOfStrings) size() int {
|
||||
l := 1 + 2 // The value tag (0x44) + name-length field (2 bytes)
|
||||
l += len(s.name)
|
||||
l += 2 // value-length field (2 bytes)
|
||||
|
||||
@@ -2,35 +2,38 @@ package ipp
|
||||
|
||||
import "io"
|
||||
|
||||
type textWithoutLanguage struct {
|
||||
// TextWithoutLanguage is the TextWithoutLanguage attribute
|
||||
type TextWithoutLanguage struct {
|
||||
name string
|
||||
value string
|
||||
}
|
||||
|
||||
func NewtextWithoutLanguage(name, value string) *textWithoutLanguage {
|
||||
c := new(textWithoutLanguage)
|
||||
// NewtextWithoutLanguage creates a new textWithoutLanguage attribute
|
||||
func NewtextWithoutLanguage(name, value string) *TextWithoutLanguage {
|
||||
c := new(TextWithoutLanguage)
|
||||
c.name = name
|
||||
c.value = value
|
||||
return c
|
||||
}
|
||||
|
||||
func (c textWithoutLanguage) Name() string {
|
||||
// Name returns the name of the attribute
|
||||
func (c TextWithoutLanguage) Name() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c textWithoutLanguage) String() string {
|
||||
func (c TextWithoutLanguage) String() string {
|
||||
return c.name + ":" + c.value
|
||||
}
|
||||
|
||||
func (c *textWithoutLanguage) valueTag() tag {
|
||||
func (c *TextWithoutLanguage) valueTag() tag {
|
||||
return textWithoutLanguageValueTag
|
||||
}
|
||||
|
||||
func (c *textWithoutLanguage) unmarshal(byteStream io.Reader) {
|
||||
func (c *TextWithoutLanguage) unmarshal(byteStream io.Reader) {
|
||||
c.name, c.value = unmarshalSingleValue(byteStream)
|
||||
}
|
||||
|
||||
func (c *textWithoutLanguage) marshal() []byte {
|
||||
func (c *TextWithoutLanguage) marshal() []byte {
|
||||
l := 5 + len(c.name) + len(c.value)
|
||||
b := make([]byte, l)
|
||||
b[0] = byte(textWithoutLanguageValueTag)
|
||||
@@ -38,7 +41,7 @@ func (c *textWithoutLanguage) marshal() []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
func (c *textWithoutLanguage) size() int {
|
||||
func (c *TextWithoutLanguage) size() int {
|
||||
l := 1 + 4 // The attribute tag + 2 lengths
|
||||
l += len(c.name)
|
||||
l += len(c.value)
|
||||
|
||||
40
packages/ipp/unsupportedvalue.go
Normal file
40
packages/ipp/unsupportedvalue.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package ipp
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// UnSupportedValue represents a ipp unsupported attributes attribute
|
||||
type UnSupportedValue struct {
|
||||
name string
|
||||
}
|
||||
|
||||
// NewUnsupportedValue creates a new unsupported attributes attribute
|
||||
func NewUnsupportedValue() *UnSupportedValue {
|
||||
c := new(UnSupportedValue)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *UnSupportedValue) unmarshal(byteStream io.Reader) {
|
||||
c.name, _ = unmarshalSingleValue(byteStream)
|
||||
}
|
||||
|
||||
// Name returns the name of the attribute
|
||||
func (c *UnSupportedValue) Name() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c *UnSupportedValue) marshal() (data []byte) {
|
||||
log.Error("Unmarshal unsupported value is not implemented yet")
|
||||
return
|
||||
}
|
||||
|
||||
func (c *UnSupportedValue) valueTag() tag {
|
||||
return unsupportedValueTag
|
||||
}
|
||||
|
||||
func (c UnSupportedValue) String() string {
|
||||
return c.name
|
||||
}
|
||||
@@ -4,41 +4,49 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type uriValue struct {
|
||||
// URIValue represents a ipp URI value attribute
|
||||
type URIValue struct {
|
||||
name string
|
||||
value string
|
||||
}
|
||||
|
||||
func NewURIValue(name, value string) *uriValue {
|
||||
u := new(uriValue)
|
||||
// NewURIValue creates a new URIValue attribute
|
||||
func NewURIValue(name, value string) *URIValue {
|
||||
u := new(URIValue)
|
||||
u.name = name
|
||||
u.value = value
|
||||
return u
|
||||
}
|
||||
|
||||
func (u uriValue) Name() string {
|
||||
// Name returns the name of the attribute
|
||||
func (u URIValue) Name() string {
|
||||
return u.name
|
||||
}
|
||||
|
||||
func (u uriValue) String() string {
|
||||
// Value returns the value of the attribute
|
||||
func (u URIValue) Value() string {
|
||||
return u.value
|
||||
}
|
||||
|
||||
func (u URIValue) String() string {
|
||||
return u.name + ":" + u.value
|
||||
}
|
||||
|
||||
func (u *uriValue) valueTag() tag {
|
||||
func (u *URIValue) valueTag() tag {
|
||||
return uriValueTag
|
||||
}
|
||||
|
||||
func (u *uriValue) unmarshal(byteStream io.Reader) {
|
||||
func (u *URIValue) unmarshal(byteStream io.Reader) {
|
||||
u.name, u.value = unmarshalSingleValue(byteStream)
|
||||
}
|
||||
|
||||
func (u *uriValue) marshal() []byte {
|
||||
func (u *URIValue) marshal() []byte {
|
||||
res := make([]byte, u.size())
|
||||
res[0] = byte(uriValueTag)
|
||||
marshalNameValue(u.name, u.value, res[1:])
|
||||
return res
|
||||
}
|
||||
func (u *uriValue) size() int {
|
||||
func (u *URIValue) size() int {
|
||||
l := 1 + 4 // The attribute tag + 2 lengths
|
||||
l += len(u.name)
|
||||
l += len(u.value)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func TestMarshalUriValue(T *testing.T) {
|
||||
var u uriValue
|
||||
var u URIValue
|
||||
u.name = "foo"
|
||||
u.value = "bar"
|
||||
b := u.marshal()
|
||||
|
||||
Reference in New Issue
Block a user