Boost Beast gives "The handle is invalid" error after http:async_write - boost

Initially I got error "The file handle supplied is invalid". This is because my socket was closed. I corrected that error.
Now I get another error "The handle is invalid"....Any idea what could be the issue
Below is my code, which is very simple:
void BeastResponse::write(http::response<http::file_body> responseFile)
{
std::cout << "BeastResponse while file write: " << this << std::endl;
auto self = shared_from_this();
http::async_write(m_stream, responseFile, [self](beast::error_code ec, std::size_t t)
{
if (ec)
{
std::cout << "File Write Failed" << ": " << ec.message() << std::endl;
std::cout << t << std::endl;
}
else
{
std::cout << t << std::endl;
};
});
}
Here , t = 4kb when I get the error. So I think async_write after it does the first block of 4kb, my handler or socket is going to a bad state.
If the change to http:write instead of http:async_write, there is no issues

Below code works for me...
void BeastResponse::write(http::response<http::file_body>&& responseFile)
{
std::cout << "BeastResponse while file write: " << this << std::endl;
auto self = shared_from_this();
// copy file into the member variable, m_response_file
m_response_file = std::move(responseFile)
// 2nd parameter must be a member variable of BeastResponse
http::async_write(m_stream, m_response_file, [self](beast::error_code ec, std::size_t t)
{
if (ec)
{
std::cout << "File Write Failed" << ": " << ec.message() << std::endl;
std::cout << t << std::endl;
}
else
{
std::cout << t << std::endl;
};
});
}

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.

How to set an extension field of the message by using reflection in protobuffer

How to set an extension field of the message in protobuffer? The code is like this:
message Header {
optional string name = 1;
extensions 2 to 10;
}
message PbDirectiveHeader {
extend Header {
optional string message_id = 2;
}
}
PbDirectiveHeader header_msg;
std::cout << "header_msg des : " << header_msg.GetDescriptor() << std::endl;
const google::protobuf::FieldDescriptor* message_id_dec = header_msg.GetDescriptor()->FindExtensionByName("message_id");
if (message_id_dec != nullptr) {
std::cout << "header_msg message_id's des containing_type: " << message_id_dec->containing_type() << std::endl;
header_msg.GetReflection()->SetString(&header_msg, message_id_dec, "123456");
std::cout << "message_id:" << header_msg.GetReflection()->GetString(header_msg, message_id_dec) << std::endl;
} else {
std::cout << "header_msg message_id des is nullptr" << std::endl;
}
the error message is :
[libprotobuf FATAL google/protobuf/generated_message_reflection.cc:86] Protocol Buffer reflection usage error:
...
Problem : Field does not match message type.
If I use reflection to set the name field of Header message, there is no error, but if I turn to set the extension field of message_id, the error happens again. how to solve my problem?
I find a solution to solve my problem
PbDirectiveHeader header_msg;
Header header;
std::cout << "header_msg des : " << header_msg.GetDescriptor() << std::endl;
const google::protobuf::FieldDescriptor* message_id_dec = header_msg.GetDescriptor()->FindExtensionByName("message_id");
if (message_id_dec != nullptr) {
std::cout << "header_msg message_id's des containing_type: " << message_id_dec->containing_type() << std::endl;
header.GetReflection()->SetString(&header, message_id_dec, "123456");
std::cout << "message_id:" << header.GetReflection()->GetString(header, message_id_dec) << std::endl;
} else {
std::cout << "headermessage_id des is nullptr" << std::endl;
}
Use extension message to find an extension field, then use the base message to set/get the extension field's value.

Socket operation on non-socket with zeromq ZMQ_PUB socket

