ostinato/rpc/pbrpcchannel.h
Srivats P 75ce626532 Convert RPC channel's static vars to data members
Using static vars meant all connections were using the same static vars!
A bug that has existed since 2009!

This code is ugly, but since it is such a fundamental piece of code for
every operation, no refactoring is being done except to convert the
static vars to data members renaming where required to avoid name
conflicts. The one exception is that `cumLen` which was a per hdr.type
variable is now a single data member across all types. Since for a
single connection messages will be sequential this is expected to work
(fingers crossed!)

For the future we should look at replacing the custom RPC code with GRPC
(issue #305).

Fixes #304
2020-05-12 21:33:54 +05:30

129 lines
4.1 KiB
C++

/*
Copyright (C) 2010 Srivats P.
This file is part of "Ostinato"
This is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef _PB_RPC_CHANNEL_H
#define _PB_RPC_CHANNEL_H
#include <QString>
#include <QTcpServer>
#include <QTcpSocket>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/service.h>
#include "pbrpccommon.h"
#include "pbrpccontroller.h"
class PbRpcChannel : public QObject, public ::google::protobuf::RpcChannel
{
Q_OBJECT
// If isPending is TRUE, then controller, done, response
// and pendingMethodId correspond to the last method called by
// the service stub
bool isPending;
int pendingMethodId;
// controller, done, response are set to the corresponding values
// passed by the stub to CallMethod(). They are reset to NULL when
// we get a response back from the server in on_mpSocket_readyRead()
// after calling done->Run().
/*! \todo (MED) : change controller, done and response to references
instead of pointers? */
const ::google::protobuf::MethodDescriptor *method;
::google::protobuf::RpcController *controller;
::google::protobuf::Closure *done;
::google::protobuf::Message *response;
typedef struct _RpcCall {
const ::google::protobuf::MethodDescriptor *method;
::google::protobuf::RpcController *controller;
const ::google::protobuf::Message *request;
::google::protobuf::Message *response;
::google::protobuf::Closure *done;
} RpcCall;
QList<RpcCall> pendingCallList;
const ::google::protobuf::Message &notifPrototype;
::google::protobuf::Message *notif;
QString mServerHost;
quint16 mServerPort;
QTcpSocket *mpSocket;
::google::protobuf::io::CopyingInputStreamAdaptor *inStream;
::google::protobuf::io::CopyingOutputStreamAdaptor *outStream;
uchar sendBuffer_[4096];
// receive RPC related vars
bool parsing{false};
QByteArray buffer; // used for response type messages
QByteArray errorBuf; // used for error type messages
quint32 cumLen{0};
quint16 type;
quint16 methodId;
quint32 len;
public:
PbRpcChannel(QString serverName, quint16 port,
const ::google::protobuf::Message &notifProto);
~PbRpcChannel();
void establish();
void establish(QString serverName, quint16 port);
void tearDown();
const QString serverName() const
{
return mpSocket->peerName();
}
quint16 serverPort() const { return mServerPort; }
QAbstractSocket::SocketState state() const
{ return mpSocket->state(); }
void CallMethod(const ::google::protobuf::MethodDescriptor *method,
::google::protobuf::RpcController *controller,
const ::google::protobuf::Message *req,
::google::protobuf::Message *response,
::google::protobuf::Closure* done);
signals:
void connected();
void disconnected();
void error(QAbstractSocket::SocketError socketError);
void stateChanged(QAbstractSocket::SocketState socketState);
void notification(int notifType, ::google::protobuf::Message *notifData);
private slots:
void on_mpSocket_connected();
void on_mpSocket_disconnected();
void on_mpSocket_stateChanged(QAbstractSocket::SocketState socketState);
void on_mpSocket_error(QAbstractSocket::SocketError socketError);
void on_mpSocket_readyRead();
};
#endif