How to get user defined field in message file INET - c++

I would to send user data, so i added a field in the message file :
class MpeiMacHeader extends MacHeaderBase
{
MPEIMacType type;
uint32_t data;
}
This is what the received message looks like :
msg fields
I didn't success to get the field data in my code. I tried several expressions, i could only get : msg fields
But when I try to compile with msg->content in my code :
no member named 'content' in 'omnetpp::cMessage'
How to get this field in my code ? There is a getData() in generated files, but i didn't find how to use it.

I tried to get the data in handleSelfMessage(), I found a solution using handleLowerPacket() :
void MpeiMac::handleLowerPacket(Packet *packet)
{
if (packet->hasBitError())
{
...
}
else
{
const auto& hdr = packet->peekAtFront<MpeiMacHeader>();
packet->setKind(hdr->getType());
if( hostID == 0 )
data = hdr->getData();
// simply pass the massage as self message, to be processed by the FSM.
handleSelfMessage(packet);
}
}
Maybe this section can explain : inet_developers-guide :

Related

How to create protobuf messages that use "oneof" definition

I'm trying to create 3 messages, start_now, stop_now, and HeartBeat,as defined in the .proto file below. I have already compiled the .proto file using the c++ compiler and have the necessary .h file. It is my understanding that the "oneof" definition allows for only one of the fields to be set at a time. My goal is to create a message,Serialize it using SerializeToString(), then on the receiving end I want to utilize the ParseToString() to get back my message in readable form.
syntax = "proto3";
package jomba;
message SimpleMessage {
}
message Jacket {
uint32 value = 1;
}
message Message {
oneof payload {
SimpleMessage start_now = 1;
SimpleMessage stop_now = 2;
Jacket heart_beat = 3;
}
}
Within the generated header file there is an enum created within class Message which shows the individual fields of the Message. I don't see any set_() functions within this class to generate any of the messages.
enum PayloadCase {
kStartNow = 1,
kStopNow = 2,
kHeartBeat = 3,
PAYLOAD_NOT_SET = 0,
};

quickfix toAdmin to add username , password error

I have referd to here :
QuickFix Login Failed due to password missing
and here :
How to make the login part in QuickFIX
to add username and password in toAdmin like following :
void Application::toAdmin( FIX::Message& message, const FIX::SessionID& sessionID)
{
if (FIX::MsgType_Logon == message.getHeader().getField(FIX::FIELD::MsgType))
{
FIX44::Logon& logon_message = dynamic_cast<FIX44::Logon&>(message);
FIX::Username username = std::string("my_username") ;
logon_message.setField( username );
}
}
This cause compiler error in gcc 4.8.2 :
error: cannot dynamic_cast ??message?? (of type ??class FIX::Message??) to type ??class FIX44::Logon&?? (target is not pointer or reference to complete type)
then I change my code to
FIX44::Logon* logon_message = (FIX44::Logon*)(&message);
FIX::Username username = std::string("my_username") ;
logon_message->setField( username );
this time , compiler error again :
error: invalid use of incomplete type ??class FIX44::Logon??
logon_message->setField( username );
^
What should I modify so that I can correctly set username and password in
function toAdmin ? what is wrong with logon_message->setField( username ); ?
Edit :
according to this webpage :
https://sourceforge.net/p/quickfix/mailman/message/26233433/
The following works fine to me :
if (FIX::MsgType_Logon == message.getHeader().getField(FIX::FIELD::MsgType))
{
message.getHeader().setField(553, "XXXXXXXXX");
message.getHeader().setField(554, "yyyyyyyyy");
}
Have you tried
FIX44::Logon* logon_message = dynamic_cast<FIX44::Logon*>(message);
or
FIX44::Logon* logon_message = dynamic_cast<FIX44::Logon*>( *(message) );
or
FIX44::Logon* logon_message = dynamic_cast<FIX44::Logon*>(&message);
I think this may be an issue of dereferencing message correctly.
The error message suggests that you did not #include "quickfix/fix44/Logon.h".
That is why it thinks that you are using an incomplete type. Your compiler now probably just sees a forward declared: class FIX44::Logon; and it does not know what methods this class contains.
The other answers correctly state that you don't even need to downcast
message.setField(FIX::Username(username));
message.setField(FIX::Password(password));
You don't need to cast your message. Ultimately you end up calling setField which is a function available to the base class FIX::Message.
void FIXSession::toAdmin(FIX::Message& msg, const FIX::SessionID& sid)
{
const std::string& field = msg.getHeader().getField(FIX::FIELD::MsgType);
if (FIX::MsgType_Logon == field)
{
FIX::Dictionary dd(m_sessionSettings.get(sid));
if (dd.has(FixSettingUsername))
{
FIX::Username username = dd.getString(FixSettingUsername);
msg.setField(username);
}
if (dd.has(FixSettingPassword))
{
FIX::Password password = dd.getString(FixSettingPassword);
msg.setField(password);
}
if (dd.has(FIX::SEND_RESETSEQNUMFLAG))
{
FIX::ResetSeqNumFlag rsn(dd.getBool(FIX::SEND_RESETSEQNUMFLAG));
msg.setField(rsn);
}
}
}

