1 /*
2  * SRT - Secure, Reliable, Transport
3  * Copyright (c) 2018 Haivision Systems Inc.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  */
10 
11 #include "socketoptions.hpp"
12 #include "verbose.hpp"
13 
14 using namespace std;
15 
16 
17 extern const set<string> true_names = { "1", "yes", "on", "true" };
18 extern const set<string> false_names = { "0", "no", "off", "false" };
19 
20 extern const std::map<std::string, int> enummap_transtype = {
21     { "live", SRTT_LIVE },
22     { "file", SRTT_FILE }
23 };
24 
25 
26 const char* const SocketOption::mode_names[3] = {
27     "listener", "caller", "rendezvous"
28 };
29 
SrtInterpretMode(const string & modestr,const string & host,const string & adapter)30 SocketOption::Mode SrtInterpretMode(const string& modestr, const string& host, const string& adapter)
31 {
32     SocketOption::Mode mode = SocketOption::FAILURE;
33 
34     if (modestr == "client" || modestr == "caller")
35     {
36         mode = SocketOption::CALLER;
37     }
38     else if (modestr == "server" || modestr == "listener")
39     {
40         mode = SocketOption::LISTENER;
41     }
42     else if (modestr == "rendezvous")
43     {
44         mode = SocketOption::RENDEZVOUS;
45     }
46     else if (modestr == "default")
47     {
48         // Use the following convention:
49         // 1. Server for source, Client for target
50         // 2. If host is empty, then always server.
51         if ( host == "" )
52             mode = SocketOption::LISTENER;
53         //else if ( !dir_output )
54         //mode = "server";
55         else
56         {
57             // Host is given, so check also "adapter"
58             if (adapter != "")
59                 mode = SocketOption::RENDEZVOUS;
60             else
61                 mode = SocketOption::CALLER;
62         }
63     }
64     else
65     {
66         mode = SocketOption::FAILURE;
67     }
68 
69     return mode;
70 }
71 
SrtConfigurePre(SRTSOCKET socket,string host,map<string,string> options,vector<string> * failures)72 SocketOption::Mode SrtConfigurePre(SRTSOCKET socket, string host, map<string, string> options, vector<string>* failures)
73 {
74     vector<string> dummy;
75     vector<string>& fails = failures ? *failures : dummy;
76 
77     string modestr = "default", adapter;
78 
79     if (options.count("mode"))
80     {
81         modestr = options["mode"];
82     }
83 
84     if (options.count("adapter"))
85     {
86         adapter = options["adapter"];
87     }
88 
89     SocketOption::Mode mode = SrtInterpretMode(modestr, host, adapter);
90     if (mode == SocketOption::FAILURE)
91     {
92         fails.push_back("mode");
93     }
94 
95     if (options.count("linger"))
96     {
97         linger lin;
98         lin.l_linger = stoi(options["linger"]);
99         lin.l_onoff  = lin.l_linger > 0 ? 1 : 0;
100         srt_setsockopt(socket, SocketOption::PRE, SRTO_LINGER, &lin, sizeof(linger));
101     }
102 
103 
104     bool all_clear = true;
105     for (const auto &o: srt_options)
106     {
107         if ( o.binding == SocketOption::PRE && options.count(o.name) )
108         {
109             string value = options.at(o.name);
110             bool ok = o.apply<SocketOption::SRT>(socket, value);
111             if ( !ok )
112             {
113                 fails.push_back(o.name);
114                 all_clear = false;
115             }
116         }
117     }
118 
119     return all_clear ? mode : SocketOption::FAILURE;
120 }
121 
SrtConfigurePost(SRTSOCKET socket,map<string,string> options,vector<string> * failures)122 void SrtConfigurePost(SRTSOCKET socket, map<string, string> options, vector<string>* failures)
123 {
124     vector<string> dummy;
125     vector<string>& fails = failures ? *failures : dummy;
126 
127     for (const auto &o: srt_options)
128     {
129         if ( o.binding == SocketOption::POST && options.count(o.name) )
130         {
131             string value = options.at(o.name);
132             Verb() << "Setting option: " << o.name << " = " << value;
133             bool ok = o.apply<SocketOption::SRT>(socket, value);
134             if ( !ok )
135                 fails.push_back(o.name);
136         }
137     }
138 }
139 
140