live555对ipv6的扩展

从live555的官网看live555的发展历史,实在是历史悠久,保守估计已经发展了至少16年以上了,同时,这也导致了live555在很多架构和考虑上面不能满足现代化的多线程、ipv6方面的需求,虽然官方也开启了对ipv6功能支持的众筹,但是已经很久了,预计很长时间内是不会有这个计划支持了,因为要改动的地方还真是蛮多的:

,在上一期中我们已经为live555的多线程开了个头《经过两个多月的攻关,终于搞定了live555多线程并稳定压测通过》,今天我们要来聊一下我们在live555扩展IPv6方面是怎么做到的!

设计过程

IPV4 地址

rtsp://192.168.1.100:554/ch1

rtsp://admin:12345@192.168.1.100:554/ch1

IPV6 地址

rtsp://[2001:0:9d38:953c:38b0:d177:88d8:a5e0]:554/ch1

rtsp://admin:12345@[2001:0:9d38:953c:38b0:d177:88d8:a5e0]:554/ch1

支持IPv6修改步骤

增加live_ipv4_ipv6.h和live_ipv4_ipv6.cpp两个文件

用途: 在live所有用到类型为netAddressBits的文件中,包含该头文件,针对ipv4和ipv6进行不同的处理;

live_ipv4_ipv6.h

#ifndef __LIVE_IPV4_IPV6
#define __LIVE_IPV4_IPV6 typedef enum LIVE_IPVER_ENUM
{
LIVE_IP_VER_4 = 0,
LIVE_IP_VER_6
}LIVE_IP_VER_ENUM; extern LIVE_IP_VER_ENUM live_ip_ver; #endif

live_ipv4_ipv6.cpp

#include "live_ipv4_ipv6.h"
LIVE_IP_VER_ENUM live_ip_ver = LIVE_IP_VER_6;

NetAddress.hh

增加以下定义, 并注释掉typedef u_int32_t netAddressBits;

typedef struct __LIVE_NET_ADDRESS_INADDR
{
struct in_addr sin_addr;
struct in6_addr sin6_addr; __LIVE_NET_ADDRESS_INADDR()
{
sin_addr.s_addr = INADDR_ANY;
sin6_addr = in6addr_any;
}; }LIVE_NET_ADDRESS_INADDR; //typedef u_int32_t netAddressBits; //注释掉该句,在所有用到netAddressBits的地方,均用LIVE_NET_ADDRESS_INADDR替代; //增加以下定义
typedef struct __LIVE_NET_ADDRESS_SOCKADDR_IN
{
struct sockaddr_in saddr4;
struct sockaddr_in6 saddr6;
}LIVE_NET_ADDRESS_SOCKADDR_IN;

将所有struct in_addr 改为 LIVE_NET_ADDRESS, 除了以下几处:

void AddressString::init(struct in_addr addr)

将所有struct sockaddr_in 改为 LIVE_NET_ADDRESS_SOCKADDR_IN;

在EasyRtspClient中,将调用到LIVE_NET_ADDRESS_SOCKADDR_IN的函数,增加一个参数,用于标识是IPv4还是IPv6;

从调用以下代码开始,进行区分,用于标识该客户端需要使用IPv4还是IPv6进行连接;

