how to implement onvif CreatePullPointSubscription operation by gsoap - 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.

Related

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

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;
};
});
}

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 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