• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "mdns_common.h"
17 
18 namespace OHOS {
19 namespace NetManagerStandard {
20 
21 namespace {
22 constexpr const char *MDNS_TYPE_TCP = "_tcp";
23 constexpr const char *MDNS_TYPE_UDP = "_udp";
24 constexpr const char *MDNS_TYPE_PREFIX = "_";
25 constexpr size_t MDNS_TYPE_SEGMENT = 2;
26 constexpr size_t MDNS_INSTANCE_SEGMENT = 3;
27 constexpr size_t MDNS_NAME_IDX = 0;
28 constexpr size_t MDNS_TYPE1_IDX = 1;
29 constexpr size_t MDNS_TYPE2_IDX = 2;
30 constexpr int32_t TYPE_SIZE = 2;
31 
32 } // namespace
33 
EndsWith(const std::string_view & str,const std::string_view & pat)34 bool EndsWith(const std::string_view &str, const std::string_view &pat)
35 {
36     if (str.length() < pat.length()) {
37         return false;
38     }
39     return std::mismatch(pat.rbegin(), pat.rend(), str.rbegin()).first == pat.rend();
40 }
41 
StartsWith(const std::string_view & str,const std::string_view & pat)42 bool StartsWith(const std::string_view &str, const std::string_view &pat)
43 {
44     if (str.length() < pat.length()) {
45         return false;
46     }
47     return std::mismatch(pat.begin(), pat.end(), str.begin()).first == pat.end();
48 }
49 
Split(const std::string_view & s,char seperator)50 std::vector<std::string_view> Split(const std::string_view &s, char seperator)
51 {
52     std::vector<std::string_view> output;
53     std::string::size_type prev = 0;
54     std::string::size_type pos = 0;
55     while ((pos = s.find(seperator, pos)) != std::string::npos) {
56         if (pos > prev) {
57             output.push_back(s.substr(prev, pos - prev));
58         }
59         prev = ++pos;
60     }
61     if (prev < s.size()) {
62         output.push_back(s.substr(prev));
63     }
64     return output;
65 }
66 
GetMDNSTypeIndex(const std::vector<std::string_view> & views)67 int32_t GetMDNSTypeIndex(const std::vector<std::string_view> &views)
68 {
69     int32_t index = -1;
70     for (size_t i = 0; i < views.size(); ++i) {
71         if (views[i] == MDNS_TYPE_TCP || views[i] == MDNS_TYPE_UDP) {
72             index = static_cast<int32_t>(i);
73         }
74     }
75     return index;
76 }
77 
IsNameValid(const std::string & name)78 bool IsNameValid(const std::string &name)
79 {
80     return 0 < name.size() && name.size() <= MDNS_MAX_DOMAIN_LABEL;
81 }
82 
IsTypeValid(const std::string & type)83 bool IsTypeValid(const std::string &type)
84 {
85     auto views = Split(type, MDNS_DOMAIN_SPLITER);
86     return views.size() == MDNS_TYPE_SEGMENT && views[0].size() <= MDNS_MAX_DOMAIN_LABEL &&
87            StartsWith(views[0], MDNS_TYPE_PREFIX) && (views[1] == MDNS_TYPE_UDP || views[1] == MDNS_TYPE_TCP);
88 }
89 
IsPortValid(int port)90 bool IsPortValid(int port)
91 {
92     return 0 <= port && port <= UINT16_MAX;
93 }
94 
IsInstanceValid(const std::string & instance)95 bool IsInstanceValid(const std::string &instance)
96 {
97     auto views = Split(instance, MDNS_DOMAIN_SPLITER);
98     if (views.size() == MDNS_INSTANCE_SEGMENT) {
99         return views[MDNS_NAME_IDX].size() <= MDNS_MAX_DOMAIN_LABEL &&
100            views[MDNS_TYPE1_IDX].size() <= MDNS_MAX_DOMAIN_LABEL &&
101            StartsWith(views[MDNS_TYPE1_IDX], MDNS_TYPE_PREFIX) &&
102            (views[MDNS_TYPE2_IDX] == MDNS_TYPE_UDP || views[MDNS_TYPE2_IDX] == MDNS_TYPE_TCP);
103     } else if (views.size() > MDNS_INSTANCE_SEGMENT) {
104         int32_t typeIndex = GetMDNSTypeIndex(views);
105         if (typeIndex <= TYPE_SIZE) {
106             return false;
107         }
108         std::string name = std::string(views[MDNS_NAME_IDX].begin(), views[typeIndex - TYPE_SIZE].end());
109         return name.size() <= MDNS_MAX_DOMAIN_LABEL &&
110            views[typeIndex - 1].size() <= MDNS_MAX_DOMAIN_LABEL &&
111            StartsWith(views[typeIndex - 1], MDNS_TYPE_PREFIX) &&
112            (views[typeIndex] == MDNS_TYPE_UDP || views[typeIndex] == MDNS_TYPE_TCP);
113     }
114     return false;
115 }
116 
IsDomainValid(const std::string & domain)117 bool IsDomainValid(const std::string &domain)
118 {
119     return domain.size() + static_cast<size_t>(!EndsWith(domain, MDNS_DOMAIN_SPLITER_STR)) <= MDNS_MAX_DOMAIN;
120 }
121 
ExtractNameAndType(const std::string & instance,std::string & name,std::string & type)122 void ExtractNameAndType(const std::string &instance, std::string &name, std::string &type)
123 {
124     auto views = Split(instance, MDNS_DOMAIN_SPLITER);
125     int32_t typeIndex = GetMDNSTypeIndex(views);
126     if (views.size() == MDNS_INSTANCE_SEGMENT || views.size() == MDNS_INSTANCE_SEGMENT + 1) {
127         name = std::string(views[MDNS_NAME_IDX].begin(), views[MDNS_NAME_IDX].end());
128         type = std::string(views[MDNS_TYPE1_IDX].begin(), views[MDNS_TYPE2_IDX].end());
129     } else if (typeIndex > TYPE_SIZE) {
130         name = std::string(views[MDNS_NAME_IDX].begin(), views[typeIndex - TYPE_SIZE].end());
131         type = std::string(views[typeIndex - 1].begin(), views[typeIndex].end());
132     }
133 }
134 
135 } // namespace NetManagerStandard
136 } // namespace OHOS
137