Boolean RTSPClient::parseRTSPURL(UsageEnvironment& env, char const* url,
char*& username, char*& password,
NetAddress& address,
portNumBits& portNum,
char const** urlSuffix) { do {
// Parse the URL as "rtsp://[<username>[:<password>]@]<server-address-or-name>[:<port>][/<stream-name>]"
char const* prefix = "rtsp://";
unsigned const prefixLength = 7;
if (_strncasecmp(url, prefix, prefixLength) != 0) {
env.setResultMsg("URL is not of the form \"", prefix, "\"");
break;
} unsigned const parseBufferSize = 100;
char parseBuffer[parseBufferSize] = {0};
char const* from = &url[prefixLength]; // Check whether "<username>[:<password>]@" occurs next.
// We do this by checking whether '@' appears before the end of the URL, or before the first '/'.
username = password = NULL; // default return values
char const* colonPasswordStart = NULL;
char const* p;
//此处检查字符[
for (p = from; *p != '\0' && *p != '/' && *p != '['; ++p) {
if (*p == ':' && colonPasswordStart == NULL) {
colonPasswordStart = p;
} else if (*p == '@') {
// We found <username> (and perhaps <password>). Copy them into newly-allocated result strings:
if (colonPasswordStart == NULL) colonPasswordStart = p; char const* usernameStart = from;
unsigned usernameLen = colonPasswordStart - usernameStart;
username = new char[usernameLen + 1] ; // allow for the trailing '\0'
copyUsernameOrPasswordStringFromURL(username, usernameStart, usernameLen); char const* passwordStart = colonPasswordStart;
if (passwordStart < p) ++passwordStart; // skip over the ':'
unsigned passwordLen = p - passwordStart;
password = new char[passwordLen + 1]; // allow for the trailing '\0'
copyUsernameOrPasswordStringFromURL(password, passwordStart, passwordLen); from = p + 1; // skip over the '@'
break;
}
} // Next, parse <server-address-or-name>
char* to = &parseBuffer[0];
unsigned i; live_ip_ver = LIVE_IP_VER_4; //默认为IPv4
if (*from == '[') //如果地址是以符号[开头,则为IPv6 因为ipv6的地址是以符号[开头
{
live_ip_ver = LIVE_IP_VER_6;
} if (live_ip_ver == LIVE_IP_VER_6)
{
*from ++; // 跳过符号[
for (i = 0; i < parseBufferSize; ++i) {
if (*from == '\0' || *from == ']' || *from == '/') {
// We've completed parsing the address
*to = '\0';
break;
}
*to++ = *from++;
}
if (i == parseBufferSize) {
env.setResultMsg("URL is too long");
break;
} *from ++; // 跳过符号]
}
else //IPV4
{
for (i = 0; i < parseBufferSize; ++i) {
if (*from == '\0' || *from == ':' || *from == '/') {
// We've completed parsing the address
*to = '\0';
break;
}
*to++ = *from++;
}
if (i == parseBufferSize) {
env.setResultMsg("URL is too long");
break;
}
}
//rtsp://[2001:0:9d38:953c:14b3:7a:3f57:fe40]:554/ch1
//strcpy(parseBuffer, "2001:0:9d38:953c:38b0:d177:88d8:a5e0"); NetAddressList addresses(parseBuffer);
if (addresses.numAddresses() == 0) {
env.setResultMsg("Failed to find network address for \"",
parseBuffer, "\"");
break;
}
address = *(addresses.firstAddress()); portNum = 554; // default value char nextChar = *from;
if (nextChar == ':') {
int portNumInt;
if (sscanf(++from, "%d", &portNumInt) != 1) {
env.setResultMsg("No port number follows ':'");
break;
}
if (portNumInt < 1 || portNumInt > 65535) {
env.setResultMsg("Bad port number");
break;
}
portNum = (portNumBits)portNumInt;
while (*from >= '0' && *from <= '9') ++from; // skip over port number
} // The remainder of the URL is the suffix:
if (urlSuffix != NULL) *urlSuffix = from; return True;
} while (0); return False;
}

其中, live_ip_ver 为全局变量,用于标识该IP地址类型;

后面用到struct sockaddr_in 和 struct in_addr 的地方, 使用LIVE_NET_ADDRESS_SOCKADDR_IN来区分,并进行相应的处理;

live555中,就不能使用live_ip_ver这个全局变量了, 因为要同时兼容IPv4和IPv6, 将在下篇说明;

live555技术交流

  • 邮件:289042893@qq.com

  • live555技术交流群:475947825