Using Persistent Flash Message Library for ColdFusion

I am trying to use a library for showing Flash Messages https://github.com/elpete/flashmessage But I am having trouble getting it working correctly. The documentation isn't that great and I am new to ColdFusion. I want to have the ability to have persistent error messages across pages. Specifically during checkout so when the user needs to go back or a validation error occurs the message will appear. According to the documentation:
The FlashMessage.cfc needs three parameters to work:
A reference to your flash storage object. This object will need
get(key) and put(key, value) methods. A config object with the
following properties: A unique flashKey name to avoid naming
conflicts. A reference to your containerTemplatePath. This is the view
that surrounds each of the individual messages. It will have
references to a flashMessages array and your messageTemplatePath. A
reference to your messageTemplatePath. This is the view that
represents a single message in FlashMessage. It will have a reference
to a single flash message. The name is chosen by you in your container
template. Create your object with your two parameters and then use it
as normal.
I am getting the error
the function getMessages has an invalid return value , can't cast null value to value of type [array]
I had this script somewhat working at one point but it seems very finicky. I believe it is my implementation of it. I am hoping someone here can help me figure out where I went wrong. Or give me some pointers because I am not sure I am even implementing it correctly.
This is What I have in my testing script:
<cfscript>
alertStorage = createObject("component", 'alert');
config = {
flashKey = "myCustomFlashKey",
containerTemplatePath = "/flashmessage/views/_templates/FlashMessageContainer.cfm",
messageTemplatePath = "/flashmessage/views/_templates/FlashMessage.cfm"
};
flash = new flashmessage.models.FlashMessage(alertStorage, config);
flash.message('blah');
flash.danger('boom');
</cfscript>
And inside of alert.cfc I have:
component {
public any function get(key) {
for(var i = 1; i < ArrayLen(session[key]); i++) {
return session[key][i];
}
}
public any function put(key, value) {
ArrayAppend(session.myCustomFlashKey, value);
return true;
}
public any function exists() {
if(structKeyExists(session,"myCustomFlashKey")) {
return true;
} else {
session.myCustomFlashKey = ArrayNew();
return false;
}
}
}
The Flash Message Component looks like this:
component name="FlashMessage" singleton {
/**
* #flashStorage.inject coldbox:flash
* #config.inject coldbox:setting:flashmessage
*/
public FlashMessage function init(any flashStorage, any config) {
instance.flashKey = arguments.config.flashKey;
singleton.flashStorage = arguments.flashStorage;
instance.containerTemplatePath = arguments.config.containerTemplatePath;
instance.messageTemplatePath = arguments.config.messageTemplatePath;
// Initialize our flash messages to an empty array if it hasn't ever been created
if (! singleton.flashStorage.exists(instance.flashKey)) {
setMessages([]);
}
return this;
}
public void function message(required string text, string type = "default") {
appendMessage({ message: arguments.text, type = arguments.type });
}
public any function onMissingMethod(required string methodName, required struct methodArgs) {
message(methodArgs[1], methodName);
}
public any function render() {
var flashMessages = getMessages();
var flashMessageTemplatePath = instance.messageTemplatePath;
savecontent variable="messagesHTML" {
include "#instance.containerTemplatePath#";
}
setMessages([]);
return messagesHTML;
}
public array function getMessages() {
return singleton.flashStorage.get(instance.flashKey, []);
}
private void function setMessages(required array messages) {
singleton.flashStorage.put(
name = instance.flashKey,
value = arguments.messages
);
}
private void function appendMessage(required struct message) {
var currentMessages = getMessages();
ArrayAppend(currentMessages, arguments.message);
setMessages(currentMessages);
}
}

How do I provide ObjectContent that is a string

