add support for Open Connectivity Foundation DCPs
This commit is contained in:
parent
e739c716b4
commit
9af4afce08
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
*.zip
|
*.zip
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
|
*.download
|
2
Makefile
Normal file
2
Makefile
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
gen:
|
||||||
|
(cd cmd/goupnpdcpgen/; go install); go generate ./...
|
@ -2,15 +2,21 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
var packageTmpl = template.Must(template.New("package").Parse(`{{$name := .Metadata.Name}}
|
var templateFuncs = template.FuncMap{
|
||||||
|
"base": filepath.Base,
|
||||||
|
}
|
||||||
|
|
||||||
|
var packageTmpl = template.Must(template.New("package").Funcs(templateFuncs).Parse(`{{$name := .Metadata.Name}}
|
||||||
// Client for UPnP Device Control Protocol {{.Metadata.OfficialName}}.
|
// Client for UPnP Device Control Protocol {{.Metadata.OfficialName}}.
|
||||||
// {{if .Metadata.DocURL}}
|
// {{if .DocURLs}}
|
||||||
// This DCP is documented in detail at: {{.Metadata.DocURL}}{{end}}
|
// This DCP is documented in detail at: {{range .DocURLs}}
|
||||||
|
// - {{.}}{{end}}{{end}}
|
||||||
//
|
//
|
||||||
// Typically, use one of the New* functions to create clients for services.
|
// Typically, use one of the New* functions to create clients for services.
|
||||||
package {{$name}}
|
package {{$name | base}}
|
||||||
|
|
||||||
// ***********************************************************
|
// ***********************************************************
|
||||||
// GENERATED FILE - DO NOT EDIT BY HAND. See README.md
|
// GENERATED FILE - DO NOT EDIT BY HAND. See README.md
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
// DCP collects together information about a UPnP Device Control Protocol.
|
// DCP collects together information about a UPnP Device Control Protocol.
|
||||||
type DCP struct {
|
type DCP struct {
|
||||||
Metadata DCPMetadata
|
Metadata DCPMetadata
|
||||||
|
DocURLs []string
|
||||||
DeviceTypes map[string]*URNParts
|
DeviceTypes map[string]*URNParts
|
||||||
ServiceTypes map[string]*URNParts
|
ServiceTypes map[string]*URNParts
|
||||||
Services []SCPDWithURN
|
Services []SCPDWithURN
|
||||||
@ -29,22 +30,33 @@ func newDCP(metadata DCPMetadata) *DCP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dcp *DCP) processZipFile(filename string) error {
|
func (dcp *DCP) Reset() {
|
||||||
archive, err := zip.OpenReader(filename)
|
dcp.DocURLs = nil
|
||||||
if err != nil {
|
dcp.DeviceTypes = make(map[string]*URNParts)
|
||||||
return fmt.Errorf("error reading zip file %q: %v", filename, err)
|
dcp.ServiceTypes = make(map[string]*URNParts)
|
||||||
}
|
}
|
||||||
defer archive.Close()
|
|
||||||
for _, deviceFile := range globFiles("*/device/*.xml", archive) {
|
func (dcp *DCP) processZipFile(archive []*zip.File, devices, services []string) error {
|
||||||
if err := dcp.processDeviceFile(deviceFile); err != nil {
|
var f int
|
||||||
return err
|
for _, devicesGlob := range devices {
|
||||||
|
for _, deviceFile := range globFiles(devicesGlob, archive) {
|
||||||
|
if err := dcp.processDeviceFile(deviceFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, scpdFile := range globFiles("*/service/*.xml", archive) {
|
for _, scpdsGlob := range services {
|
||||||
if err := dcp.processSCPDFile(scpdFile); err != nil {
|
for _, scpdFile := range globFiles(scpdsGlob, archive) {
|
||||||
return err
|
if err := dcp.processSCPDFile(scpdFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if f < 1 {
|
||||||
|
return fmt.Errorf("no sdcp/device found in %q and %q", devices, services)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,24 +9,22 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func acquireFile(specFilename string, xmlSpecURL string) error {
|
func acquireFile(specFilename string, xmlSpecURL string) error {
|
||||||
if f, err := os.Open(specFilename); err != nil {
|
tmpFilename := specFilename + ".download"
|
||||||
if !os.IsNotExist(err) {
|
defer os.Remove(tmpFilename)
|
||||||
return err
|
|
||||||
}
|
if fileExists(specFilename) {
|
||||||
} else {
|
|
||||||
f.Close()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpFilename := specFilename + ".download"
|
|
||||||
if err := downloadFile(tmpFilename, xmlSpecURL); err != nil {
|
if err := downloadFile(tmpFilename, xmlSpecURL); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return os.Rename(tmpFilename, specFilename)
|
return copyFile(specFilename, tmpFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
func downloadFile(filename, url string) error {
|
func downloadFile(filename, url string) error {
|
||||||
@ -54,10 +52,11 @@ func downloadFile(filename, url string) error {
|
|||||||
return w.Close()
|
return w.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func globFiles(pattern string, archive *zip.ReadCloser) []*zip.File {
|
func globFiles(pattern string, archive []*zip.File) []*zip.File {
|
||||||
var files []*zip.File
|
var files []*zip.File
|
||||||
for _, f := range archive.File {
|
pattern = strings.ToLower(pattern)
|
||||||
if matched, err := path.Match(pattern, f.Name); err != nil {
|
for _, f := range archive {
|
||||||
|
if matched, err := path.Match(pattern, strings.ToLower(f.Name)); err != nil {
|
||||||
// This shouldn't happen - all patterns are hard-coded, errors in them
|
// This shouldn't happen - all patterns are hard-coded, errors in them
|
||||||
// are a programming error.
|
// are a programming error.
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -93,3 +92,30 @@ func urnPartsFromSCPDFilename(filename string) (*URNParts, error) {
|
|||||||
Version: version,
|
Version: version,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyFile(dst string, src string) error {
|
||||||
|
f, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return writeFile(dst, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeFile(dst string, r io.ReadCloser) error {
|
||||||
|
defer r.Close()
|
||||||
|
f, err := os.Create(dst)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(f, r)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileExists(p string) bool {
|
||||||
|
f, err := os.Open(p)
|
||||||
|
if err != nil {
|
||||||
|
return !os.IsNotExist(err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
@ -35,25 +35,19 @@ func run(dcpName, specsDir string, useGofmt bool) error {
|
|||||||
return fmt.Errorf("could not create specs-dir %q: %v", specsDir, err)
|
return fmt.Errorf("could not create specs-dir %q: %v", specsDir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, d := range dcpMetadata {
|
for _, metadata := range dcpMetadata {
|
||||||
if d.Name != dcpName {
|
if metadata.Name != dcpName {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
specFilename := filepath.Join(specsDir, d.Name+".zip")
|
|
||||||
err := acquireFile(specFilename, d.XMLSpecURL)
|
dcp := newDCP(metadata)
|
||||||
|
|
||||||
|
err := metadata.Src.process(".", metadata.Name, dcp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not acquire spec for %s: %v", d.Name, err)
|
return fmt.Errorf("error processing spec %s: %v", metadata.Name, err)
|
||||||
}
|
}
|
||||||
dcp := newDCP(d)
|
|
||||||
if err := dcp.processZipFile(specFilename); err != nil {
|
if err := dcp.writeCode(filepath.Base(metadata.Name)+".go", useGofmt); err != nil {
|
||||||
return fmt.Errorf("error processing spec for %s in file %q: %v", d.Name, specFilename, err)
|
|
||||||
}
|
|
||||||
for i, hack := range d.Hacks {
|
|
||||||
if err := hack(dcp); err != nil {
|
|
||||||
return fmt.Errorf("error with Hack[%d] for %s: %v", i, d.Name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := dcp.writeCode(d.Name+".go", useGofmt); err != nil {
|
|
||||||
return fmt.Errorf("error writing package %q: %v", dcp.Metadata.Name, err)
|
return fmt.Errorf("error writing package %q: %v", dcp.Metadata.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,69 +1,127 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
// DCP contains extra metadata to use when generating DCP source files.
|
// DCP contains extra metadata to use when generating DCP source files.
|
||||||
type DCPMetadata struct {
|
type DCPMetadata struct {
|
||||||
Name string // What to name the Go DCP package.
|
Name string // What to name the Go DCP package.
|
||||||
OfficialName string // Official name for the DCP.
|
OfficialName string // Official name for the DCP.
|
||||||
DocURL string // Optional - URL for further documentation about the DCP.
|
Src dcpProvider
|
||||||
XMLSpecURL string // Where to download the XML spec from.
|
|
||||||
// Any special-case functions to run against the DCP before writing it out.
|
|
||||||
Hacks []DCPHackFn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var dcpMetadata = []DCPMetadata{
|
var dcpMetadata = []DCPMetadata{
|
||||||
{
|
{
|
||||||
Name: "internetgateway1",
|
Name: "internetgateway1",
|
||||||
OfficialName: "Internet Gateway Device v1",
|
OfficialName: "Internet Gateway Device v1",
|
||||||
DocURL: "http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf",
|
Src: upnpdotorg{
|
||||||
XMLSpecURL: "http://upnp.org/specs/gw/UPnP-gw-IGD-TestFiles-20010921.zip",
|
DocURL: "http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf",
|
||||||
Hacks: []DCPHackFn{totalBytesHack},
|
XMLSpecURL: "http://upnp.org/specs/gw/UPnP-gw-IGD-TestFiles-20010921.zip",
|
||||||
|
Hacks: []DCPHackFn{
|
||||||
|
fixTotalBytes("urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "internetgateway2",
|
Name: "internetgateway2",
|
||||||
OfficialName: "Internet Gateway Device v2",
|
OfficialName: "Internet Gateway Device v2",
|
||||||
DocURL: "http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v2-Device.pdf",
|
Src: upnpdotorg{
|
||||||
XMLSpecURL: "http://upnp.org/specs/gw/UPnP-gw-IGD-Testfiles-20110224.zip",
|
DocURL: "http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v2-Device.pdf",
|
||||||
Hacks: []DCPHackFn{
|
XMLSpecURL: "http://upnp.org/specs/gw/UPnP-gw-IGD-Testfiles-20110224.zip",
|
||||||
func(dcp *DCP) error {
|
Hacks: []DCPHackFn{
|
||||||
missingURN := "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"
|
fixMissingURN("urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"),
|
||||||
if _, ok := dcp.ServiceTypes[missingURN]; ok {
|
fixTotalBytes("urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"),
|
||||||
return nil
|
},
|
||||||
}
|
|
||||||
urnParts, err := extractURNParts(missingURN, serviceURNPrefix)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
dcp.ServiceTypes[missingURN] = urnParts
|
|
||||||
return nil
|
|
||||||
}, totalBytesHack,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "av1",
|
Name: "av1",
|
||||||
OfficialName: "MediaServer v1 and MediaRenderer v1",
|
OfficialName: "MediaServer v1 and MediaRenderer v1",
|
||||||
DocURL: "http://upnp.org/specs/av/av1/",
|
Src: upnpdotorg{
|
||||||
XMLSpecURL: "http://upnp.org/specs/av/UPnP-av-TestFiles-20070927.zip",
|
DocURL: "http://upnp.org/specs/av/av1/",
|
||||||
|
XMLSpecURL: "http://upnp.org/specs/av/UPnP-av-TestFiles-20070927.zip",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ocf/internetgateway1",
|
||||||
|
OfficialName: "Internet Gateway Device v1 - Open Connectivity Foundation",
|
||||||
|
Src: openconnectivitydotorg{
|
||||||
|
SpecsURL: ocfSpecsURL,
|
||||||
|
DocPath: "*/DeviceProtection_1/UPnP-gw-*v1*.pdf",
|
||||||
|
XMLSpecZipPath: "*/DeviceProtection_1/UPnP-gw-IGD-TestFiles-*.zip",
|
||||||
|
XMLServicePath: []string{"*/service/*1.xml"},
|
||||||
|
XMLDevicePath: []string{"*/device/*1.xml"},
|
||||||
|
Hacks: []DCPHackFn{
|
||||||
|
fixMissingURN("urn:schemas-upnp-org:service:DeviceProtection:1"),
|
||||||
|
fixMissingURN("urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"),
|
||||||
|
fixTotalBytes(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ocf/internetgateway2",
|
||||||
|
OfficialName: "Internet Gateway Device v2 - Open Connectivity Foundation",
|
||||||
|
Src: openconnectivitydotorg{
|
||||||
|
SpecsURL: ocfSpecsURL,
|
||||||
|
DocPath: "*/Internet Gateway_2/UPnP-gw-*.pdf",
|
||||||
|
XMLSpecZipPath: "*/Internet Gateway_2/UPnP-gw-IGD-TestFiles-*.zip",
|
||||||
|
XMLServicePath: []string{"*/service/*1.xml", "*/service/*2.xml"},
|
||||||
|
XMLDevicePath: []string{"*/device/*1.xml", "*/device/*2.xml"},
|
||||||
|
Hacks: []DCPHackFn{
|
||||||
|
fixMissingURN("urn:schemas-upnp-org:service:DeviceProtection:1"),
|
||||||
|
fixTotalBytes(),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func totalBytesHack(dcp *DCP) error {
|
func fixTotalBytes(malformedURNs ...string) func(dcp *DCP) error {
|
||||||
for _, service := range dcp.Services {
|
malformedVariables := []string{
|
||||||
if service.URN == "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" {
|
"TotalBytesSent",
|
||||||
variables := service.SCPD.StateVariables
|
"TotalBytesReceived",
|
||||||
for key, variable := range variables {
|
}
|
||||||
varName := variable.Name
|
return func(dcp *DCP) error {
|
||||||
if varName == "TotalBytesSent" || varName == "TotalBytesReceived" {
|
for _, service := range dcp.Services {
|
||||||
// Fix size of total bytes which is by default ui4 or maximum 4 GiB.
|
var process bool
|
||||||
variable.DataType.Name = "ui8"
|
for _, malformedURN := range malformedURNs {
|
||||||
variables[key] = variable
|
if service.URN == malformedURN {
|
||||||
|
process = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if process || len(malformedURNs) < 1 {
|
||||||
|
variables := service.SCPD.StateVariables
|
||||||
|
for key, variable := range variables {
|
||||||
|
varName := variable.Name
|
||||||
|
for _, malformedVariable := range malformedVariables {
|
||||||
|
if strings.HasSuffix(varName, malformedVariable) {
|
||||||
|
// Fix size of total bytes which is by default ui4 or maximum 4 GiB.
|
||||||
|
variable.DataType.Name = "ui8"
|
||||||
|
variables[key] = variable
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
func fixMissingURN(missingURNs ...string) func(dcp *DCP) error {
|
||||||
|
return func(dcp *DCP) error {
|
||||||
|
for _, missingURN := range missingURNs {
|
||||||
|
if _, ok := dcp.ServiceTypes[missingURN]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
urnParts, err := extractURNParts(missingURN, serviceURNPrefix)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dcp.ServiceTypes[missingURN] = urnParts
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DCPHackFn func(*DCP) error
|
type DCPHackFn func(*DCP) error
|
||||||
|
101
cmd/goupnpdcpgen/provider.go
Normal file
101
cmd/goupnpdcpgen/provider.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type dcpProvider interface {
|
||||||
|
process(tmpdir, name string, dcp *DCP) error
|
||||||
|
}
|
||||||
|
type upnpdotorg struct {
|
||||||
|
DocURL string // Optional - URL for further documentation about the DCP.
|
||||||
|
XMLSpecURL string // Where to download the XML spec from.
|
||||||
|
// Any special-case functions to run against the DCP before writing it out.
|
||||||
|
Hacks []DCPHackFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u upnpdotorg) process(tmpdir, name string, dcp *DCP) error {
|
||||||
|
dcp.DocURLs = append(dcp.DocURLs, u.DocURL)
|
||||||
|
specFilename := filepath.Join(tmpdir, name+".zip")
|
||||||
|
err := acquireFile(specFilename, u.XMLSpecURL)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not acquire spec for %s: %v", name, err)
|
||||||
|
}
|
||||||
|
archive, err := zip.OpenReader(specFilename)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading zip file %q: %v", specFilename, err)
|
||||||
|
}
|
||||||
|
defer archive.Close()
|
||||||
|
if err := dcp.processZipFile(archive.File, []string{"*/device/*.xml"}, []string{"*/service/*.xml"}); err != nil {
|
||||||
|
return fmt.Errorf("error processing spec file %q: %v", specFilename, err)
|
||||||
|
}
|
||||||
|
for i, hack := range u.Hacks {
|
||||||
|
if err := hack(dcp); err != nil {
|
||||||
|
return fmt.Errorf("error with Hack[%d] for %s: %v", i, name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const ocfSpecsURL = "https://openconnectivity.org/upnp-specs/upnpresources.zip"
|
||||||
|
|
||||||
|
type openconnectivitydotorg struct {
|
||||||
|
DocPath string // Optional - Glob to the related documentation about the DCP.
|
||||||
|
SpecsURL string // The HTTP location of the zip archive containing all XML spec.
|
||||||
|
XMLSpecZipPath string // Glob to the zip XML spec file within upnpresources.zip.
|
||||||
|
// Glob to the services XML files within the ZIP matching XMLSpecZipPath.
|
||||||
|
XMLServicePath []string
|
||||||
|
// Glob to the devices XML files within the ZIP matching XMLSpecZipPath.
|
||||||
|
XMLDevicePath []string
|
||||||
|
// Any special-case functions to run against the DCP before writing it out.
|
||||||
|
Hacks []DCPHackFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o openconnectivitydotorg) process(tmpdir, name string, dcp *DCP) error {
|
||||||
|
fname := filepath.Base(name)
|
||||||
|
allSpecsFilename := filepath.Join(tmpdir, "openconnectivitydotorg_"+fname+".zip")
|
||||||
|
err := acquireFile(allSpecsFilename, o.SpecsURL)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not acquire specs %s: %v", name, err)
|
||||||
|
}
|
||||||
|
allSpecsArchive, err := zip.OpenReader(allSpecsFilename)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading zip file %q: %v", allSpecsFilename, err)
|
||||||
|
}
|
||||||
|
specsArchives := globFiles(o.XMLSpecZipPath, allSpecsArchive.File)
|
||||||
|
if len(specsArchives) < 1 {
|
||||||
|
return fmt.Errorf("zip archive %q does not contain specifications at %q", allSpecsFilename, o.XMLSpecZipPath)
|
||||||
|
}
|
||||||
|
for _, specArchive := range specsArchives {
|
||||||
|
f, err := specArchive.Open()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading zip file %q: %v", specArchive.Name, err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
b, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
archive, err := zip.NewReader(bytes.NewReader(b), specArchive.FileInfo().Size())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading zip file %q: %v", specArchive.Name, err)
|
||||||
|
}
|
||||||
|
if err := dcp.processZipFile(archive.File, o.XMLDevicePath, o.XMLServicePath); err != nil {
|
||||||
|
return fmt.Errorf("error processing spec file %q: %v", specArchive.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, hack := range o.Hacks {
|
||||||
|
if err := hack(dcp); err != nil {
|
||||||
|
return fmt.Errorf("error with Hack[%d] for %s: %v", i, name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, d := range globFiles(o.DocPath, allSpecsArchive.File) {
|
||||||
|
dcp.DocURLs = append(dcp.DocURLs, d.Name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
// Client for UPnP Device Control Protocol MediaServer v1 and MediaRenderer v1.
|
// Client for UPnP Device Control Protocol MediaServer v1 and MediaRenderer v1.
|
||||||
//
|
//
|
||||||
// This DCP is documented in detail at: http://upnp.org/specs/av/av1/
|
// This DCP is documented in detail at:
|
||||||
|
// - http://upnp.org/specs/av/av1/
|
||||||
//
|
//
|
||||||
// Typically, use one of the New* functions to create clients for services.
|
// Typically, use one of the New* functions to create clients for services.
|
||||||
package av1
|
package av1
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Client for UPnP Device Control Protocol Internet Gateway Device v1.
|
// Client for UPnP Device Control Protocol Internet Gateway Device v1.
|
||||||
//
|
//
|
||||||
// This DCP is documented in detail at: http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf
|
// This DCP is documented in detail at:
|
||||||
|
// - http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf
|
||||||
//
|
//
|
||||||
// Typically, use one of the New* functions to create clients for services.
|
// Typically, use one of the New* functions to create clients for services.
|
||||||
package internetgateway1
|
package internetgateway1
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Client for UPnP Device Control Protocol Internet Gateway Device v2.
|
// Client for UPnP Device Control Protocol Internet Gateway Device v2.
|
||||||
//
|
//
|
||||||
// This DCP is documented in detail at: http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v2-Device.pdf
|
// This DCP is documented in detail at:
|
||||||
|
// - http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v2-Device.pdf
|
||||||
//
|
//
|
||||||
// Typically, use one of the New* functions to create clients for services.
|
// Typically, use one of the New* functions to create clients for services.
|
||||||
package internetgateway2
|
package internetgateway2
|
||||||
|
2
dcps/ocf/internetgateway2/gen.go
Normal file
2
dcps/ocf/internetgateway2/gen.go
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
//go:generate goupnpdcpgen -dcp_name ocf/internetgateway2
|
||||||
|
package internetgateway2
|
6158
dcps/ocf/internetgateway2/internetgateway2.go
Normal file
6158
dcps/ocf/internetgateway2/internetgateway2.go
Normal file
File diff suppressed because it is too large
Load Diff
2
go.sum
2
go.sum
@ -1,6 +1,4 @@
|
|||||||
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150 h1:vlNjIqmUZ9CMAWsbURYl3a6wZbw7q5RHVvlXTNS/Bs8=
|
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150 h1:vlNjIqmUZ9CMAWsbURYl3a6wZbw7q5RHVvlXTNS/Bs8=
|
||||||
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
|
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
Loading…
Reference in New Issue
Block a user