145 lines
3.3 KiB
Go
145 lines
3.3 KiB
Go
package ipp
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
type ippResponseHeader struct {
|
|
versionNumber versionNumber
|
|
statusCode statusCode
|
|
requestID uint32
|
|
}
|
|
|
|
func (h ippResponseHeader) String() string {
|
|
return fmt.Sprintf("Version number: %v Status code: %v Request Id: %v", h.versionNumber, h.statusCode, h.requestID)
|
|
}
|
|
|
|
func (h *ippResponseHeader) marshal() []byte {
|
|
a := make([]byte, 8)
|
|
binary.BigEndian.PutUint16(a[0:2], uint16(h.versionNumber))
|
|
binary.BigEndian.PutUint16(a[2:4], uint16(h.statusCode))
|
|
binary.BigEndian.PutUint32(a[4:8], h.requestID)
|
|
|
|
return a
|
|
}
|
|
|
|
func (h *ippResponseHeader) unmarshal(byteStream io.Reader) {
|
|
binary.Read(byteStream, binary.BigEndian, &h.versionNumber)
|
|
binary.Read(byteStream, binary.BigEndian, &h.statusCode)
|
|
binary.Read(byteStream, binary.BigEndian, &h.requestID)
|
|
}
|
|
|
|
// Response represens a ipp response object
|
|
type Response struct {
|
|
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.header.versionNumber = 0x0101
|
|
r.header.requestID = requestID
|
|
r.header.statusCode = code
|
|
return r
|
|
}
|
|
|
|
func (r Response) String() string {
|
|
return r.header.String() + "\n" + r.a.String()
|
|
}
|
|
|
|
func (r Response) Header() ippResponseHeader {
|
|
return r.header
|
|
}
|
|
|
|
// 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()...)
|
|
if len(r.a.operation) > 0 {
|
|
a = append(a, byte(operationAttributes))
|
|
for _, e := range r.a.operation {
|
|
a = append(a, e.marshal()...)
|
|
}
|
|
}
|
|
if len(r.a.job) > 0 {
|
|
a = append(a, byte(jobAttributes))
|
|
for _, e := range r.a.job {
|
|
a = append(a, e.marshal()...)
|
|
}
|
|
}
|
|
if len(r.a.printer) > 0 {
|
|
a = append(a, byte(printerAttributes))
|
|
for _, e := range r.a.printer {
|
|
a = append(a, e.marshal()...)
|
|
}
|
|
}
|
|
a = append(a, byte(endOfAttributes))
|
|
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)
|
|
r.a = UnMarshalAttributes(buffbody)
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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
|
|
}
|