35ed4ccbb22ec3ab8b9737de6004f78f8190e4f3
Stefan Schuermans continue implementing confi...

Stefan Schuermans authored 7 years ago

1) /*
2)  * EtherPix simulator
3)  *
4)  * Copyright 2017 Stefan Schuermans <stefan schuermans info>
5)  *
6)  * This program is free software: you can redistribute it and/or modify
7)  * it under the terms of the GNU General Public License as published by
8)  * the Free Software Foundation, version 3 of the License.
9)  *
10)  *
11)  * This program is distributed in the hope that it will be useful,
12)  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13)  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14)  * GNU General Public License for more details.
15)  *
16)  * You should have received a copy of the GNU Lesser General Public License
17)  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18)  */
19) 
Stefan Schuermans complete implementation of...

Stefan Schuermans authored 7 years ago

20) #include <arpa/inet.h>
Stefan Schuermans implement receiving packets

Stefan Schuermans authored 7 years ago

21) #include <errno.h>
Stefan Schuermans implement drawing pixels

Stefan Schuermans authored 7 years ago

22) #include <gtkmm.h>
Stefan Schuermans complete implementation of...

Stefan Schuermans authored 7 years ago

23) #include <map>
Stefan Schuermans continue implementing confi...

Stefan Schuermans authored 7 years ago

24) #include <sstream>
25) #include <stdexcept>
Stefan Schuermans implement receiving packets

Stefan Schuermans authored 7 years ago

26) #include <stdint.h>
27) #include <string.h>
Stefan Schuermans complete implementation of...

Stefan Schuermans authored 7 years ago

28) #include <vector>
Stefan Schuermans continue implementing confi...

Stefan Schuermans authored 7 years ago

29) 
Stefan Schuermans implement drawing pixels

Stefan Schuermans authored 7 years ago

30) #include "bbox.h"
Stefan Schuermans continue implementing confi...

Stefan Schuermans authored 7 years ago

31) #include "distri.h"
Stefan Schuermans complete implementation of...

Stefan Schuermans authored 7 years ago

32) #include "mapping.h"
33) #include "pixel.h"
Stefan Schuermans implement drawing pixels

Stefan Schuermans authored 7 years ago

34) #include "transform.h"
Stefan Schuermans continue implementing confi...

Stefan Schuermans authored 7 years ago

35) 
36) /// constructor
37) Distri::Distri():
38)   m_distno(0),
39)   m_outputs(0),
Stefan Schuermans complete implementation of...

Stefan Schuermans authored 7 years ago

40)   m_pixels(0),
41)   m_mappings(),
Stefan Schuermans implement receiving packets

Stefan Schuermans authored 7 years ago

42)   m_outputMap(),
43)   m_sock(-1),
44)   m_packets(0)
Stefan Schuermans continue implementing confi...

Stefan Schuermans authored 7 years ago

45) {
Stefan Schuermans implement receiving packets

Stefan Schuermans authored 7 years ago

46)   // initialize address to localhost and automatic port
47)   m_addr.sin_family = AF_INET;
48)   m_addr.sin_addr.s_addr = INADDR_LOOPBACK;
49)   m_addr.sin_port = htons(0);
50) }
51) 
52) /// destructor
53) Distri::~Distri()
54) {
55)   stop();
Stefan Schuermans continue implementing confi...

Stefan Schuermans authored 7 years ago

56) }
57) 
58) /**
59)  * @brief initialize
60)  * @param[in] distno distributor number
61)  * @param[in] outputs number of outputs
62)  * @param[in] pixels number of pixels per output
63)  */
64) void Distri::init(unsigned long distno, unsigned long outputs,
65)                   unsigned long pixels)
66) {
67)   m_distno = distno;
68)   m_outputs = outputs;
69)   m_pixels = pixels;
70) }
71) 
Stefan Schuermans complete implementation of...

Stefan Schuermans authored 7 years ago

72) /**
73)  * @brief set network address
74)  * @param[in] addr IPv4/port network address (UDP)
75)  */
76) void Distri::setAddr(struct sockaddr_in const &addr)
77) {
78)   m_addr = addr;
79) }
80) 
Stefan Schuermans continue implementing confi...

Stefan Schuermans authored 7 years ago

81) /**
82)  * @brief get mapping
83)  * @param[in] chan color channel
84)  * @return mapping mapping object of color channel
85)  * @throws std::exception in case of error
86)  */
87) Mapping const& Distri::getMapping(Mapping::Channel chan) const
88) {
89)   if (chan >= Mapping::ChannelCount) {
90)     std::stringstream msg;
91)     msg << "invalid channel: " << chan;
92)     throw std::runtime_error(msg.str());
93)   }
94)   return m_mappings[chan];
95) }
96) 
97) /**
98)  * @brief set mapping
99)  * @param[in] chan color channel
100)  * @param[in] mapping new mapping object for color channel
101)  * @throws std::exception in case of error
102)  */
103) void Distri::setMapping(Mapping::Channel chan, Mapping const &mapping)
104) {
105)   if (chan >= Mapping::ChannelCount) {
106)     std::stringstream msg;
107)     msg << "invalid channel: " << chan;
108)     throw std::runtime_error(msg.str());
109)   }
110)   m_mappings[chan] = mapping;
111) }
112) 
Stefan Schuermans complete implementation of...

Stefan Schuermans authored 7 years ago

