goupnp/v2alpha/cmd/goupnp2srvgen/main.go
2022-05-27 07:10:15 +01:00

125 lines
2.7 KiB
Go

package main
import (
"encoding/xml"
"errors"
"flag"
"fmt"
"os"
"strings"
"github.com/huin/goupnp/v2alpha/cmd/goupnp2srvgen/zipread"
"github.com/huin/goupnp/v2alpha/description/srvdesc"
"github.com/huin/goupnp/v2alpha/description/xmlsrvdesc"
)
var (
upnpresourcesZip = flag.String("upnpresources_zip", "", "Path to upnpresources.zip.")
)
func main() {
flag.Parse()
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}
func run() error {
if len(flag.Args()) > 0 {
return fmt.Errorf("unused arguments: %s", strings.Join(flag.Args(), " "))
}
if *upnpresourcesZip == "" {
return errors.New("-upnpresources_zip is a required flag.")
}
f, err := os.Open(*upnpresourcesZip)
if err != nil {
return err
}
defer f.Close()
upnpresources, err := zipread.FromOsFile(f)
if err != nil {
return err
}
for _, m := range manifests {
if err := processDCP(upnpresources, m); err != nil {
return fmt.Errorf("processing DCP %s: %w", m.Path, err)
}
}
return nil
}
var manifests = []*DCPSpecManifest{
{
Path: "standardizeddcps/Internet Gateway_2/UPnP-gw-IGD-TestFiles-20101210.zip",
Services: map[string]string{
"LANHostConfigManagement:1": "xml data files/service/LANHostConfigManagement1.xml",
"WANPPPConnection:1": "xml data files/service/WANPPPConnection1.xml",
},
},
}
func processDCP(
upnpresources *zipread.ZipRead,
manifest *DCPSpecManifest,
) error {
dcpSpecData, err := upnpresources.OpenZip(manifest.Path)
if err != nil {
return err
}
for name, path := range manifest.Services {
if err := processService(dcpSpecData, name, path); err != nil {
return fmt.Errorf("processing service %s: %w", name, err)
}
}
return nil
}
func processService(
dcpSpecData *zipread.ZipRead,
name string,
path string,
) error {
fmt.Printf("%s\n", name)
f, err := dcpSpecData.Open(path)
if err != nil {
return err
}
defer f.Close()
d := xml.NewDecoder(f)
xmlSCPD := &xmlsrvdesc.SCPD{}
if err := d.Decode(xmlSCPD); err != nil {
return err
}
xmlSCPD.Clean()
for _, action := range xmlSCPD.Actions {
fmt.Printf("* %s()\n", action.Name)
for _, arg := range action.Arguments {
direction := "?"
if arg.Direction == "in" {
direction = "<-"
} else if arg.Direction == "out" {
direction = "->"
}
fmt.Printf(" %s %s %s\n", direction, arg.Name, arg.RelatedStateVariable)
}
}
_, err = srvdesc.FromXML(xmlSCPD)
if err != nil {
return err
}
return nil
}
type DCPSpecManifest struct {
// Path is the file path within upnpresources.zip to the DCP spec ZIP file.
Path string
// Services maps from a service name (e.g. "FooBar:1") to a path within the DCP spec ZIP file
// (e.g. "xml data files/service/FooBar1.xml").
Services map[string]string
}