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
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 <protocols.h>
34 const size_t RECV_BUFFER_SIZE = 2048;
37 Service::Service(IDescriptorSet& descriptors, const std::string& interface) :
38 m_interface(interface),
39 m_descriptors(descriptors)
43 void Service::addRequest(AsyncRequest&& req)
46 m_socket.reset(new SockRAII());
48 if (CKM_API_SUCCESS != (ret = m_socket->connect(m_interface.c_str()))) {
49 LogError("Socket connection failed: " << ret);
51 req.observer->ReceivedError(ret);
56 if (m_sendQueue.empty())
59 m_sendQueue.push(std::move(req));
62 void Service::serviceError(int error)
66 // stop listening on socket
67 m_descriptors.remove(m_socket->get(), false);
72 // notify observers waiting for response
73 for(const auto& it: m_responseMap) {
74 it.second.observer->ReceivedError(error);
76 m_responseMap.clear();
78 // notify observers waiting for send
79 while(!m_sendQueue.empty()) {
80 m_sendQueue.front().observer->ReceivedError(error);
84 // clear response buffer
85 m_responseBuffer.reset();
88 void Service::socketReady(int sock, short revents)
90 if (sock != m_socket->get()) {
91 LogError("Unexpected socket: " << sock << "!=" << m_socket->get());
92 serviceError(CKM_API_ERROR_SOCKET);
97 if (revents & POLLOUT)
99 else if (revents & POLLIN)
102 LogError("Unexpected event: " << revents << "!=" << POLLOUT);
103 serviceError(CKM_API_ERROR_SOCKET);
105 } catch (const IReceiver::BadResponse&) {
106 serviceError(CKM_API_ERROR_BAD_RESPONSE);
107 } catch (std::exception &e) {
108 LogError("STD exception " << e.what());
109 serviceError(CKM_API_ERROR_UNKNOWN);
111 LogError("Unknown exception occurred");
112 serviceError(CKM_API_ERROR_UNKNOWN);
116 void Service::sendData()
118 // nothing to send? -> stop watching POLLOUT
119 if (m_sendQueue.empty()) {
124 while (!m_sendQueue.empty()) {
125 AsyncRequest& req = m_sendQueue.front();
127 ssize_t temp = TEMP_FAILURE_RETRY(write(m_socket->get(),
128 &req.buffer[req.written],
129 req.buffer.size() - req.written));
132 // can't write? -> go to sleep
133 if (EAGAIN == err || EWOULDBLOCK == err)
136 LogError("Error in write: " << GetErrnoString(err));
137 serviceError(CKM_API_ERROR_SEND_FAILED);
143 // finished? -> move request to response map
144 if(req.written == req.buffer.size()) {
145 AsyncRequest finished = std::move(m_sendQueue.front());
148 // update poll flags if necessary
149 if(m_sendQueue.empty() || m_responseMap.empty())
150 watch((m_sendQueue.empty()? 0 : POLLOUT) | POLLIN);
152 m_responseMap.insert(std::make_pair(finished.id,finished));
157 void Service::receiveData()
159 char buffer[RECV_BUFFER_SIZE];
161 ssize_t temp = TEMP_FAILURE_RETRY(read(m_socket->get(), buffer, RECV_BUFFER_SIZE));
164 LogError("Error in read: " << GetErrnoString(err));
165 serviceError(CKM_API_ERROR_RECV_FAILED);
170 LogError("Read return 0/Connection closed by server(?)");
171 serviceError(CKM_API_ERROR_RECV_FAILED);
175 if (!m_responseBuffer)
176 m_responseBuffer.reset(new MessageBuffer());
178 RawBuffer raw(buffer, buffer+temp);
179 m_responseBuffer->Push(raw);
181 // parse while you can
182 while(m_responseBuffer->Ready())
184 std::unique_ptr<IReceiver> receiver;
185 if (m_interface == SERVICE_SOCKET_CKM_STORAGE)
186 receiver.reset(new StorageReceiver(*m_responseBuffer, m_responseMap));
187 else if (m_interface == SERVICE_SOCKET_OCSP)
188 receiver.reset(new OcspReceiver(*m_responseBuffer, m_responseMap));
190 LogError("Unknown service " << m_interface);
191 serviceError(CKM_API_ERROR_RECV_FAILED);
194 receiver->parseResponse();
196 if (m_responseMap.empty())
197 watch(m_sendQueue.empty()?0:POLLOUT);
201 void Service::watch(short events)
204 m_descriptors.remove(m_socket->get(), false);
206 m_descriptors.add(m_socket->get(),
208 [this](int sock, short revents){ socketReady(sock, revents); });