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)
23 #include <dpl/log/log.h>
24 #include <storage-receiver.h>
25 #include <ocsp-receiver.h>
26 #include <protocols.h>
31 const size_t RECV_BUFFER_SIZE = 2048;
34 Service::Service(IDescriptorSet& descriptors, const std::string& interface) :
35 m_interface(interface),
36 m_descriptors(descriptors)
40 void Service::addRequest(AsyncRequest&& req)
43 m_socket.reset(new SockRAII());
45 if (CKM_API_SUCCESS != (ret = m_socket->Connect(m_interface.c_str()))) {
46 LogError("Socket connection failed: " << ret);
48 req.observer->ReceivedError(ret);
53 if (m_sendQueue.empty())
56 m_sendQueue.push(std::move(req));
59 void Service::serviceError(int error)
63 // stop listening on socket
64 m_descriptors.remove(m_socket->Get(), false);
69 // notify observers waiting for response
70 for(const auto& it: m_responseMap) {
71 it.second.observer->ReceivedError(error);
73 m_responseMap.clear();
75 // notify observers waiting for send
76 while(!m_sendQueue.empty()) {
77 m_sendQueue.front().observer->ReceivedError(error);
81 // clear response buffer
82 m_responseBuffer.reset();
85 void Service::socketReady(int sock, short revents)
87 if (sock != m_socket->Get()) {
88 LogError("Unexpected socket: " << sock << "!=" << m_socket->Get());
89 serviceError(CKM_API_ERROR_SOCKET);
94 if (revents & POLLOUT)
96 else if (revents & POLLIN)
99 LogError("Unexpected event: " << revents << "!=" << POLLOUT);
100 serviceError(CKM_API_ERROR_SOCKET);
102 } catch (const IReceiver::BadResponse&) {
103 serviceError(CKM_API_ERROR_BAD_RESPONSE);
104 } catch (std::exception &e) {
105 LogError("STD exception " << e.what());
106 serviceError(CKM_API_ERROR_UNKNOWN);
108 LogError("Unknown exception occurred");
109 serviceError(CKM_API_ERROR_UNKNOWN);
113 void Service::sendData()
115 // nothing to send? -> stop watching POLLOUT
116 if (m_sendQueue.empty()) {
121 while (!m_sendQueue.empty()) {
122 AsyncRequest& req = m_sendQueue.front();
124 ssize_t temp = TEMP_FAILURE_RETRY(write(m_socket->Get(),
125 &req.buffer[req.written],
126 req.buffer.size() - req.written));
129 // can't write? -> go to sleep
130 if (EAGAIN == err || EWOULDBLOCK == err)
133 LogError("Error in write: " << strerror(err));
134 serviceError(CKM_API_ERROR_SEND_FAILED);
140 // finished? -> move request to response map
141 if(req.written == req.buffer.size()) {
142 AsyncRequest finished = std::move(m_sendQueue.front());
145 // update poll flags if necessary
146 if(m_sendQueue.empty() || m_responseMap.empty())
147 watch((m_sendQueue.empty()? 0 : POLLOUT) | POLLIN);
149 m_responseMap.insert(std::make_pair(finished.id,finished));
154 void Service::receiveData()
156 char buffer[RECV_BUFFER_SIZE];
158 ssize_t temp = TEMP_FAILURE_RETRY(read(m_socket->Get(), buffer, RECV_BUFFER_SIZE));
161 LogError("Error in read: " << strerror(err));
162 serviceError(CKM_API_ERROR_RECV_FAILED);
167 LogError("Read return 0/Connection closed by server(?)");
168 serviceError(CKM_API_ERROR_RECV_FAILED);
172 if (!m_responseBuffer)
173 m_responseBuffer.reset(new MessageBuffer());
175 RawBuffer raw(buffer, buffer+temp);
176 m_responseBuffer->Push(raw);
178 // parse while you can
179 while(m_responseBuffer->Ready())
181 std::unique_ptr<IReceiver> receiver;
182 if (m_interface == SERVICE_SOCKET_CKM_STORAGE)
183 receiver.reset(new StorageReceiver(*m_responseBuffer, m_responseMap));
184 else if (m_interface == SERVICE_SOCKET_OCSP)
185 receiver.reset(new OcspReceiver(*m_responseBuffer, m_responseMap));
187 LogError("Unknown service " << m_interface);
188 serviceError(CKM_API_ERROR_RECV_FAILED);
191 receiver->parseResponse();
193 if (m_responseMap.empty())
194 watch(m_sendQueue.empty()?0:POLLOUT);
198 void Service::watch(short events)
201 m_descriptors.remove(m_socket->Get(), false);
203 m_descriptors.add(m_socket->Get(),
205 [this](int sock, short revents){ socketReady(sock, revents); });