2 * Copyright (c) 2000 - 2015 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
18 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
24 #include <dpl/errno_string.h>
25 #include <dpl/log/log.h>
27 #include <storage-receiver.h>
28 #include <ocsp-receiver.h>
29 #include <encryption-receiver.h>
30 #include <protocols.h>
35 const size_t RECV_BUFFER_SIZE = 2048;
38 Service::Service(IDescriptorSet& descriptors, const std::string& interface) :
39 m_interface(interface),
40 m_descriptors(descriptors)
44 void Service::addRequest(AsyncRequest&& req)
47 m_socket.reset(new SockRAII());
49 if (CKM_API_SUCCESS != (ret = m_socket->connect(m_interface.c_str()))) {
50 LogError("Socket connection failed: " << ret);
52 req.observer->ReceivedError(ret);
57 if (m_sendQueue.empty())
60 m_sendQueue.push(std::move(req));
63 void Service::serviceError(int error)
67 // stop listening on socket
68 m_descriptors.remove(m_socket->get(), false);
73 // notify observers waiting for response
74 for(const auto& it: m_responseMap) {
75 it.second.observer->ReceivedError(error);
77 m_responseMap.clear();
79 // notify observers waiting for send
80 while(!m_sendQueue.empty()) {
81 m_sendQueue.front().observer->ReceivedError(error);
85 // clear response buffer
86 m_responseBuffer.reset();
89 void Service::socketReady(int sock, short revents)
91 if (sock != m_socket->get()) {
92 LogError("Unexpected socket: " << sock << "!=" << m_socket->get());
93 serviceError(CKM_API_ERROR_SOCKET);
98 if (revents & POLLOUT)
100 else if (revents & POLLIN)
103 LogError("Unexpected event: " << revents << "!=" << POLLOUT);
104 serviceError(CKM_API_ERROR_SOCKET);
106 } catch (const IReceiver::BadResponse&) {
107 serviceError(CKM_API_ERROR_BAD_RESPONSE);
108 } catch (std::exception &e) {
109 LogError("STD exception " << e.what());
110 serviceError(CKM_API_ERROR_UNKNOWN);
112 LogError("Unknown exception occurred");
113 serviceError(CKM_API_ERROR_UNKNOWN);
117 void Service::sendData()
119 // nothing to send? -> stop watching POLLOUT
120 if (m_sendQueue.empty()) {
125 while (!m_sendQueue.empty()) {
126 AsyncRequest& req = m_sendQueue.front();
128 ssize_t temp = TEMP_FAILURE_RETRY(write(m_socket->get(),
129 &req.buffer[req.written],
130 req.buffer.size() - req.written));
133 // can't write? -> go to sleep
134 if (EAGAIN == err || EWOULDBLOCK == err)
137 LogError("Error in write: " << GetErrnoString(err));
138 serviceError(CKM_API_ERROR_SEND_FAILED);
144 // finished? -> move request to response map
145 if(req.written == req.buffer.size()) {
146 AsyncRequest finished = std::move(m_sendQueue.front());
149 // update poll flags if necessary
150 if(m_sendQueue.empty() || m_responseMap.empty())
151 watch((m_sendQueue.empty()? 0 : POLLOUT) | POLLIN);
153 m_responseMap.insert(std::make_pair(finished.id,finished));
158 void Service::receiveData()
160 char buffer[RECV_BUFFER_SIZE];
162 ssize_t temp = TEMP_FAILURE_RETRY(read(m_socket->get(), buffer, RECV_BUFFER_SIZE));
165 LogError("Error in read: " << GetErrnoString(err));
166 serviceError(CKM_API_ERROR_RECV_FAILED);
171 LogError("Read return 0/Connection closed by server(?)");
172 serviceError(CKM_API_ERROR_RECV_FAILED);
176 if (!m_responseBuffer)
177 m_responseBuffer.reset(new MessageBuffer());
179 RawBuffer raw(buffer, buffer+temp);
180 m_responseBuffer->Push(raw);
182 // parse while you can
183 while(m_responseBuffer->Ready())
185 std::unique_ptr<IReceiver> receiver;
186 if (m_interface == SERVICE_SOCKET_CKM_STORAGE)
187 receiver.reset(new StorageReceiver(*m_responseBuffer, m_responseMap));
188 else if (m_interface == SERVICE_SOCKET_OCSP)
189 receiver.reset(new OcspReceiver(*m_responseBuffer, m_responseMap));
190 else if (m_interface == SERVICE_SOCKET_ENCRYPTION)
191 receiver.reset(new EncryptionReceiver(*m_responseBuffer, m_responseMap));
193 LogError("Unknown service " << m_interface);
194 serviceError(CKM_API_ERROR_RECV_FAILED);
197 receiver->processResponse();
199 if (m_responseMap.empty())
200 watch(m_sendQueue.empty()?0:POLLOUT);
204 void Service::watch(short events)
207 m_descriptors.remove(m_socket->get(), false);
209 m_descriptors.add(m_socket->get(),
211 [this](int sock, short revents){ socketReady(sock, revents); });