1 | #include <string> |
2 | |
3 | #include "mtx/events/voip.hpp" |
4 | |
5 | #include <nlohmann/json.hpp> |
6 | |
7 | using json = nlohmann::json; |
8 | |
9 | namespace { |
10 | std::string |
11 | version(const json &obj) |
12 | { |
13 | auto v = obj.at(key: "version" ); |
14 | return v.is_number() ? "0" : v.get<std::string>(); |
15 | } |
16 | |
17 | void |
18 | add_version(json &obj, std::string_view version) |
19 | { |
20 | if (version == "0" ) |
21 | obj["version" ] = 0; |
22 | else |
23 | obj["version" ] = version; |
24 | } |
25 | } |
26 | |
27 | namespace mtx::events::voip { |
28 | |
29 | // RTC Session Description |
30 | void |
31 | from_json(const json &obj, RTCSessionDescriptionInit &content) |
32 | { |
33 | content.sdp = obj.at(key: "sdp" ).get<std::string>(); |
34 | if (obj.at(key: "type" ).get<std::string>() == "answer" ) |
35 | content.type = RTCSessionDescriptionInit::Type::Answer; |
36 | else if (obj.at(key: "type" ).get<std::string>() == "offer" ) |
37 | content.type = RTCSessionDescriptionInit::Type::Offer; |
38 | } |
39 | |
40 | void |
41 | to_json(json &obj, const RTCSessionDescriptionInit &content) |
42 | { |
43 | obj["sdp" ] = content.sdp; |
44 | if (content.type == RTCSessionDescriptionInit::Type::Answer) |
45 | obj["type" ] = "answer" ; |
46 | else if (content.type == RTCSessionDescriptionInit::Type::Offer) |
47 | obj["type" ] = "offer" ; |
48 | } |
49 | |
50 | // m.call.invite |
51 | void |
52 | from_json(const json &obj, CallInvite &content) |
53 | { |
54 | content.call_id = obj.at(key: "call_id" ).get<std::string>(); |
55 | content.offer = obj.at(key: "offer" ).get<RTCSessionDescriptionInit>(); |
56 | content.version = version(obj); |
57 | content.lifetime = obj.at(key: "lifetime" ).get<uint32_t>(); |
58 | if (content.version != "0" ) { |
59 | content.party_id = obj.at(key: "party_id" ).get<std::string>(); |
60 | if (obj.contains(key: "invitee" )) |
61 | content.invitee = obj.at(key: "invitee" ).get<std::string>(); |
62 | } |
63 | } |
64 | |
65 | void |
66 | to_json(json &obj, const CallInvite &content) |
67 | { |
68 | obj["call_id" ] = content.call_id; |
69 | obj["offer" ] = content.offer; |
70 | add_version(obj, version: content.version); |
71 | obj["lifetime" ] = content.lifetime; |
72 | if (content.version != "0" ) { |
73 | obj["party_id" ] = content.party_id; |
74 | obj["invitee" ] = content.invitee; |
75 | } |
76 | } |
77 | |
78 | // m.call.candidates |
79 | void |
80 | from_json(const json &obj, CallCandidates::Candidate &content) |
81 | { |
82 | if (obj.contains(key: "sdpMid" )) |
83 | content.sdpMid = obj.at(key: "sdpMid" ).get<std::string>(); |
84 | if (obj.contains(key: "sdpMLineIndex" )) |
85 | content.sdpMLineIndex = obj.at(key: "sdpMLineIndex" ).get<uint16_t>(); |
86 | if (obj.contains(key: "candidate" )) |
87 | content.candidate = obj.at(key: "candidate" ).get<std::string>(); |
88 | } |
89 | |
90 | void |
91 | to_json(json &obj, const CallCandidates::Candidate &content) |
92 | { |
93 | obj["sdpMid" ] = content.sdpMid; |
94 | obj["sdpMLineIndex" ] = content.sdpMLineIndex; |
95 | obj["candidate" ] = content.candidate; |
96 | } |
97 | |
98 | void |
99 | from_json(const json &obj, CallCandidates &content) |
100 | { |
101 | content.call_id = obj.at(key: "call_id" ).get<std::string>(); |
102 | content.candidates = obj.at(key: "candidates" ).get<std::vector<CallCandidates::Candidate>>(); |
103 | content.version = version(obj); |
104 | if (content.version != "0" ) { |
105 | content.party_id = obj.at(key: "party_id" ).get<std::string>(); |
106 | } |
107 | } |
108 | |
109 | void |
110 | to_json(json &obj, const CallCandidates &content) |
111 | { |
112 | obj["call_id" ] = content.call_id; |
113 | obj["candidates" ] = content.candidates; |
114 | add_version(obj, version: content.version); |
115 | if (content.version != "0" ) { |
116 | obj["party_id" ] = content.party_id; |
117 | } |
118 | } |
119 | |
120 | // m.call.answer |
121 | void |
122 | from_json(const json &obj, CallAnswer &content) |
123 | { |
124 | content.call_id = obj.at(key: "call_id" ).get<std::string>(); |
125 | content.answer = obj.at(key: "answer" ).get<RTCSessionDescriptionInit>(); |
126 | content.version = version(obj); |
127 | if (content.version != "0" ) { |
128 | content.party_id = obj.at(key: "party_id" ).get<std::string>(); |
129 | } |
130 | } |
131 | |
132 | void |
133 | to_json(json &obj, const CallAnswer &content) |
134 | { |
135 | obj["call_id" ] = content.call_id; |
136 | obj["answer" ] = content.answer; |
137 | add_version(obj, version: content.version); |
138 | if (content.version != "0" ) { |
139 | obj["party_id" ] = content.party_id; |
140 | } |
141 | } |
142 | |
143 | // m.call.hangup |
144 | void |
145 | from_json(const json &obj, CallHangUp &content) |
146 | { |
147 | content.call_id = obj.at(key: "call_id" ).get<std::string>(); |
148 | content.version = version(obj); |
149 | if (content.version != "0" ) { |
150 | content.party_id = obj.at(key: "party_id" ).get<std::string>(); |
151 | } |
152 | if (obj.count(key: "reason" ) == 0) { |
153 | content.reason = CallHangUp::Reason::User; |
154 | } else { |
155 | if (obj.at(key: "reason" ).get<std::string>() == "ice_failed" ) |
156 | content.reason = CallHangUp::Reason::ICEFailed; |
157 | else if (obj.at(key: "reason" ).get<std::string>() == "invite_timeout" ) |
158 | content.reason = CallHangUp::Reason::InviteTimeOut; |
159 | else if (obj.at(key: "reason" ).get<std::string>() == "ice_timeout" ) |
160 | content.reason = CallHangUp::Reason::ICETimeOut; |
161 | else if (obj.at(key: "reason" ).get<std::string>() == "user_hangup" ) |
162 | content.reason = CallHangUp::Reason::UserHangUp; |
163 | else if (obj.at(key: "reason" ).get<std::string>() == "user_media_failed" ) |
164 | content.reason = CallHangUp::Reason::UserMediaFailed; |
165 | else if (obj.at(key: "reason" ).get<std::string>() == "user_busy" ) |
166 | content.reason = CallHangUp::Reason::UserBusy; |
167 | else if (obj.at(key: "reason" ).get<std::string>() == "unknown_error" ) |
168 | content.reason = CallHangUp::Reason::UnknownError; |
169 | } |
170 | } |
171 | |
172 | void |
173 | to_json(json &obj, const CallHangUp &content) |
174 | { |
175 | obj["call_id" ] = content.call_id; |
176 | add_version(obj, version: content.version); |
177 | if (content.version != "0" ) { |
178 | obj["party_id" ] = content.party_id; |
179 | } |
180 | if (content.reason == CallHangUp::Reason::ICEFailed) |
181 | obj["reason" ] = "ice_failed" ; |
182 | else if (content.reason == CallHangUp::Reason::InviteTimeOut) |
183 | obj["reason" ] = "invite_timeout" ; |
184 | else if (content.reason == CallHangUp::Reason::ICETimeOut) |
185 | obj["reason" ] = "ice_timeout" ; |
186 | else if (content.reason == CallHangUp::Reason::UserHangUp) |
187 | obj["reason" ] = "user_hangup" ; |
188 | else if (content.reason == CallHangUp::Reason::UserMediaFailed) |
189 | obj["reason" ] = "user_media_failed" ; |
190 | else if (content.reason == CallHangUp::Reason::UserBusy) |
191 | obj["reason" ] = "user_busy" ; |
192 | else if (content.reason == CallHangUp::Reason::UnknownError) |
193 | obj["reason" ] = "unknown_error" ; |
194 | } |
195 | |
196 | // m.call.select_answer |
197 | void |
198 | from_json(const json &obj, CallSelectAnswer &content) |
199 | { |
200 | content.call_id = obj.at(key: "call_id" ).get<std::string>(); |
201 | content.version = version(obj); |
202 | content.party_id = obj.at(key: "party_id" ).get<std::string>(); |
203 | content.selected_party_id = obj.at(key: "selected_party_id" ).get<std::string>(); |
204 | } |
205 | |
206 | void |
207 | to_json(json &obj, const CallSelectAnswer &content) |
208 | { |
209 | obj["call_id" ] = content.call_id; |
210 | add_version(obj, version: content.version); |
211 | obj["party_id" ] = content.party_id; |
212 | obj["selected_party_id" ] = content.selected_party_id; |
213 | } |
214 | |
215 | // m.call.reject |
216 | void |
217 | from_json(const json &obj, CallReject &content) |
218 | { |
219 | content.call_id = obj.at(key: "call_id" ).get<std::string>(); |
220 | content.version = version(obj); |
221 | content.party_id = obj.at(key: "party_id" ).get<std::string>(); |
222 | } |
223 | |
224 | void |
225 | to_json(json &obj, const CallReject &content) |
226 | { |
227 | obj["call_id" ] = content.call_id; |
228 | add_version(obj, version: content.version); |
229 | obj["party_id" ] = content.party_id; |
230 | } |
231 | |
232 | // m.call.negotiate |
233 | void |
234 | from_json(const json &obj, CallNegotiate &content) |
235 | { |
236 | content.call_id = obj.at(key: "call_id" ).get<std::string>(); |
237 | content.party_id = obj.at(key: "party_id" ).get<std::string>(); |
238 | content.lifetime = obj.at(key: "lifetime" ).get<uint32_t>(); |
239 | content.description = obj.at(key: "description" ); |
240 | } |
241 | |
242 | void |
243 | to_json(json &obj, const CallNegotiate &content) |
244 | { |
245 | obj["call_id" ] = content.call_id; |
246 | obj["party_id" ] = content.party_id; |
247 | obj["lifetime" ] = content.lifetime; |
248 | obj["description" ] = content.description; |
249 | } |
250 | |
251 | } // namespace mtx::events::voip |
252 | |