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