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
22 #include <dpl/rpc/generic_rpc_connection.h>
23 #include <dpl/scoped_array.h>
24 #include <dpl/log/log.h>
25 #include <dpl/aligned.h>
32 namespace // anonymous
52 unsigned char data[1];
55 } // namespace Protocol
56 } // namespace anonymous
58 GenericRPCConnection::GenericRPCConnection(AbstractWaitableInputOutput *inputOutput)
59 : m_inputOutput(inputOutput)
61 LogPedantic("Opening generic RPC...");
62 WaitableInputOutputExecutionContextSupport::Open(inputOutput);
63 LogPedantic("Generic RPC opened");
66 GenericRPCConnection::~GenericRPCConnection()
68 // Ensure RPC is closed
69 LogPedantic("Closing generic RPC...");
70 WaitableInputOutputExecutionContextSupport::Close();
71 LogPedantic("Generic RPC closed");
74 void GenericRPCConnection::AsyncCall(const RPCFunction &function)
76 LogPedantic("Executing async call");
79 BinaryQueue serializedCall = function.Serialize();
82 Protocol::AsyncCall call;
83 call.size = static_cast<unsigned short>(serializedCall.Size());
84 call.type = Protocol::PacketType_AsyncCall;
86 m_outputStream.AppendCopy(&call, sizeof(Protocol::Header));
87 m_outputStream.AppendMoveFrom(serializedCall);
89 // Try to feed output with data
94 Catch (WaitableInputOutputExecutionContextSupport::Exception::NotOpened)
96 // Error occurred while feeding
97 ReThrow(AbstractRPCConnection::Exception::AsyncCallFailed);
101 void GenericRPCConnection::Ping()
103 LogPedantic("Executing ping call");
106 Protocol::AsyncCall call;
108 call.type = Protocol::PacketType_PingPong;
110 m_outputStream.AppendCopy(&call, sizeof(Protocol::Header));
112 // Try to feed output with data
117 Catch (WaitableInputOutputExecutionContextSupport::Exception::NotOpened)
119 // Error occurred while feeding
120 ReThrow(AbstractRPCConnection::Exception::PingFailed);
124 void GenericRPCConnection::OnInputStreamRead()
126 LogPedantic("Interpreting " << m_inputStream.Size() << " bytes buffer");
128 // Enough bytes to read at least one header ?
129 if (m_inputStream.Size() >= sizeof(Protocol::Header))
131 // Begin consuming as much packets as it is possible
132 while (m_inputStream.Size() >= sizeof(Protocol::Header))
134 Protocol::Header header;
135 m_inputStream.Flatten(&header, sizeof(header));
137 if (m_inputStream.Size() >= sizeof(Protocol::Header) + header.size)
139 LogPedantic("Will parse packet of type: " << header.type);
141 // Allocate new packet (header + real packet data)
142 void *binaryPacket = malloc(sizeof(Protocol::Header) + header.size);
144 if (binaryPacket == NULL)
145 throw std::bad_alloc();
147 // Get it from stream
148 m_inputStream.FlattenConsume(binaryPacket, sizeof(Protocol::Header) + header.size);
150 // Parse specific packet
153 case Protocol::PacketType_AsyncCall:
157 // No need to delete packet data, we can use it
158 call.AppendUnmanaged(binaryPacket, sizeof(Protocol::Header) + header.size, &BinaryQueue::BufferDeleterFree, NULL);
160 // ...but just remove protocol header
161 call.Consume(sizeof(Protocol::Header));
163 LogPedantic("Async call of size: " << header.size << " parsed");
165 // Call async call event listeners
166 DPL::Event::EventSupport<AbstractRPCConnectionEvents::AsyncCallEvent>::
167 EmitEvent(AbstractRPCConnectionEvents::AsyncCallEvent(
168 RPCFunction(call), EventSender(this)), DPL::Event::EmitMode::Queued);
172 case Protocol::PacketType_PingPong:
174 // Reply with ping/pong
177 // Do not need packet data
180 LogPedantic("Ping pong replied");
185 LogPedantic("Warning: Unknown packet type");
192 LogPedantic("Too few bytes to read packet");
199 LogPedantic("Too few bytes to read header");
203 void GenericRPCConnection::OnInputStreamClosed()
206 DPL::Event::EventSupport<AbstractRPCConnectionEvents::ConnectionClosedEvent>::
207 EmitEvent(AbstractRPCConnectionEvents::ConnectionClosedEvent(
208 EventSender(this)), DPL::Event::EmitMode::Queued);
211 void GenericRPCConnection::OnInputStreamBroken()
214 DPL::Event::EventSupport<AbstractRPCConnectionEvents::ConnectionBrokenEvent>::
215 EmitEvent(AbstractRPCConnectionEvents::ConnectionBrokenEvent(
216 EventSender(this)), DPL::Event::EmitMode::Queued);