Commit 884ebf15 authored by 王思远's avatar 王思远

UTC:2025-11-21 9:33:34 :

parent 80067a9c
......@@ -31,6 +31,8 @@ list (REMOVE_ITEM SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/generated_msgs/converter-example.c"
)
# add_definitions ("-DASN_EMIT_DEBUG=1")
add_executable (asn1Demo
${SOURCES}
)
#include <array>
#include <atomic>
#include <cerrno>
#include <chrono>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <memory>
#include <random>
#include <string>
#include <arpa/inet.h>
......@@ -16,6 +18,10 @@
#include <sys/socket.h>
#include <unistd.h>
extern "C" {
#include <asn_random_fill.h>
}
#include <MessageFrame.h>
constexpr ::std::size_t MTU = 1024;
......@@ -39,7 +45,6 @@ using MessagePtr = ::std::unique_ptr<MessageType, void (*)(MessageType *)>;
auto fill = stream.fill();
auto width = stream.width();
stream << "MessageFrame{";
::std::unique_ptr<char[]> buffer;
::std::size_t bufferSize = 1024;
while (true) {
......@@ -49,14 +54,14 @@ using MessagePtr = ::std::unique_ptr<MessageType, void (*)(MessageType *)>;
reinterpret_cast<const void *>(&message), buffer.get(), bufferSize);
if (encodeResult.encoded < 0) {
stream << "ENCODE_ERROR";
} else if (encodeResult.encoded <= bufferSize) {
} else if (static_cast<::std::size_t>(encodeResult.encoded)
<= bufferSize) {
stream.write(buffer.get(), encodeResult.encoded);
break;
} else {
bufferSize *= 2;
}
}
stream << "}";
stream.flags(flags);
stream.fill(fill);
......@@ -66,6 +71,63 @@ using MessagePtr = ::std::unique_ptr<MessageType, void (*)(MessageType *)>;
}
/**
* @brief Fill random string.
*
* @param[out] output String to fill.
* @param[in] minSize Minimum size.
* @param[in] maxSize Maximum size.
*/
void fillRandomString(OCTET_STRING &output,
::std::size_t minSize,
::std::size_t maxSize)
{
::std::random_device randomDev;
::std::default_random_engine engine(randomDev());
::std::size_t size = minSize == maxSize
? minSize
: ::std::uniform_int_distribution<::std::size_t>(
minSize, maxSize)(engine);
output.buf = reinterpret_cast<::std::uint8_t *>(::calloc(1, size));
output.size = size;
::std::uniform_int_distribution<::std::uint8_t> generator(0x20, 0x7E);
for (::std::size_t i = 0; i < size; ++i) {
output.buf[i] = generator(engine);
}
}
/**
* @brief Fill random number.
*
* @tparam NumType Number type.
*
* @param[out] output Output value to fill.
* @param[in] minSize Minimum size.
* @param[in] maxSize Maximum size.
*/
template<typename NumType>
void fillRandomNumber(NumType &output, ::std::int64_t min, ::std::int64_t max)
{
::std::random_device randomDev;
::std::default_random_engine engine(randomDev());
::std::uniform_int_distribution<NumType> generator(
static_cast<NumType>(min), static_cast<NumType>(max));
output = generator(engine);
return;
}
/**
* @brief Get message count.
*
* @return Message count.
*/
::std::uint64_t getCount()
{
static ::std::atomic<::std::uint64_t> count(0);
return count.fetch_add(1);
}
/**
* @brief Make BSM message.
*
* @return Fake message made.
......@@ -77,13 +139,13 @@ MessagePtr<MessageFrame> makeBSMMessage()
releaseMessage(MessageFrame));
ret->present = MessageFrame_PR::MessageFrame_PR_bsmFrame;
::asn_dec_rval_t result = ::asn_decode(
nullptr, ATS_RANDOM, &::asn_DEF_BasicSafetyMessage,
reinterpret_cast<void **>(&ret->choice.bsmFrame), nullptr, 0);
if (result.code != RC_OK) {
::std::cerr << "Failed to generate BSM message." << ::std::endl;
return MessagePtr<MessageFrame>(nullptr, releaseMessage(MessageFrame));
}
ret->choice.bsmFrame.msgCnt = getCount();
fillRandomString(ret->choice.bsmFrame.id, 8, 8);
fillRandomNumber(ret->choice.bsmFrame.size.width, 3, 5);
fillRandomNumber(ret->choice.bsmFrame.size.length, 10, 20);
ret->choice.bsmFrame.size.height = reinterpret_cast<VehicleHeight_t *>(
::malloc(sizeof(VehicleHeight_t)));
fillRandomNumber(*(ret->choice.bsmFrame.size.height), 3, 5);
return ret;
}
......@@ -98,15 +160,17 @@ MessagePtr<MessageFrame> makeMapMessage()
MessagePtr<MessageFrame> ret(
reinterpret_cast<MessageFrame *>(::calloc(1, sizeof(MessageFrame))),
releaseMessage(MessageFrame));
ret->present = MessageFrame_PR::MessageFrame_PR_mapFrame;
::asn_dec_rval_t result = ::asn_decode(
nullptr, ATS_RANDOM, &::asn_DEF_MapData,
reinterpret_cast<void **>(&ret->choice.mapFrame), nullptr, 0);
if (result.code != RC_OK) {
::std::cerr << "Failed to generate Map message." << ::std::endl;
return MessagePtr<MessageFrame>(nullptr, releaseMessage(MessageFrame));
}
ret->choice.mapFrame.msgCnt = getCount();
ret->choice.mapFrame.timeStamp = reinterpret_cast<MinuteOfTheYear_t *>(
::calloc(1, sizeof(MinuteOfTheYear_t)));
fillRandomNumber(*ret->choice.mapFrame.timeStamp, 0, 3000);
Node_t *node = reinterpret_cast<Node_t *>(::calloc(1, sizeof(Node_t)));
fillRandomNumber(node->id.id, 0, 65535);
fillRandomNumber(node->refPos.Long, 0, 10000);
fillRandomNumber(node->refPos.lat, 0, 10000);
asn_sequence_add(&(ret->choice.mapFrame.nodes.list), node);
return ret;
}
......@@ -116,20 +180,45 @@ MessagePtr<MessageFrame> makeMapMessage()
*
* @return Fake message made.
*/
MessagePtr<MessageFrame> makeSPATMessage()
MessagePtr<MessageFrame> makeSpatMessage()
{
MessagePtr<MessageFrame> ret(
reinterpret_cast<MessageFrame *>(::calloc(1, sizeof(MessageFrame))),
releaseMessage(MessageFrame));
ret->present = MessageFrame_PR::MessageFrame_PR_spatFrame;
::asn_dec_rval_t result = ::asn_decode(
nullptr, ATS_RANDOM, &::asn_DEF_SPAT,
reinterpret_cast<void **>(&ret->choice.spatFrame), nullptr, 0);
if (result.code != RC_OK) {
::std::cerr << "Failed to generate SPAT message." << ::std::endl;
return MessagePtr<MessageFrame>(nullptr, releaseMessage(MessageFrame));
}
ret->choice.spatFrame.msgCnt = getCount();
ret->choice.spatFrame.timeStamp
= reinterpret_cast<DSecond_t *>(::calloc(1, sizeof(DSecond_t)));
fillRandomNumber(*ret->choice.spatFrame.timeStamp, 0, 65535);
IntersectionState_t *intersectionState
= reinterpret_cast<IntersectionState_t *>(
::calloc(1, sizeof(IntersectionState_t)));
fillRandomNumber(intersectionState->intersectionId.id, 0, 65535);
intersectionState->status.bits_unused = 0;
intersectionState->status.buf
= reinterpret_cast<::std::uint8_t *>(::calloc(1, 2));
intersectionState->status.buf[0] = 0x01;
intersectionState->status.buf[1] = 0x00;
intersectionState->status.size = 2;
intersectionState->timeStamp = reinterpret_cast<MinuteOfTheYear_t *>(
::calloc(1, sizeof(MinuteOfTheYear_t)));
fillRandomNumber(*intersectionState->timeStamp, 0, 3000);
Phase_t *phase = reinterpret_cast<Phase_t *>(::calloc(1, sizeof(Phase_t)));
fillRandomNumber(phase->id, 0, 255);
PhaseState_t *phaseState
= reinterpret_cast<PhaseState_t *>(::calloc(1, sizeof(PhaseState_t)));
fillRandomNumber(phaseState->light, 0, 8);
asn_sequence_add(&(phase->phaseStates.list), phaseState);
asn_sequence_add(&(intersectionState->phases.list), phase);
asn_sequence_add(&(ret->choice.spatFrame.intersections.list),
intersectionState);
return ret;
}
......@@ -175,20 +264,23 @@ void readData(int fd)
*/
void writeData(int fd)
{
MessagePtr<MessageFrame> messages[] {makeBSMMessage(), makeMapMessage(),
makeSPATMessage()};
for (auto &message : messages) {
using Generator = MessagePtr<MessageFrame> (*)();
Generator generators[] = {makeBSMMessage, makeMapMessage, makeSpatMessage};
for (auto &generator : generators) {
auto message = generator();
if (message == nullptr) {
continue;
return;
}
::std::cout << "Message generated." << ::std::endl;
char buffer[MTU];
::asn_enc_rval_t encodeResult = asn_encode_to_buffer(
nullptr, ATS_UNALIGNED_CANONICAL_PER, &asn_DEF_MessageFrame,
reinterpret_cast<void *>(message.get()), buffer, sizeof(buffer));
reinterpret_cast<const void *>(message.get()), buffer,
sizeof(buffer));
if (encodeResult.encoded > 0) {
ssize_t sizeSent = ::send(fd, buffer, encodeResult.encoded, 0);
if (sizeSent <= 0) {
if (sizeSent >= 0) {
::std::cout
<< ::std::chrono::duration_cast<::std::chrono::seconds>(
::std::chrono::system_clock::now()
......@@ -197,11 +289,33 @@ void writeData(int fd)
<< " Data sent: " << *message << ::std::endl;
} else {
int err = errno;
::std::cerr << "Failed to send data: " << ::strerror(err);
::std::cerr << "Failed to send data: " << ::strerror(err)
<< ::std::endl;
return;
}
} else {
::std::cerr << "Encode error." << ::std::endl;
int err = errno;
switch (err) {
case EINVAL: {
::std::cerr << "Encode error: Incorrect parameters to the "
"function, such as NULLs."
<< ::std::endl;
} break;
case ENOENT: {
::std::cerr << "Encode error: Encoding transfer syntax is "
"not defined (for this type)."
<< ::std::endl;
} break;
case EBADF: {
::std::cerr << "Encode error: The structure has invalid "
"form or content constraint "
"failed."
<< ::std::endl;
} break;
default:
::std::cerr << "Encode error: " << ::strerror(err)
<< ::std::endl;
}
}
}
}
......@@ -232,7 +346,8 @@ int main(int argc, char *argv[])
int fd = ::socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
int err = errno;
::std::cerr << "Failed to create socket: " << ::strerror(err);
::std::cerr << "Failed to create socket: " << ::strerror(err)
<< ::std::endl;
return -1;
}
::std::unique_ptr<int, void (*)(int *)> autoCloseFd(&fd,
......@@ -251,7 +366,8 @@ int main(int argc, char *argv[])
sizeof(bindAddress));
if (bindResult < 0) {
int err = errno;
::std::cerr << "Failed to bind listen port: " << ::strerror(err);
::std::cerr << "Failed to bind listen port: " << ::strerror(err)
<< ::std::endl;
return -1;
}
......@@ -265,11 +381,12 @@ int main(int argc, char *argv[])
}
targetAddress.sin_port = targetPort;
auto connectResult
= ::connect(AF_INET, reinterpret_cast<::sockaddr *>(&targetAddress),
sizeof(targetPort));
= ::connect(fd, reinterpret_cast<::sockaddr *>(&targetAddress),
sizeof(targetAddress));
if (connectResult < 0) {
int err = errno;
::std::cerr << "Failed to connect to DMD3A port: " << ::strerror(err);
::std::cerr << "Failed to connect to DMD3A port: " << ::strerror(err)
<< ::std::endl;
return -1;
}
......@@ -284,7 +401,8 @@ int main(int argc, char *argv[])
quitEvent = ::eventfd(0, 0);
if (quitEvent < 0) {
int err = errno;
::std::cerr << "Failed to create quit event: " << ::strerror(err);
::std::cerr << "Failed to create quit event: " << ::strerror(err)
<< ::std::endl;
return -1;
}
::std::unique_ptr<int, void (*)(int *)> autoCloseQuitEvent(
......@@ -319,11 +437,14 @@ int main(int argc, char *argv[])
::std::array<::pollfd, 2> fds {
::pollfd {.fd = fd, .events = POLLIN, .revents = 0},
::pollfd {.fd = quitEvent, .events = POLLIN, .revents = 0}};
auto pollResult
= ::poll(fds.data(), fds.size(),
::std::chrono::duration_cast<::std::chrono::milliseconds>(
nextTimestamp - ::std::chrono::steady_clock::now())
.count());
now = ::std::chrono::steady_clock::now();
auto pollResult = ::poll(
fds.data(), fds.size(),
(now < nextTimestamp
? ::std::chrono::duration_cast<::std::chrono::milliseconds>(
nextTimestamp - now)
.count()
: 0));
if (pollResult > 0) {
for (auto &status : fds) {
if (status.revents & POLLIN) {
......@@ -331,7 +452,7 @@ int main(int argc, char *argv[])
::readData(fd);
} else if (status.fd == quitEvent) {
::std::cout << "Quit event received." << ::std::endl;
break;
return 0;
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment