fix #29: add authentification support

This commit is contained in:
mpromonet 2016-07-10 13:40:01 +00:00
parent 3c5a24d096
commit f8de2847a8

View File

@ -50,13 +50,38 @@ void sighandler(int n)
}
// -----------------------------------------
// create UserAuthenticationDatabase for RTSP server
// -----------------------------------------
UserAuthenticationDatabase* createUserAuthenticationDatabase(const std::list<std::string> & userPasswordList, const char* realm)
{
UserAuthenticationDatabase* auth = NULL;
if (userPasswordList.size() > 0)
{
auth = new UserAuthenticationDatabase(realm, (realm != NULL) );
std::list<std::string>::const_iterator it;
for (it = userPasswordList.begin(); it != userPasswordList.end(); ++it)
{
std::istringstream is(*it);
std::string user;
getline(is, user, ':');
std::string password;
getline(is, password);
auth->addUserRecord(user.c_str(), password.c_str());
}
}
return auth;
}
// -----------------------------------------
// create RTSP server
// -----------------------------------------
RTSPServer* createRTSPServer(UsageEnvironment& env, unsigned short rtspPort, unsigned short rtspOverHTTPPort, int timeout, unsigned int hlsSegment)
RTSPServer* createRTSPServer(UsageEnvironment& env, unsigned short rtspPort, unsigned short rtspOverHTTPPort, int timeout, unsigned int hlsSegment, const std::list<std::string> & userPasswordList, const char* realm)
{
UserAuthenticationDatabase* authDB = NULL;
RTSPServer* rtspServer = HTTPServer::createNew(env, rtspPort, authDB, timeout, hlsSegment);
UserAuthenticationDatabase* auth = createUserAuthenticationDatabase(userPasswordList, realm);
RTSPServer* rtspServer = HTTPServer::createNew(env, rtspPort, auth, timeout, hlsSegment);
if (rtspServer != NULL)
{
// set http tunneling
@ -114,6 +139,9 @@ void addSession(RTSPServer* rtspServer, const std::string & sessionName, ServerM
}
}
// -----------------------------------------
// convert V4L2 pix format to RTP mime
// -----------------------------------------
std::string getRtpFormat(int format, bool muxTS)
{
std::string rtpFormat;
@ -136,6 +164,9 @@ std::string getRtpFormat(int format, bool muxTS)
return rtpFormat;
}
// -----------------------------------------
// convert string format to fourcc
// -----------------------------------------
int decodeFormat(const char* fmt)
{
char fourcc[4];
@ -147,6 +178,29 @@ int decodeFormat(const char* fmt)
return v4l2_fourcc(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
}
// -------------------------------------------------------
// decode multicast url <group>:<rtp_port>:<rtcp_port>
// -------------------------------------------------------
void decodeMulticastUrl(const std::string & maddr, in_addr & destinationAddress, unsigned short & rtpPortNum, unsigned short & rtcpPortNum)
{
std::istringstream is(maddr);
std::string ip;
getline(is, ip, ':');
if (!ip.empty())
{
destinationAddress.s_addr = inet_addr(ip.c_str());
}
std::string port;
getline(is, port, ':');
rtpPortNum = 20000;
if (!port.empty())
{
rtpPortNum = atoi(port.c_str());
}
rtcpPortNum = rtpPortNum+1;
}
// -----------------------------------------
// entry point
// -----------------------------------------
@ -174,16 +228,19 @@ int main(int argc, char** argv)
int timeout = 65;
bool muxTS = false;
unsigned int hlsSegment = 0;
const char* realm = NULL;
std::list<std::string> userPasswordList;
// decode parameters
int c = 0;
while ((c = getopt (argc, argv, "v::Q:O:" "I:P:p:m:u:M:ct:TS::" "rwsf::F:W:H:" "h")) != -1)
while ((c = getopt (argc, argv, "v::Q:O:" "I:P:p:m:u:M:ct:TS::R:U:" "rwsf::F:W:H:" "h")) != -1)
{
switch (c)
{
case 'v': verbose = 1; if (optarg && *optarg=='v') verbose++; break;
case 'Q': queueSize = atoi(optarg); break;
case 'O': outputFile = optarg; break;
// RTSP/RTP
case 'I': ReceivingInterfaceAddr = inet_addr(optarg); break;
case 'P': rtspPort = atoi(optarg); break;
@ -195,6 +252,9 @@ int main(int argc, char** argv)
case 't': timeout = atoi(optarg); break;
case 'T': muxTS = true; break;
case 'S': hlsSegment = optarg ? atoi(optarg) : 5; muxTS=true; break;
case 'R': realm = optarg; break;
case 'U': userPasswordList.push_back(optarg); break;
// V4L2
case 'r': ioTypeIn = V4l2DeviceFactory::IOTYPE_READ; break;
case 'w': ioTypeOut = V4l2DeviceFactory::IOTYPE_READ; break;
@ -214,17 +274,21 @@ int main(int argc, char** argv)
std::cout << "\t -vv : very verbose" << std::endl;
std::cout << "\t -Q length : Number of frame queue (default "<< queueSize << ")" << std::endl;
std::cout << "\t -O output : Copy captured frame to a file or a V4L2 device" << std::endl;
std::cout << "\t RTSP/RTP options :" << std::endl;
std::cout << "\t -I addr : RTSP interface (default autodetect)" << std::endl;
std::cout << "\t -P port : RTSP port (default "<< rtspPort << ")" << std::endl;
std::cout << "\t -p port : RTSP over HTTP port (default "<< rtspOverHTTPPort << ")" << std::endl;
std::cout << "\t -U user:password : RTSP user and password" << std::endl;
std::cout << "\t -R realm : use md5 password 'md5(<username>:<realm>:<password>')" << std::endl;
std::cout << "\t -u url : unicast url (default " << url << ")" << std::endl;
std::cout << "\t -m url : multicast url (default " << murl << ")" << std::endl;
std::cout << "\t -M addr : multicast group:port (default is random_address:20000)" << std::endl;
std::cout << "\t -c : don't repeat config (default repeat config before IDR frame)" << std::endl;
std::cout << "\t -t timeout: RTCP expiration timeout in seconds (default " << timeout << ")" << std::endl;
std::cout << "\t -T : send Transport Stream instead of elementary Stream" << std::endl;
std::cout << "\t -S[duration]: enable HLS & MPEG-DASH with segment duration in seconds (default 5)" << std::endl;
std::cout << "\t -T : send Transport Stream instead of elementary Stream" << std::endl;
std::cout << "\t -S[duration]: enable HLS & MPEG-DASH with segment duration in seconds (default 5)"<< std::endl;
std::cout << "\t V4L2 options :" << std::endl;
std::cout << "\t -r : V4L2 capture using read interface (default use memory mapped buffers)" << std::endl;
std::cout << "\t -w : V4L2 capture using write interface (default use memory mapped buffers)"<< std::endl;
@ -234,7 +298,7 @@ int main(int argc, char** argv)
std::cout << "\t -W width : V4L2 capture width (default "<< width << ")" << std::endl;
std::cout << "\t -H height : V4L2 capture height (default "<< height << ")" << std::endl;
std::cout << "\t -F fps : V4L2 capture framerate (default "<< fps << ")" << std::endl;
std::cout << "\t device : V4L2 capture device (default "<< dev_name << ")" << std::endl;
std::cout << "\t device : V4L2 capture device (default "<< dev_name << ")" << std::endl;
exit(0);
}
}
@ -258,28 +322,15 @@ int main(int argc, char** argv)
UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);
// split multicast info
std::istringstream is(maddr);
std::string ip;
getline(is, ip, ':');
struct in_addr destinationAddress;
destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);
if (!ip.empty())
{
destinationAddress.s_addr = inet_addr(ip.c_str());
}
std::string port;
getline(is, port, ':');
unsigned short rtpPortNum = 20000;
if (!port.empty())
{
rtpPortNum = atoi(port.c_str());
}
unsigned short rtcpPortNum = rtpPortNum+1;
unsigned char ttl = 5;
decodeMulticastUrl(maddr, destinationAddress, rtpPortNum, rtcpPortNum);
// create RTSP server
RTSPServer* rtspServer = createRTSPServer(*env, rtspPort, rtspOverHTTPPort, timeout, hlsSegment);
RTSPServer* rtspServer = createRTSPServer(*env, rtspPort, rtspOverHTTPPort, timeout, hlsSegment, userPasswordList, realm);
if (rtspServer == NULL)
{
LOG(ERROR) << "Failed to create RTSP server: " << env->getResultMsg();