Stefan Schuermans commited on 2017-06-10 21:21:50
Showing 6 changed files, with 270 additions and 15 deletions.
| ... | ... |
@@ -18,19 +18,23 @@ |
| 18 | 18 |
*/ |
| 19 | 19 |
|
| 20 | 20 |
#include <algorithm> |
| 21 |
+#include <arpa/inet.h> |
|
| 21 | 22 |
#include <cctype> |
| 22 | 23 |
#include <cmath> |
| 23 | 24 |
#include <cstdlib> |
| 24 | 25 |
#include <functional> |
| 25 | 26 |
#include <fstream> |
| 26 | 27 |
#include <map> |
| 28 |
+#include <netinet/in.h> |
|
| 27 | 29 |
#include <stdexcept> |
| 28 | 30 |
#include <sstream> |
| 29 | 31 |
#include <string> |
| 32 |
+#include <sys/socket.h> |
|
| 30 | 33 |
|
| 31 | 34 |
#include "config.h" |
| 32 | 35 |
#include "distri.h" |
| 33 | 36 |
#include "mapping.h" |
| 37 |
+#include "pixel.h" |
|
| 34 | 38 |
|
| 35 | 39 |
/** |
| 36 | 40 |
* @brief constructor |
| ... | ... |
@@ -265,6 +269,48 @@ void Config::str2d3(std::string const &str, |
| 265 | 269 |
} |
| 266 | 270 |
} |
| 267 | 271 |
|
| 272 |
+/** |
|
| 273 |
+ * @brief convert string to IPv4/port address |
|
| 274 |
+ * @param[in] str string containing IPv4/port address |
|
| 275 |
+ * @throws std::exception in case of error |
|
| 276 |
+ */ |
|
| 277 |
+void Config::str2addr(std::string const &str, struct sockaddr_in &addr) |
|
| 278 |
+{
|
|
| 279 |
+ // split address into IPv4 and port |
|
| 280 |
+ std::vector<std::string> fields; |
|
| 281 |
+ split_chr(str, ':', fields); |
|
| 282 |
+ if (fields.size() != 2) {
|
|
| 283 |
+ std::stringstream msg; |
|
| 284 |
+ msg << "expected \"<IPv4>:<port>\", found \"" << str << "\""; |
|
| 285 |
+ throw std::runtime_error(msg.str()); |
|
| 286 |
+ } |
|
| 287 |
+ std::string &strIPv4 = fields[0], &strPort = fields[1]; |
|
| 288 |
+ |
|
| 289 |
+ // parse IPv4 address |
|
| 290 |
+ if (! inet_aton(strIPv4.c_str(), &addr.sin_addr)) {
|
|
| 291 |
+ std::stringstream msg; |
|
| 292 |
+ msg << "invalid IPv4 \"" << strIPv4 << "\""; |
|
| 293 |
+ throw std::runtime_error(msg.str()); |
|
| 294 |
+ } |
|
| 295 |
+ |
|
| 296 |
+ // parse port |
|
| 297 |
+ unsigned long port; |
|
| 298 |
+ try {
|
|
| 299 |
+ port = str2ul(strPort); |
|
| 300 |
+ if (port == 0 || port > 65535) {
|
|
| 301 |
+ throw std::runtime_error("port number out of range");
|
|
| 302 |
+ } |
|
| 303 |
+ } catch (std::exception &ex) {
|
|
| 304 |
+ std::stringstream msg; |
|
| 305 |
+ msg << "invalid port number \"" << strPort << "\": " << ex.what(); |
|
| 306 |
+ throw std::runtime_error(msg.str()); |
|
| 307 |
+ } |
|
| 308 |
+ addr.sin_port = htons(port); |
|
| 309 |
+ |
|
| 310 |
+ // fin in remaining fields of address structure |
|
| 311 |
+ addr.sin_family = AF_INET; |
|
| 312 |
+} |
|
| 313 |
+ |
|
| 268 | 314 |
/** |
| 269 | 315 |
* @brief read config file |
| 270 | 316 |
* @param[in] configFile name of config file |
| ... | ... |
@@ -470,7 +516,18 @@ void Config::proc_distributorAddr(std::vector<std::string> const &setFields, |
| 470 | 516 |
} |
| 471 | 517 |
|
| 472 | 518 |
// parse address |
| 473 |
- // TODO |
|
| 519 |
+ struct sockaddr_in addr; |
|
| 520 |
+ try {
|
|
| 521 |
+ str2addr(valFields[0], addr); |
|
| 522 |
+ } catch (std::exception &ex) {
|
|
| 523 |
+ std::stringstream msg; |
|
| 524 |
+ msg << "invalid value for \"mdistributorAddr " << distri.getNo() << "\": " |
|
| 525 |
+ << ex.what(); |
|
| 526 |
+ throw std::runtime_error(msg.str()); |
|
| 527 |
+ } |
|
| 528 |
+ |
|
| 529 |
+ // set address |
|
| 530 |
+ distri.setAddr(addr); |
|
| 474 | 531 |
} |
| 475 | 532 |
|
| 476 | 533 |
/** |
| ... | ... |
@@ -595,19 +652,20 @@ void Config::proc_output(std::vector<std::string> const &setFields, |
| 595 | 652 |
throw std::runtime_error(msg.str()); |
| 596 | 653 |
} |
| 597 | 654 |
|
| 655 |
+ // add output to distributor |
|
| 656 |
+ try {
|
|
| 657 |
+ distri.addOutput(outno); |
|
| 658 |
+ } catch (std::exception &ex) {
|
|
| 659 |
+ std::stringstream msg; |
|
| 660 |
+ msg << "cannot add output " << outno << " to distributor " << distno |
|
| 661 |
+ << ": " << ex.what(); |
|
| 662 |
+ throw std::runtime_error(msg.str()); |
|
| 663 |
+ } |
|
| 664 |
+ |
|
| 598 | 665 |
// parse all pixels |
| 599 |
- unsigned long pixels = distri.getPixels(); |
|
| 600 | 666 |
std::vector<std::string>::const_iterator pix; |
| 601 | 667 |
unsigned long p; |
| 602 | 668 |
for (pix = valFields.begin(), p = 0; pix != valFields.end(); ++pix, ++p) {
|
| 603 |
- // check maximum number of pixels |
|
| 604 |
- if (p >= pixels) {
|
|
| 605 |
- std::stringstream msg; |
|
| 606 |
- msg << "too many pixels (" << (p + 1) << ")"
|
|
| 607 |
- << p << " for output " << outno << " of distributor " << distno |
|
| 608 |
- << ": only " << pixels << " pixels supported"; |
|
| 609 |
- throw std::runtime_error(msg.str()); |
|
| 610 |
- } |
|
| 611 | 669 |
// parse pixel description |
| 612 | 670 |
double x, y, r; |
| 613 | 671 |
try {
|
| ... | ... |
@@ -620,10 +678,15 @@ void Config::proc_output(std::vector<std::string> const &setFields, |
| 620 | 678 |
throw std::runtime_error(msg.str()); |
| 621 | 679 |
} |
| 622 | 680 |
// add pixel |
| 623 |
- // TODO |
|
| 624 |
- (void)x; |
|
| 625 |
- (void)y; |
|
| 626 |
- (void)r; |
|
| 681 |
+ try {
|
|
| 682 |
+ distri.addPixel(outno, Pixel(x, y, r)); |
|
| 683 |
+ } catch (std::exception &ex) {
|
|
| 684 |
+ std::stringstream msg; |
|
| 685 |
+ msg << "cannot add pixel \"" << *pix << "\" (pixel " |
|
| 686 |
+ << p << ") to output " << outno << " of distributor " << distno |
|
| 687 |
+ << ": " << ex.what(); |
|
| 688 |
+ throw std::runtime_error(msg.str()); |
|
| 689 |
+ } |
|
| 627 | 690 |
} // for pixel |
| 628 | 691 |
} |
| 629 | 692 |
|
| ... | ... |
@@ -20,6 +20,7 @@ |
| 20 | 20 |
#ifndef CONFIG_H |
| 21 | 21 |
#define CONFIG_H |
| 22 | 22 |
|
| 23 |
+#include <arpa/inet.h> |
|
| 23 | 24 |
#include <map> |
| 24 | 25 |
#include <string> |
| 25 | 26 |
#include <vector> |
| ... | ... |
@@ -100,6 +101,13 @@ protected: |
| 100 | 101 |
static void str2d3(std::string const &str, |
| 101 | 102 |
double &d1, double &d2, double &d3); |
| 102 | 103 |
|
| 104 |
+ /** |
|
| 105 |
+ * @brief convert string to IPv4/port address |
|
| 106 |
+ * @param[in] str string containing IPv4/port address |
|
| 107 |
+ * @throws std::exception in case of error |
|
| 108 |
+ */ |
|
| 109 |
+ static void str2addr(std::string const &str, struct sockaddr_in &addr); |
|
| 110 |
+ |
|
| 103 | 111 |
/** |
| 104 | 112 |
* @brief read config file |
| 105 | 113 |
* @param[in] configFile name of config file |
| ... | ... |
@@ -17,16 +17,23 @@ |
| 17 | 17 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | 18 |
*/ |
| 19 | 19 |
|
| 20 |
+#include <arpa/inet.h> |
|
| 21 |
+#include <map> |
|
| 20 | 22 |
#include <sstream> |
| 21 | 23 |
#include <stdexcept> |
| 24 |
+#include <vector> |
|
| 22 | 25 |
|
| 23 | 26 |
#include "distri.h" |
| 27 |
+#include "mapping.h" |
|
| 28 |
+#include "pixel.h" |
|
| 24 | 29 |
|
| 25 | 30 |
/// constructor |
| 26 | 31 |
Distri::Distri(): |
| 27 | 32 |
m_distno(0), |
| 28 | 33 |
m_outputs(0), |
| 29 |
- m_pixels(0) |
|
| 34 |
+ m_pixels(0), |
|
| 35 |
+ m_mappings(), |
|
| 36 |
+ m_outputMap() |
|
| 30 | 37 |
{
|
| 31 | 38 |
} |
| 32 | 39 |
|
| ... | ... |
@@ -44,6 +51,15 @@ void Distri::init(unsigned long distno, unsigned long outputs, |
| 44 | 51 |
m_pixels = pixels; |
| 45 | 52 |
} |
| 46 | 53 |
|
| 54 |
+/** |
|
| 55 |
+ * @brief set network address |
|
| 56 |
+ * @param[in] addr IPv4/port network address (UDP) |
|
| 57 |
+ */ |
|
| 58 |
+void Distri::setAddr(struct sockaddr_in const &addr) |
|
| 59 |
+{
|
|
| 60 |
+ m_addr = addr; |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 47 | 63 |
/** |
| 48 | 64 |
* @brief get mapping |
| 49 | 65 |
* @param[in] chan color channel |
| ... | ... |
@@ -76,3 +92,52 @@ void Distri::setMapping(Mapping::Channel chan, Mapping const &mapping) |
| 76 | 92 |
m_mappings[chan] = mapping; |
| 77 | 93 |
} |
| 78 | 94 |
|
| 95 |
+/** |
|
| 96 |
+ * @brief add output to distributor |
|
| 97 |
+ * @param[in] outno number of output |
|
| 98 |
+ * @throws std::exception in case of error |
|
| 99 |
+ */ |
|
| 100 |
+void Distri::addOutput(unsigned long outno) |
|
| 101 |
+{
|
|
| 102 |
+ if (outno >= m_outputs) {
|
|
| 103 |
+ std::stringstream msg; |
|
| 104 |
+ msg << "invalid output number " << outno << ": only " << m_outputs |
|
| 105 |
+ << " outputs supported"; |
|
| 106 |
+ throw std::runtime_error(msg.str()); |
|
| 107 |
+ } |
|
| 108 |
+ |
|
| 109 |
+ if (m_outputMap.find(outno) != m_outputMap.end()) {
|
|
| 110 |
+ std::stringstream msg; |
|
| 111 |
+ msg << "output " << outno << " already exists"; |
|
| 112 |
+ throw std::runtime_error(msg.str()); |
|
| 113 |
+ } |
|
| 114 |
+ |
|
| 115 |
+ m_outputMap[outno]; |
|
| 116 |
+} |
|
| 117 |
+ |
|
| 118 |
+/** |
|
| 119 |
+ * @brief add pixel to output of distributor |
|
| 120 |
+ * @param[in] outno number of output |
|
| 121 |
+ * @param[in] pixel pixel object to add |
|
| 122 |
+ * @throws std::exception in case of error |
|
| 123 |
+ */ |
|
| 124 |
+void Distri::addPixel(unsigned long outno, Pixel const &pixel) |
|
| 125 |
+{
|
|
| 126 |
+ if (m_outputMap.find(outno) == m_outputMap.end()) {
|
|
| 127 |
+ std::stringstream msg; |
|
| 128 |
+ msg << "output " << outno << " does not exist"; |
|
| 129 |
+ throw std::runtime_error(msg.str()); |
|
| 130 |
+ } |
|
| 131 |
+ |
|
| 132 |
+ Output &output = m_outputMap[outno]; |
|
| 133 |
+ |
|
| 134 |
+ if (output.m_pixels.size() >= m_pixels) {
|
|
| 135 |
+ std::stringstream msg; |
|
| 136 |
+ msg << "cannot add pixel to output " << outno << ": already " << m_pixels |
|
| 137 |
+ << " pixels at this output (this is the maximum)"; |
|
| 138 |
+ throw std::runtime_error(msg.str()); |
|
| 139 |
+ } |
|
| 140 |
+ |
|
| 141 |
+ output.m_pixels.push_back(pixel); |
|
| 142 |
+} |
|
| 143 |
+ |
| ... | ... |
@@ -20,7 +20,12 @@ |
| 20 | 20 |
#ifndef DISTRI_H |
| 21 | 21 |
#define DISTRI_H |
| 22 | 22 |
|
| 23 |
+#include <arpa/inet.h> |
|
| 24 |
+#include <map> |
|
| 25 |
+#include <vector> |
|
| 26 |
+ |
|
| 23 | 27 |
#include "mapping.h" |
| 28 |
+#include "pixel.h" |
|
| 24 | 29 |
|
| 25 | 30 |
/// distributor |
| 26 | 31 |
class Distri |
| ... | ... |
@@ -46,6 +51,12 @@ public: |
| 46 | 51 |
/// get number of pixels at each output |
| 47 | 52 |
unsigned long getPixels() const { return m_pixels; }
|
| 48 | 53 |
|
| 54 |
+ /** |
|
| 55 |
+ * @brief set network address |
|
| 56 |
+ * @param[in] addr IPv4/port network address (UDP) |
|
| 57 |
+ */ |
|
| 58 |
+ void setAddr(struct sockaddr_in const &addr); |
|
| 59 |
+ |
|
| 49 | 60 |
/** |
| 50 | 61 |
* @brief get mapping |
| 51 | 62 |
* @param[in] chan color channel |
| ... | ... |
@@ -62,6 +73,30 @@ public: |
| 62 | 73 |
*/ |
| 63 | 74 |
void setMapping(Mapping::Channel chan, Mapping const &mapping); |
| 64 | 75 |
|
| 76 |
+ /** |
|
| 77 |
+ * @brief add output to distributor |
|
| 78 |
+ * @param[in] outno number of output |
|
| 79 |
+ * @throws std::exception in case of error |
|
| 80 |
+ */ |
|
| 81 |
+ void addOutput(unsigned long outno); |
|
| 82 |
+ |
|
| 83 |
+ /** |
|
| 84 |
+ * @brief add pixel to output of distributor |
|
| 85 |
+ * @param[in] outno number of output |
|
| 86 |
+ * @param[in] pixel pixel object to add |
|
| 87 |
+ * @throws std::exception in case of error |
|
| 88 |
+ */ |
|
| 89 |
+ void addPixel(unsigned long outno, Pixel const &pixel); |
|
| 90 |
+ |
|
| 91 |
+protected: |
|
| 92 |
+ /// output data |
|
| 93 |
+ struct Output {
|
|
| 94 |
+ std::vector<Pixel> m_pixels; ///< pixels at this output |
|
| 95 |
+ }; |
|
| 96 |
+ |
|
| 97 |
+ /// map out outputs: output number -> output data |
|
| 98 |
+ typedef std::map<unsigned long, Output> OutputMap; |
|
| 99 |
+ |
|
| 65 | 100 |
protected: |
| 66 | 101 |
/// distributor number |
| 67 | 102 |
unsigned long m_distno; |
| ... | ... |
@@ -69,8 +104,12 @@ protected: |
| 69 | 104 |
unsigned long m_outputs; |
| 70 | 105 |
/// number of pixels per output |
| 71 | 106 |
unsigned long m_pixels; |
| 107 |
+ /// network address |
|
| 108 |
+ struct sockaddr_in m_addr; |
|
| 72 | 109 |
/// mappings of color channels |
| 73 | 110 |
Mapping m_mappings[Mapping::ChannelCount]; |
| 111 |
+ /// outputs |
|
| 112 |
+ OutputMap m_outputMap; |
|
| 74 | 113 |
}; |
| 75 | 114 |
|
| 76 | 115 |
#endif // #ifndef DISTRI_H |
| ... | ... |
@@ -0,0 +1,37 @@ |
| 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 |
+ |
|
| 20 |
+#include "pixel.h" |
|
| 21 |
+ |
|
| 22 |
+/// default constructor |
|
| 23 |
+Pixel::Pixel(): |
|
| 24 |
+ m_x(0.5), |
|
| 25 |
+ m_y(0.5), |
|
| 26 |
+ m_r(0.0) |
|
| 27 |
+{
|
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+/// constructor based on coordinates and radius |
|
| 31 |
+Pixel::Pixel(double x, double y, double r): |
|
| 32 |
+ m_x(x), |
|
| 33 |
+ m_y(y), |
|
| 34 |
+ m_r(r) |
|
| 35 |
+{
|
|
| 36 |
+} |
|
| 37 |
+ |
| ... | ... |
@@ -0,0 +1,43 @@ |
| 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 |
+ |
|
| 20 |
+#ifndef PIXEL_H |
|
| 21 |
+#define PIXEL_H |
|
| 22 |
+ |
|
| 23 |
+/// a simulated pixel |
|
| 24 |
+class Pixel |
|
| 25 |
+{
|
|
| 26 |
+public: |
|
| 27 |
+ /// default constructor |
|
| 28 |
+ Pixel(); |
|
| 29 |
+ |
|
| 30 |
+ /// constructor based on coordinates and radius |
|
| 31 |
+ Pixel(double x, double y, double r); |
|
| 32 |
+ |
|
| 33 |
+protected: |
|
| 34 |
+ /// parameters of pixel |
|
| 35 |
+ //@{
|
|
| 36 |
+ double m_x; ///< x coordinate |
|
| 37 |
+ double m_y; ///< y coordinate |
|
| 38 |
+ double m_r; ///< radius |
|
| 39 |
+ //@} |
|
| 40 |
+}; |
|
| 41 |
+ |
|
| 42 |
+#endif // #ifndef PIXEL_H |
|
| 43 |
+ |
|
| 0 | 44 |