More types. Printing from chromeos works a little bit.
This commit is contained in:
35
main.go
35
main.go
@@ -1,10 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"ippserver/packages/ipp"
|
||||
"ippserver/packages/mdnsserver"
|
||||
"net/http"
|
||||
@@ -17,6 +15,7 @@ func main() {
|
||||
customFormatter.TimestampFormat = "2006-01-02 15:04:05"
|
||||
log.SetFormatter(customFormatter)
|
||||
customFormatter.FullTimestamp = true
|
||||
log.SetLevel(log.DebugLevel)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
@@ -37,18 +36,18 @@ func handle(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Unsupported method", http.StatusMethodNotAllowed)
|
||||
|
||||
}
|
||||
// body := make([]byte, r.ContentLength)
|
||||
// io.ReadFull(r.Body, body)
|
||||
// log.Infof("Body %x", body)
|
||||
//body := make([]byte, r.ContentLength)
|
||||
//io.ReadFull(r.Body, body)
|
||||
//log.Infof("Body %x", body)
|
||||
|
||||
request := ipp.NewRequest()
|
||||
rdata := make([]byte, r.ContentLength)
|
||||
io.ReadFull(r.Body, rdata)
|
||||
//rdata := make([]byte, r.ContentLength)
|
||||
//io.ReadFull(r.Body, rdata)
|
||||
//log.Printf("Data %x", rdata)
|
||||
fmt.Printf("data % #0x", rdata)
|
||||
buf := bytes.NewBuffer(rdata)
|
||||
request.UnMarshal(buf)
|
||||
fmt.Printf("%v", request)
|
||||
//fmt.Printf("data % #0x", rdata)
|
||||
//buf := bytes.NewBuffer(rdata)
|
||||
request.UnMarshal(r.Body)
|
||||
fmt.Printf("Request: \n%v\n", request)
|
||||
response := ipp.NewResponse(ipp.SuccessfulOk, request.RequestId())
|
||||
var a ipp.Attribute
|
||||
a = ipp.NewCharSetValue("attributes-charset", "utf-8")
|
||||
@@ -59,10 +58,20 @@ func handle(w http.ResponseWriter, r *http.Request) {
|
||||
response.AddOperatonAttribute(a)
|
||||
a = ipp.NewtextWithoutLanguage("printer-make-and-model", "ChroBro 001")
|
||||
response.AddOperatonAttribute(a)
|
||||
a = ipp.NewEnum("printer-state", uint16(3))
|
||||
a = ipp.NewEnum("printer-state", int32(ipp.Idle))
|
||||
response.AddOperatonAttribute(a)
|
||||
a = ipp.NewKeyWord("ipp-versions-supported", "1.0", "1.1", "2.0")
|
||||
response.AddOperatonAttribute(a)
|
||||
response.AddOperatonAttribute(ipp.NewKeyWord("ipp-features-supported", "wfds-print-1.0"))
|
||||
response.AddOperatonAttribute(ipp.NewMimeMediaType("document-format-supported", "image/pwg-raster"))
|
||||
response.AddOperatonAttribute(ipp.NewKeyWord("media-supported", "iso_a4_210x297mm"))
|
||||
response.AddOperatonAttribute(ipp.NewKeyWord("sides-supported", "one-sided", "two-sided-long-edge", "two-sided-short-edge"))
|
||||
response.AddOperatonAttribute(ipp.NewKeyWord("print-color-mode-supported", "auto", "color", "monochrome"))
|
||||
|
||||
fmt.Printf("Response:\n%v\n", response)
|
||||
data := response.Marshal()
|
||||
log.Infof("% x", data)
|
||||
|
||||
log.Debugf("% x", data)
|
||||
w.Write(data)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
package ipp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type enum struct {
|
||||
name string
|
||||
value uint16
|
||||
value int32
|
||||
}
|
||||
|
||||
func NewEnum(name string, value uint16) *enum {
|
||||
func NewEnum(name string, value int32) *enum {
|
||||
e := new(enum)
|
||||
e.name = name
|
||||
e.value = value
|
||||
@@ -18,7 +20,7 @@ func NewEnum(name string, value uint16) *enum {
|
||||
}
|
||||
|
||||
func (e enum) String() string {
|
||||
return e.name + ":" + string(e.value)
|
||||
return e.name + ":" + fmt.Sprint(e.value)
|
||||
}
|
||||
func (e *enum) valueTag() tag {
|
||||
return enumValueTag
|
||||
@@ -31,18 +33,14 @@ func (e *enum) unmarshal(byteStream io.Reader) {
|
||||
|
||||
func (e *enum) marshal() []byte {
|
||||
l := 3 + len(e.name) + 6
|
||||
b := make([]byte, l, l)
|
||||
p := 0
|
||||
b[0] = byte(enumValueTag)
|
||||
p += 1
|
||||
binary.BigEndian.PutUint16(b[p:p+2], uint16(len(e.name)))
|
||||
p += 2
|
||||
copy(b[p:], []byte(e.name))
|
||||
p += len(e.name)
|
||||
binary.BigEndian.PutUint16(b[p:p+2], uint16(4))
|
||||
p += 2
|
||||
binary.BigEndian.PutUint32(b[p:p+4], uint32(e.value))
|
||||
return b
|
||||
b := make([]byte, 0, l)
|
||||
buf := bytes.NewBuffer(b)
|
||||
buf.WriteByte(byte(enumValueTag))
|
||||
binary.Write(buf, binary.BigEndian, uint16(len(e.name)))
|
||||
buf.WriteString(e.name)
|
||||
binary.Write(buf, binary.BigEndian, uint16(4))
|
||||
binary.Write(buf, binary.BigEndian, e.value)
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
func (e *enum) size() int {
|
||||
|
||||
@@ -1,87 +1,33 @@
|
||||
package ipp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
type keyWord struct {
|
||||
name string
|
||||
values []string
|
||||
sos *setOfStrings
|
||||
}
|
||||
|
||||
func NewKeyWord() *keyWord {
|
||||
func NewKeyWord(name string, values ...string) *keyWord {
|
||||
|
||||
k := new(keyWord)
|
||||
k.values = make([]string, 0)
|
||||
k.sos = NewSetOfStrings(name, keyWordValueTag, values)
|
||||
return k
|
||||
}
|
||||
|
||||
func (k keyWord) String() string {
|
||||
r := k.name + " :"
|
||||
for _, v := range k.values {
|
||||
r = r + " " + v
|
||||
}
|
||||
return r
|
||||
}
|
||||
func (k *keyWord) valueTag() tag {
|
||||
return keyWordValueTag
|
||||
}
|
||||
|
||||
// func (k *keyWord) unmarshal(byteStream io.Reader) {
|
||||
// if len(k.values) == 0 {
|
||||
// var v string
|
||||
// k.name, v = unmarshalSingleValue(byteStream)
|
||||
// k.values = append(k.values, v)
|
||||
// } else {
|
||||
// var v string
|
||||
// _, v = unmarshalSingleValue(byteStream)
|
||||
// k.values = append(k.values, v)
|
||||
// }
|
||||
// }
|
||||
|
||||
func (k *keyWord) marshal() []byte {
|
||||
l := 5 + len(k.name) + len(k.values[0])
|
||||
for i := range k.values[1:] {
|
||||
l += 5 + len(k.values[i+1])
|
||||
}
|
||||
res := make([]byte, 0, l)
|
||||
p := 0
|
||||
res[p] = byte(keyWordValueTag)
|
||||
p += 1
|
||||
binary.BigEndian.PutUint16(res[p:p+2], uint16(len(k.name)))
|
||||
p += 2
|
||||
copy(res[p:], []byte(k.name))
|
||||
p += len(k.name)
|
||||
binary.BigEndian.PutUint16(res[p:p+2], uint16(len(k.values[0])))
|
||||
p += 2
|
||||
copy(res[p:], []byte(k.values[0]))
|
||||
p += len(k.values[0])
|
||||
for i := range k.values[1:] {
|
||||
res[p] = byte(keyWordValueTag)
|
||||
p += 1
|
||||
binary.BigEndian.PutUint16(res[p:p+2], uint16(0))
|
||||
p = p + 2
|
||||
binary.BigEndian.PutUint16(res[p:p+2], uint16(len(k.values[i+1])))
|
||||
p = p + 2
|
||||
copy(res[p:], []byte(k.values[i+1]))
|
||||
p += len(k.values[i+1])
|
||||
}
|
||||
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func (k *keyWord) AddValue(v string) {
|
||||
k.values = append(k.values, v)
|
||||
return k.sos.String()
|
||||
}
|
||||
|
||||
func (k *keyWord) size() int {
|
||||
l := 1 + 2 // The value tag (0x44) + name-length field (2 bytes)
|
||||
l += len(k.name)
|
||||
l += 2 // value-length field (2 bytes)
|
||||
l += len(k.values[0])
|
||||
// Add all additional values
|
||||
for _, v := range k.values[1:] {
|
||||
l += 1 + 4 // The value tag (0x44) + 2 length fields (2 bytes)
|
||||
l += len(v)
|
||||
}
|
||||
return l
|
||||
return k.sos.size()
|
||||
}
|
||||
|
||||
func (k *keyWord) valueTag() tag {
|
||||
return k.sos.valueTag()
|
||||
}
|
||||
|
||||
func (k *keyWord) marshal() []byte {
|
||||
return k.sos.marshal()
|
||||
}
|
||||
|
||||
func (k *keyWord) addValue(v string) {
|
||||
k.sos.AddValue(v)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package ipp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// func TestUnmarshalSimpleKeyword(T *testing.T) {
|
||||
// testdata := []byte{
|
||||
// 0x00, 0x14,
|
||||
@@ -13,3 +19,18 @@ package ipp
|
||||
// assert.Equal(T, k.name, "requested-attributes")
|
||||
// assert.Equal(T, k.values[0], "printer-make-and-model")
|
||||
// }
|
||||
|
||||
func TestMarshalSimpleKeyword(T *testing.T) {
|
||||
testdata := []byte{
|
||||
0x44, 0x00, 0x14,
|
||||
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x64, 0x2d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||
0x00, 0x16,
|
||||
0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2d, 0x6d, 0x61, 0x6b, 0x65, 0x2d, 0x61, 0x6e, 0x64, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
|
||||
}
|
||||
|
||||
k := NewKeyWord("requested-attributes")
|
||||
k.addValue("printer-make-and-model")
|
||||
m := k.marshal()
|
||||
assert.Equal(T, testdata, m, "Should be equal")
|
||||
|
||||
}
|
||||
|
||||
@@ -76,6 +76,14 @@ const (
|
||||
PurgeJobs operationId = 0x0012
|
||||
)
|
||||
|
||||
type printerState int32
|
||||
|
||||
const (
|
||||
Idle printerState = 3
|
||||
Preocessing printerState = 4
|
||||
Stopped printerState = 5
|
||||
)
|
||||
|
||||
type statusCode uint16
|
||||
|
||||
const (
|
||||
|
||||
32
packages/ipp/mimemediatype.go
Normal file
32
packages/ipp/mimemediatype.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package ipp
|
||||
|
||||
type mimeMediaType struct {
|
||||
sos *setOfStrings
|
||||
}
|
||||
|
||||
func NewMimeMediaType(name string, values ...string) *mimeMediaType {
|
||||
|
||||
m := new(mimeMediaType)
|
||||
m.sos = NewSetOfStrings(name, mimeMediaTypeValueTag, values)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m mimeMediaType) String() string {
|
||||
return m.sos.String()
|
||||
}
|
||||
|
||||
func (m *mimeMediaType) size() int {
|
||||
return m.sos.size()
|
||||
}
|
||||
|
||||
func (m *mimeMediaType) valueTag() tag {
|
||||
return m.sos.valueTag()
|
||||
}
|
||||
|
||||
func (m *mimeMediaType) marshal() []byte {
|
||||
return m.sos.marshal()
|
||||
}
|
||||
|
||||
func (m *mimeMediaType) addValue(v string) {
|
||||
m.sos.AddValue(v)
|
||||
}
|
||||
41
packages/ipp/namewithoutlanguage.go
Normal file
41
packages/ipp/namewithoutlanguage.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package ipp
|
||||
|
||||
import "io"
|
||||
|
||||
type nameWithoutLanguage struct {
|
||||
name string
|
||||
value string
|
||||
}
|
||||
|
||||
func NewNameWithoutLanguage(name, value string) *nameWithoutLanguage {
|
||||
c := new(nameWithoutLanguage)
|
||||
c.name = name
|
||||
c.value = value
|
||||
return c
|
||||
}
|
||||
|
||||
func (c nameWithoutLanguage) String() string {
|
||||
return c.name + ":" + c.value
|
||||
}
|
||||
func (c *nameWithoutLanguage) valueTag() tag {
|
||||
return nameWithoutLanguageValueTag
|
||||
}
|
||||
|
||||
func (c *nameWithoutLanguage) unmarshal(byteStream io.Reader) {
|
||||
c.name, c.value = unmarshalSingleValue(byteStream)
|
||||
}
|
||||
|
||||
func (c *nameWithoutLanguage) marshal() []byte {
|
||||
l := 5 + len(c.name) + len(c.value)
|
||||
b := make([]byte, l, l)
|
||||
b[0] = byte(nameWithoutLanguageValueTag)
|
||||
marshalNameValue(c.name, c.value, b[1:])
|
||||
return b
|
||||
}
|
||||
|
||||
func (c *nameWithoutLanguage) size() int {
|
||||
l := 1 + 4 // The attribute tag + 2 lengths
|
||||
l += len(c.name)
|
||||
l += len(c.value)
|
||||
return l
|
||||
}
|
||||
26
packages/ipp/printerstate_string.go
Normal file
26
packages/ipp/printerstate_string.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// Code generated by "stringer -type printerState ."; DO NOT EDIT.
|
||||
|
||||
package ipp
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[Idle-3]
|
||||
_ = x[Preocessing-4]
|
||||
_ = x[Stopped-5]
|
||||
}
|
||||
|
||||
const _printerState_name = "IdlePreocessingStopped"
|
||||
|
||||
var _printerState_index = [...]uint8{0, 4, 15, 22}
|
||||
|
||||
func (i printerState) String() string {
|
||||
i -= 3
|
||||
if i < 0 || i >= printerState(len(_printerState_index)-1) {
|
||||
return "printerState(" + strconv.FormatInt(int64(i+3), 10) + ")"
|
||||
}
|
||||
return _printerState_name[_printerState_index[i]:_printerState_index[i+1]]
|
||||
}
|
||||
@@ -26,16 +26,19 @@ func (h ippRequestHeader) String() string {
|
||||
|
||||
type Attribute interface {
|
||||
valueTag() tag
|
||||
//unmarshal(io.Reader)
|
||||
marshal() []byte
|
||||
size() int
|
||||
//size() int
|
||||
}
|
||||
|
||||
type AddValuer interface {
|
||||
addValue(string)
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
header ippRequestHeader
|
||||
operationAttributes map[string]Attribute
|
||||
jobAttributes map[string]Attribute
|
||||
printerAttributes map[string]Attribute
|
||||
header ippRequestHeader
|
||||
}
|
||||
|
||||
func NewRequest() *Request {
|
||||
@@ -52,21 +55,29 @@ func (r Request) String() string {
|
||||
for _, a := range r.operationAttributes {
|
||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||
}
|
||||
s = s + " PrinterAttributes" + "\n"
|
||||
for _, a := range r.printerAttributes {
|
||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||
}
|
||||
s = s + " JobAttributes" + "\n"
|
||||
for _, a := range r.jobAttributes {
|
||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *Request) UnMarshal(body io.Reader) {
|
||||
r.header.marshal(body)
|
||||
log.Infof("Header %v", r.header)
|
||||
log.Debugf("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)
|
||||
log.Debugf("got tag - %v", tag)
|
||||
|
||||
if tag == operationAttributes {
|
||||
var lastKeyword *keyWord
|
||||
var lastAddValuer AddValuer
|
||||
nextoperationattr:
|
||||
for tag != endOfAttributes {
|
||||
|
||||
@@ -74,7 +85,7 @@ func (r *Request) UnMarshal(body io.Reader) {
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
log.Infof("Value tag - %v", tag)
|
||||
log.Debugf("Value tag - %v", tag)
|
||||
switch tag {
|
||||
case endOfAttributes:
|
||||
err = binary.Read(body, binary.BigEndian, &tag)
|
||||
@@ -85,40 +96,61 @@ func (r *Request) UnMarshal(body io.Reader) {
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
log.Infof("got tag - %v", tag)
|
||||
log.Debugf("got tag - %v", tag)
|
||||
err = binary.Read(body, binary.BigEndian, &tag)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
log.Infof("got tag - %v", tag)
|
||||
log.Debugf("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)
|
||||
log.Debugf("%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)
|
||||
log.Debugf("%v %v", u.name, u.value)
|
||||
case naturalLanguageValueTag:
|
||||
n := NewNaturalLanguage("", "")
|
||||
n.unmarshal(body)
|
||||
r.operationAttributes[n.name] = n
|
||||
log.Infof("%v %v", n.name, n.value)
|
||||
log.Debugf("%v %v", n.name, n.value)
|
||||
case keyWordValueTag:
|
||||
name, value := unmarshalSingleValue(body)
|
||||
if name == "" {
|
||||
lastKeyword.AddValue(value)
|
||||
lastAddValuer.addValue(value)
|
||||
} else {
|
||||
k := NewKeyWord()
|
||||
k.name = name
|
||||
k.AddValue(value)
|
||||
r.operationAttributes[k.name] = k
|
||||
lastKeyword = k
|
||||
k := NewKeyWord(name, value)
|
||||
r.operationAttributes[name] = k
|
||||
lastAddValuer = k
|
||||
}
|
||||
log.Debugf("%v : %v", name, value)
|
||||
case nameWithoutLanguageValueTag:
|
||||
n := NewNameWithoutLanguage("", "")
|
||||
n.unmarshal(body)
|
||||
r.operationAttributes[n.name] = n
|
||||
log.Debugf("%v %v", n.name, n.value)
|
||||
case mimeMediaTypeValueTag:
|
||||
name, value := unmarshalSingleValue(body)
|
||||
if name == "" {
|
||||
lastAddValuer.addValue(value)
|
||||
} else {
|
||||
m := NewMimeMediaType(name, value)
|
||||
r.operationAttributes[name] = m
|
||||
lastAddValuer = m
|
||||
}
|
||||
case jobAttributes:
|
||||
log.Debug("Start job attributes")
|
||||
case resolutionValueTag:
|
||||
res := NewResolution()
|
||||
res.unmarshal(body)
|
||||
r.operationAttributes["resolution"] = res
|
||||
log.Debugf("Resolution %v", res)
|
||||
|
||||
default:
|
||||
log.Errorf("Unsupported tag %v", tag)
|
||||
|
||||
|
||||
@@ -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.operationAttributes, 4)
|
||||
v := req.operationAttributes["requested-attributes"].(*keyWord).values
|
||||
v := req.operationAttributes["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")
|
||||
|
||||
48
packages/ipp/resolution.go
Normal file
48
packages/ipp/resolution.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package ipp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type resolution struct {
|
||||
name string
|
||||
crossFeedResolution int32
|
||||
feedResolution int32
|
||||
units int8
|
||||
}
|
||||
|
||||
func NewResolution() *resolution {
|
||||
r := new(resolution)
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *resolution) unmarshal(byteStream io.Reader) {
|
||||
var length uint16
|
||||
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, &r.crossFeedResolution)
|
||||
binary.Read(byteStream, binary.BigEndian, &r.feedResolution)
|
||||
binary.Read(byteStream, binary.BigEndian, &r.units)
|
||||
}
|
||||
|
||||
func (r resolution) String() string {
|
||||
return fmt.Sprintf("%v:%v:%v", r.crossFeedResolution, r.feedResolution, r.units)
|
||||
}
|
||||
|
||||
func (r *resolution) marshal() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func (r *resolution) valueTag() tag {
|
||||
return resolutionValueTag
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package ipp
|
||||
|
||||
import "encoding/binary"
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ippResponseHeader struct {
|
||||
versionNumber versionNumber
|
||||
@@ -8,6 +11,10 @@ type ippResponseHeader struct {
|
||||
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, 8)
|
||||
binary.BigEndian.PutUint16(a[0:2], uint16(h.versionNumber))
|
||||
@@ -53,7 +60,20 @@ func NewResponse(code statusCode, requestId uint32) *Response {
|
||||
// }
|
||||
|
||||
func (r Response) String() string {
|
||||
return ""
|
||||
|
||||
s := r.header.String() + "\n" + " OperationAttributes" + "\n"
|
||||
for _, a := range r.operationAttributes {
|
||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||
}
|
||||
s = s + " PrinterAttributes" + "\n"
|
||||
for _, a := range r.printerAttributes {
|
||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||
}
|
||||
s = s + " JobAttributes" + "\n"
|
||||
for _, a := range r.jobAttributes {
|
||||
s = s + fmt.Sprintf(" %v (%v)\n", a, a.valueTag())
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (r *Response) Marshal() []byte {
|
||||
|
||||
88
packages/ipp/setofstrings.go
Normal file
88
packages/ipp/setofstrings.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package ipp
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
type setOfStrings struct {
|
||||
vTag tag
|
||||
name string
|
||||
values []string
|
||||
}
|
||||
|
||||
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 {
|
||||
r := s.name + " :"
|
||||
for _, v := range s.values {
|
||||
r = r + " " + v
|
||||
}
|
||||
return r
|
||||
}
|
||||
func (s *setOfStrings) valueTag() tag {
|
||||
return s.vTag
|
||||
}
|
||||
|
||||
// func (k *keyWord) unmarshal(byteStream io.Reader) {
|
||||
// if len(k.values) == 0 {
|
||||
// var v string
|
||||
// k.name, v = unmarshalSingleValue(byteStream)
|
||||
// k.values = append(k.values, v)
|
||||
// } else {
|
||||
// var v string
|
||||
// _, v = unmarshalSingleValue(byteStream)
|
||||
// k.values = append(k.values, v)
|
||||
// }
|
||||
// }
|
||||
|
||||
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])
|
||||
}
|
||||
res := make([]byte, l, l)
|
||||
p := 0
|
||||
res[p] = byte(s.vTag)
|
||||
p += 1
|
||||
binary.BigEndian.PutUint16(res[p:p+2], uint16(len(s.name)))
|
||||
p += 2
|
||||
copy(res[p:], []byte(s.name))
|
||||
p += len(s.name)
|
||||
binary.BigEndian.PutUint16(res[p:p+2], uint16(len(s.values[0])))
|
||||
p += 2
|
||||
copy(res[p:], []byte(s.values[0]))
|
||||
p += len(s.values[0])
|
||||
for i := range s.values[1:] {
|
||||
res[p] = byte(s.vTag)
|
||||
p += 1
|
||||
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])))
|
||||
p = p + 2
|
||||
copy(res[p:], []byte(s.values[i+1]))
|
||||
p += len(s.values[i+1])
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *setOfStrings) AddValue(v string) {
|
||||
s.values = append(s.values, v)
|
||||
}
|
||||
|
||||
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)
|
||||
l += len(s.values[0])
|
||||
// Add all additional values
|
||||
for _, v := range s.values[1:] {
|
||||
l += 1 + 4 // The value tag (0x44) + 2 length fields (2 bytes)
|
||||
l += len(v)
|
||||
}
|
||||
return l
|
||||
}
|
||||
@@ -24,7 +24,7 @@ func Run(ctx context.Context) {
|
||||
log.Fatalf("EntryGroupNew() failed: %v", err)
|
||||
}
|
||||
|
||||
hostname, err := a.GetHostName()
|
||||
//hostname, err := a.GetHostName()
|
||||
if err != nil {
|
||||
log.Fatalf("GetHostName() failed: %v", err)
|
||||
}
|
||||
@@ -40,7 +40,7 @@ func Run(ctx context.Context) {
|
||||
txt = append(txt, []byte("Color=T"))
|
||||
txt = append(txt, []byte("rp=ipp/print"))
|
||||
txt = append(txt, []byte("ty=ChroBro 001"))
|
||||
err = eg.AddService(avahi.InterfaceUnspec, avahi.ProtoUnspec, 0, hostname, "_ipp._tcp", "local", fqdn, 1234, txt)
|
||||
err = eg.AddService(avahi.InterfaceUnspec, avahi.ProtoUnspec, 0, "ChroBro 1000", "_ipp._tcp", "local", fqdn, 1234, txt)
|
||||
if err != nil {
|
||||
log.Fatalf("AddService() failed: %v", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user