1 /* -*- c++ -*- */
2 /*
3 * Copyright 2014 Free Software Foundation, Inc.
4 *
5 * This file is part of GNU Radio.
6 *
7 * This is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this software; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #include "zmq_common_impl.h"
24 #include <gnuradio/block.h>
25 #include <gnuradio/io_signature.h>
26 #include <cstring>
27 #include <sstream>
28
29 #define GR_HEADER_MAGIC 0x5FF0
30 #define GR_HEADER_VERSION 0x01
31
32 namespace gr {
33 namespace zeromq {
34
35 struct membuf : std::streambuf {
membufgr::zeromq::membuf36 membuf(void* b, size_t len)
37 {
38 char* bc = static_cast<char*>(b);
39 this->setg(bc, bc, bc + len);
40 }
41 };
42
gen_tag_header(uint64_t offset,std::vector<gr::tag_t> & tags)43 std::string gen_tag_header(uint64_t offset, std::vector<gr::tag_t>& tags)
44 {
45 std::stringbuf sb("");
46 std::ostream ss(&sb);
47
48 uint16_t header_magic = GR_HEADER_MAGIC;
49 uint8_t header_version = GR_HEADER_VERSION;
50 uint64_t ntags = (uint64_t)tags.size();
51
52 ss.write((const char*)&header_magic, sizeof(uint16_t));
53 ss.write((const char*)&header_version, sizeof(uint8_t));
54 ss.write((const char*)&offset, sizeof(uint64_t));
55 ss.write((const char*)&ntags, sizeof(uint64_t));
56
57 for (size_t i = 0; i < tags.size(); i++) {
58 ss.write((const char*)&tags[i].offset, sizeof(uint64_t));
59 pmt::serialize(tags[i].key, sb);
60 pmt::serialize(tags[i].value, sb);
61 pmt::serialize(tags[i].srcid, sb);
62 }
63
64 return sb.str();
65 }
66
parse_tag_header(zmq::message_t & msg,uint64_t & offset_out,std::vector<gr::tag_t> & tags_out)67 size_t parse_tag_header(zmq::message_t& msg,
68 uint64_t& offset_out,
69 std::vector<gr::tag_t>& tags_out)
70 {
71 membuf sb(msg.data(), msg.size());
72 std::istream iss(&sb);
73
74 size_t min_len =
75 sizeof(uint16_t) + sizeof(uint8_t) + sizeof(uint64_t) + sizeof(uint64_t);
76 if (msg.size() < min_len)
77 throw std::runtime_error("incoming zmq msg too small to hold gr tag header!");
78
79 uint16_t header_magic;
80 uint8_t header_version;
81 uint64_t rcv_ntags;
82
83 iss.read((char*)&header_magic, sizeof(uint16_t));
84 iss.read((char*)&header_version, sizeof(uint8_t));
85
86 if (header_magic != GR_HEADER_MAGIC)
87 throw std::runtime_error("gr header magic does not match!");
88
89 if (header_version != 1)
90 throw std::runtime_error("gr header version too high!");
91
92 iss.read((char*)&offset_out, sizeof(uint64_t));
93 iss.read((char*)&rcv_ntags, sizeof(uint64_t));
94
95 for (size_t i = 0; i < rcv_ntags; i++) {
96 gr::tag_t newtag;
97 sb.sgetn((char*)&(newtag.offset), sizeof(uint64_t));
98 newtag.key = pmt::deserialize(sb);
99 newtag.value = pmt::deserialize(sb);
100 newtag.srcid = pmt::deserialize(sb);
101 tags_out.push_back(newtag);
102 }
103
104 return msg.size() - sb.in_avail();
105 }
106 } /* namespace zeromq */
107 } /* namespace gr */
108
109 // vim: ts=2 sw=2 expandtab
110