1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "client/mdns_utils.h" 18 19 #include <android-base/strings.h> 20 21 namespace mdns { 22 23 // <Instance>.<Service>.<Domain> 24 std::optional<MdnsInstance> mdns_parse_instance_name(std::string_view name) { 25 CHECK(!name.empty()); 26 27 // Return the whole name if it doesn't fall under <Instance>.<Service>.<Domain> or 28 // <Instance>.<Service> 29 bool has_local_suffix = false; 30 // Strip the local suffix, if any 31 { 32 std::string local_suffix = ".local"; 33 local_suffix += android::base::EndsWith(name, ".") ? "." : ""; 34 35 if (android::base::ConsumeSuffix(&name, local_suffix)) { 36 if (name.empty()) { 37 return std::nullopt; 38 } 39 has_local_suffix = true; 40 } 41 } 42 43 std::string transport; 44 // Strip the transport suffix, if any 45 { 46 std::string add_dot = (!has_local_suffix && android::base::EndsWith(name, ".")) ? "." : ""; 47 std::array<std::string, 2> transport_suffixes{"._tcp", "._udp"}; 48 49 for (const auto& t : transport_suffixes) { 50 if (android::base::ConsumeSuffix(&name, t + add_dot)) { 51 if (name.empty()) { 52 return std::nullopt; 53 } 54 transport = t.substr(1); 55 break; 56 } 57 } 58 59 if (has_local_suffix && transport.empty()) { 60 return std::nullopt; 61 } 62 } 63 64 if (!has_local_suffix && transport.empty()) { 65 return std::make_optional<MdnsInstance>(name, "", ""); 66 } 67 68 // Split the service name from the instance name 69 auto pos = name.rfind("."); 70 if (pos == 0 || pos == std::string::npos || pos == name.size() - 1) { 71 return std::nullopt; 72 } 73 74 return std::make_optional<MdnsInstance>(name.substr(0, pos), name.substr(pos + 1), transport); 75 } 76 77 } // namespace mdns 78