成功扩展live555支持ipv6,同时支持RTSPServer & RTSPClient的更多相关文章

  1. VC++ IPv6的支持

    最近根据项目需要,要在产品中添加对IpV6的支持,因此研究了一下IPV6的相关内容,Ipv6 与原来最直观的改变就是地址结构的改变,IP地址由原来的32位扩展为128,这样原来的地址结构肯定就不够用了 ...

  2. Azure Load Balancer : 支持 IPv6

    越来越多的网站开始支持 IPv6,即使是哪些只提供 api 服务的站点也需要支持 IPv6,比如苹果应用商店中的 app 早就强制要求服务器端支持 IPv6 了.笔者在前文<Azure Load ...

  3. iOS应用支持IPV6,就那点事儿

    原文连接   果然是苹果打个哈欠,iOS行业内就得起一次风暴呀.自从5月初Apple明文规定所有开发者在6月1号以后提交新版本需要支持IPV6-Only的网络,大家便开始热火朝天的研究如何支持IPV6 ...

  4. iOS应用支持IPV6

    一.IPV6-Only支持是啥? 首先IPV6,是对IPV4地址空间的扩充.目前当我们用iOS设备连接上Wifi.4G.3G等网络时,设备被分配的地址均是IPV4地址,但是随着运营商和企业逐渐部署IP ...

  5. keepalive配置支持ipv6、ipv4双棧支持

    因公司业务需要,keepalived需要同时支持ipv6和ipv4 keepalived版本1.2.23. keepalived 配置: 重点:ipv6的虚IP配置在 virtual_ipaddres ...

  6. 配置阿里云ECS支持IPv6,解决苹果app审核失败问题

    前几天iOS的App提交给苹果审核没通过,给出的原因是:该应用在 IPv6 的环境下无法使用.检查发现:阿里云优化过的系统没有启用IPv6协议,需要配置启用一下,但是只单独启用IPv6也是无法直接提供 ...

  7. 阿里云ECS centos7.2 支持IPv6

    公司的项目因为服务器没有支持IPv6而被appstore给退回来了 第一部分 第一步:编辑 /etc/sysctl.conf 文件,将其中三条禁用IPv6的设置更改为: 第二步:使用命令启动启用IPv ...

  8. 最佳实践:阿里云VPC、ECS支持IPv6啦!

    12月6日,阿里云宣布为企业提供全栈IPv6解决方案. 阿里云专有网络VPC.云服务器ECS,作为阿里云的核心产品,也于2018年11月底上线双栈VPC.双栈ECS,目前正在对外公测中. 那么如何在阿 ...

  9. nfs 支持ipv6

    mount 一个ipv6 nfs 项目在docker里mount 一个nfs来读写,而现在需要支持ipv6,所以先写了各小demo,最后成功mount,这里记录一下 #include <sys/ ...

随机推荐

  1. 在CcentOS系统上将deb包转换为rpm包

    deb文件格式本是ubuntu/debian系统下的安装文件,那么我想要在redhat/centos/fedora中安装,需要把deb格式的软件包转化成rpm格式. 需要用到的转换工具:alien_8 ...

  2. ES怎么进行字段添加索引,并保留原有数据

    1.先将原索引进行备份 curl -XPOST '192.168.46.163:9200/_reindex?pretty' -H 'Content-Type: application/json' -d ...

  3. PS PNG导出的时候是否交错有什么影响

    已解决 导出png格式交错什么意思 我百度的答案一律说png支持交错,可是交错两个字的意思是什么啊,那位专家请指教.谢谢啦!! 问题补充: 我用photoshop或者coreldraw制作按钮时候不是 ...

  4. C中的C文件与h文件辨析

    简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程:       1.预处理阶段 2.词法与语法分析阶段 .编译阶段,首先编译成纯 ...

  5. C++_友元函数(转)

    1.为什么要引入友元函数:在实现类之间数据共享时,减少系统开销,提高效率 具体来说:为了使其他类的成员函数直接访问该类的私有变量 即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同 ...

  6. 51单片机 | 实现SMC1602液晶屏显示实例

    ———————————————————————————————————————————— LCD1602 - - - - - - - - - - - - - - - - - - - - - - - - ...

  7. ubuntu 安装时出错 sudo apt-get update Reading package lists… Error

    安装过程出错 首先出现问题sudo apt-get updateReading package lists… Error!E: Encountered a section with no Packag ...

  8. CLR 完全介绍

    From: http://msdn.microsoft.com/zh-cn/magazine/cc164193.aspx http://msdn.microsoft.com/en-us/magazin ...

  9. Python 多线程和单线程本质应用区别

    先了解下CPU的简单运行原理: 它运行速度非常快,1s内可以运行成千上万次,一个核心可以把1s切分成成千上万个时间片段,这个核心确实同时只能运行一个任务:但是可以将多个任务交替执行,比如上一个时间片段 ...

  10. MyReport报表引擎2.7.8.8公布

    支持嵌套子报表直接编辑保存,多个子报表同一时候存储在一个报表格式文件中,设计更简便,避免了嵌套报表的多个报表格式载入. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5 ...