149 lines
3.2 KiB
Go
149 lines
3.2 KiB
Go
package ipp
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
type ippMessageHeader struct {
|
|
versionNumber versionNumber
|
|
operationID OperationID
|
|
requestID uint32
|
|
}
|
|
|
|
func (h *ippMessageHeader) 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 *ippMessageHeader) 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 ippMessageHeader) String() string {
|
|
return fmt.Sprintf("Version number: %v Operation Id: %v Request Id: %v", h.versionNumber, h.operationID, h.requestID)
|
|
}
|
|
|
|
type AddValuer interface {
|
|
addValue(interface{})
|
|
}
|
|
|
|
type Request struct {
|
|
a *Attributes
|
|
header ippMessageHeader
|
|
}
|
|
|
|
func NewRequest(op OperationID, requestID uint32) *Request {
|
|
r := new(Request)
|
|
r.header.operationID = op
|
|
r.header.requestID = requestID
|
|
r.header.versionNumber = 0x0200
|
|
r.a = new(Attributes)
|
|
return r
|
|
}
|
|
|
|
func (r Request) String() string {
|
|
return r.header.String() + "\n" + r.a.String()
|
|
}
|
|
|
|
func (r *Request) UnMarshal(body io.Reader) {
|
|
buffbody := bufio.NewReader(body)
|
|
r.header.unmarshal(buffbody)
|
|
r.a = UnMarshalAttributes(buffbody)
|
|
}
|
|
|
|
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 {
|
|
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
|
|
}
|
|
|
|
// Marshal converts the request object to a ipp request
|
|
func (r *Request) Marshal() []byte {
|
|
|
|
var buf bytes.Buffer
|
|
buf.Write(r.header.marshal())
|
|
if len(r.a.operation) > 0 {
|
|
buf.WriteByte(byte(operationAttributes))
|
|
for _, e := range r.a.operation {
|
|
buf.Write(e.marshal())
|
|
}
|
|
}
|
|
if len(r.a.job) > 0 {
|
|
buf.WriteByte(byte(jobAttributes))
|
|
for _, e := range r.a.job {
|
|
buf.Write(e.marshal())
|
|
}
|
|
}
|
|
if len(r.a.printer) > 0 {
|
|
buf.WriteByte(byte(printerAttributes))
|
|
for _, e := range r.a.printer {
|
|
buf.Write(e.marshal())
|
|
}
|
|
}
|
|
buf.WriteByte(byte(endOfAttributes))
|
|
return buf.Bytes()
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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
|
|
}
|