当前位置: 首页 > article >正文

aioice里面candidate固定UDP端口测试

环境:

aioice0.9.0

问题描述:

aioice里面candidate固定UDP端口测试

解决方案:

/miniconda3/envs/nerfstream/lib/python3.10/site-packages/aioice

import hashlib
import ipaddress
import random
from typing import Optional
import logging

# 配置日志级别,默认为 INFO,可改为 DEBUG 查看详细调试信息
logging.basicConfig(level=logging.INFO)

class Candidate:
    """
    表示一个 ICE 候选者,包括固定端口功能和多种优化。
    """
    FIXED_PORT = 59990  # 定义固定端口

    def __init__(
        self,
        foundation: str,
        component: int,
        transport: str,
        priority: int,
        host: str,
        port: Optional[int] = None,  # 端口可以是 None,将被替换为固定端口
        type: str = "host",
        related_address: Optional[str] = None,
        related_port: Optional[int] = None,
        tcptype: Optional[str] = None,
        generation: Optional[int] = None,
    ) -> None:
        """
        初始化候选者对象,并强制使用固定端口。
        """
        self.foundation = foundation
        self.component = component
        self.transport = transport
        self.priority = priority
        self.host = host
        self.port = self.get_fixed_port() if port is None else port  # 设置为固定端口或提供的端口
        self.type = type
        self.related_address = related_address
        self.related_port = related_port
        self.tcptype = tcptype
        self.generation = generation

        # 输出候选者信息到日志
        logging.info(f"创建候选者:host={self.host}, port={self.port}, type={self.type}")

    @classmethod
    def get_fixed_port(cls) -> int:
        """
        返回固定端口值,并记录日志。
        """
        fixed_port = cls.FIXED_PORT
        logging.debug(f"Returning fixed port: {fixed_port}")
        return fixed_port

    @classmethod
    def from_sdp(cls, sdp: str):
        """
        从 SDP 字符串中解析一个 ICE 候选者。

        示例 SDP:
        '6815297761 1 udp 659136 192.168.1.1 12345 typ host'
        """
        bits = sdp.split()
        if len(bits) < 8:
            raise ValueError("SDP 描述字段不足")

        kwargs = {
            "foundation": bits[0],
            "component": int(bits[1]),
            "transport": bits[2],
            "priority": int(bits[3]),
            "host": bits[4],
            "port": cls.get_fixed_port(),  # 使用固定端口
            "type": bits[7],
        }

        # 提取 SDP 中的附加信息
        for i in range(8, len(bits), 2):
            if bits[i] == "raddr":
                kwargs["related_address"] = bits[i + 1]
            elif bits[i] == "rport":
                kwargs["related_port"] = int(bits[i + 1])
            elif bits[i] == "tcptype":
                kwargs["tcptype"] = bits[i + 1]
            elif bits[i] == "generation":
                kwargs["generation"] = int(bits[i + 1])

        return cls(**kwargs)

    def to_sdp(self) -> str:
        """
        返回一个适用于 SDP 的字符串表示形式。
        """
        sdp = f"{self.foundation} {self.component} {self.transport} {self.priority} {self.host} {self.port} typ {self.type}"
        if self.related_address is not None:
            sdp += f" raddr {self.related_address}"
        if self.related_port is not None:
            sdp += f" rport {self.related_port}"
        if self.tcptype is not None:
            sdp += f" tcptype {self.tcptype}"
        if self.generation is not None:
            sdp += f" generation {self.generation}"
        return sdp

    def can_pair_with(self, other) -> bool:
        """
        判断本地候选者是否可以与远程候选者配对。

        配对条件:
        - 组件相同
        - 使用相同的传输协议
        - IP 地址版本相同
        """
        a = ipaddress.ip_address(self.host)
        b = ipaddress.ip_address(other.host)
        return (
            self.component == other.component
            and self.transport.lower() == other.transport.lower()
            and a.version == b.version
        )

    def __repr__(self) -> str:
        """
        返回候选者的字符串表示形式。
        """
        return f"Candidate({self.to_sdp()})"


# 工具函数部分
def candidate_foundation(candidate_type: str, candidate_transport: str, base_address: str) -> str:
    """
    计算候选者的 Foundation(基础标识符)。
    """
    key = f"{candidate_type}|{candidate_transport}|{base_address}"
    return hashlib.md5(key.encode("ascii")).hexdigest()


def candidate_priority(candidate_component: int, candidate_type: str, local_pref: int = 65535) -> int:
    """
    计算候选者优先级。
    优先级从高到低的顺序为:host > srflx > relay。
    """
    type_preferences = {
        "host": 126,   # Host 类型优先级最高
        "srflx": 100,  # Server reflexive 类型
        "relay": 0,    # Relay 类型优先级最低
    }
    type_pref = type_preferences.get(candidate_type, 0)
    return (1 << 24) * type_pref + (1 << 8) * local_pref + (256 - candidate_component)


# 测试代码部分
if __name__ == "__main__":
    # 测试创建候选者
    candidate = Candidate(
        foundation="1",
        component=1,
        transport="udp",
        priority=candidate_priority(1, "host"),
        host="192.168.168.77",  # 使用你的本地 IP 地址
        type="host",
    )
    print(candidate)  # 打印候选者信息
    print(candidate.to_sdp())  # 打印 SDP 字符串

    # 测试从 SDP 创建候选者
    sdp_example = "1 1 udp 100 192.168.1.1 12345 typ host"
    candidate_from_sdp = Candidate.from_sdp(sdp_example)
    print(candidate_from_sdp)  # 打印解析后的候选者
    print(candidate_from_sdp.to_sdp())  # 打印 SDP 字符串

    # 模拟 WebRTC 应用程序创建多个候选者
    candidates = [
        Candidate(
            foundation=str(i),
            component=1,
            transport="udp",
            priority=candidate_priority(1, "host"),
            host=f"192.168.1.{i % 255}",  # 使用不同的 IP 地址模拟不同设备
            type="host",
        )
        for i in range(1, 6)
    ]
    for c in candidates:
        print(c)

运行没有成功

在这里插入图片描述


http://www.kler.cn/a/446154.html

相关文章:

  • 线程知识总结(一)
  • 技术文档的规划布局:打造清晰且有条理的知识传递框架
  • 怿星科技联合赛力斯举办workshop活动,进一步推动双方合作
  • PC寄存器(Program Counter Register) jvm
  • Pygubu-Designer 使用指南
  • 基于Arduino的平衡车机械臂
  • 本地maven项目打包部署到maven远程私库
  • skyler实战渗透笔记—Kioptrix-2
  • 2.2.2 进程通信
  • Vue.js前端框架教程5:Vue数据拷贝和数组函数
  • 如何利用Java爬虫获得1688商品详情
  • clickhouse-介绍、安装、数据类型、sql
  • RTMP、RTSP、RTP、HLS、MPEG-DASH协议的简介,以及应用场景
  • 本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——11上位机与小车交互
  • Unity Runtime控制编辑器的一些操作
  • 如何用Redis实现分布式锁?
  • 账号安全再升级!跨境卫士的网页元素控制功能详解
  • 【单片机】IIC需要注意什么(企业级回答)
  • 使用RTP 协议 对 H264 封包和解包
  • 浏览器可以直接请求 websocket
  • 基于springboot+vue实现的医院急诊(病房)管理系统 (源码+L文+ppt)4-122
  • 变量的作用域和生命周期
  • docker pull失败处理
  • 人脸生成3d模型 Era3D
  • 【漏洞复现】CVE-2023-37461 Arbitrary File Writing
  • Web3.0安全开发实践:探索比特币DeFi生态中的PSBT