Merge "Add the exception handling when using manual cert mode" into tizen_2.1
[platform/framework/native/net.git] / src / FNet_DnsRequestHandler.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18  * @file                FNet_DnsRequestHandler.cpp
19  * @brief               This is the implementation file for the _DnsRequestHandler Class.
20  *
21  */
22
23 #include <netdb.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <FNetIp4Address.h>
27 #include <FNetIpHostEntry.h>
28 #include <FBaseSysLog.h>
29 #include "FNet_NetTypes.h"
30 #include "FNet_IpHostEntryImpl.h"
31 #include "FNet_DnsEvent.h"
32 #include "FNet_DnsEventArg.h"
33 #include "FNet_DnsRequestHandler.h"
34
35 using namespace std;
36 using namespace Tizen::Base;
37 using namespace Tizen::Base::Runtime;
38 using namespace Tizen::Base::Collection;
39 using namespace Tizen::Base::Utility;
40
41 namespace Tizen { namespace Net
42 {
43
44 _DnsRequestHandler::_DnsRequestHandler(_DnsRequest* pDnsRequest)
45         : __pThread(null)
46         , __isStarted(false)
47 {
48         __pDnsRequest.reset(pDnsRequest);
49 }
50
51 result
52 _DnsRequestHandler::Construct()
53 {
54         result r = E_SUCCESS;
55
56         unique_ptr<Thread> pThread(new (std::nothrow) Thread());
57         SysTryReturnResult(NID_NET, pThread != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
58
59         r = pThread->Construct(*this);
60         SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM,
61                         "A system error has been occurred. Failed to construct a thread.");
62
63         __pThread = move(pThread);
64
65         return r;
66 }
67
68 _DnsRequestHandler::~_DnsRequestHandler()
69 {
70         if (__pThread != null)
71         {
72                 __pThread->Join();
73         }
74 }
75
76 Object*
77 _DnsRequestHandler::Run()
78 {
79         if (__pDnsRequest.get() != null)
80         {
81                 __pDnsRequest->Execute();
82
83                 __pDnsRequest.reset(null);
84         }
85
86         return null;
87 }
88
89 result
90 _DnsRequestHandler::Start()
91 {
92         result r = E_SUCCESS;
93
94         //start thread
95         SysTryReturnResult(NID_NET, __pThread != null, E_SYSTEM,
96                         "A system error has been occurred. __pThread must not be null.");
97
98         r = __pThread->Start();
99         SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM,
100                         "A system error has been occurred. Failed to start the thread.");
101
102         __isStarted = true;
103
104         return r;
105 }
106
107 bool
108 _DnsRequestHandler::IsRequestStarted()
109 {
110         return __isStarted;
111 }
112
113 result
114 _DnsRequestHandler::FireNetworkStoppedEvent()
115 {
116         result r = E_SUCCESS;
117
118         _DnsEventArg* pDnsEventArg = null;
119         
120         _DnsEvent& dnsEvent = __pDnsRequest->GetDnsEvent();     
121
122         // callback app with error E_NETWORK_UNAVAILABLE
123         pDnsEventArg = new (std::nothrow) _DnsEventArg(E_NETWORK_UNAVAILABLE, null);
124         SysTryReturnResult(NID_NET, pDnsEventArg != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
125
126         r = dnsEvent.FireAsync(*pDnsEventArg);
127
128         return r;
129 }
130
131 result
132 _DnsRequestHandler::DnsCallBack(struct hostent* pHostent, int dnsId, _DnsEvent& dnsEvent)
133 {
134         //NOTE: DONOT DELETE pHostent
135
136         result r = E_SUCCESS;
137
138         _DnsEventArg* pDnsEventArg = null;
139         unique_ptr<IpHostEntry> pIpHostEntry;
140         _IpHostEntryImpl* pIpHostEntryImpl = null;
141
142         SysLog(NID_NET, "DnsCallBack() has been called with DNS ID:%d", dnsId);
143
144         // we need to check for null, if null send callback to listener with  E_DNS_NOT_FOUND error
145         if (pHostent != null)
146         {
147                 struct in_addr** pInAddrList = null;
148
149                 pInAddrList = (struct in_addr**) pHostent->h_addr_list;
150
151                 //check we have got IP addresses and host name
152                 if (pInAddrList != null && *pInAddrList != null && pHostent->h_name != null)
153                 {
154                         // we have resolved the host. now populate the contents
155                         pIpHostEntry.reset(_IpHostEntryImpl::CreateIpHostEntryN());
156                         SysTryReturnResult(NID_NET, pIpHostEntry != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
157
158                         pIpHostEntryImpl = _IpHostEntryImpl::GetInstance(*pIpHostEntry);
159                         SysTryReturnResult(NID_NET, pIpHostEntryImpl != null, E_SYSTEM,
160                                         "A system error has been occurred. Failed to get IpHostEntry instance.");
161
162                         // fill address list
163                         r = SetAddressList(pHostent, *pIpHostEntryImpl);
164                         SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM,
165                                         "A system error has been occurred. Failed to set hostent to address list.");
166
167                         // Fill aliases
168                         r = SetAliasList(pHostent, *pIpHostEntryImpl);
169                         SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM,
170                                         "A system error has been occurred. Failed to set hostent to alias list.");
171                 }
172                 else
173                 {
174                         r = E_DNS_NOT_FOUND;
175                         SysLogException(NID_NET, r, "[%s] An error has been occurred getting host information.", GetErrorMessage(E_DNS_NOT_FOUND));
176                 }
177         }
178         else
179         {
180                 r = E_DNS_NOT_FOUND;
181                 SysLogException(NID_NET, r, "[%s] An error has been occurred getting host information.", GetErrorMessage(E_DNS_NOT_FOUND));
182         }
183         
184         // call app calback now.
185         //ownership of pIpHostEntry transferred to pDnsEventArg
186         pDnsEventArg = new (std::nothrow) _DnsEventArg(r, pIpHostEntry.get());
187         SysTryReturnResult(NID_NET, pDnsEventArg != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
188
189         pIpHostEntry.release();
190
191         r = dnsEvent.FireAsync(*pDnsEventArg);
192
193         SysLog(NID_NET, "[%s] DnsCallBack() has been done.", GetErrorMessage(r));
194
195         return r;
196 }
197
198 result
199 _DnsRequestHandler::SetAddressList(const struct hostent* pHostent, _IpHostEntryImpl& ipHostEntryImpl)
200 {
201         result r = E_SUCCESS;
202
203         // fill address list
204         struct in_addr** pInAddrList = null;
205
206         pInAddrList = (struct in_addr**) pHostent->h_addr_list;
207         SysTryReturnResult(NID_NET, pInAddrList != null, E_OPERATION_FAILED, "An error has been occurred in DNS response.");
208
209         unique_ptr<ArrayList, _CollectionDeleter> pAddrList(new (std::nothrow) ArrayList());
210         SysTryReturnResult(NID_NET, pAddrList != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
211
212         r = pAddrList->Construct();
213         SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM,
214                         "A system error has been occurred. Failed to construct an address list.");
215
216         for (int addrCount = 0; pInAddrList[addrCount] != null; addrCount++)
217         {
218                 SysLog(NID_NET, "Resolved IP Address is %s", inet_ntoa(*pInAddrList[addrCount]));
219
220                 unique_ptr<IpAddress> pIpAddress(new (std::nothrow) Ip4Address(ntohl((*pInAddrList[addrCount]).s_addr)));
221                 SysTryReturnResult(NID_NET, pIpAddress != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
222
223                 r = pAddrList->Add(*pIpAddress);
224                 SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM,
225                                 "A system error has been occurred. Failed to add the address to address list.");
226
227                 pIpAddress.release();
228         }
229
230         r = ipHostEntryImpl.SetAddressList(*pAddrList);
231         SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM, "A system error has been occurred. Failed to set address list.");
232
233         pAddrList.release();
234
235         return r;
236 }
237
238 result
239 _DnsRequestHandler::SetAliasList(const struct hostent* pHostent, _IpHostEntryImpl& ipHostEntryImpl)
240 {
241         result r = E_SUCCESS;
242
243         unique_ptr<ArrayList, _CollectionDeleter> pAliasList(new (std::nothrow) ArrayList());
244         SysTryReturnResult(NID_NET, pAliasList != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
245
246         r = pAliasList->Construct();
247         SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM,
248                         "A system error has been occurred. Failed to construct an alias list.");
249
250         //Add Hostname to alias list
251         if (pHostent->h_name != null)
252         {
253                 SysSecureLog(NID_NET, "Hostname: %s", pHostent->h_name);
254
255                 unique_ptr<String> pHostName(new (std::nothrow) String());
256                 SysTryReturnResult(NID_NET, pHostName != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
257
258                 r = StringUtil::Utf8ToString(pHostent->h_name, *pHostName);
259                 SysTryReturnResult(NID_NET, r != E_OUT_OF_MEMORY, r, "Propagating.");
260                 if (r == E_INVALID_ENCODING_RANGE)
261                 {
262                         SysLog(NID_NET, "Failed to convert UTF-8 string into a Unicode string.");
263                 }
264                 else
265                 {
266                         r = pAliasList->Add(*pHostName);
267                         SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM,
268                                         "A system error has been occurred. Failed to add the hostname to alias list.");
269
270                         pHostName.release();
271                 }
272         }
273
274         r = ipHostEntryImpl.SetAliasList(*pAliasList);
275         SysTryReturnResult(NID_NET, r == E_SUCCESS, E_SYSTEM,
276                         "A system error has been occurred. Failed to set alias list.");
277
278         pAliasList.release();
279         
280         return r;
281 }
282
283 // _DnsRequest class implementation
284 _DnsRequest::_DnsRequest(_NetDnsEventType msgType, char* pMsgData, _DnsEvent& dnsEvent)
285         : __msgType(msgType)
286         , __dnsEvent(dnsEvent)
287 {
288         __pMsgData.reset(pMsgData);
289 }
290
291 _DnsRequest::~_DnsRequest()
292 {
293 }
294
295 void
296 _DnsRequest::Execute()
297 {
298         if (__msgType == NET_DNS_EVENT_HOSTNAME)
299         {
300                 struct hostent* pHostent = null;
301
302                 pHostent = (hostent*) gethostbyname(__pMsgData.get());
303                 _DnsRequestHandler::DnsCallBack(pHostent, NET_DNS_EVENT_HOSTNAME, __dnsEvent);
304         }
305         else if (__msgType == NET_DNS_EVENT_ADDRESS)
306         {
307                 struct hostent* pHostent = null;
308                 struct in_addr ipv4addr;
309
310                 inet_pton(AF_INET, __pMsgData.get(), &ipv4addr);
311
312                 pHostent = (hostent*) gethostbyaddr(&ipv4addr, sizeof(ipv4addr), AF_INET);
313                 _DnsRequestHandler::DnsCallBack(pHostent, NET_DNS_EVENT_ADDRESS, __dnsEvent);
314         }
315
316 }
317
318 _DnsEvent&
319 _DnsRequest::GetDnsEvent()
320 {
321         return  __dnsEvent;
322 }
323
324 } } // Tizen::Net