mirror of
https://gitee.com/konyshe/goodlink.git
synced 2025-09-26 20:51:22 +08:00
122 lines
3.0 KiB
Go
122 lines
3.0 KiB
Go
package upnp
|
|
|
|
import (
|
|
"log"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
// "net/http"
|
|
)
|
|
|
|
type Gateway struct {
|
|
GatewayName string //网关名称
|
|
Host string //网关ip和端口
|
|
DeviceDescUrl string //网关设备描述路径
|
|
Cache string //cache
|
|
ST string
|
|
USN string
|
|
deviceType string //设备的urn "urn:schemas-upnp-org:service:WANIPConnection:1"
|
|
ControlURL string //设备端口映射请求路径
|
|
ServiceType string //提供upnp服务的服务类型
|
|
}
|
|
|
|
type SearchGateway struct {
|
|
searchMessage string
|
|
upnp *Upnp
|
|
}
|
|
|
|
func (this *SearchGateway) Send() bool {
|
|
this.buildRequest()
|
|
c := make(chan string)
|
|
go this.send(c)
|
|
result := <-c
|
|
if result == "" {
|
|
//超时了
|
|
this.upnp.Active = false
|
|
return false
|
|
}
|
|
this.resolve(result)
|
|
|
|
this.upnp.Gateway.ServiceType = "urn:schemas-upnp-org:service:WANIPConnection:1"
|
|
this.upnp.Active = true
|
|
return true
|
|
}
|
|
func (this *SearchGateway) send(c chan string) {
|
|
//发送组播消息,要带上端口,格式如:"239.255.255.250:1900"
|
|
var conn *net.UDPConn
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
//超时了
|
|
}
|
|
}()
|
|
go func(conn *net.UDPConn) {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
//没超时
|
|
}
|
|
}()
|
|
//超时时间为3秒
|
|
time.Sleep(time.Second * 3)
|
|
c <- ""
|
|
conn.Close()
|
|
}(conn)
|
|
remotAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
|
|
if err != nil {
|
|
log.Println("组播地址格式不正确")
|
|
}
|
|
locaAddr, err := net.ResolveUDPAddr("udp", this.upnp.LocalHost+":")
|
|
|
|
if err != nil {
|
|
log.Println("本地ip地址格式不正确")
|
|
}
|
|
conn, err = net.ListenUDP("udp", locaAddr)
|
|
defer conn.Close()
|
|
if err != nil {
|
|
log.Println("监听udp出错")
|
|
}
|
|
_, err = conn.WriteToUDP([]byte(this.searchMessage), remotAddr)
|
|
if err != nil {
|
|
log.Println("发送msg到组播地址出错")
|
|
}
|
|
buf := make([]byte, 1024)
|
|
n, _, err := conn.ReadFromUDP(buf)
|
|
if err != nil {
|
|
log.Println("从组播地址接搜消息出错")
|
|
}
|
|
|
|
result := string(buf[:n])
|
|
c <- result
|
|
}
|
|
func (this *SearchGateway) buildRequest() {
|
|
this.searchMessage = "M-SEARCH * HTTP/1.1\r\n" +
|
|
"HOST: 239.255.255.250:1900\r\n" +
|
|
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
|
|
"MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n"
|
|
}
|
|
|
|
func (this *SearchGateway) resolve(result string) {
|
|
this.upnp.Gateway = &Gateway{}
|
|
|
|
lines := strings.Split(result, "\r\n")
|
|
for _, line := range lines {
|
|
//按照第一个冒号分为两个字符串
|
|
nameValues := strings.SplitAfterN(line, ":", 2)
|
|
if len(nameValues) < 2 {
|
|
continue
|
|
}
|
|
switch strings.ToUpper(strings.Trim(strings.Split(nameValues[0], ":")[0], " ")) {
|
|
case "ST":
|
|
this.upnp.Gateway.ST = nameValues[1]
|
|
case "CACHE-CONTROL":
|
|
this.upnp.Gateway.Cache = nameValues[1]
|
|
case "LOCATION":
|
|
urls := strings.Split(strings.Split(nameValues[1], "//")[1], "/")
|
|
this.upnp.Gateway.Host = urls[0]
|
|
this.upnp.Gateway.DeviceDescUrl = "/" + urls[1]
|
|
case "SERVER":
|
|
this.upnp.Gateway.GatewayName = nameValues[1]
|
|
default:
|
|
}
|
|
}
|
|
}
|