| 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 | |