update the header for Doxygen
[platform/framework/native/bluetooth.git] / src / FNetBt_BluetoothOppSystemAdapter.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 // @file        FNetBt_BluetoothOppSystemAdapter.cpp
18 // @brief       This is the implementation file for the _BluetoothOppSystemAdapter class.
19 //
20
21 #include <unique_ptr.h>
22 #include <pthread.h>
23 #include <FBaseByteBuffer.h>
24 #include <FBaseUtilStringUtil.h>
25 #include <FNetBtBluetoothTypes.h>
26 #include <FNetBtBluetoothDevice.h>
27 #include <FBaseSysLog.h>
28 #include <FBase_StringConverter.h>
29 #include "FNetBt_BluetoothOppSystemAdapter.h"
30 #include "FNetBt_BluetoothGapSystemAdapter.h"
31 #include "FNetBt_BluetoothDeviceImpl.h"
32 #include "FNetBt_BluetoothOppClientImpl.h"
33 #include "FNetBt_BluetoothOppServerImpl.h"
34
35 using namespace std;
36 using namespace Tizen::Base;
37 using namespace Tizen::Base::Collection;
38 using namespace Tizen::Base::Utility;
39
40 namespace Tizen { namespace Net { namespace Bluetooth
41 {
42
43 _BluetoothOppSystemAdapter* _BluetoothOppSystemAdapter::__pInstance = null;
44
45 _BluetoothOppSystemAdapter::_BluetoothOppSystemAdapter(void)
46         : __pOppServerImpl(null)
47         , __pOppClientImpl(null)
48         , __serverTransferId(0)
49         , __serverRecvFileName()
50         , __serverRecvFileSize(0)
51 {
52 }
53
54 _BluetoothOppSystemAdapter::~_BluetoothOppSystemAdapter(void)
55 {
56 }
57
58 void
59 _BluetoothOppSystemAdapter::InitSingleton(void)
60 {
61         static _BluetoothOppSystemAdapter inst = _BluetoothOppSystemAdapter();
62
63         __pInstance = &inst;
64 }
65
66 _BluetoothOppSystemAdapter*
67 _BluetoothOppSystemAdapter::GetInstance(void)
68 {
69         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
70
71         if (__pInstance == null)
72         {
73                 ClearLastResult();
74                 pthread_once(&onceBlock, InitSingleton);
75                 result r = GetLastResult();
76                 if (IsFailed(r))
77                 {
78                         onceBlock = PTHREAD_ONCE_INIT;
79                 }
80         }
81
82         return __pInstance;
83 }
84
85 result
86 _BluetoothOppSystemAdapter::StartOppServer(const _BluetoothOppServerImpl& impl, const Tizen::Base::String& dstPath)
87 {
88         unique_ptr<char[]> pUuidStr;
89         bool isUsed = false;
90         unique_ptr<char[]> pConvertedDestPath;
91         result r = E_SUCCESS;
92         int ret = BT_ERROR_NONE;
93
94         // check OPP server's availability
95         pUuidStr.reset(_StringConverter::CopyToCharArrayN(UuId(BT_SVC_UUID_OPP).ToString()));
96         ret = bt_adapter_is_service_used(pUuidStr.get() , &isUsed);
97         SysTryReturnResult(NID_NET_BT, (ret == BT_ERROR_NONE) && !isUsed, E_SERVICE_UNAVAILABLE, "OPP Server is not available. [0x%08X]", ret);
98
99         pConvertedDestPath.reset(_StringConverter::CopyToCharArrayN(dstPath));
100         SysTryReturnResult(NID_NET_BT, pConvertedDestPath != null, E_INACCESSIBLE_PATH, "The file path is invalid.");
101
102         ret = bt_opp_server_initialize_by_connection_request(pConvertedDestPath.get(), &OnOppServerConnectionRequested, null);
103         SysLog(NID_NET_BT, "Starting the OPP Server %s. [0x%-04X]", ret == BT_ERROR_NONE ? "is successful" : "fails", ret);
104
105         if (ret == BT_ERROR_NONE)
106         {
107                 __pOppServerImpl = const_cast <_BluetoothOppServerImpl*>(&impl);
108         }
109         else
110         {
111                 r = E_FAILURE;
112         }
113
114         return r;
115 }
116
117 result
118 _BluetoothOppSystemAdapter::StopOppServer(void)
119 {
120         int ret = BT_ERROR_NONE;
121
122         ret = bt_opp_server_deinitialize();
123         SysLog(NID_NET_BT, "Stop the OPP Server %s. [0x%08X]", ret == BT_ERROR_NONE ? "is successful" : "fails", ret);
124
125         if (ret == BT_ERROR_NONE)
126         {
127                 __pOppServerImpl = null;
128                 return E_SUCCESS;
129         }
130
131         return E_FAILURE;
132 }
133
134 result
135 _BluetoothOppSystemAdapter::SetOppReceivePath(const Tizen::Base::String& dstPath)
136 {
137         char* pConvertedDestPath = NULL;
138         result r = E_FAILURE;
139         int ret = BT_ERROR_NONE;
140
141         pConvertedDestPath = _StringConverter::CopyToCharArrayN(dstPath);
142         SysTryReturnResult(NID_NET_BT, pConvertedDestPath != null, E_INACCESSIBLE_PATH, "The file path is invalid.");
143
144         ret = bt_opp_server_set_destination(pConvertedDestPath);
145         SysLog(NID_NET_BT, "Setting the receive path of the OPP Server %s. [0x%08X]",
146                         ret == BT_ERROR_NONE ? "is successful" : "fails", ret);
147
148         if (ret == BT_ERROR_NONE)
149         {
150                 r = E_SUCCESS;
151         }
152
153         delete[] pConvertedDestPath;
154         return r;
155 }
156
157 result
158 _BluetoothOppSystemAdapter::AcceptOppPush(const Tizen::Base::String& fileName)
159 {
160         result r = E_FAILURE;
161         int ret = BT_ERROR_NONE;
162
163         char* pConvertedfileName = _StringConverter::CopyToCharArrayN(fileName);
164         SysTryReturnResult(NID_NET_BT, pConvertedfileName != null, E_FAILURE, "The file name is invalid.");
165
166         ret = bt_opp_server_accept(&OnOppServerTransferInProgress, &OnOppServerTransferCompleted, pConvertedfileName, null,
167                         &__serverTransferId);
168         SysLog(NID_NET_BT, "Accepting the OPP push request %s. [0x%08X]", ret == BT_ERROR_NONE ? "is successful" : "fails", ret);
169
170         if (ret == BT_ERROR_NONE)
171         {
172                 r = E_SUCCESS;
173         }
174
175         delete[] pConvertedfileName;
176         return r;
177 }
178
179 result
180 _BluetoothOppSystemAdapter::RejectOppPush(void)
181 {
182         int ret = BT_ERROR_NONE;
183
184         ret = bt_opp_server_reject();
185         SysLog(NID_NET_BT, "Rejecting the OPP push request %s. [0x%08X]", ret == BT_ERROR_NONE ? "is successful" : "fails", ret);
186
187         if (ret == BT_ERROR_NONE)
188         {
189                 return E_SUCCESS;
190         }
191
192         return E_FAILURE;
193 }
194
195 result
196 _BluetoothOppSystemAdapter::StopOppTransfer(void)
197 {
198         int ret = BT_ERROR_NONE;
199
200         // if a file transfer is not started yet, the default transfer ID (0) is used for terminating the OPP server.
201         ret = bt_opp_server_cancel_transfer(__serverTransferId);
202         SysLog(NID_NET_BT, "Stop the OPP file transfer (ID:%d) %s. [0x%08X]", __serverTransferId,
203                         ret == BT_ERROR_NONE ? "is successful" : "fails", ret);
204
205         if (ret == BT_ERROR_NONE)
206         {
207                 return E_SUCCESS;
208         }
209
210         return E_OPERATION_FAILED;
211 }
212
213 result
214 _BluetoothOppSystemAdapter::PushOppFile(const _BluetoothOppClientImpl& impl, const Tizen::Base::ByteBuffer& serverAddress,
215                 const Tizen::Base::String& filePath)
216 {
217         result r = E_FAILURE;
218         int ret = BT_ERROR_NONE;
219         unique_ptr<char[]> pServerDevAddr;
220         unique_ptr<char[]> pFileName;
221
222         SysTryReturnResult(NID_NET_BT, __pOppClientImpl == null, E_SERVICE_UNAVAILABLE, "The already OPP client is running.");
223         SysTryReturnResult(NID_NET_BT, serverAddress.GetRemaining() == _BT_ADDRESS_LENGTH, E_FAILURE,
224                                                 "The address of the remote device is incorrect.");
225
226         pFileName.reset(_StringConverter::CopyToCharArrayN(filePath));
227         SysTryReturnResult(NID_NET_BT, pFileName != null, E_INACCESSIBLE_PATH, "The file path is invalid.");
228         pServerDevAddr.reset(_StringConverter::CopyToCharArrayN(_BluetoothDeviceImpl::GetAddressString(serverAddress)));
229         SysTryReturnResult(NID_NET_BT, pServerDevAddr != null, E_FAILURE, "The server address is invalid.");
230
231         if (bt_opp_client_initialize() == BT_ERROR_NONE)
232         {
233                 (void) bt_opp_client_add_file(pFileName.get());
234                 ret = bt_opp_client_push_files(pServerDevAddr.get(), &OnOppClientConnectionResponded, &OnOppClientTransferInProgress,
235                                 &OnOppClientTransferCompleted, null);
236                 SysLog(NID_NET_BT, "Sending a push request to  device [%s] %s. [0x%08X]", pServerDevAddr.get(),
237                                 ret == BT_ERROR_NONE ? "is successful" : "fails", ret);
238
239                 if (ret == BT_ERROR_NONE)
240                 {
241                         __pOppClientImpl = const_cast<_BluetoothOppClientImpl*>(&impl);
242                         r = E_SUCCESS;
243                 }
244                 else
245                 {
246                         bt_opp_client_deinitialize();
247                 }
248         }
249
250         return r;
251 }
252
253 result
254 _BluetoothOppSystemAdapter::CancelOppPush(void)
255 {
256         int ret = BT_ERROR_NONE;
257
258         ret = bt_opp_client_cancel_push();
259         SysLog(NID_NET_BT, "Cancel the OPP file transfer %s. [0x%08X]", ret == BT_ERROR_NONE ? "is successful" : "fails", ret);
260
261         if (ret == BT_ERROR_NONE)
262         {
263                 return E_SUCCESS;
264         }
265
266         return E_FAILURE;
267 }
268
269 void
270 _BluetoothOppSystemAdapter::OnOppClientConnectionResponded(int status, const char* pRemoteAddress, void* pUserData)
271 {
272         _BluetoothOppSystemAdapter* pOppAdapter = _BluetoothOppSystemAdapter::GetInstance();
273
274         if (pOppAdapter->__pOppClientImpl)
275         {
276                 if (status == BT_ERROR_NONE)
277                 {
278                         pOppAdapter->__pOppClientImpl->OnOppPushResponded(E_SUCCESS);
279                 }
280                 else
281                 {
282                         pOppAdapter->__pOppClientImpl->OnOppPushResponded(E_SYSTEM);
283                         pOppAdapter->__pOppClientImpl = null;
284                         bt_opp_client_deinitialize();
285                 }
286         }
287 }
288
289 void
290 _BluetoothOppSystemAdapter::OnOppClientTransferInProgress(const char* pFilePath, long long fileSize, int progress, void* pUserData)
291 {
292         _BluetoothOppSystemAdapter* pOppAdapter = _BluetoothOppSystemAdapter::GetInstance();
293
294         pOppAdapter->__serverRecvFileSize = fileSize;
295         // converts the UTF8 multibyte string to Unicode String
296         (void) StringUtil::Utf8ToString(pFilePath, pOppAdapter->__serverRecvFileName);
297
298         if (pOppAdapter->__pOppClientImpl)
299         {
300                 pOppAdapter->__pOppClientImpl->OnOppTransferInProgress(progress);
301         }
302 }
303
304 void
305 _BluetoothOppSystemAdapter::OnOppClientTransferCompleted(int status, const char* pRemoteAddress, void* pUserData)
306 {
307         bool isCompleted = true;
308         _BluetoothOppSystemAdapter* pOppAdapter = _BluetoothOppSystemAdapter::GetInstance();
309
310         if (pOppAdapter->__pOppClientImpl)
311         {
312                 if (status != BT_ERROR_NONE)
313                 {
314                         isCompleted = false;
315                 }
316
317                 pOppAdapter->__pOppClientImpl->OnOppTransferDone(pOppAdapter->__serverRecvFileName, pOppAdapter->__serverRecvFileSize,
318                                 isCompleted);
319                 pOppAdapter->__pOppClientImpl = null;
320                 // TODO: Is it right that the following statement is located in the next of callback?
321                 bt_opp_client_deinitialize();
322         }
323 }
324
325 void
326 _BluetoothOppSystemAdapter::OnOppServerConnectionRequested(const char* pRemoteAddress, void* pUserData)
327 {
328         result r = E_SUCCESS;
329         BluetoothDevice requester;
330         ByteBuffer deviceAddress;
331         String deviceAddressStr(pRemoteAddress);
332         _BluetoothOppSystemAdapter* pOppAdapter = _BluetoothOppSystemAdapter::GetInstance();
333
334         if (pOppAdapter->__pOppServerImpl)
335         {
336                 deviceAddress.Construct(_BT_ADDRESS_LENGTH);
337                 (void) _BluetoothDeviceImpl::GetAddressByteBuffer(deviceAddressStr, L":", deviceAddress);
338
339                 r = _BluetoothGapSystemAdapter::GetPairedDevice(deviceAddress, requester);
340                 SysTryReturnVoidResult(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, "[E_SYSTEM] Getting information of the request has failed.");
341
342                 pOppAdapter->__pOppServerImpl->OnOppPushRequested(requester);
343         }
344 }
345
346 void
347 _BluetoothOppSystemAdapter::OnOppServerTransferInProgress(const char* pFilePath, long long fileSize, int progress, void* pUserData)
348 {
349         _BluetoothOppSystemAdapter* pOppAdapter = _BluetoothOppSystemAdapter::GetInstance();
350
351         if (pOppAdapter->__pOppServerImpl)
352         {
353                 pOppAdapter->__pOppServerImpl->OnOppTransferInProgress(progress);
354         }
355 }
356
357 void
358 _BluetoothOppSystemAdapter::OnOppServerTransferCompleted(int status, const char* pFilePath, long long fileSize, void* pUserData)
359 {
360         bool isCompleted = true;
361         String convertedFilePath;
362
363         _BluetoothOppSystemAdapter* pOppAdapter = _BluetoothOppSystemAdapter::GetInstance();
364
365         if (pOppAdapter->__pOppServerImpl)
366         {
367                 pOppAdapter->__serverTransferId = 0;
368
369                 if (status != BT_ERROR_NONE)
370                 {
371                         isCompleted = false;
372                 }
373                 // TODO: not file name but file path
374                 // converts the UTF8 multibyte string to Unicode String
375                 (void) StringUtil::Utf8ToString(pFilePath, convertedFilePath);
376                 pOppAdapter->__pOppServerImpl->OnOppTransferDone(convertedFilePath, fileSize, isCompleted);
377         }
378 }
379
380 } } } // Tizen::Net::Bluetooth