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_info.h"
16
17 #include <sstream>
18 #include <algorithm>
19 #include <iomanip>
20
21 namespace OHOS {
22 namespace Wifi {
FindPacket(std::string & dnsName)23 inline std::string FindPacket(std::string &dnsName)
24 {
25 if (dnsName == "_tcp.local.") {
26 return "c00c";
27 }
28 if (dnsName == "local.") {
29 return "c011";
30 }
31 if (dnsName == "_udp.local.") {
32 return "c01c";
33 }
34 return "";
35 }
36
37
WifiP2pDnsSdServiceInfo(const std::vector<std::string> & queryList)38 WifiP2pDnsSdServiceInfo::WifiP2pDnsSdServiceInfo(const std::vector<std::string> &queryList)
39 : WifiP2pServiceInfo(queryList)
40 {}
41
WifiP2pDnsSdServiceInfo()42 WifiP2pDnsSdServiceInfo::WifiP2pDnsSdServiceInfo()
43 {}
44
Create(const std::string & instanceName,const std::string & serviceType,const std::map<std::string,std::string> & txtMap,const std::string & svrName)45 WifiP2pDnsSdServiceInfo WifiP2pDnsSdServiceInfo::Create(const std::string &instanceName, const std::string &serviceType,
46 const std::map<std::string, std::string> &txtMap, const std::string &svrName)
47 {
48 WifiP2PDnsTxtRecord txtRecord;
49 for (auto it = txtMap.begin(); it != txtMap.end(); ++it) {
50 txtRecord.SetRecord(it->first, it->second);
51 }
52 std::vector<std::string> queries;
53 queries.push_back(BuildPtrServiceQuery(instanceName, serviceType, svrName));
54 queries.push_back(BuildTxtServiceQuery(instanceName, serviceType, txtRecord, svrName));
55
56 WifiP2pDnsSdServiceInfo dnsSdServInfo(queries);
57 dnsSdServInfo.SetServiceName(svrName);
58 dnsSdServInfo.SetServicerProtocolType(P2pServicerProtocolType::SERVICE_TYPE_BONJOUR);
59 return dnsSdServInfo;
60 }
BuildPtrServiceQuery(const std::string & instanceName,const std::string & serviceType,const std::string & svrName)61 std::string WifiP2pDnsSdServiceInfo::BuildPtrServiceQuery(
62 const std::string &instanceName, const std::string &serviceType, const std::string &svrName)
63 {
64 std::stringstream ret;
65 std::vector<unsigned char> buf;
66
67 ret << "bonjour ";
68 ret << BuildRequest(serviceType + ".local.", DNS_PTR_TYPE, VERSION_1);
69 ret << " ";
70
71 std::stringstream stream(instanceName);
72 buf.clear();
73 buf.push_back(static_cast<unsigned char>(stream.str().length()));
74 ret << Bin2HexStr(buf);
75
76 ret << Bin2HexStr(stream.str());
77 ret << "c027";
78
79 ret << Bin2HexStr(std::string(";"));
80 buf.clear();
81 buf.push_back(static_cast<unsigned char>(svrName.length()));
82 ret << Bin2HexStr(buf);
83 ret << Bin2HexStr(svrName);
84 return ret.str();
85 }
86
BuildTxtServiceQuery(const std::string & instanceName,const std::string & serviceType,const WifiP2PDnsTxtRecord & txtRecord,const std::string & svrName)87 std::string WifiP2pDnsSdServiceInfo::BuildTxtServiceQuery(const std::string &instanceName,
88 const std::string &serviceType, const WifiP2PDnsTxtRecord &txtRecord, const std::string &svrName)
89 {
90 std::string ret("");
91 ret += std::string("bonjour ");
92 std::string dnsName = instanceName + std::string(".") + serviceType + std::string(".local.");
93 ret += BuildRequest(dnsName, DNS_TXT_TYPE, VERSION_1);
94 ret += std::string(" ");
95 std::vector<unsigned char> rawData = txtRecord.GetData();
96 if (rawData.empty()) {
97 ret += std::string("00");
98 } else {
99 ret += Bin2HexStr(rawData);
100 }
101
102 if (!svrName.empty()) {
103 if (!rawData.empty()) {
104 ret += std::string("00");
105 }
106 ret.append(Bin2HexStr(std::string(";")));
107 std::vector<unsigned char> buf;
108 buf.push_back(static_cast<unsigned char>(svrName.length()));
109 ret.append(Bin2HexStr(buf));
110 ret.append(Bin2HexStr(svrName));
111 }
112
113 return ret;
114 }
115
BuildRequest(const std::string & dnsName,int dnsType,int version)116 std::string WifiP2pDnsSdServiceInfo::BuildRequest(const std::string &dnsName, int dnsType, int version)
117 {
118 std::stringstream ret;
119 std::string name = dnsName;
120 const int stepFour = 4;
121 const int stepTwo = 2;
122 if (dnsType == WifiP2pDnsSdServiceInfo::DNS_TXT_TYPE) {
123 transform(name.begin(), name.end(), name.begin(), ::tolower);
124 }
125 ret << TurnDnsNameToStream(name);
126 ret << std::hex << std::setw(stepFour) << std::setfill('0') << dnsType;
127 ret << std::hex << std::setw(stepTwo) << std::setfill('0') << version;
128 return ret.str();
129 }
130
TurnDnsNameToStream(const std::string & dnsName)131 std::string WifiP2pDnsSdServiceInfo::TurnDnsNameToStream(const std::string &dnsName)
132 {
133 std::stringstream ret;
134 std::string name = dnsName;
135 const int stepTwo = 2;
136
137 while (true) {
138 std::string data = FindPacket(name);
139 if (!data.empty()) {
140 ret << data;
141 break;
142 }
143 auto i = name.find_first_of('.');
144 if (i == std::string::npos) {
145 if (name.length() > 0) {
146 ret << std::hex << std::setw(stepTwo) << std::setfill('0') << name.length();
147 ret << Bin2HexStr(name);
148 }
149 ret << "00"; /* for *\0 */
150 break;
151 }
152 if (i != 0) { /* for .* create dnsreq with (null, "*") will make the dnsname like ".tcp" */
153 std::string splitName = name.substr(0, i);
154 ret << std::hex << std::setw(stepTwo) << std::setfill('0') << splitName.length();
155 ret << Bin2HexStr(splitName);
156 }
157 name = name.substr(i + 1);
158 }
159 return ret.str();
160 }
161 } // namespace Wifi
162 } // namespace OHOS