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>
33 namespace // anonymous
53 unsigned char data[1];
56 } // namespace Protocol
57 } // namespace anonymous
59 GenericRPCConnection::GenericRPCConnection(AbstractWaitableInputOutput *inputOutput)
60 : m_inputOutput(inputOutput)
62 LogPedantic("Opening generic RPC...");
63 WaitableInputOutputExecutionContextSupport::Open(inputOutput);
64 LogPedantic("Generic RPC opened");
67 GenericRPCConnection::~GenericRPCConnection()
69 // Ensure RPC is closed
70 LogPedantic("Closing generic RPC...");
71 WaitableInputOutputExecutionContextSupport::Close();
72 LogPedantic("Generic RPC closed");
75 void GenericRPCConnection::AsyncCall(const RPCFunction &function)
77 LogPedantic("Executing async call");
80 BinaryQueue serializedCall = function.Serialize();
83 Protocol::AsyncCall call;
84 call.size = static_cast<unsigned short>(serializedCall.Size());
85 call.type = Protocol::PacketType_AsyncCall;
87 m_outputStream.AppendCopy(&call, sizeof(Protocol::Header));
88 m_outputStream.AppendMoveFrom(serializedCall);
90 // Try to feed output with data
95 Catch (WaitableInputOutputExecutionContextSupport::Exception::NotOpened)
97 // Error occurred while feeding
98 ReThrow(AbstractRPCConnection::Exception::AsyncCallFailed);
102 void GenericRPCConnection::Ping()
104 LogPedantic("Executing ping call");
107 Protocol::AsyncCall call;
109 call.type = Protocol::PacketType_PingPong;
111 m_outputStream.AppendCopy(&call, sizeof(Protocol::Header));
113 // Try to feed output with data
118 Catch (WaitableInputOutputExecutionContextSupport::Exception::NotOpened)
120 // Error occurred while feeding
121 ReThrow(AbstractRPCConnection::Exception::PingFailed);
125 void GenericRPCConnection::OnInputStreamRead()
127 LogPedantic("Interpreting " << m_inputStream.Size() << " bytes buffer");
129 // Enough bytes to read at least one header ?
130 if (m_inputStream.Size() >= sizeof(Protocol::Header))
132 // Begin consuming as much packets as it is possible
133 while (m_inputStream.Size() >= sizeof(Protocol::Header))
135 Protocol::Header header;
136 m_inputStream.Flatten(&header, sizeof(header));
138 if (m_inputStream.Size() >= sizeof(Protocol::Header) + header.size)
140 LogPedantic("Will parse packet of type: " << header.type);
142 // Allocate new packet (header + real packet data)
143 void *binaryPacket = malloc(sizeof(Protocol::Header) + header.size);
145 if (binaryPacket == NULL)
146 throw std::bad_alloc();
148 // Get it from stream
149 m_inputStream.FlattenConsume(binaryPacket, sizeof(Protocol::Header) + header.size);
151 // Parse specific packet
154 case Protocol::PacketType_AsyncCall:
158 // No need to delete packet data, we can use it
159 call.AppendUnmanaged(binaryPacket, sizeof(Protocol::Header) + header.size, &BinaryQueue::BufferDeleterFree, NULL);
161 // ...but just remove protocol header
162 call.Consume(sizeof(Protocol::Header));
164 LogPedantic("Async call of size: " << header.size << " parsed");
166 // Call async call event listeners
167 DPL::Event::EventSupport<AbstractRPCConnectionEvents::AsyncCallEvent>::
168 EmitEvent(AbstractRPCConnectionEvents::AsyncCallEvent(
169 RPCFunction(call), EventSender(this)), DPL::Event::EmitMode::Queued);
173 case Protocol::PacketType_PingPong:
175 // Reply with ping/pong
178 // Do not need packet data
181 LogPedantic("Ping pong replied");
186 LogPedantic("Warning: Unknown packet type");
193 LogPedantic("Too few bytes to read packet");
200 LogPedantic("Too few bytes to read header");
204 void GenericRPCConnection::OnInputStreamClosed()
207 DPL::Event::EventSupport<AbstractRPCConnectionEvents::ConnectionClosedEvent>::
208 EmitEvent(AbstractRPCConnectionEvents::ConnectionClosedEvent(
209 EventSender(this)), DPL::Event::EmitMode::Queued);
212 void GenericRPCConnection::OnInputStreamBroken()
215 DPL::Event::EventSupport<AbstractRPCConnectionEvents::ConnectionBrokenEvent>::
216 EmitEvent(AbstractRPCConnectionEvents::ConnectionBrokenEvent(
217 EventSender(this)), DPL::Event::EmitMode::Queued);