forked from p4lang/behavioral-model
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtransport_nn.cpp
127 lines (110 loc) · 3.59 KB
/
transport_nn.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* Copyright 2013-present Barefoot Networks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Antonin Bas ([email protected])
*
*/
#include <bm/config.h>
#ifdef BM_NANOMSG_ON
#include <bm/bm_sim/transport.h>
#include <bm/bm_sim/nn.h>
#include <nanomsg/pubsub.h>
#include <iostream>
#include <string>
namespace bm {
class TransportNanomsg : public TransportIface {
public:
explicit TransportNanomsg(const std::string &addr)
: addr(addr), s(AF_SP, NN_PUB) { }
private:
int open_() override {
try {
s.bind(addr.c_str());
} catch (const nn::exception &e) {
std::cerr << "Nanomsg returned a exception when trying to bind to "
<< "address '" << addr << "'.\n"
<< "The exception is: " << e.what() << "\n"
<< "This may happen if\n"
<< "1) the address provided is invalid,\n"
<< "2) another instance of bmv2 is running and using the same "
<< "address, or\n"
<< "3) you have insufficent permissions (e.g. you are using an "
<< "IPC socket on Unix, the file already exists and you don't "
<< "have permission to access it)\n";
std::exit(1);
}
// TODO(antonin): review if linger is actually needed
int linger = 0;
s.setsockopt(NN_SOL_SOCKET, NN_LINGER, &linger, sizeof (linger));
return 0;
}
int send_(const std::string &msg) const override {
s.send(msg.data(), msg.size(), 0);
return 0;
}
int send_(const char *msg, int len) const override {
s.send(msg, len, 0);
return 0;
}
// do not use this function, I think I should just remove it...
int send_msgs_(const std::initializer_list<std::string> &msgs)
const override {
size_t num_msgs = msgs.size();
if (num_msgs == 0) return 0;
struct nn_msghdr msghdr;
std::memset(&msghdr, 0, sizeof(msghdr));
struct nn_iovec iov[num_msgs];
int i = 0;
for (const auto &msg : msgs) {
// wish I could write this, but string.data() return const char *
// iov[i].iov_base = msg.data();
std::unique_ptr<char[]> data(new char[msg.size()]);
msg.copy(data.get(), msg.size());
iov[i].iov_base = data.get();
iov[i].iov_len = msg.size();
i++;
}
msghdr.msg_iov = iov;
msghdr.msg_iovlen = num_msgs;
s.sendmsg(&msghdr, 0);
return 0;
}
int send_msgs_(const std::initializer_list<MsgBuf> &msgs) const override {
size_t num_msgs = msgs.size();
if (num_msgs == 0) return 0;
struct nn_msghdr msghdr;
std::memset(&msghdr, 0, sizeof(msghdr));
struct nn_iovec iov[num_msgs];
int i = 0;
for (const auto &msg : msgs) {
iov[i].iov_base = msg.buf;
iov[i].iov_len = msg.len;
i++;
}
msghdr.msg_iov = iov;
msghdr.msg_iovlen = num_msgs;
s.sendmsg(&msghdr, 0);
return 0;
}
private:
std::string addr;
nn::socket s;
};
std::unique_ptr<TransportIface>
TransportIface::make_nanomsg(const std::string &addr) {
return std::unique_ptr<TransportIface>(new TransportNanomsg(addr));
}
} // namespace bm
#endif // BM_NANOMSG_ON