2 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 * @file client-common.cpp
18 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19 * @author Zofia Abramowska (z.abramowska@samsung.com)
21 * @brief This file is implementation of client-common functions.
26 #include <sys/types.h>
27 #include <sys/socket.h>
31 #include <dpl/errno_string.h>
32 #include <dpl/log/log.h>
33 #include <dpl/serialization.h>
34 #include <dpl/singleton.h>
35 #include <dpl/singleton_safe_impl.h>
37 #include <message-buffer.h>
39 #include <ckm/ckm-error.h>
40 #include <ckmc/ckmc-type.h>
41 #include <protocols.h>
42 #include <client-common.h>
44 IMPLEMENT_SAFE_SINGLETON(CKM::Log::LogSystem);
48 const int POLL_TIMEOUT = 8000;
50 void centKeyClientEnableLogSystem(void) {
51 CKM::Singleton<CKM::Log::LogSystem>::Instance().SetTag("CKM_CLIENT");
54 } // namespace anonymous
58 SockRAII::SockRAII() : m_sock(-1) {}
65 int SockRAII::Connect(char const * const interface)
71 LogError("No valid interface address given.");
72 throw CKM_API_ERROR_INPUT_PARAM;
75 sock = socket(AF_UNIX, SOCK_STREAM, 0);
77 LogError("Error creating socket: " << CKM::GetErrnoString(errno));
78 throw CKM_API_ERROR_SOCKET;
81 // configure non-blocking mode
83 if((flags = fcntl(sock, F_GETFL, 0)) < 0 || fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0)
85 LogError("Error in fcntl: " << CKM::GetErrnoString(errno));
86 throw CKM_API_ERROR_SOCKET;
89 sockaddr_un clientAddr;
90 memset(&clientAddr, 0, sizeof(clientAddr));
91 clientAddr.sun_family = AF_UNIX;
92 if(strlen(interface) >= sizeof(clientAddr.sun_path))
94 LogError("Error: interface name " << interface << "is too long. Max len is:" << sizeof(clientAddr.sun_path));
95 throw CKM_API_ERROR_INPUT_PARAM;
98 strcpy(clientAddr.sun_path, interface);
99 LogDebug("ClientAddr.sun_path = " << interface);
101 int retval = TEMP_FAILURE_RETRY(::connect(sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr)));
107 LogError("Access denied");
108 throw CKM_API_ERROR_ACCESS_DENIED;
113 if( 0 >= WaitForSocket(POLLOUT, POLL_TIMEOUT))
115 LogError("Error in WaitForSocket.");
116 throw CKM_API_ERROR_SOCKET;
120 size_t len = sizeof(error);
121 retval = getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len);
124 LogError("Error in getsockopt: " << CKM::GetErrnoString(error));
125 throw CKM_API_ERROR_SOCKET;
130 LogError("Access denied");
131 throw CKM_API_ERROR_ACCESS_DENIED;
136 LogError("Error in connect: " << CKM::GetErrnoString(error));
137 throw CKM_API_ERROR_SOCKET;
144 LogError("Error connecting socket: " << CKM::GetErrnoString(errno));
145 throw CKM_API_ERROR_SOCKET;
150 catch(int & error_code) {
157 return CKM_API_SUCCESS;
160 bool SockRAII::isConnected() const {
161 return (m_sock != -1);
164 void SockRAII::Disconnect() {
170 int SockRAII::WaitForSocket(int event, int timeout)
175 desc[0].events = event;
177 while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) {
183 LogDebug("Poll timeout");
184 } else if(-1 == retval) {
185 LogError("Error in poll: " << CKM::GetErrnoString(errno));
190 int SockRAII::Get() const {
194 } // namespace anonymous
198 AliasSupport::AliasSupport(const Alias &alias)
200 std::size_t separator_pos = alias.rfind(CKM::LABEL_NAME_SEPARATOR);
201 if(separator_pos == Alias::npos)
206 m_label = alias.substr(0, separator_pos);
207 m_name = alias.substr(separator_pos + strlen(CKM::LABEL_NAME_SEPARATOR));
211 Alias AliasSupport::merge(const Label &label, const Name &name)
216 std::stringstream output;
217 output << label << std::string(CKM::LABEL_NAME_SEPARATOR) << name;
221 const Name & AliasSupport::getName() const {
225 const Label & AliasSupport::getLabel() const {
229 bool AliasSupport::isLabelEmpty() const {
230 return m_label.empty();
233 ServiceConnection::ServiceConnection(char const * const service_interface) {
234 if(service_interface)
235 m_service_interface = std::string(service_interface);
238 int ServiceConnection::processRequest( const CKM::RawBuffer &send_buf,
239 CKM::MessageBuffer &recv_buf) {
241 if(CKM_API_SUCCESS != (ec = send(send_buf)))
244 return receive(recv_buf);
247 int ServiceConnection::Connect()
253 return SockRAII::Connect(m_service_interface.c_str());
256 int ServiceConnection::send(const CKM::RawBuffer &send_buf)
258 if( ! isConnected() )
261 if(CKM_API_SUCCESS != (ec = ServiceConnection::Connect()))
263 LogError("send failed, connect fail code: " << ec);
268 int ec = CKM_API_SUCCESS;
270 while((send_buf.size() - done) > 0)
272 if( 0 >= WaitForSocket(POLLOUT, POLL_TIMEOUT)) {
273 LogError("Error in WaitForSocket.");
274 ec = CKM_API_ERROR_SOCKET;
278 ssize_t temp = TEMP_FAILURE_RETRY(write(Get(), &send_buf[done], send_buf.size() - done));
280 LogError("Error in write: " << CKM::GetErrnoString(errno));
281 ec = CKM_API_ERROR_SOCKET;
288 if(ec != CKM_API_SUCCESS)
294 int ServiceConnection::receive(CKM::MessageBuffer &recv_buf)
296 if( ! isConnected() )
298 LogError("Not connected!");
299 return CKM_API_ERROR_SOCKET;
302 int ec = CKM_API_SUCCESS;
303 const size_t c_recv_buf_len = 2048;
304 char buffer[c_recv_buf_len];
307 if( 0 >= WaitForSocket(POLLIN, POLL_TIMEOUT)) {
308 LogError("Error in WaitForSocket.");
309 ec = CKM_API_ERROR_SOCKET;
313 ssize_t temp = TEMP_FAILURE_RETRY(read(Get(), buffer, sizeof(buffer)));
315 LogError("Error in read: " << CKM::GetErrnoString(errno));
316 ec = CKM_API_ERROR_SOCKET;
321 LogError("Read return 0/Connection closed by server(?)");
322 ec = CKM_API_ERROR_SOCKET;
326 CKM::RawBuffer raw(buffer, buffer+temp);
329 while(!recv_buf.Ready());
331 if(ec != CKM_API_SUCCESS)
337 ServiceConnection::~ServiceConnection()
341 int try_catch(const std::function<int()>& func)
343 int retval = CKM_API_ERROR_UNKNOWN;
346 } catch (MessageBuffer::Exception::Base &e) {
347 LogError("CKM::MessageBuffer::Exception " << e.DumpToString());
348 } catch (std::exception &e) {
349 LogError("STD exception " << e.what());
351 LogError("Unknown exception occured");
356 void try_catch_async(const std::function<void()>& func, const std::function<void(int)>& error)
360 } catch (const MessageBuffer::Exception::Base& e) {
361 LogError("CKM::MessageBuffer::Exception " << e.DumpToString());
362 error(CKM_API_ERROR_BAD_REQUEST);
363 } catch (const std::exception& e) {
364 LogError("STD exception " << e.what());
365 error(CKM_API_ERROR_UNKNOWN);
367 LogError("Unknown exception occured");
368 error(CKM_API_ERROR_UNKNOWN);
374 static void init_lib(void) __attribute__ ((constructor));
375 static void init_lib(void)
377 centKeyClientEnableLogSystem();
380 static void fini_lib(void) __attribute__ ((destructor));
381 static void fini_lib(void)