mirror of
				https://github.com/aler9/gortsplib
				synced 2025-10-31 10:36:26 +08:00 
			
		
		
		
	multicast: add readOnly flag (#423)
This commit is contained in:
		| @@ -25,6 +25,7 @@ type MultiConn struct { | ||||
| // NewMultiConn allocates a MultiConn. | ||||
| func NewMultiConn( | ||||
| 	address string, | ||||
| 	readOnly bool, | ||||
| 	listenPacket func(network, address string) (net.PacketConn, error), | ||||
| ) (Conn, error) { | ||||
| 	addr, err := net.ResolveUDPAddr("udp4", address) | ||||
| @@ -67,42 +68,47 @@ func NewMultiConn( | ||||
| 		return nil, fmt.Errorf("no multicast-capable interfaces found") | ||||
| 	} | ||||
|  | ||||
| 	writeConns := make([]*net.UDPConn, len(enabledInterfaces)) | ||||
| 	writeConnIPs := make([]*ipv4.PacketConn, len(enabledInterfaces)) | ||||
| 	var writeConns []*net.UDPConn | ||||
| 	var writeConnIPs []*ipv4.PacketConn | ||||
|  | ||||
| 	for i, intf := range enabledInterfaces { | ||||
| 		tmp, err := listenPacket("udp4", "224.0.0.0:"+strconv.FormatInt(int64(addr.Port), 10)) | ||||
| 		if err != nil { | ||||
| 			for j := 0; j < i; j++ { | ||||
| 				writeConns[j].Close() //nolint:errcheck | ||||
| 	if !readOnly { | ||||
| 		writeConns = make([]*net.UDPConn, len(enabledInterfaces)) | ||||
| 		writeConnIPs = make([]*ipv4.PacketConn, len(enabledInterfaces)) | ||||
|  | ||||
| 		for i, intf := range enabledInterfaces { | ||||
| 			tmp, err := listenPacket("udp4", "224.0.0.0:"+strconv.FormatInt(int64(addr.Port), 10)) | ||||
| 			if err != nil { | ||||
| 				for j := 0; j < i; j++ { | ||||
| 					writeConns[j].Close() //nolint:errcheck | ||||
| 				} | ||||
| 				readConn.Close() //nolint:errcheck | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			readConn.Close() //nolint:errcheck | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		writeConn := tmp.(*net.UDPConn) | ||||
| 			writeConn := tmp.(*net.UDPConn) | ||||
|  | ||||
| 		writeConnIP := ipv4.NewPacketConn(writeConn) | ||||
| 			writeConnIP := ipv4.NewPacketConn(writeConn) | ||||
|  | ||||
| 		err = writeConnIP.SetMulticastInterface(intf) | ||||
| 		if err != nil { | ||||
| 			for j := 0; j < i; j++ { | ||||
| 				writeConns[j].Close() //nolint:errcheck | ||||
| 			err = writeConnIP.SetMulticastInterface(intf) | ||||
| 			if err != nil { | ||||
| 				for j := 0; j < i; j++ { | ||||
| 					writeConns[j].Close() //nolint:errcheck | ||||
| 				} | ||||
| 				readConn.Close() //nolint:errcheck | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			readConn.Close() //nolint:errcheck | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		err = writeConnIP.SetMulticastTTL(multicastTTL) | ||||
| 		if err != nil { | ||||
| 			for j := 0; j < i; j++ { | ||||
| 				writeConns[j].Close() //nolint:errcheck | ||||
| 			err = writeConnIP.SetMulticastTTL(multicastTTL) | ||||
| 			if err != nil { | ||||
| 				for j := 0; j < i; j++ { | ||||
| 					writeConns[j].Close() //nolint:errcheck | ||||
| 				} | ||||
| 				readConn.Close() //nolint:errcheck | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			readConn.Close() //nolint:errcheck | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		writeConns[i] = writeConn | ||||
| 		writeConnIPs[i] = writeConnIP | ||||
| 			writeConns[i] = writeConn | ||||
| 			writeConnIPs[i] = writeConnIP | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return &MultiConn{ | ||||
|   | ||||
| @@ -24,6 +24,7 @@ type MultiConn struct { | ||||
| // NewMultiConn allocates a MultiConn. | ||||
| func NewMultiConn( | ||||
| 	address string, | ||||
| 	readOnly bool, | ||||
| 	_ func(network, address string) (net.PacketConn, error), | ||||
| ) (Conn, error) { | ||||
| 	addr, err := net.ResolveUDPAddr("udp4", address) | ||||
| @@ -84,76 +85,82 @@ func NewMultiConn( | ||||
| 		return nil, fmt.Errorf("no multicast-capable interfaces found") | ||||
| 	} | ||||
|  | ||||
| 	writeSocks := make([]int, len(enabledInterfaces)) | ||||
| 	var writeFiles []*os.File | ||||
| 	var writeConns []net.PacketConn | ||||
|  | ||||
| 	for i, intf := range enabledInterfaces { | ||||
| 		writeSock, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) | ||||
| 		if err != nil { | ||||
| 			for j := 0; j < i; j++ { | ||||
| 				syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 	if !readOnly { | ||||
| 		writeSocks := make([]int, len(enabledInterfaces)) | ||||
|  | ||||
| 		for i, intf := range enabledInterfaces { | ||||
| 			writeSock, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP) | ||||
| 			if err != nil { | ||||
| 				for j := 0; j < i; j++ { | ||||
| 					syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 				} | ||||
| 				syscall.Close(readSock) //nolint:errcheck | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			syscall.Close(readSock) //nolint:errcheck | ||||
| 			return nil, err | ||||
|  | ||||
| 			err = syscall.SetsockoptInt(writeSock, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) | ||||
| 			if err != nil { | ||||
| 				syscall.Close(writeSock) //nolint:errcheck | ||||
| 				for j := 0; j < i; j++ { | ||||
| 					syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 				} | ||||
| 				syscall.Close(readSock) //nolint:errcheck | ||||
| 				return nil, err | ||||
| 			} | ||||
|  | ||||
| 			var lsa syscall.SockaddrInet4 | ||||
| 			lsa.Port = addr.Port | ||||
| 			copy(lsa.Addr[:], addr.IP.To4()) | ||||
| 			err = syscall.Bind(writeSock, &lsa) | ||||
| 			if err != nil { | ||||
| 				syscall.Close(writeSock) //nolint:errcheck | ||||
| 				for j := 0; j < i; j++ { | ||||
| 					syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 				} | ||||
| 				syscall.Close(readSock) //nolint:errcheck | ||||
| 				return nil, err | ||||
| 			} | ||||
|  | ||||
| 			var mreqn syscall.IPMreqn | ||||
| 			mreqn.Ifindex = int32(intf.Index) | ||||
|  | ||||
| 			err = syscall.SetsockoptIPMreqn(writeSock, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, &mreqn) | ||||
| 			if err != nil { | ||||
| 				syscall.Close(writeSock) //nolint:errcheck | ||||
| 				for j := 0; j < i; j++ { | ||||
| 					syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 				} | ||||
| 				syscall.Close(readSock) //nolint:errcheck | ||||
| 				return nil, err | ||||
| 			} | ||||
|  | ||||
| 			err = syscall.SetsockoptInt(writeSock, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, multicastTTL) | ||||
| 			if err != nil { | ||||
| 				syscall.Close(writeSock) //nolint:errcheck | ||||
| 				for j := 0; j < i; j++ { | ||||
| 					syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 				} | ||||
| 				syscall.Close(readSock) //nolint:errcheck | ||||
| 				return nil, err | ||||
| 			} | ||||
|  | ||||
| 			writeSocks[i] = writeSock | ||||
| 		} | ||||
|  | ||||
| 		err = syscall.SetsockoptInt(writeSock, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) | ||||
| 		if err != nil { | ||||
| 			syscall.Close(writeSock) //nolint:errcheck | ||||
| 			for j := 0; j < i; j++ { | ||||
| 				syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 			} | ||||
| 			syscall.Close(readSock) //nolint:errcheck | ||||
| 			return nil, err | ||||
| 		writeFiles = make([]*os.File, len(writeSocks)) | ||||
| 		writeConns = make([]net.PacketConn, len(writeSocks)) | ||||
|  | ||||
| 		for i, writeSock := range writeSocks { | ||||
| 			writeFiles[i] = os.NewFile(uintptr(writeSock), "") | ||||
| 			writeConns[i], _ = net.FilePacketConn(writeFiles[i]) | ||||
| 		} | ||||
|  | ||||
| 		var lsa syscall.SockaddrInet4 | ||||
| 		lsa.Port = addr.Port | ||||
| 		copy(lsa.Addr[:], addr.IP.To4()) | ||||
| 		err = syscall.Bind(writeSock, &lsa) | ||||
| 		if err != nil { | ||||
| 			syscall.Close(writeSock) //nolint:errcheck | ||||
| 			for j := 0; j < i; j++ { | ||||
| 				syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 			} | ||||
| 			syscall.Close(readSock) //nolint:errcheck | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		var mreqn syscall.IPMreqn | ||||
| 		mreqn.Ifindex = int32(intf.Index) | ||||
|  | ||||
| 		err = syscall.SetsockoptIPMreqn(writeSock, syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, &mreqn) | ||||
| 		if err != nil { | ||||
| 			syscall.Close(writeSock) //nolint:errcheck | ||||
| 			for j := 0; j < i; j++ { | ||||
| 				syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 			} | ||||
| 			syscall.Close(readSock) //nolint:errcheck | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		err = syscall.SetsockoptInt(writeSock, syscall.IPPROTO_IP, syscall.IP_MULTICAST_TTL, multicastTTL) | ||||
| 		if err != nil { | ||||
| 			syscall.Close(writeSock) //nolint:errcheck | ||||
| 			for j := 0; j < i; j++ { | ||||
| 				syscall.Close(writeSocks[j]) //nolint:errcheck | ||||
| 			} | ||||
| 			syscall.Close(readSock) //nolint:errcheck | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		writeSocks[i] = writeSock | ||||
| 	} | ||||
|  | ||||
| 	readFile := os.NewFile(uintptr(readSock), "") | ||||
| 	readConn, _ := net.FilePacketConn(readFile) | ||||
| 	writeFiles := make([]*os.File, len(writeSocks)) | ||||
| 	writeConns := make([]net.PacketConn, len(writeSocks)) | ||||
|  | ||||
| 	for i, writeSock := range writeSocks { | ||||
| 		writeFiles[i] = os.NewFile(uintptr(writeSock), "") | ||||
| 		writeConns[i], _ = net.FilePacketConn(writeFiles[i]) | ||||
| 	} | ||||
|  | ||||
| 	return &MultiConn{ | ||||
| 		addr:       addr, | ||||
|   | ||||
| @@ -76,7 +76,7 @@ func newServerUDPListener( | ||||
| 	var listenIP net.IP | ||||
| 	if multicastEnable { | ||||
| 		var err error | ||||
| 		pc, err = multicast.NewMultiConn(address, listenPacket) | ||||
| 		pc, err = multicast.NewMultiConn(address, false, listenPacket) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Alessandro Ros
					Alessandro Ros