代码拉取完成,页面将自动刷新
package upnp
import (
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
// FROM: http://upnp.org/specs/arch/UPnP-arch-DeviceArchitecture-v1.1.pdf
// Service description section, only include REQUIRED fields
type srvResponse struct {
// configuration number to which the device description belongs
ConfigID string `xml:"configId,attr"`
// version templates
SpecVersion specVersionType `xml:"specVersion"`
// action list
ActionList []actionType `xml:"actionList>action"`
// state table
StatesTable []stateType `xml:"serviceStateTable>stateVariable"`
}
type actionType struct {
// action name
Name string `xml:"name"`
// agrument list
Arguments []argumentType `xml:"argumentList>argument"`
}
type argumentType struct {
// argument name
Name string `xml:"name"`
// must be in or out
Direction string `xml:"direction"`
// TODO: comment
RelatedStateVariable string `xml:"relatedStateVariable"`
}
type stateType struct {
// state name
Name string `xml:"name"`
// state type
Type string `xml:"dataType"`
}
// Service service
type Service struct {
ID string
// scpd url in full
scpd string
// control url in full
ctl string
// event url in full
event string
// service type
stype string
// action list
actions []Action
parsed bool
}
func (d *Device) loadService(dev deviceType) error {
for _, s := range dev.ServiceList {
s.SCPDURL = strings.TrimPrefix(s.SCPDURL, "/")
s.ControlURL = strings.TrimPrefix(s.ControlURL, "/")
s.EventSubURL = strings.TrimPrefix(s.EventSubURL, "/")
d.serviceList = append(d.serviceList, &Service{
ID: s.ServiceID,
scpd: d.urlPrefix + "/" + s.SCPDURL,
ctl: d.urlPrefix + "/" + s.ControlURL,
event: d.urlPrefix + "/" + s.EventSubURL,
stype: s.ServiceType,
})
}
if len(dev.DeviceList) > 0 {
for _, sub := range dev.DeviceList {
if err := d.loadService(sub); err != nil {
return err
}
}
}
return nil
}
func getActArgs(action actionType, key string) []string {
var ret []string
for _, arg := range action.Arguments {
if arg.Direction == key {
ret = append(ret, arg.Name)
}
}
return ret
}
func (s *Service) parse() error {
resp, err := http.Get(s.scpd)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
data, _ := ioutil.ReadAll(resp.Body)
return fmt.Errorf("GET scpd info fail, http_code=%d\n%s", resp.StatusCode, string(data))
}
var srv srvResponse
if err := xml.NewDecoder(resp.Body).Decode(&srv); err != nil {
return err
}
for _, act := range srv.ActionList {
switch act.Name {
case "GetGenericPortMappingEntry":
s.actions = append(s.actions,
newGetPortMappingAction(s, getActArgs(act, "in"), getActArgs(act, "out")))
case "AddPortMapping":
s.actions = append(s.actions,
newAddPortMappingAction(s, getActArgs(act, "in"), getActArgs(act, "out")))
case "DeletePortMapping":
s.actions = append(s.actions,
newDeletePortMappingAction(s, getActArgs(act, "in"), getActArgs(act, "out")))
case "GetExternalIPAddress":
s.actions = append(s.actions,
newGetExtIPAction(s, getActArgs(act, "in"), getActArgs(act, "out")))
}
}
// data, _ := json.MarshalIndent(srv, "", " ")
// fmt.Println(string(data))
s.parsed = true
return nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。