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

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

parent 80067a9c
...@@ -31,6 +31,8 @@ list (REMOVE_ITEM SOURCES ...@@ -31,6 +31,8 @@ list (REMOVE_ITEM SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/generated_msgs/converter-example.c" "${CMAKE_CURRENT_SOURCE_DIR}/generated_msgs/converter-example.c"
) )
# add_definitions ("-DASN_EMIT_DEBUG=1")
add_executable (asn1Demo add_executable (asn1Demo
${SOURCES} ${SOURCES}
) )
#include <array> #include <array>
#include <atomic>
#include <cerrno> #include <cerrno>
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <random>
#include <string> #include <string>
#include <arpa/inet.h> #include <arpa/inet.h>
...@@ -16,6 +18,10 @@ ...@@ -16,6 +18,10 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
extern "C" {
#include <asn_random_fill.h>
}
#include <MessageFrame.h> #include <MessageFrame.h>
constexpr ::std::size_t MTU = 1024; constexpr ::std::size_t MTU = 1024;
...@@ -39,7 +45,6 @@ using MessagePtr = ::std::unique_ptr<MessageType, void (*)(MessageType *)>; ...@@ -39,7 +45,6 @@ using MessagePtr = ::std::unique_ptr<MessageType, void (*)(MessageType *)>;
auto fill = stream.fill(); auto fill = stream.fill();
auto width = stream.width(); auto width = stream.width();
stream << "MessageFrame{";
::std::unique_ptr<char[]> buffer; ::std::unique_ptr<char[]> buffer;
::std::size_t bufferSize = 1024; ::std::size_t bufferSize = 1024;
while (true) { while (true) {
...@@ -49,14 +54,14 @@ using MessagePtr = ::std::unique_ptr<MessageType, void (*)(MessageType *)>; ...@@ -49,14 +54,14 @@ using MessagePtr = ::std::unique_ptr<MessageType, void (*)(MessageType *)>;
reinterpret_cast<const void *>(&message), buffer.get(), bufferSize); reinterpret_cast<const void *>(&message), buffer.get(), bufferSize);
if (encodeResult.encoded < 0) { if (encodeResult.encoded < 0) {
stream << "ENCODE_ERROR"; stream << "ENCODE_ERROR";
} else if (encodeResult.encoded <= bufferSize) { } else if (static_cast<::std::size_t>(encodeResult.encoded)
<= bufferSize) {
stream.write(buffer.get(), encodeResult.encoded); stream.write(buffer.get(), encodeResult.encoded);
break; break;
} else { } else {
bufferSize *= 2; bufferSize *= 2;
} }
} }
stream << "}";
stream.flags(flags); stream.flags(flags);
stream.fill(fill); stream.fill(fill);
...@@ -66,6 +71,63 @@ using MessagePtr = ::std::unique_ptr<MessageType, void (*)(MessageType *)>; ...@@ -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. * @brief Make BSM message.
* *
* @return Fake message made. * @return Fake message made.
...@@ -77,13 +139,13 @@ MessagePtr<MessageFrame> makeBSMMessage() ...@@ -77,13 +139,13 @@ MessagePtr<MessageFrame> makeBSMMessage()
releaseMessage(MessageFrame)); releaseMessage(MessageFrame));
ret->present = MessageFrame_PR::MessageFrame_PR_bsmFrame; ret->present = MessageFrame_PR::MessageFrame_PR_bsmFrame;
::asn_dec_rval_t result = ::asn_decode( ret->choice.bsmFrame.msgCnt = getCount();
nullptr, ATS_RANDOM, &::asn_DEF_BasicSafetyMessage, fillRandomString(ret->choice.bsmFrame.id, 8, 8);
reinterpret_cast<void **>(&ret->choice.bsmFrame), nullptr, 0); fillRandomNumber(ret->choice.bsmFrame.size.width, 3, 5);
if (result.code != RC_OK) { fillRandomNumber(ret->choice.bsmFrame.size.length, 10, 20);
::std::cerr << "Failed to generate BSM message." << ::std::endl; ret->choice.bsmFrame.size.height = reinterpret_cast<VehicleHeight_t *>(
return MessagePtr<MessageFrame>(nullptr, releaseMessage(MessageFrame)); ::malloc(sizeof(VehicleHeight_t)));
} fillRandomNumber(*(ret->choice.bsmFrame.size.height), 3, 5);
return ret; return ret;
} }
...@@ -98,15 +160,17 @@ MessagePtr<MessageFrame> makeMapMessage() ...@@ -98,15 +160,17 @@ MessagePtr<MessageFrame> makeMapMessage()
MessagePtr<MessageFrame> ret( MessagePtr<MessageFrame> ret(
reinterpret_cast<MessageFrame *>(::calloc(1, sizeof(MessageFrame))), reinterpret_cast<MessageFrame *>(::calloc(1, sizeof(MessageFrame))),
releaseMessage(MessageFrame)); releaseMessage(MessageFrame));
ret->present = MessageFrame_PR::MessageFrame_PR_mapFrame; ret->present = MessageFrame_PR::MessageFrame_PR_mapFrame;
::asn_dec_rval_t result = ::asn_decode( ret->choice.mapFrame.msgCnt = getCount();
nullptr, ATS_RANDOM, &::asn_DEF_MapData, ret->choice.mapFrame.timeStamp = reinterpret_cast<MinuteOfTheYear_t *>(
reinterpret_cast<void **>(&ret->choice.mapFrame), nullptr, 0); ::calloc(1, sizeof(MinuteOfTheYear_t)));
if (result.code != RC_OK) { fillRandomNumber(*ret->choice.mapFrame.timeStamp, 0, 3000);
::std::cerr << "Failed to generate Map message." << ::std::endl;
return MessagePtr<MessageFrame>(nullptr, releaseMessage(MessageFrame)); 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; return ret;
} }
...@@ -116,20 +180,45 @@ MessagePtr<MessageFrame> makeMapMessage() ...@@ -116,20 +180,45 @@ MessagePtr<MessageFrame> makeMapMessage()
* *
* @return Fake message made. * @return Fake message made.
*/ */
MessagePtr<MessageFrame> makeSPATMessage() MessagePtr<MessageFrame> makeSpatMessage()
{ {
MessagePtr<MessageFrame> ret( MessagePtr<MessageFrame> ret(
reinterpret_cast<MessageFrame *>(::calloc(1, sizeof(MessageFrame))), reinterpret_cast<MessageFrame *>(::calloc(1, sizeof(MessageFrame))),
releaseMessage(MessageFrame)); releaseMessage(MessageFrame));
ret->present = MessageFrame_PR::MessageFrame_PR_spatFrame; ret->present = MessageFrame_PR::MessageFrame_PR_spatFrame;
::asn_dec_rval_t result = ::asn_decode( ret->choice.spatFrame.msgCnt = getCount();
nullptr, ATS_RANDOM, &::asn_DEF_SPAT, ret->choice.spatFrame.timeStamp
reinterpret_cast<void **>(&ret->choice.spatFrame), nullptr, 0); = reinterpret_cast<DSecond_t *>(::calloc(1, sizeof(DSecond_t)));
if (result.code != RC_OK) { fillRandomNumber(*ret->choice.spatFrame.timeStamp, 0, 65535);
::std::cerr << "Failed to generate SPAT message." << ::std::endl;
return MessagePtr<MessageFrame>(nullptr, releaseMessage(MessageFrame)); 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; return ret;
} }
...@@ -175,20 +264,23 @@ void readData(int fd) ...@@ -175,20 +264,23 @@ void readData(int fd)
*/ */
void writeData(int fd) void writeData(int fd)
{ {
MessagePtr<MessageFrame> messages[] {makeBSMMessage(), makeMapMessage(), using Generator = MessagePtr<MessageFrame> (*)();
makeSPATMessage()}; Generator generators[] = {makeBSMMessage, makeMapMessage, makeSpatMessage};
for (auto &message : messages) { for (auto &generator : generators) {
auto message = generator();
if (message == nullptr) { if (message == nullptr) {
continue; return;
} }
::std::cout << "Message generated." << ::std::endl;
char buffer[MTU]; char buffer[MTU];
::asn_enc_rval_t encodeResult = asn_encode_to_buffer( ::asn_enc_rval_t encodeResult = asn_encode_to_buffer(
nullptr, ATS_UNALIGNED_CANONICAL_PER, &asn_DEF_MessageFrame, 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) { if (encodeResult.encoded > 0) {
ssize_t sizeSent = ::send(fd, buffer, encodeResult.encoded, 0); ssize_t sizeSent = ::send(fd, buffer, encodeResult.encoded, 0);
if (sizeSent <= 0) { if (sizeSent >= 0) {
::std::cout ::std::cout
<< ::std::chrono::duration_cast<::std::chrono::seconds>( << ::std::chrono::duration_cast<::std::chrono::seconds>(
::std::chrono::system_clock::now() ::std::chrono::system_clock::now()
...@@ -197,11 +289,33 @@ void writeData(int fd) ...@@ -197,11 +289,33 @@ void writeData(int fd)
<< " Data sent: " << *message << ::std::endl; << " Data sent: " << *message << ::std::endl;
} else { } else {
int err = errno; int err = errno;
::std::cerr << "Failed to send data: " << ::strerror(err); ::std::cerr << "Failed to send data: " << ::strerror(err)
<< ::std::endl;
return; return;
} }
} else { } 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[]) ...@@ -232,7 +346,8 @@ int main(int argc, char *argv[])
int fd = ::socket(AF_INET, SOCK_DGRAM, 0); int fd = ::socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) { if (fd < 0) {
int err = errno; int err = errno;
::std::cerr << "Failed to create socket: " << ::strerror(err); ::std::cerr << "Failed to create socket: " << ::strerror(err)
<< ::std::endl;
return -1; return -1;
} }
::std::unique_ptr<int, void (*)(int *)> autoCloseFd(&fd, ::std::unique_ptr<int, void (*)(int *)> autoCloseFd(&fd,
...@@ -251,7 +366,8 @@ int main(int argc, char *argv[]) ...@@ -251,7 +366,8 @@ int main(int argc, char *argv[])
sizeof(bindAddress)); sizeof(bindAddress));
if (bindResult < 0) { if (bindResult < 0) {
int err = errno; 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; return -1;
} }
...@@ -265,11 +381,12 @@ int main(int argc, char *argv[]) ...@@ -265,11 +381,12 @@ int main(int argc, char *argv[])
} }
targetAddress.sin_port = targetPort; targetAddress.sin_port = targetPort;
auto connectResult auto connectResult
= ::connect(AF_INET, reinterpret_cast<::sockaddr *>(&targetAddress), = ::connect(fd, reinterpret_cast<::sockaddr *>(&targetAddress),
sizeof(targetPort)); sizeof(targetAddress));
if (connectResult < 0) { if (connectResult < 0) {
int err = errno; 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; return -1;
} }
...@@ -284,7 +401,8 @@ int main(int argc, char *argv[]) ...@@ -284,7 +401,8 @@ int main(int argc, char *argv[])
quitEvent = ::eventfd(0, 0); quitEvent = ::eventfd(0, 0);
if (quitEvent < 0) { if (quitEvent < 0) {
int err = errno; 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; return -1;
} }
::std::unique_ptr<int, void (*)(int *)> autoCloseQuitEvent( ::std::unique_ptr<int, void (*)(int *)> autoCloseQuitEvent(
...@@ -319,11 +437,14 @@ int main(int argc, char *argv[]) ...@@ -319,11 +437,14 @@ int main(int argc, char *argv[])
::std::array<::pollfd, 2> fds { ::std::array<::pollfd, 2> fds {
::pollfd {.fd = fd, .events = POLLIN, .revents = 0}, ::pollfd {.fd = fd, .events = POLLIN, .revents = 0},
::pollfd {.fd = quitEvent, .events = POLLIN, .revents = 0}}; ::pollfd {.fd = quitEvent, .events = POLLIN, .revents = 0}};
auto pollResult now = ::std::chrono::steady_clock::now();
= ::poll(fds.data(), fds.size(), auto pollResult = ::poll(
::std::chrono::duration_cast<::std::chrono::milliseconds>( fds.data(), fds.size(),
nextTimestamp - ::std::chrono::steady_clock::now()) (now < nextTimestamp
.count()); ? ::std::chrono::duration_cast<::std::chrono::milliseconds>(
nextTimestamp - now)
.count()
: 0));
if (pollResult > 0) { if (pollResult > 0) {
for (auto &status : fds) { for (auto &status : fds) {
if (status.revents & POLLIN) { if (status.revents & POLLIN) {
...@@ -331,7 +452,7 @@ int main(int argc, char *argv[]) ...@@ -331,7 +452,7 @@ int main(int argc, char *argv[])
::readData(fd); ::readData(fd);
} else if (status.fd == quitEvent) { } else if (status.fd == quitEvent) {
::std::cout << "Quit event received." << ::std::endl; ::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