How to iterate a protobuffer repeatedfield inside a grpc service? - c++11

Should I have a mutable reference to the field, I would be able to use:
enum my_types{
type_unknown = 0;
type_one = 1;
tpye_two = 2;
}
message My_message{
repeated my_types lotsa_types = 1;
}
message My_response{
//whatever
}
service My_service{
rpc my_rpc(My_message) returns (My_response) {}
}
::grpc::Status My_server::my_rpc(
::grpc::ServerContext* context, const ::my_namespace::My_message* request,
::my_namespace::My_reply* response
){
std::cout << "Recieved numbers";
for(my_types& single_number: *request->mutable_lotsa_types()){
std::cout << " " << single_number << " ";
}
std::cout << std::endl;
}
but I can not, because request is given by a const modifier via the grpc service call:
error: passing ‘const my_namespace::My_message’ as ‘this’ argument discards qualifiers [-fpermissive]
How can the const RepeatedFiled be iterated over?

Related

How can I access and use the packet contents in the received node using INET in OMNeT++?

In omnet++/INET I have two nodes(Standardhost) and by extending UDPBasicApp application, I have to send sensor values to the other node. I made my own .msg definition like below:
class PlantPacket extends FieldsChunk
{
double sensorValue;
}
I have no problem with sending this value and I used this code:
void MyUdp::sendPacket()
{
std::ostringstream str;
str << packetName << "-" << numSent;
Packet *packet = new Packet(str.str().c_str());
const auto& payload = makeShared<PlantPacket>();
payload->setChunkLength(B(par("messageLength")));
payload->setSensorValue(sensorValue);
payload->addTag<CreationTimeTag>()->setCreationTime(simTime());
packet->insertAtBack(payload);
L3Address destAddr = chooseDestAddr();
socket.sendTo(packet, destAddr, destPort);
}
My problem is to retrieve the sensorValue in the received node. I used this code but I got an error:
void MyUdp::processPacket(Packet *pk)
{
EV_INFO << "Received packet: " << UdpSocket::getReceivedPacketInfo(pk) << endl;
PlantPacket* payload = check_and_cast<PlantPacket*>(pk);
EV_INFO << "packet content1: " << payload->getSensorValue() << endl;
delete pk;
}
Error: Cannot convert between integer units -- in module (inet::Udp)
How can I solve this problem?
The payload has been added using insertAtBack therefore it must be obtained using peekAtBack or popAtBack. The code should look like:
void MyUdp::processPacket(Packet *pk)
{
EV_INFO << "Received packet: " << UdpSocket::getReceivedPacketInfo(pk) << endl;
const auto& payload = pk->peekAtBack<PlantPacket>();
EV_INFO << "packet content1: " << payload->getSensorValue() << endl;
delete pk;
}

how to implement onvif CreatePullPointSubscription operation by gsoap

