goonvif/onvif/ws-discovery/networking.go

96 lines
2.7 KiB
Go

package wsdiscovery
/*******************************************************
* Copyright (C) 2018 Palanjyan Zhorzhik
*
* This file is part of ws-discovery project.
*
* ws-discovery can be copied and/or distributed without the express
* permission of Palanjyan Zhorzhik
*******************************************************/
import (
"errors"
"net"
"os"
"time"
"github.com/gofrs/uuid"
"golang.org/x/net/ipv4"
)
const bufSize = 8192
//SendProbe to device
func SendProbe(interfaceName string, scopes, types []string, namespaces map[string]string) ([]string, error) {
// Creating UUID Version 4
uuidV4 := uuid.Must(uuid.NewV4())
//fmt.Printf("UUIDv4: %s\n", uuidV4)
probeSOAP := buildProbeMessage(uuidV4.String(), scopes, types, namespaces)
//probeSOAP = `<?xml version="1.0" encoding="UTF-8"?>
//<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing">
//<Header>
//<a:Action mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action>
//<a:MessageID>uuid:78a2ed98-bc1f-4b08-9668-094fcba81e35</a:MessageID><a:ReplyTo>
//<a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
//</a:ReplyTo><a:To mustUnderstand="1">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To>
//</Header>
//<Body><Probe xmlns="http://schemas.xmlsoap.org/ws/2005/04/discovery">
//<d:Types xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:dp0="http://www.onvif.org/ver10/network/wsdl">dp0:NetworkVideoTransmitter</d:Types>
//</Probe>
//</Body>
//</Envelope>`
return sendUDPMulticast(probeSOAP.String(), interfaceName)
}
func sendUDPMulticast(msg string, interfaceName string) ([]string, error) {
c, err := net.ListenPacket("udp4", "0.0.0.0:0")
if err != nil {
return nil, err
}
defer c.Close()
iface, err := net.InterfaceByName(interfaceName)
if err != nil {
return nil, err
}
p := ipv4.NewPacketConn(c)
group := net.IPv4(239, 255, 255, 250)
if err := p.JoinGroup(iface, &net.UDPAddr{IP: group}); err != nil {
return nil, err
}
dst := &net.UDPAddr{IP: group, Port: 3702}
data := []byte(msg)
for _, ifi := range []*net.Interface{iface} {
if err := p.SetMulticastInterface(ifi); err != nil {
return nil, err
}
p.SetMulticastTTL(2)
if _, err := p.WriteTo(data, nil, dst); err != nil {
return nil, err
}
}
if err := p.SetReadDeadline(time.Now().Add(time.Second * 1)); err != nil {
return nil, err
}
var result []string
for {
b := make([]byte, bufSize)
n, _, _, err := p.ReadFrom(b)
if err != nil {
if !errors.Is(err, os.ErrDeadlineExceeded) {
return nil, err
}
break
}
result = append(result, string(b[0:n]))
}
return result, nil
}