merge with master
[framework/osp/net.git] / src / http / FNetHttp_HttpSessionImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 /**
19  * @file                FNetHttp_HttpSessionImpl.cpp
20  * @brief               This is the implementation file for _HttpSessionImpl class.
21  */
22
23 #include <unique_ptr.h>
24 #include <FBaseString.h>
25 #include <FBaseUtilStringUtil.h>
26 #include <FIoFile.h>
27 #include <FNetNetConnection.h>
28 #include <FNetManagedNetConnection.h>
29 #include <FNetNetConnectionManager.h>
30 #include <FNetHttpHttpSession.h>
31 #include <FNetHttpHttpAuthentication.h>
32 #include <FBaseSysLog.h>
33 #include <FBaseRtMutex.h>
34 #include <FBaseRtMutexGuard.h>
35 #include <FBase_StringConverter.h>
36 #include <FBaseRt_EventDispatcher.h>
37 #include "FNet_ManagedNetConnectionImpl.h"
38 #include "FNet_NetConnectionInfoImpl.h"
39 #include "FNet_NetConnectionImpl.h"
40 #include "FNet_NetConnectionManagerImpl.h"
41 #include "FNetHttp_HttpCommon.h"
42 #include "FNetHttp_HttpDeleter.h"
43 #include "FNetHttp_HttpSessionImpl.h"
44 #include "FNetHttp_HttpMultipleConnectionInfo.h"
45 #include "FNetHttp_HttpTransactionImpl.h"
46 #include "FNetHttp_HttpCurl.h"
47 #include "FNetHttp_HttpRequestImpl.h"
48 #include "FNetHttp_HttpResponseImpl.h"
49 #include "FNetHttp_HttpHeaderImpl.h"
50 #include "FNetHttp_HttpAuthenticationImpl.h"
51 #include "FNetHttp_HttpCookieStorageManagerImpl.h"
52 #include "FNetHttp_HttpTransactionEventArg.h"
53 #include "FNetHttp_HttpTransactionEvent.h"
54 #include "FNetHttp_HttpNetConnectionEventListenerImpl.h"
55 #include "FNetHttp_HttpManagedNetConnectionEventListenerImpl.h"
56
57 using namespace std;
58 using namespace Tizen::Base;
59 using namespace Tizen::Base::Runtime;
60 using namespace Tizen::Base::Utility;
61 using namespace Tizen::Base::Collection;
62 using namespace Tizen::Io;
63 using namespace Tizen::Net;
64
65 namespace Tizen { namespace Net { namespace Http
66 {
67
68 int _HttpSessionImpl::__generatedSessionId = -1;
69 int _HttpSessionImpl::__countOfSessions = 0;
70
71 _HttpSessionImpl::_HttpSessionImpl(HttpSession* pHttpSession)
72         : __sessionId(-1)
73         , __pHttpSession(pHttpSession)
74         , __isConstructed(false)
75         , __sessionMode(NET_HTTP_SESSION_MODE_NORMAL)
76         , __pProxyAddress(null)
77         , __pCommonHeader(null)
78         , __cookieFlag(NET_HTTP_COOKIE_FLAG_NONE)
79         , __countOfTransaction(0)
80         , __isSecure(false)
81         , __isValid(false)
82         , __isClosed(false)
83         , __isAutoRedirectionEnabled(false)
84         , __isAlreadyResumed(false)
85         , __pHttpMultipleConnectionInfo(null)
86         , __pCookieStorageMgr(null)
87         , __pNetConnection(null)
88         , __pNetConnectionListener(null)
89         , __pManagedNetConnection(null)
90         , __pManagedNetConnectionListener(null)
91 {
92 }
93
94 _HttpSessionImpl::~_HttpSessionImpl(void)
95 {
96         SysLog(NID_NET_HTTP, "The HttpSession[%d] instance will be deleted.", __sessionId);
97
98         Dispose();
99
100         if (__pProxyAddress != null)
101         {
102                 delete __pProxyAddress;
103                 __pProxyAddress = null;
104         }
105
106         if (__pCommonHeader != null)
107         {
108                 _HttpHeaderImpl::GetInstance(*__pCommonHeader)->RemoveAll();
109                 delete __pCommonHeader;
110                 __pCommonHeader = null;
111         }
112
113         if (__pHttpMultipleConnectionInfo != null)
114         {
115                 __pHttpMultipleConnectionInfo->Release();
116         }
117
118         if (__pCookieStorageMgr != null)
119         {
120                 _HttpCookieStorageManagerImpl::DeleteHttpCookieStorageManager(__pCookieStorageMgr);
121                 __pCookieStorageMgr = null;
122         }
123
124         if (__pNetConnection != null)
125         {
126                 delete __pNetConnection;
127                 __pNetConnection = null;
128         }
129
130         if (__pNetConnectionListener != null)
131         {
132                 delete __pNetConnectionListener;
133                 __pNetConnectionListener = null;
134         }
135
136         if (__pManagedNetConnection != null)
137         {
138                 delete __pManagedNetConnection;
139                 __pManagedNetConnection = null;
140         }
141
142         if (__pManagedNetConnectionListener != null)
143         {
144                 delete __pManagedNetConnectionListener;
145                 __pManagedNetConnectionListener = null;
146         }
147
148         __isConstructed = false;
149         __sessionMode = NET_HTTP_SESSION_MODE_NORMAL;
150
151         __countOfTransaction = 0;
152         __isSecure = false;
153         __isValid = false;
154         __isClosed = false;
155
156         SysLog(NID_NET_HTTP, "The HttpSession[%d] instance was deleted.", __sessionId);
157
158         __sessionId = -1;
159 }
160
161 String
162 _HttpSessionImpl_GetSessionModeAsString(NetHttpSessionMode sessionMode)
163 {
164         switch (sessionMode)
165         {
166         case NET_HTTP_SESSION_MODE_NORMAL:
167                 return String(L"NET_HTTP_SESSION_MODE_NORMAL");
168
169         case NET_HTTP_SESSION_MODE_PIPELINING:
170                 return String(L"NET_HTTP_SESSION_MODE_PIPELINING");
171
172         case NET_HTTP_SESSION_MODE_MULTIPLE_HOST:
173                 return String(L"NET_HTTP_SESSION_MODE_MULTIPLE_HOST");
174
175         default:
176                 return String(L"Invalid SessionMode");
177         }
178 }
179
180 String
181 _HttpSessionImpl_GetCookieFlagAsString(NetHttpCookieFlag flag)
182 {
183         switch (flag)
184         {
185         case NET_HTTP_COOKIE_FLAG_NONE:
186                 return String(L"NET_HTTP_COOKIE_FLAG_NONE");
187
188         case NET_HTTP_COOKIE_FLAG_ALWAYS_AUTOMATIC:
189                 return String(L"NET_HTTP_COOKIE_FLAG_ALWAYS_AUTOMATIC");
190
191         case NET_HTTP_COOKIE_FLAG_ALWAYS_MANUAL:
192                 return String(L"NET_HTTP_COOKIE_FLAG_ALWAYS_MANUAL");
193
194         default:
195                 return String(L"Invalid CookieFlag");
196         }
197 }
198
199 result
200 _HttpSessionImpl::Construct(NetHttpSessionMode sessionMode, const String* pProxyAddr, const String& hostAddr,
201                                                         const HttpHeader* pCommonHeader,
202                                                         NetHttpCookieFlag flag)
203 {
204         result r = E_SUCCESS;
205
206         SysTryReturnResult(NID_NET_HTTP, __isConstructed == false,
207                                            E_INVALID_STATE, "Already constructed.");
208
209         SysTryReturnResult(NID_NET_HTTP, sessionMode == NET_HTTP_SESSION_MODE_NORMAL || sessionMode == NET_HTTP_SESSION_MODE_PIPELINING || sessionMode == NET_HTTP_SESSION_MODE_MULTIPLE_HOST,
210                                            E_INVALID_ARG, "Invalid SessionMode.");
211
212         if (sessionMode != NET_HTTP_SESSION_MODE_MULTIPLE_HOST)
213         {
214                 SysTryReturnResult(NID_NET_HTTP, hostAddr.GetLength() > 0,
215                                                    E_INVALID_ARG, "Invalid hostAddr.");
216
217         }
218         SysTryReturnResult(NID_NET_HTTP, NET_HTTP_COOKIE_FLAG_NONE == flag || NET_HTTP_COOKIE_FLAG_ALWAYS_AUTOMATIC == flag || NET_HTTP_COOKIE_FLAG_ALWAYS_MANUAL == flag,
219                                            E_INVALID_ARG, "Invalid cookie flag.");
220
221         SysLog(NID_NET_HTTP, "There are currently opened sessions[%d] in the Application.", __countOfSessions);
222
223         _HttpUtility::InitializeHttp();
224
225         Mutex* pHttpMutex = _HttpUtility::GetHttpMutex();
226
227         MutexGuard locked(*pHttpMutex);
228         SysTryReturnResult(NID_NET_HTTP, locked.IsLocked(), E_SYSTEM,
229                         "Failed to lock mutex.");
230
231         SysTryReturnResult(NID_NET_HTTP, __countOfSessions < _MAX_HTTP_SESSIONS_PER_APPID_PER_PROTOCOL, E_MAX_EXCEEDED,
232                         "The number of currently opened sessions have exceeded the maximum limit(%d).", _MAX_HTTP_SESSIONS_PER_APPID_PER_PROTOCOL);
233
234         r = locked.Unlock();
235         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_SYSTEM,
236                         "Failed to unlock mutex.");
237
238         SysLog(NID_NET_HTTP, "[ManagedNetConnection] NetHttpSessionMode : %ls, Host Address : %ls, NetHttpCookieFlag : %ls",
239                    _HttpSessionImpl_GetSessionModeAsString(sessionMode).GetPointer(), hostAddr.GetPointer(), _HttpSessionImpl_GetCookieFlagAsString(flag).GetPointer());
240
241         _ManagedNetConnectionImpl* pManagedNetConnectionImpl = null;
242         NetConnectionState connState = NET_CONNECTION_STATE_NONE;
243         String tempAddress;
244         String proxyAddressOfManagedMode;
245         bool hasProtocolScheme = false;
246         Uri* pHostUri = null;
247         Uri* pProxyUri = null;
248         CURLM* pCurlM = null;
249         __sessionMode = sessionMode;
250         unique_ptr<_HttpManagedNetConnectionEventListenerImpl> pManagedNetConnectionListener;
251         unique_ptr<ManagedNetConnection> pManagedNetConnection;
252         unique_ptr<String> pProxyAddress;
253         unique_ptr<HttpHeader> pHeader;
254         unique_ptr<_HttpMultipleConnectionInfo> pHttpMultipleConnectionInfo;
255         unique_ptr<HttpCookieStorageManager, _HttpCookieStorageManagerDeleter> pCookieStorageMgr;
256
257         NetConnectionManager netConnectionManager;
258
259         r = netConnectionManager.Construct();
260         r = TransExceptionsExclusive(r, E_INVALID_CONNECTION, E_OUT_OF_MEMORY);
261         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS,
262                                            r, "Failed to construct the connection manager.");
263
264         pManagedNetConnection.reset(netConnectionManager.GetManagedNetConnectionN());
265         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS,
266                                            E_INVALID_CONNECTION, "Failed to get the managed network connection.");
267
268         pManagedNetConnectionImpl = _ManagedNetConnectionImpl::GetInstance(*pManagedNetConnection);
269         SysTryReturnResult(NID_NET_HTTP, pManagedNetConnectionImpl != null,
270                                            E_INVALID_CONNECTION, "Failed to get the managed network connection.");
271
272         pManagedNetConnectionListener.reset(new (std::nothrow) _HttpManagedNetConnectionEventListenerImpl(this));
273         SysTryReturnResult(NID_NET_HTTP, pManagedNetConnectionListener != null,
274                                            E_OUT_OF_MEMORY, "Memory allocation failed.");
275
276         r = pManagedNetConnection->SetManagedNetConnectionEventListener(pManagedNetConnectionListener.get());
277         r = TransExceptionsExclusive(r, E_INVALID_CONNECTION, E_OUT_OF_MEMORY);
278         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS,
279                                            r, "Failed to set the listener of managed network.");
280
281         if (_NetConnectionManagerImpl::IsDefaultMode() != true)
282         {
283                 SysLog(NID_NET_HTTP, "[Preference Mode] Current network is specific network preference Mode.");
284
285                 r = pManagedNetConnectionImpl->Start();
286                 r = TransExceptionsExclusive(r, E_INVALID_CONNECTION, E_OUT_OF_MEMORY);
287                 SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r, "Failed to start the managed network connection.");
288
289                 connState = pManagedNetConnectionImpl->GetConnectionState();
290                 if (connState == NET_CONNECTION_STATE_STARTED || connState == NET_CONNECTION_STATE_RESUMED || connState == NET_CONNECTION_STATE_SUSPENDED)
291                 {
292                         pManagedNetConnectionListener->SetReceivedEvent(true);
293
294                         const NetConnectionInfo* pConnectionInfo = pManagedNetConnectionImpl->GetNetConnectionInfo();
295                         SysTryReturnResult(NID_NET_HTTP, pConnectionInfo != null,
296                                                            E_INVALID_CONNECTION, "Failed to get NetConnectionInfo.");
297
298                         const _NetConnectionInfoImpl* pConnectionInfoImpl = _NetConnectionInfoImpl::GetInstance(*pConnectionInfo);
299                         SysTryReturnResult(NID_NET_HTTP, pConnectionInfoImpl != null,
300                                                            E_INVALID_CONNECTION, "Failed to get NetConnectionInfo.");
301
302                         proxyAddressOfManagedMode = pConnectionInfoImpl->GetProxyAddress();
303                         __deviceName = pConnectionInfoImpl->GetDeviceName();
304                         SysLog(NID_NET_HTTP, "[Preference Mode] Network is already started. The device name is %ls, the system proxy address is %ls.", __deviceName.GetPointer(), proxyAddressOfManagedMode.GetPointer());
305                 }
306         }
307         else
308         {
309                 pManagedNetConnectionListener->SetReceivedEvent(true);
310                 proxyAddressOfManagedMode = _NetConnectionManagerImpl::GetProxyAddress();
311                 SysLog(NID_NET_HTTP, "[Default Mode] The current network is managed network preference Mode. The system proxy address is %ls.", proxyAddressOfManagedMode.GetPointer());
312         }
313
314         if (pProxyAddr != null)
315         {
316                 SysLog(NID_NET_HTTP, "The proxy address is %ls.", pProxyAddr->GetPointer());
317
318                 pProxyAddress.reset(new (std::nothrow) String(*pProxyAddr));
319                 SysTryReturnResult(NID_NET_HTTP, pProxyAddress != null, E_OUT_OF_MEMORY,
320                                         "Memory allocation failed.");
321         }
322         else
323         {
324                 if (_NetConnectionManagerImpl::IsDefaultMode() == true || pManagedNetConnectionListener->IsEventReceived() == true)
325                 {
326                         SysLog(NID_NET_HTTP, "The proxy url is %ls.", proxyAddressOfManagedMode.GetPointer());
327
328                         pProxyAddress.reset(new (std::nothrow) String(proxyAddressOfManagedMode));
329                         SysTryReturnResult(NID_NET_HTTP, pProxyAddress != null, E_OUT_OF_MEMORY,
330                                                 "Memory allocation failed.");
331
332                 }
333                 else
334                 {
335                         SysLog(NID_NET_HTTP, "[Preference Mode] The system proxy address will be gotten after the managed connection is started.");
336                 }
337         }
338
339         pProxyAddress->Trim();
340         pProxyAddress->ToLower(tempAddress);
341
342         if (tempAddress.IsEmpty() == false)
343         {
344                 hasProtocolScheme = _HttpUtility::HasProtocolScheme(tempAddress);
345                 if (!hasProtocolScheme)
346                 {
347                         (*pProxyAddress) = _HTTP_PROTOCOL_SCHEME + (*pProxyAddress);
348                 }
349
350                 pProxyUri = new (std::nothrow) Uri();
351                 SysTryReturnResult(NID_NET_HTTP, pProxyUri != null, E_OUT_OF_MEMORY,
352                                         "Memory allocation failed.");
353
354                 r = pProxyUri->SetUri(*pProxyAddress);
355                 delete pProxyUri;
356                 SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_INVALID_PROXY,
357                                         "The proxy address is invalid.");
358         }
359
360         if (sessionMode != NET_HTTP_SESSION_MODE_MULTIPLE_HOST)
361         {
362                 __hostAddress = hostAddr;
363                 __hostAddress.Trim();
364                 __hostAddress.ToLower(tempAddress);
365
366                 hasProtocolScheme = _HttpUtility::HasProtocolScheme(tempAddress);
367                 if (!hasProtocolScheme)
368                 {
369                         //Add the prefix as "http://"
370                         __hostAddress = _HTTP_PROTOCOL_SCHEME + __hostAddress;
371                 }
372
373                 SysLog(NID_NET_HTTP, "The host address is %ls.", __hostAddress.GetPointer());
374
375                 pHostUri = new (std::nothrow) Uri();
376                 SysTryReturnResult(NID_NET_HTTP, pHostUri != null, E_OUT_OF_MEMORY,
377                                         "Memory allocation failed.");
378
379                 r = pHostUri->SetUri(__hostAddress);
380                 delete pHostUri;
381                 r = TransExceptionsExclusive(r, E_INVALID_ARG, E_OUT_OF_MEMORY);
382                 SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r, "The host address is invalid.");
383         }
384
385         if (pCommonHeader != null)
386         {
387                 String* pRawHeaderString = pCommonHeader->GetRawHeaderN();
388                 SysLog(NID_NET_HTTP, "The common header is %ls.", pRawHeaderString->GetPointer());
389                 delete pRawHeaderString;
390
391                 pHeader.reset(new (std::nothrow) HttpHeader(pCommonHeader));
392                 r = GetLastResult();
393                 SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r, "Propagating.");
394         }
395         else
396         {
397                 SysLog(NID_NET_HTTP, "The common header is null.");
398         }
399
400         __cookieFlag = flag;
401
402         pHttpMultipleConnectionInfo.reset(new (std::nothrow) _HttpMultipleConnectionInfo());
403         SysTryReturnResult(NID_NET_HTTP, pHttpMultipleConnectionInfo != null, E_OUT_OF_MEMORY,
404                                 "Memory allocation failed.");
405
406         pCurlM = curl_multi_init();
407         __sessionId = _HttpSessionImpl::GenerateSessionId();
408
409         //If sessionId is 0, delete the cookie_{appid}.txt file.
410         InitializeSession();
411
412         r = pHttpMultipleConnectionInfo->Construct(pCurlM, __sessionId, __cookieFlag);
413         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r, "Propagating.");
414
415         curl_multi_setopt(pCurlM, CURLMOPT_SOCKETFUNCTION, _HttpMultipleConnectionInfo::OnCurlMultiSocketUpdated);
416         curl_multi_setopt(pCurlM, CURLMOPT_SOCKETDATA, pHttpMultipleConnectionInfo.get());
417         curl_multi_setopt(pCurlM, CURLMOPT_TIMERFUNCTION, _HttpMultipleConnectionInfo::OnCurlMultiTimerChanged);
418         curl_multi_setopt(pCurlM, CURLMOPT_TIMERDATA, pHttpMultipleConnectionInfo.get());
419
420         if (__sessionMode == NET_HTTP_SESSION_MODE_PIPELINING)
421         {
422                 curl_multi_setopt(pCurlM, CURLMOPT_PIPELINING, 1L);
423                 SysLog(NID_NET_HTTP, "The pipelining mode was enabled. HttpSession[%d]", __sessionId);
424         }
425
426         pCookieStorageMgr.reset(_HttpCookieStorageManagerImpl::CreateHttpCookieStorageManagerN());
427         SysTryReturnResult(NID_NET_HTTP, pCookieStorageMgr != null, E_OUT_OF_MEMORY,
428                                 "Memory allocation failed.");
429
430         r = __activeTransactions.Construct();
431         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_OUT_OF_MEMORY,
432                                 "Memory allocation failed.");
433
434         r = locked.Lock();
435         SysTryReturnResult(NID_NET_HTTP, locked.IsLocked(), E_SYSTEM,
436                         "Failed to lock mutex.");
437
438         __countOfSessions++;
439
440         r = locked.Unlock();
441         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_SYSTEM,
442                         "Failed to unlock mutex.");
443
444         __isConstructed = true;
445         __isValid = true;
446
447         __pManagedNetConnection = pManagedNetConnection.release();
448         __pManagedNetConnectionListener = pManagedNetConnectionListener.release();
449         __pProxyAddress = pProxyAddress.release();
450         __pCommonHeader = pHeader.release();
451         __pHttpMultipleConnectionInfo = pHttpMultipleConnectionInfo.release();
452         __pCookieStorageMgr = pCookieStorageMgr.release();
453
454         SysLog(NID_NET_HTTP, "The HttpSession[%d] instance was created.", __sessionId);
455
456         return r;
457 }
458
459 result
460 _HttpSessionImpl::Construct(const NetConnection& netConnection, NetHttpSessionMode sessionMode,
461                                                         const String* pProxyAddr, const String& hostAddr, const HttpHeader* pCommonHeader,
462                                                         NetHttpCookieFlag flag)
463 {
464         result r = E_SUCCESS;
465
466         SysTryReturnResult(NID_NET_HTTP, __isConstructed == false,
467                                            E_INVALID_STATE, "Already constructed.");
468
469         SysTryReturnResult(NID_NET_HTTP, sessionMode == NET_HTTP_SESSION_MODE_NORMAL || sessionMode == NET_HTTP_SESSION_MODE_PIPELINING || sessionMode == NET_HTTP_SESSION_MODE_MULTIPLE_HOST,
470                                            E_INVALID_ARG, "Invalid SessionMode.");
471
472         if (sessionMode != NET_HTTP_SESSION_MODE_MULTIPLE_HOST)
473         {
474                 SysTryReturnResult(NID_NET_HTTP, hostAddr.GetLength() > 0,
475                                                    E_INVALID_ARG, "Invalid hostAddr.");
476
477         }
478         SysTryReturnResult(NID_NET_HTTP, NET_HTTP_COOKIE_FLAG_NONE == flag || NET_HTTP_COOKIE_FLAG_ALWAYS_AUTOMATIC == flag || NET_HTTP_COOKIE_FLAG_ALWAYS_MANUAL == flag,
479                                            E_INVALID_ARG, "Invalid cookie flag.");
480
481         _HttpUtility::InitializeHttp();
482
483         // Check the network state
484         NetConnectionState connState = netConnection.GetConnectionState();
485         if (connState == NET_CONNECTION_STATE_STARTED || connState == NET_CONNECTION_STATE_RESUMED || connState == NET_CONNECTION_STATE_SUSPENDED)
486         {
487                 SysLog(NID_NET_HTTP, "The custom network is available.");
488         }
489         else
490         {
491                 r = E_INVALID_CONNECTION;
492                 SysLogException(NID_NET_HTTP, r, "[E_INVALID_CONNECTION] Custom Network is not available.");
493                 return r;
494         }
495
496         const NetConnectionInfo* pConnectionInfo = null;
497         const _NetConnectionInfoImpl* pConnectionInfoImpl = null;
498         _NetConnectionImpl* pNetConnectionImpl = const_cast< _NetConnectionImpl* >(_NetConnectionImpl::GetInstance(netConnection));
499         SysTryReturnResult(NID_NET_HTTP, pNetConnectionImpl != null,
500                                            E_OUT_OF_MEMORY, "Memory allocation failed.");
501
502         SysLog(NID_NET_HTTP, "There are currently opened sessions[%d] in the Application.", __countOfSessions);
503
504         Mutex* pHttpMutex = _HttpUtility::GetHttpMutex();
505
506         MutexGuard locked(*pHttpMutex);
507         SysTryReturnResult(NID_NET_HTTP, locked.IsLocked(), E_SYSTEM,
508                         "Failed to lock mutex.");
509
510         SysTryReturnResult(NID_NET_HTTP, __countOfSessions < _MAX_HTTP_SESSIONS_PER_APPID_PER_PROTOCOL, E_MAX_EXCEEDED,
511                         "The number of currently opened sessions have exceeded the maximum limit(%d)", _MAX_HTTP_SESSIONS_PER_APPID_PER_PROTOCOL);
512
513         r = locked.Unlock();
514         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_SYSTEM,
515                         "Failed to unlock mutex.");
516
517         SysLog(NID_NET_HTTP, "[ManagedNetConnection] NetHttpSessionMode: %ls, Host Address: %ls, NetHttpCookieFlag: %ls",
518                    _HttpSessionImpl_GetSessionModeAsString(
519                            sessionMode).GetPointer(), hostAddr.GetPointer(), _HttpSessionImpl_GetCookieFlagAsString(flag).GetPointer());
520
521         String tempAddress;
522         bool hasProtocolScheme = false;
523         Uri* pHostUri = null;
524         Uri* pProxyUri = null;
525         CURLM* pCurlM = null;
526         __sessionMode = sessionMode;
527         unique_ptr<_HttpNetConnectionEventListenerImpl> pNetConnectionListener;
528         unique_ptr<NetConnection> pNetConnection;
529         unique_ptr<String> pProxyAddress;
530         unique_ptr<HttpHeader> pHeader;
531         unique_ptr<_HttpMultipleConnectionInfo> pHttpMultipleConnectionInfo;
532         unique_ptr<HttpCookieStorageManager, _HttpCookieStorageManagerDeleter> pCookieStorageMgr;
533
534         if (pProxyAddr != null)
535         {
536                 SysLog(NID_NET_HTTP, "The proxy address %ls.", pProxyAddr->GetPointer());
537
538                 pProxyAddress.reset(new (std::nothrow) String(*pProxyAddr));
539                 SysTryReturnResult(NID_NET_HTTP, pProxyAddress != null, E_OUT_OF_MEMORY,
540                                         "Memory allocation failed.");
541         }
542         else
543         {
544                 String defaultProxyUrl = pNetConnectionImpl->GetProxyAddress();
545                 SysLog(NID_NET_HTTP, "The system proxy is %ls.", defaultProxyUrl.GetPointer());
546
547                 pProxyAddress.reset(new (std::nothrow) String(defaultProxyUrl));
548                 SysTryReturnResult(NID_NET_HTTP, pProxyAddress != null, E_OUT_OF_MEMORY,
549                                         "Memory allocation failed.");
550         }
551
552         pProxyAddress->Trim();
553         pProxyAddress->ToLower(tempAddress);
554
555         if (tempAddress.IsEmpty() == false)
556         {
557                 hasProtocolScheme = _HttpUtility::HasProtocolScheme(tempAddress);
558                 if (!hasProtocolScheme)
559                 {
560                         (*pProxyAddress) = _HTTP_PROTOCOL_SCHEME + (*pProxyAddress);
561                 }
562
563                 pProxyUri = new (std::nothrow) Uri();
564                 SysTryReturnResult(NID_NET_HTTP, pProxyUri != null, E_OUT_OF_MEMORY,
565                                         "Memory allocation failed.");
566
567                 r = pProxyUri->SetUri(*pProxyAddress);
568                 delete pProxyUri;
569                 r = TransExceptionsExclusive(r, E_INVALID_PROXY, E_OUT_OF_MEMORY);
570                 SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r,
571                                         "The proxy address is invalid.");
572         }
573
574         if (sessionMode != NET_HTTP_SESSION_MODE_MULTIPLE_HOST)
575         {
576                 __hostAddress = hostAddr;
577                 __hostAddress.Trim();
578                 __hostAddress.ToLower(tempAddress);
579
580                 hasProtocolScheme = _HttpUtility::HasProtocolScheme(tempAddress);
581                 if (!hasProtocolScheme)
582                 {
583                         //Add the prefix as "http://"
584                         __hostAddress = _HTTP_PROTOCOL_SCHEME + __hostAddress;
585                 }
586
587                 SysLog(NID_NET_HTTP, "The host address is %ls.", __hostAddress.GetPointer());
588
589                 pHostUri = new (std::nothrow) Uri();
590                 SysTryReturnResult(NID_NET_HTTP, pHostUri != null, E_OUT_OF_MEMORY,
591                                         "Memory allocation failed.");
592
593                 r = pHostUri->SetUri(__hostAddress);
594                 delete pHostUri;
595                 r = TransExceptionsExclusive(r, E_INVALID_ARG, E_OUT_OF_MEMORY);
596                 SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r,
597                                         "The host address is invalid.");
598         }
599
600         if (pCommonHeader != null)
601         {
602                 String* pRawHeaderString = pCommonHeader->GetRawHeaderN();
603                 if (pRawHeaderString != null)
604                 {
605                         SysLog(NID_NET_HTTP, "The common header is %ls.", pRawHeaderString->GetPointer());
606                         delete pRawHeaderString;
607                 }
608
609                 pHeader.reset(new (std::nothrow) HttpHeader(pCommonHeader));
610                 r = GetLastResult();
611                 SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r, "Propagating.");
612         }
613         else
614         {
615                 SysLog(NID_NET_HTTP, "The common header is null.");
616         }
617
618         __cookieFlag = flag;
619
620         pHttpMultipleConnectionInfo.reset(new (std::nothrow) _HttpMultipleConnectionInfo());
621         SysTryReturnResult(NID_NET_HTTP, pHttpMultipleConnectionInfo != null, E_OUT_OF_MEMORY,
622                                 "Memory allocation failed.");
623
624         pCurlM = curl_multi_init();
625
626         __sessionId = _HttpSessionImpl::GenerateSessionId();
627
628         //If sessionId is 0, delete the cookies}.txt file.
629         InitializeSession();
630
631         r = pHttpMultipleConnectionInfo->Construct(pCurlM, __sessionId, __cookieFlag);
632         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r, "Propagating.");
633
634         curl_multi_setopt(pCurlM, CURLMOPT_SOCKETFUNCTION, _HttpMultipleConnectionInfo::OnCurlMultiSocketUpdated);
635         curl_multi_setopt(pCurlM, CURLMOPT_SOCKETDATA, pHttpMultipleConnectionInfo.get());
636         curl_multi_setopt(pCurlM, CURLMOPT_TIMERFUNCTION, _HttpMultipleConnectionInfo::OnCurlMultiTimerChanged);
637         curl_multi_setopt(pCurlM, CURLMOPT_TIMERDATA, pHttpMultipleConnectionInfo.get());
638
639         if (__sessionMode == NET_HTTP_SESSION_MODE_PIPELINING)
640         {
641                 curl_multi_setopt(pCurlM, CURLMOPT_PIPELINING, 1L);
642                 SysLog(NID_NET_HTTP, "Enable the pipelining mode, HttpSession[%d]", __sessionId);
643         }
644
645         pCookieStorageMgr.reset(_HttpCookieStorageManagerImpl::CreateHttpCookieStorageManagerN());
646         SysTryReturnResult(NID_NET_HTTP, pCookieStorageMgr != null, E_OUT_OF_MEMORY,
647                                 "Memory allocation failed.");
648
649         // Set the device name (setsockopt)
650         pConnectionInfo = netConnection.GetNetConnectionInfo();
651         pConnectionInfoImpl = _NetConnectionInfoImpl::GetInstance(*pConnectionInfo);
652
653         __deviceName = pConnectionInfoImpl->GetDeviceName();
654         if (__deviceName.IsEmpty())
655         {
656                 SysLog(NID_NET_HTTP, "[Emulator] The device name is an empty string.");
657         }
658         else
659         {
660                 SysLog(NID_NET_HTTP, "[Target] The device name is %ls.", __deviceName.GetPointer());
661         }
662
663         // Creates new NetConnection for receiving the network event.
664         pNetConnection.reset(pNetConnectionImpl->CopyInstanceN());
665         SysTryReturnResult(NID_NET_HTTP, pNetConnection != null, E_OUT_OF_MEMORY,
666                                 "Memory allocation failed.");
667
668         // New CustomNetConnectionEventListener
669         pNetConnectionListener.reset(new (std::nothrow) _HttpNetConnectionEventListenerImpl(this));
670         SysTryReturnResult(NID_NET_HTTP, pNetConnectionListener != null, E_OUT_OF_MEMORY,
671                                 "Memory allocation failed.");
672
673         // Add NetConnectionListener
674         r = pNetConnection->AddNetConnectionListener(*pNetConnectionListener);
675         r = TransExceptionsExclusive(r, E_SYSTEM, E_OUT_OF_MEMORY);
676         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r,
677                                 "Failed to add the NetConnection listener.");
678
679         r = __activeTransactions.Construct();
680         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_OUT_OF_MEMORY,
681                                 "Memory allocation failed.");
682
683         r = locked.Lock();
684         SysTryReturnResult(NID_NET_HTTP, locked.IsLocked(), E_SYSTEM,
685                         "Failed to lock mutex.");
686
687         __countOfSessions++;
688
689         r = locked.Unlock();
690         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_SYSTEM,
691                         "Failed to unlock mutex.");
692
693         __isConstructed = true;
694         __isValid = true;
695
696         __pNetConnection = pNetConnection.release();
697         __pNetConnectionListener = pNetConnectionListener.release();
698         __pProxyAddress = pProxyAddress.release();
699         __pCommonHeader = pHeader.release();
700         __pHttpMultipleConnectionInfo = pHttpMultipleConnectionInfo.release();
701         __pCookieStorageMgr = pCookieStorageMgr.release();
702
703         SysLog(NID_NET_HTTP, "The HttpSession[%d] instance was created.", __sessionId);
704
705         return r;
706 }
707
708 HttpCookieStorageManager*
709 _HttpSessionImpl::GetCookieStorageManager(void) const
710 {
711         ClearLastResult();
712
713         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
714         SysAssertf(__pCookieStorageMgr != null, "The pCookieStorageMgr must not be null.");
715
716         return __pCookieStorageMgr;
717 }
718
719 _HttpSessionImpl*
720 _HttpSessionImpl::GetInstance(HttpSession& httpSession)
721 {
722         return httpSession.__pHttpSessionImpl;
723 }
724
725 const _HttpSessionImpl*
726 _HttpSessionImpl::GetInstance(const HttpSession& httpSession)
727 {
728         return httpSession.__pHttpSessionImpl;
729 }
730
731 NetHttpSessionMode
732 _HttpSessionImpl::GetSessionMode(void) const
733 {
734         return __sessionMode;
735 }
736
737 String
738 _HttpSessionImpl::GetHostAddress(void) const
739 {
740         return __hostAddress;
741 }
742
743 String*
744 _HttpSessionImpl::GetProxyAddress(void) const
745 {
746         return __pProxyAddress;
747 }
748
749 void
750 _HttpSessionImpl::SetProxyAddress(String* pProxyAddress)
751 {
752         __pProxyAddress = pProxyAddress;
753 }
754
755 String
756 _HttpSessionImpl::GetDeviceName(void) const
757 {
758         return __deviceName;
759 }
760
761 void
762 _HttpSessionImpl::SetDeviceName(const String& deviceName)
763 {
764         __deviceName = deviceName;
765 }
766
767 NetHttpCookieFlag
768 _HttpSessionImpl::GetHttpCookieFlag(void) const
769 {
770         return __cookieFlag;
771 }
772
773 result
774 _HttpSessionImpl::SetAutoRedirectionEnabled(bool enable)
775 {
776         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
777
778         result r = E_SUCCESS;
779
780         SysTryReturnResult(NID_NET_HTTP, __countOfTransaction == 0,
781                                            E_INVALID_STATE, "The HttpTransaction is already opened. This function should be called before opening a HttpTransaction.");
782
783         if (__isAutoRedirectionEnabled == enable)
784         {
785                 SysLog(NID_NET_HTTP, "The auto redirection value is not changed[%s].", enable ? "true" : "false");
786                 return r;
787
788         }
789         else
790         {
791                 __isAutoRedirectionEnabled = enable;
792         }
793
794         SysLog(NID_NET_HTTP, "The auto redirection is set the value[%s].", enable ? "true" : "false");
795
796         return r;
797 }
798
799 bool
800 _HttpSessionImpl::IsAutoRedirectionEnabled(void) const
801 {
802         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
803
804         ClearLastResult();
805
806         return __isAutoRedirectionEnabled;
807 }
808
809 result
810 _HttpSessionImpl::CloseAllTransactions(void)
811 {
812         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
813
814         result r = E_SUCCESS;
815
816         HttpTransaction* pHttpTransaction = null;
817         _HttpTransactionImpl* pHttpTransactionImpl = null;
818         int countOfActiveTransactions = 0;
819
820         countOfActiveTransactions = __activeTransactions.GetCount();
821         for (int i = 0; i < countOfActiveTransactions; i++)
822         {
823                 pHttpTransaction = static_cast< HttpTransaction* >(__activeTransactions.GetAt(i));
824                 if (pHttpTransaction != null)
825                 {
826                         pHttpTransactionImpl = _HttpTransactionImpl::GetInstance(*pHttpTransaction);
827                         if (pHttpTransactionImpl->IsClosed() == false)
828                         {
829                                 r = CloseTransaction(*pHttpTransaction);
830                                 if (IsFailed(r))
831                                 {
832                                         SysLogException(NID_NET_HTTP, r, "[%s] Failed to close the HttpTransaction[%d].",
833                                                                         pHttpTransactionImpl->GetTransactionId(), GetErrorMessage(r));
834                                 }
835                         }
836                 }
837         }
838         __activeTransactions.RemoveAll(false);
839
840         return r;
841 }
842
843 result
844 _HttpSessionImpl::Disconnect(void)
845 {
846         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
847
848         result r = E_SUCCESS;
849
850         __isValid = false;
851         __pHttpMultipleConnectionInfo->Close();
852
853         HttpTransaction* pHttpTransaction = null;
854         _HttpTransactionImpl* pHttpTransactionImpl = null;
855         int countOfActiveTransactions = 0;
856
857         countOfActiveTransactions = __activeTransactions.GetCount();
858         for (int i = 0; i < countOfActiveTransactions; i++)
859         {
860                 pHttpTransaction = static_cast< HttpTransaction* >(__activeTransactions.GetAt(i));
861                 if (pHttpTransaction != null)
862                 {
863                         pHttpTransactionImpl = _HttpTransactionImpl::GetInstance(*pHttpTransaction);
864                         r = pHttpTransactionImpl->Abort();
865                         if (IsFailed(r))
866                         {
867                                 SysLog(NID_NET_HTTP, "Failed to abort the HttpTransaction.");
868                         }
869                 }
870         }
871
872         SysLog(NID_NET_HTTP, "The HttpSession[%d] is disconnected.", __sessionId);
873         return r;
874 }
875
876 bool
877 _HttpSessionImpl::IsSessionValid(void) const
878 {
879         return __isValid;
880 }
881
882 void
883 _HttpSessionImpl::SetSessionState(bool isValid)
884 {
885         __isValid = true;
886 }
887
888 bool
889 _HttpSessionImpl::IsConnectionStarted(void) const
890 {
891         if (__pManagedNetConnection == null)
892                 return true;
893
894         if (__pManagedNetConnectionListener != null)
895         {
896                 return __pManagedNetConnectionListener->IsEventReceived();
897         }
898
899         return false;
900 }
901
902 void
903 _HttpSessionImpl::IgnoreSslVerification(void)
904 {
905         SysLog(NID_NET_HTTP, "Ignore to verify server certificate of current HttpSession[%d]", __sessionId);
906         __isAlreadyResumed = true;
907 }
908
909 result
910 _HttpSessionImpl::Close(void)
911 {
912         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
913
914         result r = E_SUCCESS;
915
916         Mutex* pHttpMutex = _HttpUtility::GetHttpMutex();
917
918         MutexGuard locked(*pHttpMutex);
919         SysTryReturnResult(NID_NET_HTTP, locked.IsLocked(), E_SYSTEM,
920                         "Failed to lock mutex.");
921
922         __countOfSessions--;
923
924         r = locked.Unlock();
925         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_SYSTEM,
926                         "Failed to unlock mutex.");
927
928         SysLog(NID_NET_HTTP, "There are currently opened sessions[%d] in the Application.", __countOfSessions);
929
930         CloseAllTransactions();
931
932         SysLog(NID_NET_HTTP, "The HttpSession[%d] is closed.", __sessionId);
933         __isClosed = true;
934
935         return r;
936 }
937
938 HttpTransaction*
939 _HttpSessionImpl::OpenTransactionN()
940 {
941         ClearLastResult();
942         result r = E_SUCCESS;
943
944         HttpTransaction* pHttpTransaction = null;
945
946         pHttpTransaction = OpenTransactionWithCurlN(null);
947         r = GetLastResult();
948         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
949
950         SysLog(NID_NET_HTTP, "The HttpTransaction was opened.");
951
952         return pHttpTransaction;
953 }
954
955 HttpTransaction*
956 _HttpSessionImpl::OpenTransactionN(const HttpAuthentication& auth)
957 {
958         ClearLastResult();
959         result r = E_SUCCESS;
960
961         HttpTransaction* pHttpTransaction = null;
962         _HttpTransactionImpl* pHttpTransactionImpl = null;
963         const _HttpAuthenticationImpl* pHttpAuthenticationImpl = null;
964         _HttpCurl* pHttpAuthenticationRef = null;
965         CURL* pCurl = null;
966
967         pHttpAuthenticationImpl = _HttpAuthenticationImpl::GetInstance(auth);
968         pHttpAuthenticationRef = pHttpAuthenticationImpl->GetHttpCurl();
969         pCurl = pHttpAuthenticationRef->GetCurl();
970         SysTryReturn(NID_NET_HTTP, pCurl != null, null, E_INVALID_STATE,
971                                  "[E_INVALID_STATE] The curl instance must not be null.");
972
973         pHttpTransaction = OpenTransactionWithCurlN(pCurl);
974         r = GetLastResult();
975         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS && pHttpTransaction != null, null, r,
976                                  "[%s] Propagating.", GetErrorMessage(r));
977
978         pHttpTransactionImpl = _HttpTransactionImpl::GetInstance(*pHttpTransaction);
979         SysTryReturn(NID_NET_HTTP, pHttpTransactionImpl != null, null, E_SYSTEM,
980                                  "[E_SYSTEM] An internal error has occurred.");
981
982         pHttpTransactionImpl->SetHttpAuthenticationImpl(pHttpAuthenticationImpl);
983
984         SysLog(NID_NET_HTTP, "The HttpTransactio was opened with HttpAuthentication.");
985
986         return pHttpTransaction;
987 }
988
989 HttpTransaction*
990 _HttpSessionImpl::OpenTransactionWithCurlN(CURL* pCurl, bool uncheckedMaxTransactions)
991 {
992         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
993
994         ClearLastResult();
995         result r = E_SUCCESS;
996
997         unique_ptr<HttpTransaction> pHttpTransaction;
998         _HttpTransactionImpl* pHttpTransactionImpl = null;
999
1000         if (__sessionMode != NET_HTTP_SESSION_MODE_MULTIPLE_HOST && !uncheckedMaxTransactions)
1001         {
1002                 SysTryReturn(NID_NET_HTTP, __countOfTransaction < GetMaxTransactionCount(), null, E_MAX_EXCEEDED,
1003                                          "[E_MAX_EXCEEDED] Number(%d) of HttpTransaction exceeds max HttpTransaction count(%d).", __countOfTransaction, GetMaxTransactionCount());
1004         }
1005
1006         pHttpTransaction.reset(_HttpTransactionImpl::CreateHttpTransactionN());
1007         SysTryReturn(NID_NET_HTTP, pHttpTransaction != null, null, E_OUT_OF_MEMORY,
1008                                  "[E_OUT_OF_MEMORY] Memory allocation failed.");
1009
1010         pHttpTransactionImpl = _HttpTransactionImpl::GetInstance(*pHttpTransaction);
1011
1012         r = pHttpTransactionImpl->Construct(*this, __pCommonHeader, pCurl);
1013         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, r,
1014                                 "[%s] Failed to construct the HttpTransaction.", GetErrorMessage(r));
1015
1016         if (__isAlreadyResumed == true && __sessionMode != NET_HTTP_SESSION_MODE_MULTIPLE_HOST)
1017         {
1018                 pHttpTransactionImpl->IgnoreSslVerification();
1019                 SysLog(NID_NET_HTTP, "Ignore SSL verification.");
1020         }
1021
1022         r = __activeTransactions.Add(*pHttpTransaction);
1023         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, E_OUT_OF_MEMORY,
1024                                 "[E_OUT_OF_MEMORY] Memory allocation failed.");
1025
1026         __countOfTransaction++;
1027
1028         SysLog(NID_NET_HTTP, "The HttpTransaction[%d] was opened. The count of active transactions is %d.", pHttpTransactionImpl->GetTransactionId(), __countOfTransaction);
1029         return pHttpTransaction.release();
1030 }
1031
1032 result
1033 _HttpSessionImpl::CancelTransaction(HttpTransaction& httpTransaction)
1034 {
1035         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
1036
1037         result r = E_SUCCESS;
1038         _HttpTransactionImpl* pHttpTransactionImpl = _HttpTransactionImpl::GetInstance(httpTransaction);
1039
1040         SysTryReturnResult(NID_NET_HTTP, pHttpTransactionImpl->IsSubmitted() == true && pHttpTransactionImpl->IsClosed() == false,
1041                                            E_INVALID_STATE, "Either the HttpTransaction[%d] has not been submitted yet, or it has been closed.",
1042                                            pHttpTransactionImpl->GetTransactionId());
1043
1044         SysTryReturnResult(NID_NET_HTTP, pHttpTransactionImpl->IsCanceled() == false,
1045                                            E_OPERATION_CANCELED, "The HttpTransaction[%d] is already cancelled.", pHttpTransactionImpl->GetTransactionId());
1046
1047         r = CloseTransaction(httpTransaction);
1048         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r,
1049                                  "Failed to cancel the HttpTransaction[%d].", pHttpTransactionImpl->GetTransactionId());
1050
1051         pHttpTransactionImpl = _HttpTransactionImpl::GetInstance(httpTransaction);
1052         pHttpTransactionImpl->SetTransactionCanceled(true);
1053
1054         SysLog(NID_NET_HTTP, "The HttpTransaction[%d] was cancelled.", pHttpTransactionImpl->GetTransactionId());
1055
1056         return r;
1057 }
1058
1059
1060 result
1061 _HttpSessionImpl::CloseTransaction(HttpTransaction& httpTransaction)
1062 {
1063         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
1064
1065         result r = E_SUCCESS;
1066
1067         _HttpTransactionImpl* pHttpTransactionImpl = null;
1068
1069         pHttpTransactionImpl = _HttpTransactionImpl::GetInstance(httpTransaction);
1070
1071         if (pHttpTransactionImpl->IsClosed() == true)
1072         {
1073                 SysLog(NID_NET_HTTP, "The HttpTransaction[%d] is already closed. HttpSession[%d]",
1074                            pHttpTransactionImpl->GetTransactionId(), __sessionId);
1075         }
1076         else
1077         {
1078                 r = __activeTransactions.Remove(httpTransaction, false);
1079                 SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS,
1080                                                    E_INVALID_TRANSACTION, "Failed to remove HttpTransaction.");
1081
1082                 r = pHttpTransactionImpl->Close();
1083                 SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r,
1084                                          "Failed to close HttpTransaction.");
1085
1086                 __countOfTransaction--;
1087
1088                 SysLog(NID_NET_HTTP, "The HttpTransaction[%d] is now closed. HttpSession[%d]",
1089                            pHttpTransactionImpl->GetTransactionId(), __sessionId);
1090         }
1091
1092         return r;
1093
1094 }
1095
1096 int
1097 _HttpSessionImpl::GetActiveTransactionCount(void) const
1098 {
1099         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
1100
1101         ClearLastResult();
1102
1103         return __countOfTransaction;
1104 }
1105
1106 int
1107 _HttpSessionImpl::GetMaxTransactionCount(void) const
1108 {
1109         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
1110
1111         ClearLastResult();
1112
1113         if (__sessionMode == NET_HTTP_SESSION_MODE_NORMAL)
1114         {
1115                 return _MAX_HTTP_TRANSACTIONS_PER_SESSION_NORMAL;
1116         }
1117         else if (__sessionMode == NET_HTTP_SESSION_MODE_PIPELINING)
1118         {
1119                 return _MAX_HTTP_TRANSACTIONS_PER_SESSION_PIPE;
1120         }
1121         else if (__sessionMode == NET_HTTP_SESSION_MODE_MULTIPLE_HOST)
1122         {
1123                 return _MAX_HTTP_TRANSACTIONS_PER_SESSION_MULTIPLE_HOST;
1124         }
1125         else
1126         {
1127                 return -1;
1128         }
1129 }
1130
1131 HttpSession*
1132 _HttpSessionImpl::GetHttpSession(void) const
1133 {
1134         return __pHttpSession;
1135 }
1136
1137 _HttpMultipleConnectionInfo*
1138 _HttpSessionImpl::GetHttpMultipleConnectionInfo(void) const
1139 {
1140         return __pHttpMultipleConnectionInfo;
1141 }
1142
1143 result
1144 _HttpSessionImpl::Dispose(void)
1145 {
1146         SysAssertf(!__isClosed, "The HttpSession[%d] has been closed.", __sessionId);
1147
1148         result r = E_SUCCESS;
1149         if (!__isConstructed)
1150         {
1151                 SysLog(NID_NET_HTTP, "The HttpSession[%d] is not constructed yet.", __sessionId);
1152                 return r;
1153         }
1154
1155         r = Close();
1156         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r,
1157                                  "Failed to close the HttpSession[%d].", __sessionId);
1158
1159         return r;
1160 }
1161
1162 HttpTransaction*
1163 _HttpSessionImpl::ReopenTransactionWithAuthN(HttpTransaction& httpTransaction)
1164 {
1165         ClearLastResult();
1166         result r = E_SUCCESS;
1167
1168         unique_ptr<HttpTransaction> pCreatedTransaction;
1169         _HttpTransactionImpl* pCreatedTransactionImpl = null;
1170         _HttpTransactionImpl* pHttpTransactionImpl = null;
1171
1172         pHttpTransactionImpl = _HttpTransactionImpl::GetInstance(httpTransaction);
1173         SysTryReturn(NID_NET_HTTP, pHttpTransactionImpl != null, null, E_SYSTEM,
1174                                  "[E_SYSTEM] An internal error has occurred.");
1175
1176         pCreatedTransaction.reset(OpenTransactionWithCurlN(null, true));
1177         r = GetLastResult();
1178         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, r,
1179                                 "[%s] Failed to open the HttpTransaction.", GetErrorMessage(r));
1180
1181         pCreatedTransactionImpl = _HttpTransactionImpl::GetInstance(*pCreatedTransaction);
1182
1183         // The data of pHttpTransactionImpl is set to the pCreatedTransactionImpl.
1184         r = pCreatedTransactionImpl->Set(pHttpTransactionImpl);
1185         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, E_SYSTEM,
1186                                  "[E_SYSTEM] An internal error has occurred.");
1187
1188         r = CloseTransaction(httpTransaction);
1189         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, r,
1190                                 "[%s] Propagating.", GetErrorMessage(r));
1191
1192         SysLog(NID_NET_HTTP, "The HttpTransaction[%d] was re-opened.", pCreatedTransactionImpl->GetTransactionId());
1193
1194         return pCreatedTransaction.release();
1195 }
1196
1197 ArrayList*
1198 _HttpSessionImpl::GetActiveTransactions(void)
1199 {
1200         return &__activeTransactions;
1201 }
1202
1203 int
1204 _HttpSessionImpl::GenerateSessionId(void)
1205 {
1206         int sessionId = 0;
1207         Mutex* pHttpMutex = null;
1208
1209         pHttpMutex = _HttpUtility::GetHttpMutex();
1210
1211         MutexGuard locked(*pHttpMutex);
1212         SysTryReturn(NID_NET_HTTP, locked.IsLocked(), _HTTP_INVALID_ID, E_SYSTEM,
1213                         "[E_SYSTEM] Failed to lock mutex.");
1214
1215         if (__generatedSessionId >= Integer::VALUE_MAX)
1216         {
1217                 __generatedSessionId = 0;
1218         }
1219         else
1220         {
1221                 __generatedSessionId++;
1222         }
1223
1224         sessionId = __generatedSessionId;
1225
1226         return sessionId;
1227 }
1228
1229 int
1230 _HttpSessionImpl::GetSessionId(void) const
1231 {
1232         return __sessionId;
1233 }
1234
1235 result
1236 _HttpSessionImpl::InitializeSession(void)
1237 {
1238         result r = E_SUCCESS;
1239         Mutex* pHttpMutex = null;
1240
1241         pHttpMutex = _HttpUtility::GetHttpMutex();
1242
1243         MutexGuard locked(*pHttpMutex);
1244         SysTryReturnResult(NID_NET_HTTP, locked.IsLocked(), E_SYSTEM,
1245                         "Failed to lock mutex.");
1246
1247         if (__generatedSessionId == 0)
1248         {
1249                 String filePath = _HttpUtility::GetCookieFilePath();
1250                 r = TransExceptionsExclusive(r, E_SYSTEM, E_OUT_OF_MEMORY);
1251                 SysTryReturnResult(NID_NET_HTTP, filePath.IsEmpty() == false, r,
1252                                         "Failed to get the cookie path of system.");
1253
1254                 if (File::IsFileExist(filePath))
1255                 {
1256                         r = File::Remove(filePath);
1257                         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_SYSTEM,
1258                                                 "Failed to remove the cookie file[%ls].", filePath.GetPointer());
1259
1260                         SysLog(NID_NET_HTTP, "The cookie file[%ls] was removed.", filePath.GetPointer());
1261                 }
1262         }
1263
1264         return r;
1265 }
1266
1267 } } } // Tizen::Net::Http