Fairly simple question. I have some code to send a message from a serialised protobuf event (tried also with just a simple char * string). However when i call send i get the error "Socket operation on non-socket". I've tried a lot of things but to no avail.
void send_event(tp::Event event, void * z_pub)
{
assert(z_pub != NULL);
zmq_msg_t msg;
int size = event.ByteSize();
uint8_t sev[size];
event.SerializeWithCachedSizesToArray(sev);
int rc = zmq_msg_init_size(&msg, size);
memcpy(zmq_msg_data(&msg), &sev, size);
if (zmq_sendmsg(z_pub, &msg, 0) != 0)
{
cout << "Send err code: " << " " << zmq_strerror(zmq_errno()) << endl;
}
if (zmq_msg_close(&msg) != 0)
{
cout << "Closing message err code: " << zmq_strerror(zmq_errno()) << endl;
}
}
With things inited thus:
void * z_ctx_pub = zmq_ctx_new();
void * z_pub = zmq_socket(z_ctx_pub, ZMQ_PUB);
if (z_pub == NULL)
cerr << "Error creating output socket for process" << endl;
if (zmq_bind(z_pub, z_pub_uri.c_str()) != 0)
{
cout << "Binding to PUB err code: " << " " << zmq_strerror(zmq_errno()) << endl;
abort();
}
else
cout << "Bound to " << z_pub_uri << endl;
Edit: I've now moved the init to the same thread that i was doing the send in and i get:
Resource temporarily unavailable
http://paste.ubuntu.com/5984515/

boost::asio::async_write not writing to clients properly, weird behaviour

I have written a program that accepts N client connections and then writes data into them. The problem I am having now is: I can only write to N-1 clients, the first one is never written to. I have no idea why this is happening and so I wish some of you might be able to provide some assistance.
I have provided the portion of code that may be associated with this problem:
void ClientPartitionServer::AcceptClientConnections(int port) {
cout << "Listening to connections..." << endl;
cout << "Number of PartitionInstanceConnections: " <<
m_partitionInstanceConnections.size() << endl;
m_acceptor = new boost::asio::ip::tcp::acceptor(m_IOService);
m_endpoint = new boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),
m_port);
m_acceptor->open(m_endpoint->protocol());
m_acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
m_acceptor->bind(*m_endpoint);
m_acceptor->listen();
boost::asio::ip::tcp::socket* acceptingSocket =
new boost::asio::ip::tcp::socket(m_IOService);
m_acceptor->async_accept(*acceptingSocket, boost::bind(
&ClientPartitionServer::HandleAccept, this, acceptingSocket,
boost::asio::placeholders::error));
}
void ClientPartitionServer::HandleAccept(boost::asio::ip::tcp::socket* socket,
const boost::system::error_code& error) {
cout << "Connection established..." << endl;
m_clientSockets.push_back(new boost::asio::ip::tcp::socket(m_IOService));
cout << m_clientSockets.back()->is_open() << endl;
++m_clientSocketsCounter;
cout << "ClientPartitionServer identifier: " << m_identifier << endl;
cout << "Client connected on port: " << m_port << endl;
cout << "Number of clients on port: " << m_clientSocketsCounter <<
endl;
m_acceptor->async_accept(*m_clientSockets.back(), boost::bind(
&ClientPartitionServer::HandleAccept, this, m_clientSockets.back(),
boost::asio::placeholders::error));
}
void ClientPartitionServer::HandleSignal(char* content, int transferSize,
int identifier) {
if(identifier == m_identifier) {
TransferToQueueBuffer(content, transferSize);
if(m_writeCompleteFlag) {
TransferToWriteBuffer(m_queueBuffer, m_queueBufferSize);
if(m_clientSockets.size() != 0) {
for(vector<boost::asio::ip::tcp::socket*>::const_iterator i =
m_clientSockets.begin(); i != m_clientSockets.end(); ++i) {
WriteToClient(m_writeBuffer, m_queueBufferSize, *i);
}
}
}
}
}
void ClientPartitionServer::WriteToClient(char* content, int transferSize,
boost::asio::ip::tcp::socket* clientSocket) {
boost::lock_guard<boost::mutex> lock(m_writeToClientMutex);
m_writeCompleteFlag = false;
boost::asio::async_write(*clientSocket, boost::asio::buffer("ABC ",
4), boost::bind(&ClientPartitionServer::HandleWrite,
this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void ClientPartitionServer::HandleWrite(const boost::system::error_code& ec,
size_t bytes_transferred) {
cout << "handlewrite" << endl;
m_writeCompleteFlag = true;
}
Thank you for any assistance.
The first async_accept() is called on acceptingSocket which is new'd in AcceptClientConnections() and leaked.
The subsequent async_accept()s are called on sockets that are new'd in HandleAccept() and push_back()'ed into m_clientSockets.
WriteToClient() is executed only on the sockets found in m_clientSockets, never on the first socket.
Solution: push_back that first socket in AcceptClientConnections() into m_clientSockets too.

Resources