Initialize Tizen 2.3
[framework/osp/net.git] / src / sockets / FNetSock_SocketUtilityImpl.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 /**
19  * @file                FNetSock_SocketUtilityImpl.cpp
20  * @brief               This is the implementation for the _SocketUtilityImpl class.
21  */
22
23 #include <arpa/inet.h>
24 #include <sys/select.h>
25 #include <sys/time.h>
26 #include <errno.h>
27 #include <FNetSockSocket.h>
28 #include <FNetSockSecureSocket.h>
29 #include <FNetSockSocketUtility.h>
30 #include <FBaseSysLog.h>
31 #include "FNetSock_SocketImpl.h"
32 #include "FNetSock_SecureSocketImpl.h"
33 #include "FNetSock_SocketUtilityImpl.h"
34 #include "FNetSock_SocketInternalHelp.h"
35
36 using namespace Tizen::Base;
37 using namespace Tizen::Base::Collection;
38 using namespace Tizen::Base::Runtime;
39 using namespace Tizen::Net;
40
41 namespace Tizen { namespace Net { namespace Sockets
42 {
43
44 _SocketUtilityImpl::_SocketUtilityImpl(void)
45         : __isConstructed(false)
46 {
47 }
48
49 _SocketUtilityImpl::~_SocketUtilityImpl(void)
50 {
51 }
52
53 result
54 _SocketUtilityImpl::Construct(void)
55 {
56         SysAssertf(__isConstructed == false, "Already constructed. Calling Construct() twice or more on a same instance is not allowed for this class.");
57
58         __isConstructed = true;
59
60         return E_SUCCESS;
61 }
62
63 result
64 _SocketUtilityImpl::Select(IList* pCheckRead, IList* pCheckWrite, IList* pCheckError, int microSeconds)
65 {
66     SysAssertf(__isConstructed == true, "Not yet constructed. Construct() should be called before use.");
67
68         SysTryReturnResult(NID_NET_SOCK, (pCheckRead != null) || (pCheckWrite != null) || (pCheckError != null), E_INVALID_ARG, "All three descriptor parameters were null.");
69
70         result r = E_SUCCESS;
71
72         int nFds = 0;
73         fd_set readFds;
74         fd_set writeFds;
75         fd_set errorFds;
76
77         int ret = 0;
78
79         struct timeval timeout;
80
81         FD_ZERO(&readFds);
82         FD_ZERO(&writeFds);
83         FD_ZERO(&errorFds);
84
85         if (pCheckRead != null)
86         {
87                 int count = pCheckRead->GetCount();
88                 for (int i = 0; i < count; i++)
89                 {
90                         Socket* pSocket = dynamic_cast <Socket*>(pCheckRead->GetAt(i));
91                         SecureSocket* pSecSocket = dynamic_cast <SecureSocket*>(pCheckRead->GetAt(i));
92                         SysTryReturnResult(NID_NET_SOCK, (pSocket != null) || (pSecSocket != null), E_INVALID_ARG, "The given collection contains an element of incompatible class type.");
93                 }
94
95                 r = IListToSocketFdSet(*pCheckRead, &readFds, nFds);
96                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, r, "Failed to pCheckRead IListToSocketFdSet.");
97         }
98         if (pCheckWrite != null)
99         {
100                 int count = pCheckWrite->GetCount();
101                 for (int i = 0; i < count; i++)
102                 {
103                         Socket* pSocket = dynamic_cast <Socket*>(pCheckWrite->GetAt(i));
104                         SecureSocket* pSecSocket = dynamic_cast <SecureSocket*>(pCheckWrite->GetAt(i));
105                         SysTryReturnResult(NID_NET_SOCK, (pSocket != null) || (pSecSocket != null), E_INVALID_ARG, "The given collection contains an element of incompatible class type.");
106                 }
107
108                 r = IListToSocketFdSet(*pCheckWrite, &writeFds, nFds);
109                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, r, "Failed to pCheckWrite IListToSocketFdSet.");
110         }
111         if (pCheckError != null)
112         {
113                 int count = pCheckError->GetCount();
114                 for (int i = 0; i < count; i++)
115                 {
116                         Socket* pSocket = dynamic_cast <Socket*>(pCheckError->GetAt(i));
117                         SecureSocket* pSecSocket = dynamic_cast <SecureSocket*>(pCheckError->GetAt(i));
118                         SysTryReturnResult(NID_NET_SOCK, (pSocket != null) || (pSecSocket != null), E_INVALID_ARG, "The given collection contains an element of incompatible class type.");
119                 }
120
121                 r = IListToSocketFdSet(*pCheckError, &errorFds, nFds);
122                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, r, "Failed to pCheckError IListToSocketFdSet.");
123         }
124
125         if (microSeconds < _MIN_SELECT_TIMEOUT)     // If timeout value is lesser than MINIMUN value - set to minimum value by force
126         {
127                 microSeconds = _MIN_SELECT_TIMEOUT;
128         }
129
130         timeout.tv_sec = microSeconds / 1000000;
131         timeout.tv_usec = microSeconds % 1000000;
132
133         ret = select(nFds + 1, &readFds, &writeFds, &errorFds, &timeout);
134         if (ret < 0)
135         {
136                 // Error code mapping
137                 switch (errno)
138                 {
139                 case EBADF:     // An invalid file descriptor was given in one of the sets. (Perhaps a file descriptor that was already closed, or one on which an error has occurred.)
140                         r = E_INVALID_SOCKET;
141                         break;
142
143                 case EINTR:     // A signal was caught.
144                         r = E_SYSTEM;
145                         break;
146
147                 case EINVAL:    // nFds is negative or the value contained within timeout is invalid.
148                         r = E_INVALID_ARG;
149                         break;
150
151                 case ENOMEM:    // Unable to allocate memory for internal tables.
152                         r = E_OUT_OF_MEMORY;
153                         break;
154
155                 default:
156                         r = E_SYSTEM;
157                         break;
158                 }
159                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, r, "Failed to SocketUtility Select().");
160         }
161         else if (ret == 0)
162         {
163                 r = E_TIMEOUT;
164                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, r, "Failed to SocketUtility Select().");
165         }
166
167         if (pCheckRead != null)
168         {
169                 SysLog(NID_NET_SOCK, "pCheckRead SocketFdSetToIList()");
170                 r = SocketFdSetToIList(&readFds, *pCheckRead);
171                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, r, "Failed to readFds SocketFdSetToIList.");
172         }
173
174         if (pCheckWrite != null)
175         {
176                 SysLog(NID_NET_SOCK, "pCheckWrite SocketFdSetToIList()");
177                 r = SocketFdSetToIList(&writeFds, *pCheckWrite);
178                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, r, "Failed to writeFds SocketFdSetToIList.");
179         }
180
181         if (pCheckError != null)
182         {
183                 SysLog(NID_NET_SOCK, "pCheckError SocketFdSetToIList()");
184                 r = SocketFdSetToIList(&errorFds, *pCheckError);
185                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, r, "Failed to errorFds SocketFdSetToIList.");
186         }
187
188         SysLog(NID_NET_SOCK, "SocketUtility Select() is succeed.");
189
190         return E_SUCCESS;
191 }
192
193 unsigned short
194 _SocketUtilityImpl::HtoNS(unsigned short hostShort)
195 {
196         ClearLastResult();
197
198         SysAssertf(__isConstructed != false, "Not Constructed yet or Invocation of the method is not right in this state.");
199
200         return (uint16_t) htons((uint16_t) hostShort);
201 }
202
203 unsigned long
204 _SocketUtilityImpl::HtoNL(unsigned long hostLong)
205 {
206         ClearLastResult();
207
208     SysAssertf(__isConstructed != false, "Not Constructed yet or Invocation of the method is not right in this state.");
209
210         return (uint32_t) htonl((uint32_t) hostLong);
211 }
212
213 unsigned short
214 _SocketUtilityImpl::NtoHS(unsigned short netShort)
215 {
216         ClearLastResult();
217
218     SysAssertf(__isConstructed != false, "Not Constructed yet or Invocation of the method is not right in this state.");
219
220         return (uint16_t) ntohs((uint16_t) netShort);
221 }
222
223 unsigned long
224 _SocketUtilityImpl::NtoHL(unsigned long netLong)
225 {
226         ClearLastResult();
227
228     SysAssertf(__isConstructed != false, "Not Constructed yet or Invocation of the method is not right in this state.");
229
230         return (uint32_t) ntohl((uint32_t) netLong);
231 }
232
233 result
234 _SocketUtilityImpl::IListToSocketFdSet(const Tizen::Base::Collection::IList& iList, fd_set* pSet, int& nFds)
235 {
236         result r = E_SUCCESS;
237
238         int index = 0;
239         int count = 0;
240
241         Socket* pSocket = null;
242         _SocketImpl* pSocketImpl = null;
243         SecureSocket* pSecSocket = null;
244         _SecureSocketImpl* pSecSocketImpl = null;
245         IList* pList = null;
246         Object* pObj = null;
247
248         int sockFd = INVALID_HANDLE;
249
250         FD_ZERO(pSet);
251
252         count = iList.GetCount();
253
254         if (count > 0)
255         {
256                 pList = iList.GetItemsN(index, count);
257                 r = GetLastResult();
258                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, E_INVALID_ARG, "pList is a empty.");
259         }
260
261         for (int i = 0; i < count; i++)
262         {
263                 pObj = pList->GetAt(i);
264
265                 pSocket = dynamic_cast <Socket*>(pObj);
266                 pSecSocket = dynamic_cast <SecureSocket*>(pObj);
267                 SysTryReturnResult(NID_NET_SOCK, (pSocket != null) || (pSecSocket != null), E_SYSTEM, "The socket is null.");
268
269                 if (pSocket != null)
270                 {
271                         pSocketImpl = _SocketImpl::GetInstance(*pSocket);
272                         sockFd = pSocketImpl->GetSocketFd();
273                         nFds = sockFd;
274                         (void) FD_SET(sockFd, pSet);
275                 }
276
277                 if (pSecSocket != null)
278                 {
279                         pSecSocketImpl = _SecureSocketImpl::GetInstance(*pSecSocket);
280                         sockFd = pSecSocketImpl->GetSecureSocketFd();
281                         nFds = sockFd;
282                         (void) FD_SET(sockFd, pSet);
283                 }
284         }
285
286         if(pList != null)
287         {
288                 delete pList;
289                 pList = null;
290         }
291
292         return r;
293 }
294
295 result
296 _SocketUtilityImpl::SocketFdSetToIList(const fd_set* pSet, Tizen::Base::Collection::IList& iList)
297 {
298         result r = E_SUCCESS;
299
300         int index = 0;
301         int count = 0;
302
303         Socket* pSocket = null;
304         _SocketImpl* pSocketImpl = null;
305         SecureSocket* pSecSocket = null;
306         _SecureSocketImpl* pSecSocketImpl = null;
307         IList* pList = null;
308         Object* pObj = null;
309
310         int sockFd = INVALID_HANDLE;
311
312         count = iList.GetCount();
313
314         if (count > 0)
315         {
316                 pList = iList.GetItemsN(index, count);
317                 r = GetLastResult();
318                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, E_INVALID_ARG, "pList is a empty.");
319         }
320
321         for (int i = 0; i < count; i++)
322         {
323                 pObj = pList->GetAt(i);
324
325                 pSocket = dynamic_cast <Socket*>(pObj);
326                 pSecSocket = dynamic_cast <SecureSocket*>(pObj);
327                 SysTryReturnResult(NID_NET_SOCK, (pSocket != null) || (pSecSocket != null), E_SYSTEM, "The socket is null.");
328
329                 if (pSocket != null)
330                 {
331                         pSocketImpl = _SocketImpl::GetInstance(*pSocket);
332                         sockFd = pSocketImpl->GetSocketFd();
333                         if (!(FD_ISSET(sockFd, pSet)))
334                         {
335                                 SysLog(NID_NET_SOCK, "Remove pObj in iList.");
336                                 r = iList.Remove(*pObj);
337                                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, E_INVALID_ARG, "iList is a empty.");
338                         }
339                 }
340
341                 if (pSecSocket != null)
342                 {
343                         pSecSocketImpl = _SecureSocketImpl::GetInstance(*pSecSocket);
344                         sockFd = pSecSocketImpl->GetSecureSocketFd();
345                         if (!(FD_ISSET(sockFd, pSet)))
346                         {
347                                 SysLog(NID_NET_SOCK, "Remove pObj in iList.");
348                                 r = iList.Remove(*pObj);
349                                 SysTryReturnResult(NID_NET_SOCK, r == E_SUCCESS, E_INVALID_ARG, "iList is a empty.");
350                         }
351                 }
352         }
353
354         if (pList != null)
355         {
356                 delete pList;
357                 pList = null;
358         }
359
360         return r;
361 }
362
363 _SocketUtilityImpl*
364 _SocketUtilityImpl::GetInstance(SocketUtility& socketUtility)
365 {
366         return socketUtility.__pSocketUtilityImpl;
367 }
368
369 const _SocketUtilityImpl*
370 _SocketUtilityImpl::GetInstance(const SocketUtility& socketUtility)
371 {
372         return socketUtility.__pSocketUtilityImpl;
373 }
374
375 } } } // Tizen::Net::Sockets