Revert "Started experimenting with perl/python scripts to auto rename incl guards...
[aesalon.git] / src / vcomm / vcommunication / NetworkSink.cpp
blob1cdc375c372e29ca08cbb1b789d562332ecac2bf
1 /**
2 Aesalon, a tool to visualize a program's behaviour at run-time.
3 Copyright (C) 2010, Aesalon Development Team.
5 Aesalon is distributed under the terms of the GNU GPLv3. For more
6 licensing information, see the file LICENSE included with the distribution.
8 @file monitor/src/vcommunication/NetworkSink.cpp
12 #include <sys/socket.h>
13 #include <netdb.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <arpa/inet.h>
18 #include "vcommunication/NetworkSink.h"
19 #include "common/StringTo.h"
20 #include "common/StringToBool.h"
21 #include "Coordinator.h"
23 #include "common/Config.h"
25 namespace Monitor {
26 namespace VCommunication {
28 NetworkSink::NetworkSink() {
29 openSocket();
31 sem_init(&m_accessLock, 0, 1);
34 NetworkSink::~NetworkSink() {
35 sem_destroy(&m_accessLock);
37 closeSocket();
40 void NetworkSink::sinkPacket(Common::VPacket *packet) {
41 if(m_serverFd == -1) return;
43 sem_wait(&m_accessLock);
45 for(ClientFdList::iterator i = m_clientFds.begin(); i != m_clientFds.end(); ++i) {
46 sendPacket(packet, *i);
49 sem_post(&m_accessLock);
52 void NetworkSink::openSocket() {
53 m_serverFd = -1;
54 std::string port = Coordinator::instance()->vault()->get("tcpPort");
55 if(port == "") {
56 return;
58 struct addrinfo hints;
60 memset(&hints, 0, sizeof(hints));
62 hints.ai_family = AF_UNSPEC;
63 hints.ai_socktype = SOCK_STREAM;
64 hints.ai_flags = AI_PASSIVE;
65 hints.ai_protocol = 0;
66 hints.ai_canonname = NULL;
67 hints.ai_addr = NULL;
68 hints.ai_next = NULL;
70 int rv = 0;
71 struct addrinfo *result;
72 if((rv = getaddrinfo(NULL, port.c_str(), &hints, &result)) == -1) {
73 std::cout << gai_strerror(rv) << std::endl;
74 return;
77 int yes = 1;
79 struct addrinfo *rp;
80 for(rp = result; rp != NULL; rp = rp->ai_next) {
81 m_serverFd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
82 if(m_serverFd == -1) continue;
84 if(setsockopt(m_serverFd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) continue;
86 if(bind(m_serverFd, rp->ai_addr, rp->ai_addrlen) == 0) break;
88 close(m_serverFd);
90 if(rp == NULL) {
91 m_serverFd = -1;
92 return;
95 m_sockType = rp->ai_family;
97 freeaddrinfo(result);
99 if(listen(m_serverFd, AesalonConnectionQueueLength) == -1) {
100 m_serverFd = -1;
101 return;
104 int connectionCount = Common::StringTo<int>(Coordinator::instance()->vault()->get("networkWaitCount"));
106 bool shouldWait = Common::StringToBool(Coordinator::instance()->vault()->get("networkWait"));
107 if(shouldWait) waitForConnections(connectionCount);
110 void NetworkSink::closeSocket() {
111 if(m_serverFd != -1) {
112 close(m_serverFd);
116 void NetworkSink::waitForConnections(int connectionCount) {
117 std::cout << "Waiting for " << connectionCount << " connections . . ." << std::endl;
118 for(int i = 0; i < connectionCount; i ++) {
119 struct sockaddr peerAddress;
120 socklen_t peerAddressSize = sizeof(peerAddress);
121 int fd = accept(m_serverFd, &peerAddress, &peerAddressSize);
122 if(fd == -1) {
123 i --;
124 continue;
126 #if INET6_ADDRSTRLEN > INET_ADDRSTRLEN
127 char buffer[INET6_ADDRSTRLEN];
128 #else
129 char buffer[INET_ADDRSTRLEN];
130 #endif
132 void *address = NULL;
134 if(m_sockType == AF_INET) {
135 struct sockaddr_in *sin = (struct sockaddr_in *)&peerAddress;
136 address = &sin->sin_addr;
138 else if(m_sockType == AF_INET6) {
139 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&peerAddress;
140 address = &sin->sin6_addr;
142 inet_ntop(m_sockType, address, buffer, sizeof(buffer));
144 std::cout << "Client connected from " << buffer << std::endl;
146 m_clientFds.push_back(fd);
150 void NetworkSink::sendPacket(Common::VPacket *packet, int fd) {
151 ModuleID moduleID = packet->moduleID();
152 write(fd, &moduleID, sizeof(moduleID));
154 uint32_t processID = packet->processID();
155 write(fd, &processID, sizeof(processID));
157 uint32_t threadID = packet->threadID();
158 write(fd, &threadID, sizeof(threadID));
160 uint32_t dataSize = packet->dataSize();
161 write(fd, &dataSize, sizeof(dataSize));
163 write(fd, packet->data(), dataSize);
166 } // namespace VCommunication
167 } // namespace Monitor