37 #include <protobuf_comm/message_register.h> 39 #include <google/protobuf/compiler/importer.h> 40 #include <google/protobuf/dynamic_message.h> 41 #include <netinet/in.h> 42 #include <sys/types.h> 76 pb_srctree_ =
new google::protobuf::compiler::DiskSourceTree();
77 for (
size_t i = 0; i < proto_path.size(); ++i) {
78 pb_srctree_->MapPath(
"", proto_path[i]);
80 pb_importer_ =
new google::protobuf::compiler::Importer(pb_srctree_, NULL);
81 pb_factory_ =
new google::protobuf::DynamicMessageFactory(pb_importer_->pool());
83 for (
size_t i = 0; i < proto_path.size(); ++i) {
86 if ((dir = opendir(proto_path[i].c_str())) != NULL) {
87 while ((ent = readdir(dir)) != NULL) {
88 if (fnmatch(
"*.proto", ent->d_name, FNM_PATHNAME) != FNM_NOMATCH) {
90 const google::protobuf::FileDescriptor *fd =
91 pb_importer_->Import(ent->d_name);
92 for (
int i = 0; i < fd->message_type_count(); ++i) {
93 const google::protobuf::Descriptor *desc = fd->message_type(i);
95 if (! desc->FindEnumTypeByName(
"CompType"))
continue;
99 }
catch (std::logic_error &e) {
101 failed_to_load_types_.insert(std::make_pair(desc->full_name(), e.what()));
115 for (m = message_by_comp_type_.begin(); m != message_by_comp_type_.end(); ++m) {
124 google::protobuf::Message *
125 MessageRegister::create_msg(std::string &msg_type)
127 const google::protobuf::DescriptorPool *pool =
128 google::protobuf::DescriptorPool::generated_pool();
129 google::protobuf::MessageFactory *factory =
130 google::protobuf::MessageFactory::generated_factory();
132 const google::protobuf::Descriptor *desc = pool->FindMessageTypeByName(msg_type);
134 return factory->GetPrototype(desc)->New();
135 }
else if (pb_importer_) {
136 pool = pb_importer_->pool();
137 factory = pb_factory_;
139 const google::protobuf::Descriptor *cdesc = pool->FindMessageTypeByName(msg_type);
141 return factory->GetPrototype(cdesc)->New();
158 google::protobuf::Message *m = create_msg(msg_type);
160 KeyType key = key_from_desc(m->GetDescriptor());
161 std::lock_guard<std::mutex> lock(maps_mutex_);
162 if (message_by_comp_type_.find(key) != message_by_comp_type_.end()) {
163 #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)) 164 std::string msg =
"Message type " + std::to_string((
long long)key.first) +
":" +
165 std::to_string((
long long)key.second) +
" already registered";
167 std::string msg =
"Message type " + std::to_string(key.first) +
":" +
168 std::to_string(key.second) +
" already registered";
170 throw std::runtime_error(msg);
173 message_by_comp_type_[key] = m;
174 message_by_typename_[m->GetTypeName()] = m;
176 throw std::runtime_error(
"Unknown message type");
188 KeyType key(component_id, msg_type);
189 std::lock_guard<std::mutex> lock(maps_mutex_);
190 if (message_by_comp_type_.find(key) != message_by_comp_type_.end()) {
191 message_by_typename_.erase(message_by_comp_type_[key]->GetDescriptor()->full_name());
192 message_by_comp_type_.erase(key);
197 MessageRegister::KeyType
198 MessageRegister::key_from_desc(
const google::protobuf::Descriptor *desc)
200 const google::protobuf::EnumDescriptor *enumdesc = desc->FindEnumTypeByName(
"CompType");
202 throw std::logic_error(
"Message does not have CompType enum");
204 const google::protobuf::EnumValueDescriptor *compdesc =
205 enumdesc->FindValueByName(
"COMP_ID");
206 const google::protobuf::EnumValueDescriptor *msgtdesc =
207 enumdesc->FindValueByName(
"MSG_TYPE");
208 if (! compdesc || ! msgtdesc) {
209 throw std::logic_error(
"Message CompType enum hs no COMP_ID or MSG_TYPE value");
211 int comp_id = compdesc->number();
212 int msg_type = msgtdesc->number();
213 if (comp_id < 0 || comp_id > std::numeric_limits<uint16_t>::max()) {
214 throw std::logic_error(
"Message has invalid COMP_ID");
216 if (msg_type < 0 || msg_type > std::numeric_limits<uint16_t>::max()) {
217 throw std::logic_error(
"Message has invalid MSG_TYPE");
219 return KeyType(comp_id, msg_type);
228 std::shared_ptr<google::protobuf::Message>
231 KeyType key(component_id, msg_type);
233 std::lock_guard<std::mutex> lock(maps_mutex_);
234 if (message_by_comp_type_.find(key) == message_by_comp_type_.end()) {
235 #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)) 236 std::string msg =
"Message type " + std::to_string((
long long)component_id) +
":" +
237 std::to_string((
long long)msg_type) +
" not registered";
239 std::string msg =
"Message type " + std::to_string(component_id) +
":" +
240 std::to_string(msg_type) +
" not registered";
242 throw std::runtime_error(msg);
245 google::protobuf::Message *m = message_by_comp_type_[key]->New();
246 return std::shared_ptr<google::protobuf::Message>(m);
256 std::shared_ptr<google::protobuf::Message>
259 std::lock_guard<std::mutex> lock(maps_mutex_);
260 if (message_by_typename_.find(full_name) == message_by_typename_.end()) {
261 google::protobuf::Message *m = create_msg(full_name);
263 return std::shared_ptr<google::protobuf::Message>(m);
265 throw std::runtime_error(
"Message type not registered");
268 google::protobuf::Message *m = message_by_typename_[full_name]->New();
269 return std::shared_ptr<google::protobuf::Message>(m);
286 google::protobuf::Message &msg,
291 bool serialized =
false;
292 #if GOOGLE_PROTOBUF_VERSION >= 2004000 294 serialized = msg.SerializeToString(&data);
295 }
catch (google::protobuf::FatalException &e) {
296 std::string msg = std::string(
"Failed to serialize message: ") + e.what();
297 throw std::runtime_error(msg);
301 serialized = msg.SerializeToString(&data);
307 message_header.
msg_type = htons(msg_type);
308 frame_header.
payload_size = htonl(
sizeof(message_header) + data.size());
310 throw std::runtime_error(
"Cannot serialize message");
325 std::shared_ptr<google::protobuf::Message>
329 uint16_t msg_type = ntohs(message_header.
msg_type);
330 size_t data_size = ntohl(frame_header.
payload_size) -
sizeof(message_header);
332 std::shared_ptr<google::protobuf::Message> m =
334 if (! m->ParseFromArray(data, data_size)) {
335 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, 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.