113) /**
114)  * @brief add output to distributor
115)  * @param[in] outno number of output
116)  * @throws std::exception in case of error
117)  */
118) void Distri::addOutput(unsigned long outno)
119) {
120)   if (outno >= m_outputs) {
121)     std::stringstream msg;
122)     msg << "invalid output number " << outno << ": only " << m_outputs
123)         << " outputs supported";
124)     throw std::runtime_error(msg.str());
125)   }
126) 
127)   if (m_outputMap.find(outno) != m_outputMap.end()) {
128)     std::stringstream msg;
129)     msg << "output " << outno << " already exists";
130)     throw std::runtime_error(msg.str());
131)   }
132) 
133)   m_outputMap[outno];
134) }
135) 
136) /**
137)  * @brief add pixel to output of distributor
138)  * @param[in] outno number of output
139)  * @param[in] pixel pixel object to add
140)  * @throws std::exception in case of error
141)  */
142) void Distri::addPixel(unsigned long outno, Pixel const &pixel)
143) {
144)   if (m_outputMap.find(outno) == m_outputMap.end()) {
145)     std::stringstream msg;
146)     msg << "output " << outno << " does not exist";
147)     throw std::runtime_error(msg.str());
148)   }
149) 
150)   Output &output = m_outputMap[outno];
151) 
152)   if (output.m_pixels.size() >= m_pixels) {
153)     std::stringstream msg;
154)     msg << "cannot add pixel to output " << outno << ": already " << m_pixels
155)         << " pixels at this output (this is the maximum)";
156)     throw std::runtime_error(msg.str());
157)   }
158) 
159)   output.m_pixels.push_back(pixel);
160) }
161) 
Stefan Schuermans implement drawing pixels

Stefan Schuermans authored 7 years ago

162) /**
163)  * @brief add all pixels of this distributor to the bounding box
164)  * @param[in,out] bb bounding box
165)  */
166) void Distri::updateBBox(BBox &bb) const
167) {
168)   OutputMap::const_iterator out;
169)   for (out = m_outputMap.begin(); out != m_outputMap.end(); ++out) {
170)     Output const &output = out->second;
171)     std::vector<Pixel>::const_iterator pix;
172)     for (pix = output.m_pixels.begin(); pix != output.m_pixels.end(); ++pix) {
173)       Pixel const &pixel = *pix;
174)       pixel.updateBBox(bb);
175)     }
176)   }
177) }
178) 
Stefan Schuermans implement receiving packets

Stefan Schuermans authored 7 years ago

179) /**
180)  * @brief create socket and listen for incoming packets
181)  * @throws std::exception in case of error
182)  */
183) void Distri::start()
184) {
185)   // leave if  socket already exists
186)   if (m_sock != -1) {
187)     return;
188)   }
189) 
190)   // create socket
191)   m_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
192)   if (m_sock == -1) {
193)     std::stringstream msg;
194)     msg << "could not create IPv4/UDP socket: " << strerror(errno);
195)     throw::std::runtime_error(msg.str());
196)   }
197)   try {
198) 
199)     // bind socket
200)     if (bind(m_sock, (struct sockaddr *)&m_addr, sizeof(m_addr)) != 0) {
201)       std::stringstream msg;
202)       msg << "could not bind IPv4/UDP socket to \""
203)           << inet_ntoa(m_addr.sin_addr) << ":" << ntohs(m_addr.sin_port)
204)           << "\": " << strerror(errno);
205)       throw::std::runtime_error(msg.str());
206)     }
207) 
208)     // register callback on incomimg packets
209)     m_conn = Glib::signal_io().connect(sigc::mem_fun(*this, &Distri::on_packet),
210)                                        m_sock, Glib::IO_IN);
211) 
212)   } catch (...) {
213)     close(m_sock);
214)     m_sock = -1;
215)     throw;
216)   }
217) }
218) 
219) /**
220)  * @brief stop listening for incoming packets and close socket
221)  */
222) void Distri::stop()
223) {
224)   // leave if no socket
225)   if (m_sock == -1) {
226)     return;
227)   }
228) 
229)   // uninstall callback
230)   m_conn.disconnect();
231) 
232)   // close socket
233)   close(m_sock);
234) 
235)   // socket in no more there
236)   m_sock = -1;
237) }
238) 
239) /// get and reset packet conter
240) unsigned long Distri::getPacketCounterAndReset()
241) {
242)   unsigned long packets = m_packets;
243)   m_packets = 0;
244)   return packets;
245) }
246) 
Stefan Schuermans implement drawing pixels

Stefan Schuermans authored 7 years ago

247) /**
248)  * @brief draw pixels of this distributor
249)  * @param[in] cairo cairo context for drawing
250)  * @param[in] tf coordinate transformation
251)  */
252) void Distri::draw(Cairo::RefPtr<Cairo::Context> &cairo,
253)                   Transform const &tf) const
254) {
255)   OutputMap::const_iterator out;
256)   for (out = m_outputMap.begin(); out != m_outputMap.end(); ++out) {
257)     Output const &output = out->second;
258)     std::vector<Pixel>::const_iterator pix;
259)     for (pix = output.m_pixels.begin(); pix != output.m_pixels.end(); ++pix) {
260)       Pixel const &pixel = *pix;
261)       pixel.draw(cairo, tf);
262)     }
263)   }
264) }
265) 
Stefan Schuermans implement receiving packets

Stefan Schuermans authored 7 years ago

266) /**
267)  * @brief callback on packet input on socket
268)  */
269) bool Distri::on_packet(Glib::IOCondition condition)
270) {
271)   // incoming packet
272)   if (condition & Glib::IO_IN) {
273) 
274)     // read packet
275)     uint8_t buffer[65536];
276)     ssize_t sz = recv(m_sock, buffer, sizeof(buffer), 0);
277)     // success and long enough for header
278)     if (sz >= 12) {
Stefan Schuermans commen typo fix

Stefan Schuermans authored 6 years ago

279)       // check magic, 3 channels and maxval 0xFF