i have the following code of live media libraries as i was trying to understand it,i was wondering to find out how many bytes does the live media server send each time of the video file test1.264 while streaming it??
How to find out the streaming time,i pulled out my hairs but was not able to find out,can any one help me to find the above queries....
#include "liveMedia.hh"
#include "BasicUsageEnvironment.hh"
UsageEnvironment* env;
// To make the second and subsequent client for each stream reuse the same
// input stream as the first client (rather than playing the file from the
// start for each client), change the following "False" to "True":
Boolean reuseFirstSource = False;
// To stream *only* MPEG-1 or 2 video "I" frames
// (e.g., to reduce network bandwidth),
// change the following "False" to "True":
Boolean iFramesOnly = False;
static void announceStream(RTSPServer* rtspServer, ServerMediaSession* sms,
char const* streamName, char const* inputFileName); // fwd
static char newMatroskaDemuxWatchVariable;
static MatroskaFileServerDemux* demux;
static void onMatroskaDemuxCreation(MatroskaFileServerDemux* newDemux, void* /*clientData*/) {
demux = newDemux;
newMatroskaDemuxWatchVariable = 1;
}
int main(int argc, char** argv) {
// Begin by setting up our usage environment:
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
env = BasicUsageEnvironment::createNew(*scheduler);
UserAuthenticationDatabase* authDB = NULL;
#ifdef ACCESS_CONTROL
// To implement client access control to the RTSP server, do the following:
authDB = new UserAuthenticationDatabase;
authDB->addUserRecord("username1", "password1"); // replace these with real strings
// Repeat the above with each <username>, <password> that you wish to allow
// access to the server.
#endif
// Creating the RTSP server:
RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554, authDB);
if (rtspServer == NULL) {
*env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
exit(1);
}
char const* descriptionString
= "Session streamed by \"testOnDemandRTSPServer\"";
// A H.264 video elementary stream:
{
char const* streamName = "h264ESVideoTest";
char const* inputFileName = "test1.264";
ServerMediaSession* sms
= ServerMediaSession::createNew(*env, streamName, streamName,
descriptionString);
sms->addSubsession(H264VideoFileServerMediaSubsession
::createNew(*env, inputFileName, reuseFirstSource));
rtspServer->addServerMediaSession(sms);
announceStream(rtspServer, sms, streamName, inputFileName);
}
if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {
*env << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";
} else {
*env << "\n(RTSP-over-HTTP tunneling is not available.)\n";
}
env->taskScheduler().doEventLoop(); // does not return
return 0; // only to prevent compiler warning
}
static void announceStream(RTSPServer* rtspServer, ServerMediaSession* sms,
char const* streamName, char const* inputFileName) {
char* url = rtspServer->rtspURL(sms);
UsageEnvironment& env = rtspServer->envir();
env << "\n\"" << streamName << "\" stream, from the file \""
<< inputFileName << "\"\n";
env << "Play this stream using the URL \"" << url << "\"\n";
delete[] url;
}
Related
For a school project I am using IoT Hub to connect between different devices (ESP32), The intention is to use a web application to retrieve data from a device. I want to do this by using a Direct Method.
Now I have seen in the past some direct methods using python and how I can use this in Azure Functions but not yet on an ESP32. By the way, I am programming in C on the ESP32.
Does anyone have an example code for this? I am not finding really much info about direct methods in C with the library "azure-sdk-for-c-arduino".
Thanks in advance
My code at the moment (This is test code):
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/*
This is an Arduino-based Azure IoT Hub sample for ESPRESSIF ESP32 boards.
It uses our Azure Embedded SDK for C to help interact with Azure IoT.
For reference, please visit https://github.com/azure/azure-sdk-for-c.
To connect and work with Azure IoT Hub you need an MQTT client, connecting, subscribing
and publishing to specific topics to use the messaging features of the hub.
Our azure-sdk-for-c is an MQTT client support library, helping composing and parsing the
MQTT topic names and messages exchanged with the Azure IoT Hub.
This sample performs the following tasks:
- Synchronize the device clock with a NTP server;
- Initialize our "az_iot_hub_client" (struct for data, part of our azure-sdk-for-c);
- Initialize the MQTT client (here we use ESPRESSIF's esp_mqtt_client, which also handle the tcp connection and TLS);
- Connect the MQTT client (using server-certificate validation, SAS-tokens for client authentication);
- Periodically send telemetry data to the Azure IoT Hub.
To properly connect to your Azure IoT Hub, please fill the information in the `iot_configs.h` file.
*/
//Variabeles for drukknop
const int PushButton = 35;
//Variables for weight sensor;
double weight = 5.0;
// C99 libraries
#include <cstdlib>
#include <string.h>
#include <time.h>
// Libraries for MQTT client and WiFi connection
#include <WiFi.h>
#include <mqtt_client.h>
// Azure IoT SDK for C includes
#include <az_core.h>
#include <az_iot.h>
#include <azure_ca.h>
// Libraries for SendingJson
#include <ArduinoJson.h>
// Additional sample headers
#include "AzIoTSasToken.h"
#include "SerialLogger.h"
#include "iot_configs.h"
// When developing for your own Arduino-based platform,
// please follow the format '(ard;<platform>)'.
#define AZURE_SDK_CLIENT_USER_AGENT "c/" AZ_SDK_VERSION_STRING "(ard;esp32)"
// Utility macros and defines
#define sizeofarray(a) (sizeof(a) / sizeof(a[0]))
#define NTP_SERVERS "pool.ntp.org", "time.nist.gov"
#define MQTT_QOS1 1
#define DO_NOT_RETAIN_MSG 0
#define SAS_TOKEN_DURATION_IN_MINUTES 60
#define UNIX_TIME_NOV_13_2017 1510592825
#define PST_TIME_ZONE -8
#define PST_TIME_ZONE_DAYLIGHT_SAVINGS_DIFF 1
#define GMT_OFFSET_SECS (PST_TIME_ZONE * 3600)
#define GMT_OFFSET_SECS_DST ((PST_TIME_ZONE + PST_TIME_ZONE_DAYLIGHT_SAVINGS_DIFF) * 3600)
// Translate iot_configs.h defines into variables used by the sample
static const char* ssid = IOT_CONFIG_WIFI_SSID;
static const char* password = IOT_CONFIG_WIFI_PASSWORD;
static const char* host = IOT_CONFIG_IOTHUB_FQDN;
static const char* mqtt_broker_uri = "mqtts://" IOT_CONFIG_IOTHUB_FQDN;
static const char* device_id = IOT_CONFIG_DEVICE_ID;
static const int mqtt_port = AZ_IOT_DEFAULT_MQTT_CONNECT_PORT;
// Memory allocated for the sample's variables and structures.
static esp_mqtt_client_handle_t mqtt_client;
static az_iot_hub_client client;
static char mqtt_client_id[128];
static char mqtt_username[128];
static char mqtt_password[200];
static uint8_t sas_signature_buffer[256];
static unsigned long next_telemetry_send_time_ms = 0;
static char telemetry_topic[128];
static uint8_t telemetry_payload[100];
static uint32_t telemetry_send_count = 0;
#define INCOMING_DATA_BUFFER_SIZE 128
static char incoming_data[INCOMING_DATA_BUFFER_SIZE];
// Auxiliary functions
#ifndef IOT_CONFIG_USE_X509_CERT
static AzIoTSasToken sasToken(
&client,
AZ_SPAN_FROM_STR(IOT_CONFIG_DEVICE_KEY),
AZ_SPAN_FROM_BUFFER(sas_signature_buffer),
AZ_SPAN_FROM_BUFFER(mqtt_password));
#endif // IOT_CONFIG_USE_X509_CERT
static void connectToWiFi()
{
Logger.Info("Connecting to WIFI SSID " + String(ssid));
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Logger.Info("WiFi connected, IP address: " + WiFi.localIP().toString());
}
static void initializeTime()
{
Logger.Info("Setting time using SNTP");
configTime(GMT_OFFSET_SECS, GMT_OFFSET_SECS_DST, NTP_SERVERS);
time_t now = time(NULL);
while (now < UNIX_TIME_NOV_13_2017)
{
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
Logger.Info("Time initialized!");
}
void receivedCallback(char* topic, byte* payload, unsigned int length)
{
Logger.Info("Received [");
Logger.Info(topic);
Logger.Info("]: ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println("");
}
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
{
switch (event->event_id)
{
int i, r;
case MQTT_EVENT_ERROR:
Logger.Info("MQTT event MQTT_EVENT_ERROR");
break;
case MQTT_EVENT_CONNECTED:
Logger.Info("MQTT event MQTT_EVENT_CONNECTED");
r = esp_mqtt_client_subscribe(mqtt_client, AZ_IOT_HUB_CLIENT_C2D_SUBSCRIBE_TOPIC, 1);
if (r == -1)
{
Logger.Error("Could not subscribe for cloud-to-device messages.");
}
else
{
Logger.Info("Subscribed for cloud-to-device messages; message id:" + String(r));
}
break;
case MQTT_EVENT_DISCONNECTED:
Logger.Info("MQTT event MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
Logger.Info("MQTT event MQTT_EVENT_SUBSCRIBED");
break;
case MQTT_EVENT_UNSUBSCRIBED:
Logger.Info("MQTT event MQTT_EVENT_UNSUBSCRIBED");
break;
case MQTT_EVENT_PUBLISHED:
Logger.Info("MQTT event MQTT_EVENT_PUBLISHED");
break;
case MQTT_EVENT_DATA:
Logger.Info("MQTT event MQTT_EVENT_DATA");
for (i = 0; i < (INCOMING_DATA_BUFFER_SIZE - 1) && i < event->topic_len; i++)
{
incoming_data[i] = event->topic[i];
}
incoming_data[i] = '\0';
Logger.Info("Topic: " + String(incoming_data));
for (i = 0; i < (INCOMING_DATA_BUFFER_SIZE - 1) && i < event->data_len; i++)
{
incoming_data[i] = event->data[i];
}
incoming_data[i] = '\0';
if (String(incoming_data) == "GETWEIGHT")
{
Logger.Info("Send Data To The Cloud ");
sendTelemetry();
}
else
{
Logger.Info("Data: " + String(incoming_data));
}
break;
case MQTT_EVENT_BEFORE_CONNECT:
Logger.Info("MQTT event MQTT_EVENT_BEFORE_CONNECT");
break;
default:
Logger.Error("MQTT event UNKNOWN");
break;
}
return ESP_OK;
}
static void initializeIoTHubClient()
{
az_iot_hub_client_options options = az_iot_hub_client_options_default();
options.user_agent = AZ_SPAN_FROM_STR(AZURE_SDK_CLIENT_USER_AGENT);
if (az_result_failed(az_iot_hub_client_init(
&client,
az_span_create((uint8_t*)host, strlen(host)),
az_span_create((uint8_t*)device_id, strlen(device_id)),
&options)))
{
Logger.Error("Failed initializing Azure IoT Hub client");
return;
}
size_t client_id_length;
if (az_result_failed(az_iot_hub_client_get_client_id(
&client, mqtt_client_id, sizeof(mqtt_client_id) - 1, &client_id_length)))
{
Logger.Error("Failed getting client id");
return;
}
if (az_result_failed(az_iot_hub_client_get_user_name(
&client, mqtt_username, sizeofarray(mqtt_username), NULL)))
{
Logger.Error("Failed to get MQTT clientId, return code");
return;
}
Logger.Info("Client ID: " + String(mqtt_client_id));
Logger.Info("Username: " + String(mqtt_username));
}
static int initializeMqttClient()
{
#ifndef IOT_CONFIG_USE_X509_CERT
if (sasToken.Generate(SAS_TOKEN_DURATION_IN_MINUTES) != 0)
{
Logger.Error("Failed generating SAS token");
return 1;
}
#endif
esp_mqtt_client_config_t mqtt_config;
memset(&mqtt_config, 0, sizeof(mqtt_config));
mqtt_config.uri = mqtt_broker_uri;
mqtt_config.port = mqtt_port;
mqtt_config.client_id = mqtt_client_id;
mqtt_config.username = mqtt_username;
#ifdef IOT_CONFIG_USE_X509_CERT
Logger.Info("MQTT client using X509 Certificate authentication");
mqtt_config.client_cert_pem = IOT_CONFIG_DEVICE_CERT;
mqtt_config.client_key_pem = IOT_CONFIG_DEVICE_CERT_PRIVATE_KEY;
#else // Using SAS key
mqtt_config.password = (const char*)az_span_ptr(sasToken.Get());
#endif
mqtt_config.keepalive = 30;
mqtt_config.disable_clean_session = 0;
mqtt_config.disable_auto_reconnect = false;
mqtt_config.event_handle = mqtt_event_handler;
mqtt_config.user_context = NULL;
mqtt_config.cert_pem = (const char*)ca_pem;
mqtt_client = esp_mqtt_client_init(&mqtt_config);
if (mqtt_client == NULL)
{
Logger.Error("Failed creating mqtt client");
return 1;
}
esp_err_t start_result = esp_mqtt_client_start(mqtt_client);
if (start_result != ESP_OK)
{
Logger.Error("Could not start mqtt client; error code:" + start_result);
return 1;
}
else
{
Logger.Info("MQTT client started");
return 0;
}
}
/*
#brief Gets the number of seconds since UNIX epoch until now.
#return uint32_t Number of seconds.
*/
static uint32_t getEpochTimeInSecs()
{
return (uint32_t)time(NULL);
}
static void establishConnection()
{
connectToWiFi();
initializeTime();
initializeIoTHubClient();
(void)initializeMqttClient();
}
static void getTelemetryPayload(az_span payload, az_span* out_payload)
{
az_span original_payload = payload;
payload = az_span_copy(
payload, AZ_SPAN_FROM_STR("{ \"deviceId\": "));
payload = az_span_copy(payload, AZ_SPAN_FROM_STR( IOT_CONFIG_DEVICE_ID ));
payload = az_span_copy(payload, AZ_SPAN_FROM_STR( "," ));
payload = az_span_copy(payload, AZ_SPAN_FROM_STR( "\" weight\": "));
(void)az_span_u32toa(payload, weight , &payload);
payload = az_span_copy(payload, AZ_SPAN_FROM_STR(" }"));
payload = az_span_copy_u8(payload, '\0');
*out_payload = az_span_slice(original_payload, 0, az_span_size(original_payload) - az_span_size(payload) - 1);
}
static void sendTelemetry()
{
az_span telemetry = AZ_SPAN_FROM_BUFFER(telemetry_payload);
Logger.Info("Sending telemetry ...");
// The topic could be obtained just once during setup,
// however if properties are used the topic need to be generated again to reflect the
// current values of the properties.
if (az_result_failed(az_iot_hub_client_telemetry_get_publish_topic(
&client, NULL, telemetry_topic, sizeof(telemetry_topic), NULL)))
{
Logger.Error("Failed az_iot_hub_client_telemetry_get_publish_topic");
return;
}
getTelemetryPayload(telemetry, &telemetry);
if (esp_mqtt_client_publish(
mqtt_client,
telemetry_topic,
(const char*)az_span_ptr(telemetry),
az_span_size(telemetry),
MQTT_QOS1,
DO_NOT_RETAIN_MSG)
== 0)
{
Logger.Error("Failed publishing");
}
else
{
Logger.Info("Message published successfully");
}
}
// Arduino setup and loop main functions.
void setup()
{
establishConnection();
pinMode(PushButton, INPUT);
}
void loop()
{
if (WiFi.status() != WL_CONNECTED)
{
connectToWiFi();
}
#ifndef IOT_CONFIG_USE_X509_CERT
else if (sasToken.IsExpired())
{
Logger.Info("SAS token expired; reconnecting with a new one.");
(void)esp_mqtt_client_destroy(mqtt_client);
initializeMqttClient();
}
#endif
int Push_button_state = digitalRead(PushButton);
// if condition checks if push button is pressed
if ( Push_button_state == HIGH )
{
Serial.println("De Button Is ingedrukt");
sendTelemetry();
delay(500);
}
}
The idea is that when I send a Direct Method "GETWEIGHT" I get a json value back.
In your initializeMqttClient method, you can add the following line.
mqtt_client.setCallback(receivedCallback);
Your receivedCallback method can have the following definition (code from a Microsoft sample)
void receivedCallback(char* topic, byte* payload, unsigned int length)
{
Logger.Info("Received [");
Logger.Info(topic);
Logger.Info("]: ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println("");
}
You mentioned you want to retrieve data from the device, so you probably want to respond to the message. This is done by sending a message on the right topic. You need to include the status (for instance a 200 indicating 'OK') and the ID of the direct method. This id is included when you receive the direct method. For instance, if you receive a direct method with ID 42, you can respond to it by publishing:
void RespondToDirectMethod()
{
mqtt_client.publish("$iothub/methods/res/200/?$rid=42", "", false);
}
In my project,
I implement a new class called myApp which inherits from ApplicationBase and UdpSocket classes. When I build my project I get no error, but when I debug C/C++ application with the IDE, it displays the first error in errors section. And the command line display the second error when I run make :
Code of myApp.ned, myApp.h and myApp.cc in what follows :
I did include inet library in project references, and I tried the solution posted in The following NED types could not be fully resolved, due to a missing base type or interface.
import inet.applications.contract.IApp;
simple myApp like IApp
{
parameters:
int localPort = default(-1); // local UDP port number (-1: use ephemeral port)
int destPort; // remote UDP port number
string packetName = default("myApp");
string interfaceTableModule; // The path to the InterfaceTable module
double helloInterval #unit(s) = default(5s); // how often hello messages should be sent out
volatile double sendInterval #unit(s); // should usually be a random value, e.g. exponential(1)
double startTime #unit(s) = default(this.sendInterval); // application start time (start of the first packet)
double stopTime #unit(s) = default(-1s); // time of finishing sending, -1s means forever
double maxVariance = default(1); // This is the maximum of a random value to determine when the first hello message will be sent out
volatile double broadcastDelay #unit(s) = default(uniform(0s,0.01s));
int timeToLive = default(-1); // if not -1, set the TTL (IPv4) or Hop Limit (IPv6) field of sent packets to this value
bool dontFragment = default(false); // if true, asks IP to not fragment the message during routing
int typeOfService = default(-1); // if not -1, set the ToS (IPv4) or Traffic Class (IPv6) field of sent packets to this value
string multicastInterface = default(""); // if not empty, set the multicast output interface option on the socket (interface name expected)
bool receiveBroadcast = default(false); // if true, makes the socket receive broadcast packets
bool joinLocalMulticastGroups = default(false); // if true, makes the socket receive packets from all multicast groups set on local interfaces
#class(myApp);
gates:
input socketIn #labels(UdpControlInfo/up);
output socketOut #labels(UdpControlInfo/down);
}
#ifndef MYAPP_H_
#define MYAPP_H_
#include "inet/common/INETDefs.h"
#include "inet/applications/base/ApplicationBase.h"
#include "inet/transportlayer/contract/udp/UdpSocket.h"
#include "inet/transportlayer/contract/udp/UdpControlInfo_m.h"
#include "inet/common/ModuleAccess.h"
#include "inet/common/TimeTag_m.h"
#include "inet/common/packet/Packet.h"
#include "inet/common/lifecycle/ModuleOperations.h"
#include "inet/common/IProtocolRegistrationListener.h"
#include "inet/common/ProtocolTag_m.h"
#include "inet/linklayer/common/InterfaceTag_m.h"
#include "inet/networklayer/contract/IInterfaceTable.h"
#include "inet/networklayer/contract/ipv4/Ipv4Address.h"
#include "inet/networklayer/ipv4/IIpv4RoutingTable.h"
#include "inet/networklayer/ipv4/Ipv4Header_m.h"
#include "inet/networklayer/ipv4/Ipv4InterfaceData.h"
#include "inet/networklayer/common/FragmentationTag_m.h"
#include "inet/networklayer/common/L3AddressResolver.h"
#include "HelloMsg_m.h"
#include "XedMsg_m.h"
#include <omnetpp.h>
#include <vector>
#include <random>
#include <algorithm>
using namespace omnetpp;
using namespace inet;
using namespace std;
class myApp : public ApplicationBase, public UdpSocket::ICallback
{
protected:
//enum SelfMsgKinds { START = 1, SEND, STOP };
int localPort = -1, destPort = -1;
bool dontFragment = false;
const char *packetName = nullptr;
simtime_t startTime;
simtime_t stopTime;
// state
UdpSocket socket;
cMessage *selfMsg = nullptr;
cModule *host = nullptr;
cMessage *event = nullptr;
cPar *broadcastDelay = nullptr;
unsigned int sequencenumber = 0;
simtime_t helloInterval;
IInterfaceTable *ift = nullptr;
InterfaceEntry *interface80211ptr = nullptr;
int interfaceId = -1;
list<L3Address> neighbors;
Ipv4Address source;
/********** XED **********/
class XED
{
public:
L3Address originatorAddr, destinationAddr;
unsigned int random;
XED(const L3Address& originatorAddr, const L3Address& destinationAddr, unsigned int random)
: originatorAddr(originatorAddr), destinationAddr(destinationAddr), random(random) {};
bool operator==(const XED& other) const
{
return this->originatorAddr == other.originatorAddr && this->destinationAddr == other.destinationAddr
&& this->random == other.random;
}
};
list<XED> lr,ls;
/********** MTLSD **********/
class MTLSD
{
public:
L3Address originatorAddr, destinationAddr;
char *position;
simtime_t time;
MTLSD(const L3Address& originatorAddr, const L3Address& destinationAddr, char *position, simtime_t time)
: originatorAddr(originatorAddr), destinationAddr(destinationAddr), position(position), time(time) {};
bool operator==(const MTLSD& other) const
{
return this->originatorAddr == other.originatorAddr && this->destinationAddr == other.destinationAddr
&& this->position == other.position && this->time == time;
}
};
protected:
virtual int numInitStages() const override { return NUM_INIT_STAGES; }
virtual void initialize(int stage) override;
virtual void handleMessageWhenUp(cMessage *msg) override;
void handleSelfMessage(cMessage *msg);
/*virtual void processStart();
virtual void processSend();
virtual void processStop();*/
// lifecycle
virtual void handleStartOperation(LifecycleOperation *operation) override { start(); }
virtual void handleStopOperation(LifecycleOperation *operation) override { stop(); }
virtual void handleCrashOperation(LifecycleOperation *operation) override { stop(); }
void start();
void stop();
virtual void socketDataArrived(UdpSocket *socket, Packet *packet) override;
virtual void socketErrorArrived(UdpSocket *socket, Indication *indication) override;
virtual void socketClosed(UdpSocket *socket) override;
//virtual void generateMTLSDPacket();
//virtual Packet *generateXEDPacket();
virtual double generateRandom();
public:
myApp() {}
~myApp();
};
#endif /* MYAPP_H_ */
#include "myApp.h"
#include "inet/applications/base/ApplicationPacket_m.h"
#include "inet/applications/udpapp/UdpBasicApp.h"
#include "inet/common/TagBase_m.h"
#include "inet/networklayer/common/L3AddressTag_m.h"
#include <iterator>
using namespace std;
Define_Module(myApp);
myApp::~myApp()
{
EV << "App destructor" << endl;
cancelAndDelete(selfMsg);
}
void myApp::initialize(int stage)
{
ApplicationBase::initialize(stage);
if (stage == INITSTAGE_LOCAL)
{
sequencenumber = 0;
ift = getModuleFromPar<IInterfaceTable>(par("interfaceTableModule"), this);
event = new cMessage("event");
broadcastDelay = &par("broadcastDelay");
helloInterval = par("helloInterval");
localPort = par("localPort");
destPort = par("destPort");
packetName = par("packetName");
startTime = par("startTime");
stopTime = par("stopTime");
}
else if (stage == INITSTAGE_ROUTING_PROTOCOLS)
{
registerService(Protocol::manet, nullptr, gate("socketIn"));
registerProtocol(Protocol::manet, gate("socketOut"), nullptr);
}
}
void myApp::handleSelfMessage(cMessage *msg)
{
if (msg == event)
{
auto hello = makeShared<HelloMsg>();
Ipv4Address source = (interface80211ptr->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
hello->setChunkLength(b(128));
hello->setSrcAddress(source);
sequencenumber += 2;
hello->setSequencenumber(sequencenumber);
hello->setNextAddress(source);
hello->setHopdistance(1);
auto packet = new Packet("Hello", hello);
packet->addTagIfAbsent<L3AddressReq>()->setDestAddress(Ipv4Address(255, 255, 255, 255));
packet->addTagIfAbsent<L3AddressReq>()->setSrcAddress(source);
packet->addTagIfAbsent<InterfaceReq>()->setInterfaceId(interface80211ptr->getInterfaceId());
packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::manet);
packet->addTagIfAbsent<DispatchProtocolReq>()->setProtocol(&Protocol::ipv4);
send(packet, "socketOut");
packet = nullptr;
hello = nullptr;
scheduleAt(simTime()+helloInterval+broadcastDelay->doubleValue(), event);
}
}
void myApp::handleMessageWhenUp(cMessage *msg)
{
if (msg->isSelfMessage())
{
handleSelfMessage(msg);
}
else if (check_and_cast<Packet *>(msg)->getTag<PacketProtocolTag>()->getProtocol() == &Protocol::manet)
{
auto recHello = staticPtrCast<HelloMsg>(check_and_cast<Packet *>(msg)->peekData<HelloMsg>()->dupShared());
if (msg->arrivedOn("socketIn"))
{
bubble("Received hello message");
Ipv4Address source = interface80211ptr->getProtocolData<Ipv4InterfaceData>()->getIPAddress();
Ipv4Address src;
unsigned int msgsequencenumber;
int numHops;
Ipv4Address next;
src = recHello->getSrcAddress();
msgsequencenumber = recHello->getSequencenumber();
next = recHello->getNextAddress();
numHops = recHello->getHopdistance();
if (src == source)
{
EV_INFO << "Hello msg dropped. This message returned to the original creator.\n";
delete msg;
return;
}
else
{
neighbors.push_back(src);
/*list<XED>::iterator findIter = find(ls.begin()->destinationAddr, ls.end()->destinationAddr, src);
if (findIter != ls.end()->destinationAddr)
{
}*/
source = (interface80211ptr->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
//socket.bind(source, localPort);
auto xed = makeShared<XedMsg>();
xed->setChunkLength(b(128)); ///size of XED message in bits
xed->setSrcAddress(source);
xed->setDstAddress(src);
double random = generateRandom();
xed->setRandom(random);
//XED item = XED(source, src, random);
//ls.push_back(item);
auto packet = new Packet("XED", xed);
packet->addTagIfAbsent<L3AddressReq>()->setDestAddress(src);
packet->addTagIfAbsent<L3AddressReq>()->setSrcAddress(source);
packet->addTagIfAbsent<InterfaceReq>()->setInterfaceId(interfaceId);
packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::ipv4);
packet->addTagIfAbsent<DispatchProtocolReq>()->setProtocol(&Protocol::ipv4);
socket.setOutputGate(gate("socketOut"));
socket.setCallback(this);
socket.bind(source, localPort);
//emit(packetSentSignal, packet);
socket.sendTo(packet, src, destPort);
//send(packet, "socketOut");
packet = nullptr;
xed = nullptr;
/*Ipv4Address source = (interface80211ptr->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
EV << "I am node " << source << ", my neighbors are : " << endl;
list<L3Address>::iterator it;
for (it = neighbors.begin(); it != neighbors.end(); ++it)
{
EV << it. << endl;
}
for (auto const& i : neighbors)
{
EV << i.str() << endl;
}*/
EV << "I am your neighbor " << src.str();
}
delete msg;
}
else if (check_and_cast<Packet *>(msg)->getTag<PacketProtocolTag>()->getProtocol() == &Protocol::ipv4)
{
EV << "Xed message received" << endl;
//auto recXed = staticPtrCast<XedMsg>(check_and_cast<Packet *>(msg)->peekData<XedMsg>()->dupShared());
}
else
throw cRuntimeError("Message arrived on unknown gate %s", msg->getArrivalGate()->getName());
}
}
void myApp::start()
{
/*socket.setOutputGate(gate("socketOut"));
socket.setCallback(this);*/
int num_80211 = 0;
InterfaceEntry *ie;
InterfaceEntry *i_face;
const char *name;
for (int i = 0; i < ift->getNumInterfaces(); i++)
{
ie = ift->getInterface(i);
name = ie->getInterfaceName();
if (strstr(name, "wlan") != nullptr)
{
i_face = ie;
num_80211++;
interfaceId = i;
}
}
if (num_80211 == 1)
{
interface80211ptr = i_face;
interfaceId = interface80211ptr->getInterfaceId();
}
else
throw cRuntimeError("Node has found %i 80211 interfaces", num_80211);
scheduleAt(simTime() + uniform(0.0, par("maxVariance").doubleValue()), event);
}
double myApp::generateRandom()
{
double lower_bound = 10000;
double upper_bound = 100000;
uniform_real_distribution<double> unif(lower_bound,upper_bound);
default_random_engine re;
double a_random_double = unif(re);
return a_random_double;
}
void myApp::stop()
{
cancelEvent(event);
socket.close();
delayActiveOperationFinish(par("stopOperationTimeout"));
}
void myApp::socketDataArrived(UdpSocket *socket, Packet *packet)
{
emit(packetReceivedSignal, packet);
EV_INFO << "Received packet: " << UdpSocket::getReceivedPacketInfo(packet) << endl;
}
void myApp::socketErrorArrived(UdpSocket *socket, Indication *indication)
{
EV_WARN << "Ignoring UDP error report " << indication->getName() << endl;
delete indication;
}
void myApp::socketClosed(UdpSocket *socket)
{
if (operationalState == State::STOPPING_OPERATION)
startActiveOperationExtraTimeOrFinish(par("stopOperationExtraTime"));
}
Error: NED type 'myApp' could not be fully resolved due to a missing base type or interface, at /home/bocuhra/Downloads/omnetpp-5.4.1/samples/SaaS/myApp.ned:18
myApp.cc
HelloMsg_m.cc
XedMsg_m.cc
Creating executable: out/gcc-release//SaaS
/usr/bin/ld: cannot find -lINET
collect2: error: ld returned 1 exit status
Makefile:104: recipe for target 'out/gcc-release//SaaS' failed
make: *** [out/gcc-release//SaaS] Error 1
I did solve the problem by adding all ned files in my .ini file.
ned-path = .;../inet/src/inet
I implemented two simple client and server example, but it does not work. Both client and server just freeze without any messages printed.
client.cpp
int main(int argc, char * argv[])
{
std::string raw_ip = "127.0.0.1";
int port = 3333;
try
{
asio::ip::tcp::endpoint
ep(asio::ip::address::from_string(raw_ip), port);
asio::io_service ios;
asio::ip::tcp::socket sock(ios, ep.protocol());
sock.connect(ep);
asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "request from clinet\n";
asio::streambuf response;
asio::read_until(sock, response, "\n");
std::istream response_stream(&response);
std::cout << response_stream.rdbuf() << std::endl;
}
catch(system::system_error &e)
{
std::cout << "Encounter error: " << e.what() << std::endl;
return e.code().value();
}
}
server.cpp
int main(int argc, char * argv[])
{
std::string raw_ip="127.0.0.1";
int port=3333;
try
{
asio::ip::tcp::endpoint ep(asio::ip::address_v4::any(),port);
asio::io_service ios;
asio::ip::tcp::acceptor acceptor(ios, ep);
acceptor.listen();
asio::ip::tcp::socket sock(ios);
acceptor.accept(sock);
asio::streambuf request;
asio::read_until(sock, request, "\n");
std::istream request_stream(&request);
std::cout << request_stream.rdbuf() << std::endl;
asio::streambuf response;
std::ostream response_stream(&response);
response_stream << "response from server\n";
}
catch(system::system_error &e)
{
std::cout << e.what() << std::endl;
return -1;
}
return 0;
}
Also I am wondering the best way to transfer a large amount of data to/from socket, how do we tell socket that I am done writing data to socket? And how do we know that we have read the last byte of data from socket? Thanks.
You need to call the blocking function 'ios.run()in both the client and server to animateboost::io_service`. In any case, I don't think your app will produce anything usable as is. You should try and use one of the asio examples as a starting point.
The TCP blocking echo client/server example should be a good starting point for what you want to do.
http://www.boost.org/doc/libs/1_64_0/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp
http://www.boost.org/doc/libs/1_64_0/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp
On a TCP connection, you can use a single asio buffer to ensure all of the data is sent. But you should send a message beforehand to the client so it knows how much data it should expect to receive.
I am trying to use native messaging to send some data to my native windows application. It works well with the runtime.sendNativeMessage() method. When I am trying to use long lived connections which uses a port, it also can pass data from chrome to my app. However, chrome extension can only receive the first response from my app. I am sure that the port is still open because my app can still receive data from chrome. Following are my code:
Chrome Extension Script:
var port = chrome.runtime.connectNative('com.mydomain.app1');
port.onMessage.addListener(function(msg) {
console.log("Received from port:", msg);
});
port.onDisconnect.addListener(function() {
console.log("Disconnected");
});
chrome.tabs.onUpdated.addListener(
function(tabId, changeInfo, tab) {
var param = {};
param['url'] = tab.url;
port.postMessage( param);
}
}
My windows app in c++:
int _tmain(int argc, _TCHAR* argv[])
{
while( true )
{
//read the first four bytes (=> Length)
unsigned int length = 0;
for (int i = 0; i < 4; i++)
{
char c;
if( ( c=getchar()) != EOF)
length += c<<i*8;
else return 0;
}
//read the json-message
std::string msg = "";
for (int i = 0; i < length; i++)
{
msg += getchar();
}
//.... do something
//send a response message
std::string message = "{\"text\": \"This is a response message\"}";
unsigned int len = message.length();
// We need to send the 4 bytes of length information
std::cout << char(((len>>0) & 0xFF))
<< char(((len>>8) & 0xFF))
<< char(((len>>16) & 0xFF))
<< char(((len>>24) & 0xFF));
// Now we can output our message
std::cout << message.c_str();
std::cout.flush();
}
}
Notice that the last line "std::cout.flush();", if I comment it out, even the first response won't be shown in chrome. I just couldn't figure out how chrome reads from the app's stdout.
Try with automatic flushing - std::cout.setf( std::ios_base::unitbuf )
Also, the way you read/write the input/output messages length is incorrect and will fail on long messages.
This code works well for me:
int main(int argc, char* argv[])
{
std::cout.setf( std::ios_base::unitbuf );
while (true)
{
unsigned int ch, inMsgLen = 0, outMsgLen = 0;
std::string input = "", response = "";
// Read 4 bytes for data length
std::cin.read((char*)&inMsgLen, 4);
if (inMsgLen == 0)
{
break;
}
else
{
// Loop getchar to pull in the message until we reach the total length provided.
for (int i=0; i < inMsgLen; i++)
{
ch = getchar();
input += ch;
}
}
response.append("{\"echo\":").append(input).append("}");
outMsgLen = response.length();
// Send 4 bytes of data length
std::cout.write((char*)&outMsgLen, 4);
// Send the data
std::cout << response;
}
return 0;
}
First i asked this Running a function on the main thread from a boost thread and passing parameters to that function
so now i am trying this:
The following is a console c++ project where i perfectly simulated my big project
TestServicePost.cpp
#include "stdafx.h"
#include "SomeClass.h"
int _tmain(int argc, _TCHAR* argv[])
{
SomeClass* s = new SomeClass();
while(true)
{
s->update();
}
return 0;
}
SomeClass.h
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <queue>
class ServiceNote
{
public:
std::string getType()
{
std::stringstream typeSS;
typeSS << "LamasaTech.MultiWall.PostNote." << (NoteType.compare("Normal") == 0 ? "Node" : "Header") << "." << Shape << "." << Colour;
return typeSS.str();
}
int Action;
int CNoteId;
std::string Colour;
int NoteId;
std::string NoteType;
int SessionId;
std::string Shape;
std::string Style;
std::string Text;
int X;
int Y;
};
class SomeClass
{
public:
SomeClass();
~SomeClass();
void update();
private:
std::queue<ServiceNote> pendingNotes;
void addToQueue(ServiceNote sn);
void pollService(boost::asio::io_service* svc);
int getMessage(boost::asio::io_service* svc, std::string sessionId, int messageId);
boost::thread servicePoller;
};
SomeClass.cpp
#include "stdafx.h"
#include "SomeClass.h"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/asio/signal_set.hpp>
#define POLL_SERVICE = 0;
#define POLLING_WAIT_TIME 1000
#define SAVE_SESSION_EVERY 1800000
SomeClass::SomeClass()
{
boost::asio::io_service io_servicePoller;
io_servicePoller.run();
servicePoller = boost::thread(boost::bind(&SomeClass::pollService, this, &io_servicePoller));
/*boost::asio::io_service io_sessionSaver;
boost::asio::signal_set signalsSaver(io_sessionSaver, SIGINT, SIGTERM);
signalsSaver.async_wait( boost::bind(&boost::asio::io_service::stop, &io_sessionSaver));
sessionSaver = boost::thread(&SomeClass::saveSessionEvery, io_sessionSaver);*/
}
SomeClass::~SomeClass()
{
}
void SomeClass::update()
{
while(!pendingNotes.empty())
{
ServiceNote sn = pendingNotes.front();
pendingNotes.pop();
}
}
void SomeClass::addToQueue(ServiceNote sn)
{
pendingNotes.push(sn);
}
void SomeClass::pollService(boost::asio::io_service* svc)
{
int messageId = 1;
while(true)
{
if(boost::this_thread::interruption_enabled() && boost::this_thread::interruption_requested())
return;
int currentId = messageId;
messageId = getMessage(svc, "49", messageId);
if(currentId == messageId)
boost::this_thread::sleep(boost::posix_time::milliseconds(POLLING_WAIT_TIME));
}
}
int SomeClass::getMessage(boost::asio::io_service* svc, std::string sessionId, int messageId)
{
try
{
boost::asio::io_service io_service;
// Get a list of endpoints corresponding to the server name.
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query("mw.rombus.com", "http");
boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
// Try each endpoint until we successfully establish a connection.
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
// Form the request. We specify the "Connection: close" header so that the
// server will close the socket after transmitting the response. This will
// allow us to treat all data up until the EOF as the content.
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET " "/Service.svc/message/" << sessionId << "/" << messageId << " HTTP/1.0\r\n";
request_stream << "Host: " << "mw.rombus.com" << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
// Send the request.
boost::asio::write(socket, request);
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
//std::cout << "Invalid response\n";
return messageId;
}
if (status_code != 200)
{
//std::cout << "Response returned with status code " << status_code << "\n";
return messageId;
}
// Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket, response, "\r\n\r\n");
// Process the response headers.
std::string header;
std::string fullHeader = "";
while (std::getline(response_stream, header) && header != "\r")
fullHeader.append(header).append("\n");
// Write whatever content we already have to output.
std::string fullResponse = "";
if (response.size() > 0)
{
std::stringstream ss;
ss << &response;
fullResponse = ss.str();
try
{
boost::property_tree::ptree pt;
boost::property_tree::read_json(ss, pt);
ServiceNote sn;
sn.Action = pt.get<int>("Action");
sn.CNoteId = pt.get<int>("CNoteId");
sn.Colour = pt.get<std::string>("Colour");
sn.NoteId = pt.get<int>("NoteId");
sn.NoteType = pt.get<std::string>("NoteType");
sn.SessionId = pt.get<int>("SessionId");
sn.Shape = pt.get<std::string>("Shape");
sn.Style = pt.get<std::string>("Style");
sn.Text = pt.get<std::string>("Text");
sn.X = pt.get<int>("X");
sn.Y = pt.get<int>("Y");
svc->post(boost::bind(&SomeClass::addToQueue, this, sn));
//pendingNotes.push(sn);
}
catch (std::exception const& e)
{
std::string test = e.what();
//std::cerr << e.what() << std::endl;
}
messageId++;
}
// Read until EOF, writing data to output as we go.
std::string fullSth = "";
boost::system::error_code error;
while (boost::asio::read(socket, response,
boost::asio::transfer_at_least(1), error))
{
std::ostringstream ss;
ss << &response;
fullSth = ss.str();
}
if (error != boost::asio::error::eof)
throw boost::system::system_error(error);
}
catch (std::exception& e)
{
std::string test = e.what();
std::cout << "Exception: " << e.what() << "\n";
}
return messageId;
}
but i get Unhandled exception at 0x771215de in TestServicePost.exe: 0xC0000005: Access violation writing location 0xcccccce4., right after this line executes:
svc->post(boost::bind(&SomeClass::addToQueue, this, sn));
I couldn't define io_service as a class member so i can use it in the destructor ~SomeClass(), would appreciate help on that too
If io_service.post is not the best solution for me please recommend something, as you can see i have a constructor, destructor and an update method who is called every tick, i tried using this and the queue alone but it wasn't thread safe, is there an easy thread safe FIFO to use ?
In SomeClass constructor you actually do the following:
Define a local io_service instance.
Call its run() member-function, which returns immediately, because io_service has no work.
Pass an address of the local object to another thread.
This certainly won't work.
Note that io_service::run() is a kind of "message loop", so it should block the calling thread. Don't call it in object constructor.
I figured out how to declare io_service as a class member:
boost::shared_ptr< boost::asio::io_service > io_servicePoller;
and in the constructor i did the following:
SomeClass::SomeClass()
{
boost::shared_ptr< boost::asio::io_service > io_service(
new boost::asio::io_service
);
io_servicePoller = io_service;
servicePoller = boost::thread(boost::bind(&SomeClass::pollService, this, io_servicePoller));
}
Some cleanup
SomeClass::~SomeClass()
{
servicePoller.interrupt();
io_servicePoller->stop();
servicePoller.join();
}
and in update i called run which adds the stuff into the queue, then reads them in the while loop
void SomeClass::update()
{
io_servicePoller->run();
io_servicePoller->reset();
while(!pendingNotes.empty())
{
ServiceNote sn = pendingNotes.front();
pendingNotes.pop();
}
}
and changed my members signature to void SomeClass::pollService(boost::shared_ptr< boost::asio::io_service > svc)
So what happens is:
The app starts
inits my class
my class makes a service and starts the thread
the thread fetches items from the service
the main thread checks the io service queue and exuted it
then it uses the queue
Thanks to Igor R. i couldn't have done it without him
and also http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=4 where i got how to make the shared pointer