Referring to onvif core specification: If the subscription is accepted, the response contains a WS-EndpointReference to the
instantiated pull point. This WS-Endpoint provides a PullMessages operation, which is
used by the client to retrieve Notifications.
But I can't see the codes about instancing pull point, and I don't know how to implement it. Here is my coding.
SOAP_FMAC5 int SOAP_FMAC6 __tev__CreatePullPointSubscription(struct soap* soap, struct _tev__CreatePullPointSubscription *tev__CreatePullPointSubscription, struct _tev__CreatePullPointSubscriptionResponse *tev__CreatePullPointSubscriptionResponse)
{
tev__CreatePullPointSubscriptionResponse->SubscriptionReference.Address = (char *)soap_malloc(soap, sizeof(char) * 128);
strcpy(tev__CreatePullPointSubscriptionResponse->SubscriptionReference.Address, "http://192.168.12.1/Subscription?Idx=0");
tev__CreatePullPointSubscriptionResponse->wsnt__CurrentTime=time(NULL);
tev__CreatePullPointSubscriptionResponse->wsnt__TerminationTime=tev__CreatePullPointSubscriptionResponse->wsnt__CurrentTime+60;
return SOAP_OK;
}
Can anyone brighten me? Thank you in advance.
void CreatePullPointSubscription() {
struct soap *m_soap = soap_new();
m_soap->connect_timeout = SOAP_REQUEST_TIMEOUT_IN_SECONDS;
m_soap->recv_timeout = SOAP_REQUEST_TIMEOUT_IN_SECONDS;
m_soap->send_timeout = SOAP_REQUEST_TIMEOUT_IN_SECONDS;
PullPointSubscriptionBindingProxy subscriptionProxy(m_soap);
subscriptionProxy.soap_endpoint = xAddr;
if (addCredentialsToCall(m_soap)) {
_tev__CreatePullPointSubscription request;
_tev__CreatePullPointSubscriptionResponse response;
auto ret = subscriptionProxy.CreatePullPointSubscription(&request, response);
if (ret != SOAP_OK) {
soap_stream_fault(m_soap, std::cerr);
} else {
auto address = response.SubscriptionReference.Address;
std::cout << address << std::endl;
std::cout << "Subscription metadata: " << response.SubscriptionReference.Metadata << std::endl;
std::cout << "Termination time " << response.wsnt__TerminationTime << std::endl;
std::cout << "Current time " << response.wsnt__CurrentTime << std::endl;
std::string uuid = std::string(soap_rand_uuid(m_soap, "urn:uuid:"));
struct SOAP_ENV__Header header;
header.wsa5__MessageID = (char *) uuid.c_str();
header.wsa5__To = response.SubscriptionReference.Address;
m_soap->header = &header;
if (addCredentialsToCall(m_soap)) {
_tev__PullMessages tev__PullMessages;
tev__PullMessages.Timeout = "PT600S";
tev__PullMessages.MessageLimit = 100;
_tev__PullMessagesResponse tev__PullMessagesResponse;
auto ret = subscriptionProxy.PullMessages(&tev__PullMessages, tev__PullMessagesResponse);
for (auto msg : tev__PullMessagesResponse.wsnt__NotificationMessage) {
std::cout << "\tMessage is :" << msg->Topic->__mixed << std::endl;
}
} else {
std::cout << "Couldn't set credentials!!!" << std::endl;
}
}
}
subscriptionProxy.destroy();
}
This worked for me atleast to pull the event initializers.

libwebsocket: How to disconnect client if there is no server response for a while (with timeout)?

I have a client using libwebsocket to establish a connection to a server. Whenever the client sends a request, the server sends a response and after receiving the response the client closes the connection. Works fine.
But when the server does not answer to the request i have the problem that the client keeps waiting for a response forever. When nothing happens the callback is never called and its not possible to close connection with returning -1 from callback function.
Is there any way to enable a timeout for the connection to close? Or any possibility to close connection from outside the callback function?
Here is my code so far:
int callback_function(libwebsocket_context* context, libwebsocket* wsi, enum libwebsocket_callback_reasons reason, void* user, void* in, size_t len) {
switch (reason) {
case LWS_CALLBACK_CLIENT_ESTABLISHED: {
std::cout << "LWS_CALLBACK_CLIENT_ESTABLISHED" << std::endl;
libwebsocket_callback_on_writable(context, wsi);
}
break;
case LWS_CALLBACK_CLOSED:{
std::cout << "LWS_CALLBACK_CLOSED" << std::endl;
}
break;
case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
case LWS_CALLBACK_CLIENT_RECEIVE:{
std::cout << "LWS_CALLBACK_CLIENT_RECEIVE" << endl;
((char *)in)[len] = '\0';
answers_[current_request] = answers_[current_request] + string((char *)in);
if (libwebsocket_is_final_fragment(wsi)){
std::cout << "request:" << requests_[current_request] << std::endl;
std::cout << "answer:" << answers_[current_request] << std::endl;
current_request++;
if(current_request >= answers_.size()) {
ready = true;
return -1;
}
libwebsocket_callback_on_writable(context, wsi);
}
}
break;
case LWS_CALLBACK_CLIENT_WRITEABLE:{
std::cout << "LWS_CALLBACK_CLIENT_WRITEABLE" << endl;
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 + LWS_SEND_BUFFER_POST_PADDING];
const std::string message = std::string(requests_[current_request]);
std::copy(message.begin(), message.end(), &buf[LWS_SEND_BUFFER_PRE_PADDING]);
buf[LWS_SEND_BUFFER_PRE_PADDING+(int)message.size()]='\0';
int n = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], (size_t)message.size(), static_cast<libwebsocket_write_protocol>(LWS_WRITE_BINARY));
if (n < 0){
std::cout << kLogErr << "bad things are happening" << std::endl;
return -1;
}
if (n < (int)message.size()) {
std::cout << kLogErr << "Partial write LWS_CALLBACK_CLIENT_WRITEABLE" << std::endl;
return -1;
}
}
break;
default:
std::cout << "CALLBACK_DEFAULT: " << reason << endl;
break;
}
return 0;
}
vector<string> sendMessage(const string& server, int port, const string& path, const vector<string>& messages, bool& error) {
ready = error = false;
current_request = 0;
requests_ = vector<string>(messages);
answers_ = vector<string>(requests_.size(), "");
int ietf_version = -1; /* latest */
wsi_ = libwebsocket_client_connect(context_, server.c_str(), port, 2, path.c_str(), server.c_str(), "origin", NULL, ietf_version);
if (wsi_ == NULL) {
std::cout << kLogErr << "libwebsocket connect failed server:" << server << " port: " << port << " path: " << path << std::endl;
error = true;
return vector<string>();
}
bool first_time = true;
int n = 0;
while (n >= 0 && !force_exit && !ready) {
n = libwebsocket_service(context_, 0);
if(first_time) {
libwebsocket_callback_on_writable(context_, wsi_);
first_time = false;
}
if (n < 0){
continue;
}
if (wsi_ == NULL) {
break;
}
}
error = !ready;
wsi_ = NULL;
return vector<string>(answers_);
}
You could try using:
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
return -1;
break;
Or
lws_set_timeout
But I'm not a 100% sure that will work, you could also try creating an issue/question on their GitHub, they tend to answer quite fast/clear.
I'm also not sure if you should implement
I solved the problem.
I programmed a timer in
vector<string> sendMessage(const string& server, int port, const string& path, const vector<string>& messages, bool& error)
and when the timeout is reaches, the timer sets a flag and triggers
libwebsocket_callback_on_writable(context_, wsi_);
again. Then in
int callback_function(libwebsocket_context* context, libwebsocket* wsi, enum libwebsocket_callback_reasons reason, void* user, void* in, size_t len)
in case
LWS_CALLBACK_CLIENT_WRITEABLE
i check the flag and if it is set the callback is aborted with
return -1;
Works fine!

