2 * Copyright (c) 2011 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 generic_rpc_connection.cpp
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the implementation file of generic RPC connection
23 #include <dpl/rpc/generic_rpc_connection.h>
24 #include <dpl/scoped_array.h>
25 #include <dpl/log/log.h>
26 #include <dpl/aligned.h>
31 namespace // anonymous
50 unsigned char data[1];
52 } // namespace Protocol
53 } // namespace anonymous
55 GenericRPCConnection::GenericRPCConnection(
56 AbstractWaitableInputOutput *inputOutput) :
57 m_inputOutput(inputOutput)
59 LogPedantic("Opening generic RPC...");
60 WaitableInputOutputExecutionContextSupport::Open(inputOutput);
61 LogPedantic("Generic RPC opened");
64 GenericRPCConnection::~GenericRPCConnection()
66 // Ensure RPC is closed
67 LogPedantic("Closing generic RPC...");
68 WaitableInputOutputExecutionContextSupport::Close();
69 LogPedantic("Generic RPC closed");
72 void GenericRPCConnection::AsyncCall(const RPCFunction &function)
74 LogPedantic("Executing async call");
77 BinaryQueue serializedCall = function.Serialize();
80 Protocol::AsyncCall call;
81 call.size = static_cast<unsigned short>(serializedCall.Size());
82 call.type = Protocol::PacketType_AsyncCall;
84 m_outputStream.AppendCopy(&call, sizeof(Protocol::Header));
85 m_outputStream.AppendMoveFrom(serializedCall);
87 // Try to feed output with data
92 Catch(WaitableInputOutputExecutionContextSupport::Exception::NotOpened)
94 // Error occurred while feeding
95 ReThrow(AbstractRPCConnection::Exception::AsyncCallFailed);
99 void GenericRPCConnection::Ping()
101 LogPedantic("Executing ping call");
104 Protocol::AsyncCall call;
106 call.type = Protocol::PacketType_PingPong;
108 m_outputStream.AppendCopy(&call, sizeof(Protocol::Header));
110 // Try to feed output with data
115 Catch(WaitableInputOutputExecutionContextSupport::Exception::NotOpened)
117 // Error occurred while feeding
118 ReThrow(AbstractRPCConnection::Exception::PingFailed);
122 void GenericRPCConnection::OnInputStreamRead()
124 LogPedantic("Interpreting " << m_inputStream.Size() << " bytes buffer");
126 // Enough bytes to read at least one header ?
127 if (m_inputStream.Size() >= sizeof(Protocol::Header)) {
128 // Begin consuming as much packets as it is possible
129 while (m_inputStream.Size() >= sizeof(Protocol::Header)) {
130 Protocol::Header header;
131 m_inputStream.Flatten(&header, sizeof(header));
133 if (m_inputStream.Size() >= sizeof(Protocol::Header) +
136 LogPedantic("Will parse packet of type: " << header.type);
138 // Allocate new packet (header + real packet data)
139 void *binaryPacket = malloc(
140 sizeof(Protocol::Header) + header.size);
142 if (binaryPacket == NULL) {
143 throw std::bad_alloc();
146 // Get it from stream
147 m_inputStream.FlattenConsume(
149 sizeof(Protocol::Header) +
152 // Parse specific packet
153 switch (header.type) {
154 case Protocol::PacketType_AsyncCall:
158 // No need to delete packet data, we can use it
159 call.AppendUnmanaged(binaryPacket,
160 sizeof(Protocol::Header) + header.size,
161 &BinaryQueue::BufferDeleterFree,
164 // ...but just remove protocol header
165 call.Consume(sizeof(Protocol::Header));
168 "Async call of size: " << header.size <<
171 // Call async call event listeners
172 DPL::Event::EventSupport<AbstractRPCConnectionEvents::
174 EmitEvent(AbstractRPCConnectionEvents::AsyncCallEvent(
175 RPCFunction(call), EventSender(
176 this)), DPL::Event::EmitMode::Queued);
180 case Protocol::PacketType_PingPong:
182 // Reply with ping/pong
185 // Do not need packet data
188 LogPedantic("Ping pong replied");
193 LogPedantic("Warning: Unknown packet type");
198 LogPedantic("Too few bytes to read packet");
203 LogPedantic("Too few bytes to read header");
207 void GenericRPCConnection::OnInputStreamClosed()
210 DPL::Event::EventSupport<AbstractRPCConnectionEvents::ConnectionClosedEvent>
212 EmitEvent(AbstractRPCConnectionEvents::ConnectionClosedEvent(
213 EventSender(this)), DPL::Event::EmitMode::Queued);
216 void GenericRPCConnection::OnInputStreamBroken()
219 DPL::Event::EventSupport<AbstractRPCConnectionEvents::ConnectionBrokenEvent>
221 EmitEvent(AbstractRPCConnectionEvents::ConnectionBrokenEvent(
222 EventSender(this)), DPL::Event::EmitMode::Queued);