37 #include <google/protobuf/compiler/importer.h> 38 #include <google/protobuf/dynamic_message.h> 39 #include <netinet/in.h> 40 #include <protobuf_comm/message_register.h> 41 #include <sys/types.h> 46 namespace protobuf_comm {
71 pb_srctree_ =
new google::protobuf::compiler::DiskSourceTree();
72 for (
size_t i = 0; i < proto_path.size(); ++i) {
73 pb_srctree_->MapPath(
"", proto_path[i]);
75 pb_importer_ =
new google::protobuf::compiler::Importer(pb_srctree_, NULL);
76 pb_factory_ =
new google::protobuf::DynamicMessageFactory(pb_importer_->pool());
78 for (
size_t i = 0; i < proto_path.size(); ++i) {
81 if ((dir = opendir(proto_path[i].c_str())) != NULL) {
82 while ((ent = readdir(dir)) != NULL) {
83 if (fnmatch(
"*.proto", ent->d_name, FNM_PATHNAME) != FNM_NOMATCH) {
85 const google::protobuf::FileDescriptor *fd = pb_importer_->Import(ent->d_name);
86 for (
int i = 0; i < fd->message_type_count(); ++i) {
87 const google::protobuf::Descriptor *desc = fd->message_type(i);
89 if (!desc->FindEnumTypeByName(
"CompType"))
94 }
catch (std::logic_error &e) {
96 failed_to_load_types_.insert(std::make_pair(desc->full_name(), e.what()));
110 for (m = message_by_comp_type_.begin(); m != message_by_comp_type_.end(); ++m) {
118 google::protobuf::Message *
119 MessageRegister::create_msg(
const std::string &msg_type)
121 const google::protobuf::DescriptorPool *pool = google::protobuf::DescriptorPool::generated_pool();
122 google::protobuf::MessageFactory *factory = google::protobuf::MessageFactory::generated_factory();
124 const google::protobuf::Descriptor *desc = pool->FindMessageTypeByName(msg_type);
126 return factory->GetPrototype(desc)->New();
127 }
else if (pb_importer_) {
128 pool = pb_importer_->pool();
129 factory = pb_factory_;
131 const google::protobuf::Descriptor *cdesc = pool->FindMessageTypeByName(msg_type);
133 return factory->GetPrototype(cdesc)->New();
150 google::protobuf::Message *m = create_msg(msg_type);
152 KeyType key = key_from_desc(m->GetDescriptor());
153 std::lock_guard<std::mutex> lock(maps_mutex_);
154 if (message_by_comp_type_.find(key) != message_by_comp_type_.end()) {
155 #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)) 156 std::string msg =
"Message type " + std::to_string((
long long)key.first) +
":" 157 + std::to_string((
long long)key.second) +
" already registered";
159 std::string msg =
"Message type " + std::to_string(key.first) +
":" 160 + std::to_string(key.second) +
" already registered";
162 throw std::runtime_error(msg);
165 message_by_comp_type_[key] = m;
166 message_by_typename_[m->GetTypeName()] = m;
168 throw std::runtime_error(
"Unknown message type");
179 KeyType key(component_id, msg_type);
180 std::lock_guard<std::mutex> lock(maps_mutex_);
181 if (message_by_comp_type_.find(key) != message_by_comp_type_.end()) {
182 message_by_typename_.erase(message_by_comp_type_[key]->GetDescriptor()->full_name());
183 message_by_comp_type_.erase(key);
187 MessageRegister::KeyType
188 MessageRegister::key_from_desc(
const google::protobuf::Descriptor *desc)
190 const google::protobuf::EnumDescriptor *enumdesc = desc->FindEnumTypeByName(
"CompType");
192 throw std::logic_error(
"Message does not have CompType enum");
194 const google::protobuf::EnumValueDescriptor *compdesc = enumdesc->FindValueByName(
"COMP_ID");
195 const google::protobuf::EnumValueDescriptor *msgtdesc = enumdesc->FindValueByName(
"MSG_TYPE");
196 if (!compdesc || !msgtdesc) {
197 throw std::logic_error(
"Message CompType enum hs no COMP_ID or MSG_TYPE value");
199 int comp_id = compdesc->number();
200 int msg_type = msgtdesc->number();
201 if (comp_id < 0 || comp_id > std::numeric_limits<uint16_t>::max()) {
202 throw std::logic_error(
"Message has invalid COMP_ID");
204 if (msg_type < 0 || msg_type > std::numeric_limits<uint16_t>::max()) {
205 throw std::logic_error(
"Message has invalid MSG_TYPE");
207 return KeyType(comp_id, msg_type);
216 std::shared_ptr<google::protobuf::Message>
219 KeyType key(component_id, msg_type);
221 std::lock_guard<std::mutex> lock(maps_mutex_);
222 if (message_by_comp_type_.find(key) == message_by_comp_type_.end()) {
223 #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)) 224 std::string msg =
"Message type " + std::to_string((
long long)component_id) +
":" 225 + std::to_string((
long long)msg_type) +
" not registered";
227 std::string msg =
"Message type " + std::to_string(component_id) +
":" 228 + std::to_string(msg_type) +
" not registered";
230 throw std::runtime_error(msg);
233 google::protobuf::Message *m = message_by_comp_type_[key]->New();
234 return std::shared_ptr<google::protobuf::Message>(m);
243 std::shared_ptr<google::protobuf::Message>
246 std::lock_guard<std::mutex> lock(maps_mutex_);
247 if (message_by_typename_.find(full_name) == message_by_typename_.end()) {
248 google::protobuf::Message *m = create_msg(full_name);
250 return std::shared_ptr<google::protobuf::Message>(m);
252 throw std::runtime_error(
"Message type not registered");
255 google::protobuf::Message *m = message_by_typename_[full_name]->New();
256 return std::shared_ptr<google::protobuf::Message>(m);
273 const google::protobuf::Message &msg,
278 bool serialized =
false;
279 #if GOOGLE_PROTOBUF_VERSION >= 2004000 281 serialized = msg.SerializeToString(&data);
282 }
catch (google::protobuf::FatalException &e) {
283 std::string error_msg = std::string(
"Failed to serialize message: ") + e.what();
284 throw std::runtime_error(error_msg);
288 serialized = msg.SerializeToString(&data);
293 message_header.
msg_type = htons(msg_type);
294 frame_header.
payload_size = htonl(
sizeof(message_header) + data.size());
296 throw std::runtime_error(
"Cannot serialize message");
310 std::shared_ptr<google::protobuf::Message>
316 uint16_t msg_type = ntohs(message_header.
msg_type);
317 size_t data_size = ntohl(frame_header.
payload_size) -
sizeof(message_header);
319 std::shared_ptr<google::protobuf::Message> m =
new_message_for(comp_id, msg_type);
320 if (!m->ParseFromArray(data, data_size)) {
321 throw std::runtime_error(
"Failed to parse message");
void remove_message_type(uint16_t component_id, uint16_t msg_type)
Remove the given message type.
std::shared_ptr< google::protobuf::Message > deserialize(frame_header_t &frame_header, message_header_t &message_header, void *data)
Deserialize message.
void serialize(uint16_t component_id, uint16_t msg_type, const google::protobuf::Message &msg, frame_header_t &frame_header, message_header_t &message_header, std::string &data)
Serialize a message.
std::shared_ptr< google::protobuf::Message > new_message_for(uint16_t component_id, uint16_t msg_type)
Create a new message instance.
~MessageRegister()
Destructor.
std::enable_if< std::is_base_of< google::protobuf::Message, MT >::value, void >::type add_message_type()
Add a new message type.
MessageRegister()
Constructor.