Not able to store data in a private member variable from a const member function - FIX8 c++

This is my header :
class my_router_client : public FIX8::my::mine_Router {
private:
mine_session_client& _session;
mutable std::vector<std::string> vSymbolList;
public:
my_router_client(mine_session_client& session) : _session(session) {}
virtual bool operator() (const FIX8::my::SecurityList *msg) const;
void sendToServer(FIX8::Message *);
void logout();
void itertool() const;
};
I am trying to save the data obtained from security list response to the vSymbolList vector. After handling security response I am trying to iterate through the vector by itertool method. But every time I end up with an empty vector. I tried printing the contents of the vector inside securitylist response function
virtual bool operator() (const FIX8::CX::SecurityList *msg) const;
and I am able to print the contents. Is it some kind of race condition inside threads?
this is the security list response handler
bool cx_router_client::operator() (const CX::SecurityList *msg) const
{
GroupBase *dad(msg->find_group< CX::SecurityList::NoRelatedSym >());
if (dad) {
for (size_t cnt(0); cnt < dad->size(); ++cnt) {
CX::Symbol symbol;
MessageBase *details(dad->get_element(cnt));
details->get(symbol);
string ss;
ss = symbol();
vSymbolList.push_back(ss);
// cout << "at :: :: " << vSymbolList[cnt] << endl;
}
cout << "no of symbol : " << vSymbolList.size() << endl;
hypersleep<h_seconds>(1);
}
return true;
}
This is the itertool method :
void my_router_client::itertool() const
{
cout << "symbol list vector size inside itertool:: " << vSymbolList.size() << endl;
stringstream ss;
ss << this_thread::get_id();
uint64_t id = stoull(ss.str());
cout << "Thread ID #### " << id << endl;
vector<string>::iterator it = this->vSymbolList.begin();
while (it != vSymbolList.end()) {
cout << *it << endl;
it++;
}
}
This is how I use the them in main :
int main()
{
const string conf_file("myfix_client.xml");
unique_ptr<ClientSessionBase> mc(new ClientSession<mine_session_client>(my::ctx(), conf_file, "DLD1"));
mc->start(false, next_send, next_receive, mc->session_ptr()->get_login_parameters()._davi());
hypersleep<h_seconds>(1);
my_router_client *test = new my_router_client(static_cast< mine_session_client& > (*mc->session_ptr()));
hypersleep<h_seconds>(1);
test->sendToServer(makeSecurityListRequest());
hypersleep<h_seconds>(1);
test->itertool();
while(1);
}

boost::asio::read throws compilation error 'read_some' is not a member of 'boost::shared_ptr<boost::asio::ip::tcp::socket>'