I'm writing a unit test which tests the scenario where a body is sent in the request which is a plain string, i.e. not parseable as JSON.
In this test, I'm setting the HttpRequestMessage something like this:
var ojectContent = new ObjectContent(typeof(string)
, "aaaaa"
, new JsonMediaTypeFormatter());
httpRequestMessage.Content = objectContent;
The problem is, when I debug the code, the request body has been set to "aaaaa" (note the additional quotes) which is enough to cause the deserialisation code to treat the request body differently, meaning I can't test what I mean to test. I need the request body to be aaaaa.
Can anyone advise how I can set up the test so that the request body does not contain these quotes?
Edit: I have also tried new ObjectContent(typeof(object)... and it gives the same result.
Another way is to bypass the MediaTypeFormatter by using StringContent instead of ObjectContent:
var content = new StringContent("aaaaa");
httpRequestMessage.Content = content;
Okay, so I needed to create a media type formatter that didn't interfere with the input in any way. I used this:
private class DoNothingTypeFormatter : MediaTypeFormatter
{
public override bool CanReadType(Type type)
{
return false;
}
public override bool CanWriteType(Type type)
{
if (type == typeof(string))
{
return true;
}
return false;
}
public override Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, HttpContent content, TransportContext transportContext)
{
var myString = value as string;
if (myString == null)
{
throw new Exception("Everything is supposed to be a string here.");
}
var length = myString.Length;
var bytes = System.Text.Encoding.UTF8.GetBytes(myString);
return Task.Factory.StartNew(() => writeStream.Write(bytes, 0, length));
}
}
Then, when I want to generate the body of the `HttpRequestMessage', I do so like this:
objectContent = new ObjectContent(typeof(string)
, "not json"
, new DoNothingTypeFormatter());

Protocol buffer polymorphism

I have a C++ program that sends out various events, e.g. StatusEvent and DetectionEvent with different proto message definitions to a message service (currently Active MQ, via activemq-cpp APU). I want to write a message listener that receives these messages, parses them and writes them to cout, for debugging purposes. The listener has status_event_pb.h and detection_event_pb.h linked.
My question is: How can I parse the received event without knowing its type? I want to do something like (in pseudo code)
receive event
type = parseEventType(event);
if( type == events::StatusEventType) {
events::StatusEvent se = parseEvent(event);
// do stuff with se
}
else {
// handle the case when the event is a DetectionEvent
}
I looked at this question but I'm not sure if extensions are the right way to go here. A short code snippet pointing the way will be much appreciated. Examples on protobuf are so rare!
Thanks!
It seems extensions are indeed the way to go but I've got one last point to clear up. Here's the proto definition that I have so far:
// A general event, can be thought as base Event class for other event types.
message Event {
required int64 task_id = 1;
required string module_name = 2; // module that sent the event
extensions 100 to 199; // for different event types
}
// Extend the base Event with additional types of events.
extend Event {
optional StatusEvent statusEvent = 100;
optional DetectionEvent detectionEvent = 101;
}
// Contains one bounding box detected in a video frame,
// representing a region of interest.
message DetectionEvent {
optional int64 frame = 2;
optional int64 time = 4;
optional string label = 6;
}
// Indicate status change of current module to other modules in same service.
// In addition, parameter information that is to be used to other modules can
// be passed, e.g. the video frame dimensions.
message StatusEvent {
enum EventType {
MODULE_START = 1;
MODULE_END = 2;
MODULE_FATAL = 3;
}
required EventType type = 1;
required string module_name = 2; // module that sent the event
// Optional key-value pairs for data to be passed on.
message Data {
required string key = 1;
required string value = 2;
}
repeated Data data = 3;
}
My problem now is (1) how to know which specific event that the Event message contains and (2) make sure that it contains only one such event (according to the definition, it can contain both a StatusEvent and a DetectionEvent).
I would not use Protocol Buffers for that, but that's perhaps a combination of little use and other habits.
Anyway, I think I would use an abstract class here, to ease general handling and to contain routing information. Class that would not be defined using protobuf, and would contain a protobuf message.
class Message
{
public:
Type const& GetType() const;
Origin const& GetOrigin() const;
Destination const& GetDestination() const;
// ... other informations
template <class T>
void GetContent(T& proto) const
{
proto.ParseFromIstream(&mContent); // perhaps a try/catch ?
}
private:
// ...
std::stringstream mContent;
};
With this structure, you have both general and specific handling at the tip of your fingers:
void receive(Message const& message)
{
LOG("receive - " << message.GetType() << " from " << message.GetOrigin()
<< " to " << message.GetDestination());
if (message.GetType() == "StatusEvent")
{
StatusEvent statusEvent;
message.Decode(statusEvent);
// do something
}
else if (message.GetType() == "DetectionEvent")
{
DetectionEvent detectionEvent;
message.Decode(detectionEvent);
// do something
}
else
{
LOG("receive - Unhandled type");
}
}
Of course, it would be prettier if you used a std::unordered_map<Type,Handler> instead of a hardcoded if / else if + / else chain, but the principle remains identical:
Encode the type of message sent in the header
Decode only the header upon reception and dispatch based on this type
Decode the protobuf message in a part of the code where the type is known statically