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 } // Operation returns the operation is of the request. 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 }