I am trying to build up a client to get data via a specific protocol from a server.
I know that my code is not the best - but at the moment I am still experimenting with the basic functions of Boost ASIO.
I want to implement an read from TCP-Function which blocks until a specific amount of bytes have been received.
My Problem:
When I call boost::asio::read or boost::asio::write i geht following error:
error C2039: 'read_some' : is not a member of boost::shared_ptr'
I am working with VS2013 Professional, Boost 1.55.00 (precompiled).
Here is my Code: ( You can find the line by the comment "//HEEERE"
boost::mutex cout_lock;
int main()
{
// creating io_service
boost::shared_ptr<boost::asio::io_service> io_service(new boost::asio::io_service);
// creating work and assigning it to io_service
boost::shared_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(*io_service));
// creating strand and assigning it to io_service
boost::shared_ptr<boost::asio::io_service::strand> strand(new boost::asio::io_service::strand(*io_service));
// creating socket
boost::shared_ptr<boost::asio::ip::tcp::socket> socket(new boost::asio::ip::tcp::socket(*io_service));
try {
// creating resolver
boost::asio::ip::tcp::resolver resolver(*io_service);
// creating query
boost::asio::ip::tcp::resolver::query query(IPConfig_str, boost::lexical_cast<std::string>(IPConfig_PortNr));
// creating iterator
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
// creating endpoint
boost::asio::ip::tcp::endpoint endpoint = *iterator;
// connecting synchronously
socket->connect(endpoint);
}
catch(std::exception &ex) {
cout_lock.lock();
std::cout << "[main]:\t" << "Exception:" << ex.what() << std::endl;
cout_lock.unlock();
}
// Create Query
CommandCreator CMDCreator;
Command sendCommand;
CMDCreator.Create_fpga_GetSwVers(&sendCommand);
std::cout << std::endl;
std::cout << "SENT:" << std::endl;
for (int i = 0; i < sendCommand.length; i++)
{
std::cout << std::hex << std::setw(2) << std::setfill('0') << int(sendCommand.buffer[i]) << ", ";
}
std::cout << std::endl;
// Send Query
boost::system::error_code ec;
socket->async_send(boost::asio::buffer(sendCommand.buffer, sendCommand.length), boost::asio::transfer_all());
Sleep(300); // sleep 100 ms (at least 85 <- not stable!)
// Receive Answer - Header
Command receiveCommandHeader;
receiveCommandHeader.InitBuffer(4);
// Async
// socket->async_receive(boost::asio::buffer(receiveCommandHeader.buffer, receiveCommandHeader.length), 0, boost::bind(HandleRead, ec));
//HEEERE
boost::asio::read(socket, boost::asio::buffer(receiveCommandHeader.buffer, receiveCommandHeader.length), boost::asio::transfer_all(), ec);
//shutting down
socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
socket->close(ec);
io_service->stop();
return 0;
}
class Command
{
friend class CommandCreator; // TODO: is there a better and as simple method as a friend class?
public:
Command() : buffer(0)
{}
virtual ~Command()
{
delete[] buffer;
buffer = 0;
}
void InitBuffer(int const len)
{
this->length = len;
this->buffer = new uint8_t[len];
}
uint8_t* buffer;
int length;
};
Actually the problem is located at this part of boost in the file read.hpp, where async_read_some is called from 'stream_'.
void operator()(const boost::system::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
std::size_t n = 0;
switch (start_ = start)
{
case 1:
n = this->check_for_completion(ec, total_transferred_);
for (;;)
{
stream_.async_read_some(
boost::asio::buffer(buffer_ + total_transferred_, n),
BOOST_ASIO_MOVE_CAST(read_op)(*this));
return; default:
total_transferred_ += bytes_transferred;
if ((!ec && bytes_transferred == 0)
|| (n = this->check_for_completion(ec, total_transferred_)) == 0
|| total_transferred_ == boost::asio::buffer_size(buffer_))
break;
}
handler_(ec, static_cast<const std::size_t&>(total_transferred_));
}
}
Okey, I've just found the problem.
// creating socket
boost::shared_ptr<boost::asio::ip::tcp::socket> socket(new boost::asio::ip::tcp::socket(*io_service));
I created the socket as a pointer but all the interfaces of read, read_some and other boost-library functions require the object. Therefore adding the dereferencing operator did it:
boost::asio::async_read(*socket, boost::asio::buffer(receiveCommandHeader.buffer, receiveCommandHeader.length),
boost::asio::transfer_all(), boost::bind(HandleRead, ec));

Resources