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>
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"
26 namespace VCommunication
{
28 NetworkSink::NetworkSink() {
31 sem_init(&m_accessLock
, 0, 1);
34 NetworkSink::~NetworkSink() {
35 sem_destroy(&m_accessLock
);
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() {
54 std::string port
= Coordinator::instance()->vault()->get("tcpPort");
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
;
71 struct addrinfo
*result
;
72 if((rv
= getaddrinfo(NULL
, port
.c_str(), &hints
, &result
)) == -1) {
73 std::cout
<< gai_strerror(rv
) << std::endl
;
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;
95 m_sockType
= rp
->ai_family
;
99 if(listen(m_serverFd
, AesalonConnectionQueueLength
) == -1) {
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) {
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
);
126 #if INET6_ADDRSTRLEN > INET_ADDRSTRLEN
127 char buffer
[INET6_ADDRSTRLEN
];
129 char buffer
[INET_ADDRSTRLEN
];
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