1 /*
2 * Copyright (C) 2021 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 #include "wifi_p2p_dns_sd_service_response.h"
16 #include <climits>
17 #include "wifi_p2p_dns_sd_service_info.h"
18
19 namespace OHOS {
20 namespace Wifi {
WifiP2pDnsSdServiceResponse(P2pServiceStatus status,int tranId,const std::vector<unsigned char> & data)21 WifiP2pDnsSdServiceResponse::WifiP2pDnsSdServiceResponse(
22 P2pServiceStatus status, int tranId, const std::vector<unsigned char> &data)
23 : WifiP2pServiceResponse(P2pServicerProtocolType::SERVICE_TYPE_BONJOUR, status, tranId, data),
24 dnsQueryName(), instanceName(), dnsType(-1), version(-1), txtRecord(), sVmpack()
25 {
26 Init();
27 };
28
WifiP2pDnsSdServiceResponse(const WifiP2pServiceResponse & resp)29 WifiP2pDnsSdServiceResponse::WifiP2pDnsSdServiceResponse(const WifiP2pServiceResponse &resp)
30 : WifiP2pServiceResponse(resp),
31 dnsQueryName(), instanceName(), dnsType(-1), version(-1), txtRecord(), sVmpack()
32 {
33 Init();
34 };
35
Init()36 void WifiP2pDnsSdServiceResponse::Init()
37 {
38 sVmpack.insert(std::make_pair(0x0c, "_tcp.local."));
39 sVmpack.insert(std::make_pair(0x11, "local."));
40 sVmpack.insert(std::make_pair(0x1c, "_udp.local."));
41 }
42
FetchTxtData(std::istringstream & istream)43 bool WifiP2pDnsSdServiceResponse::FetchTxtData(std::istringstream &istream)
44 {
45 unsigned char t = static_cast<unsigned char>(istream.get());
46 while (!istream.eof()) {
47 if (t == 0) {
48 break;
49 }
50 if (t > (istream.str().size() - static_cast<unsigned char>(istream.tellg()))) {
51 return false;
52 }
53 std::unique_ptr<char[]> ptr = std::make_unique<char[]>(t + 1);
54 istream.read(ptr.get(), t);
55 ptr[t] = '\0';
56 std::istringstream iss(ptr.get());
57 std::string keyVal[2];
58 getline(iss, keyVal[0], '=');
59 getline(iss, keyVal[1], '=');
60 txtRecord.insert(std::make_pair(keyVal[0], keyVal[1]));
61 t = istream.get();
62 }
63 return true;
64 }
65
FetchDnsName(std::istringstream & istream,std::string & dnsName)66 bool WifiP2pDnsSdServiceResponse::FetchDnsName(std::istringstream &istream, std::string &dnsName)
67 {
68 if (!dnsQueryName.empty()) {
69 sVmpack.insert(std::make_pair(0x27, dnsQueryName));
70 }
71 dnsName = "";
72
73 unsigned char t = static_cast<unsigned char>(istream.get());
74 while (!istream.eof()) {
75 if (t == 0x00) {
76 return true;
77 } else if (t == 0xc0) {
78 t = istream.get();
79 auto it = sVmpack.find(t);
80 if (it == sVmpack.end()) {
81 return false;
82 }
83 dnsName.append(it->second);
84 return true;
85 } else {
86 if (t > (istream.str().size() - static_cast<unsigned char>(istream.tellg()))) {
87 return false;
88 }
89 std::unique_ptr<char[]> ptr = std::make_unique<char[]>(t);
90 istream.read(ptr.get(), t);
91 dnsName.append(ptr.get(), 0, t);
92 dnsName.append(".");
93 }
94 t = istream.get();
95 }
96 return false;
97 }
98
ParseData()99 bool WifiP2pDnsSdServiceResponse::ParseData()
100 {
101 std::vector<unsigned char> data = GetData();
102 if (data.empty()) {
103 return true; /* empty is ok */
104 }
105 std::string strData;
106 strData.insert(strData.begin(), data.begin(), data.end());
107 std::istringstream istream(strData);
108 std::string dnsName;
109 if (!FetchDnsName(istream, dnsName) || dnsName.empty()) {
110 return false;
111 }
112 dnsQueryName = dnsName;
113
114 const int typeAndVersionSize = 3;
115 if ((static_cast<int>(istream.str().size()) - istream.tellg()) <= typeAndVersionSize) {
116 return false;
117 }
118 dnsType = static_cast<int>(static_cast<size_t>(istream.get()) << CHAR_BIT); /* 2 Byte of high bit */
119 dnsType = istream.get();
120 version = istream.get(); /* 1 Byte */
121
122 if (dnsType == WifiP2pDnsSdServiceInfo::DNS_PTR_TYPE) {
123 std::string rData;
124 if (!FetchDnsName(istream, rData) || rData.empty()) {
125 return false;
126 }
127 if (rData.length() <= dnsQueryName.length()) {
128 return false;
129 }
130 instanceName.insert(instanceName.begin(), rData.begin(), rData.end() - dnsQueryName.length() - 1);
131 } else if (dnsType == WifiP2pDnsSdServiceInfo::DNS_TXT_TYPE) {
132 if (!FetchTxtData(istream)) {
133 return false;
134 }
135 } else {
136 return false;
137 }
138 if (!istream.eof() && istream.get() == ';') {
139 std::string svrName("");
140 unsigned char svrNameLength = static_cast<unsigned char>(istream.get());
141 std::unique_ptr<char[]> ptr = std::make_unique<char[]>(svrNameLength);
142 istream.read(ptr.get(), svrNameLength);
143 svrName.append(ptr.get(), 0, svrNameLength);
144 mSvrName = svrName;
145 }
146 return true;
147 }
148
GetQueryName() const149 const std::string &WifiP2pDnsSdServiceResponse::GetQueryName() const
150 {
151 return dnsQueryName;
152 }
153
GetInstanceName() const154 const std::string &WifiP2pDnsSdServiceResponse::GetInstanceName() const
155 {
156 return instanceName;
157 }
158
GetDnsType() const159 int WifiP2pDnsSdServiceResponse::GetDnsType() const
160 {
161 return dnsType;
162 }
163
GetVersion() const164 int WifiP2pDnsSdServiceResponse::GetVersion() const
165 {
166 return version;
167 }
168
GetTxtRecord() const169 const std::map<std::string, std::string> &WifiP2pDnsSdServiceResponse::GetTxtRecord() const
170 {
171 return txtRecord;
172 }
173 } // namespace Wifi
174 } // namespace OHOS
175