|
|
|
|
|
|
|
|
#include "lfr_socket.h" |
|
|
#include "lfr_socket.h" |
|
|
#include <boost/regex.hpp> |
|
|
|
|
|
#include <iostream> |
|
|
|
|
|
#include <string> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LFR_Socket::LFR_Socket(ExceptionCallback cb): cb(cb) |
|
|
|
|
|
{ |
|
|
|
|
|
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) |
|
|
|
|
|
{ |
|
|
|
|
|
throw std::runtime_error("Failed opening the socket"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
throw std::runtime_error("Failed setting the socket options"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
address.sin_family = AF_INET; |
|
|
|
|
|
address.sin_addr.s_addr = INADDR_ANY; |
|
|
|
|
|
address.sin_port = htons(8080); |
|
|
|
|
|
|
|
|
|
|
|
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
throw std::runtime_error("Failed binding a name to the socket"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (listen(server_fd, 3) != 0) |
|
|
|
|
|
{ |
|
|
|
|
|
throw std::runtime_error("Failed listening for connections"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
LFR_Socket::~LFR_Socket() |
|
|
|
|
|
{ |
|
|
|
|
|
endLoop(); |
|
|
|
|
|
thread->join(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void LFR_Socket::removeListener(LFR_Socket::ListenerKey key) |
|
|
|
|
|
{ |
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex); |
|
|
|
|
|
auto it = std::find_if(std::begin(listeners), std::end(listeners), [&](auto const &val){ |
|
|
|
|
|
return val.first == key; |
|
|
|
|
|
}); |
|
|
|
|
|
if(it != std::end(listeners)) |
|
|
|
|
|
{ |
|
|
|
|
|
listeners.erase(it); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void LFR_Socket::addListener(LFR_Socket::ListenerCallback cb, LFR_Socket::ListenerKey key) |
|
|
|
|
|
{ |
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex); |
|
|
|
|
|
listeners.emplace_back(key, std::move(cb)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void LFR_Socket::setStop(bool val) |
|
|
|
|
|
{ |
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex); |
|
|
|
|
|
stop = val; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void LFR_Socket::createThread() |
|
|
|
|
|
{ |
|
|
|
|
|
thread = std::make_unique<std::thread>([this](){ |
|
|
|
|
|
bool connected = false; |
|
|
|
|
|
while(true) |
|
|
|
|
|
{ |
|
|
|
|
|
LFR_Socket::LFR_Telegram telegram; |
|
|
|
|
|
bool received = false; |
|
|
|
|
|
if(!stop && !listeners.empty()) |
|
|
|
|
|
{ |
|
|
|
|
|
try |
|
|
|
|
|
{ |
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex); |
|
|
|
|
|
|
|
|
|
|
|
struct pollfd pollfds[2]; |
|
|
|
|
|
pollfds[0].fd = server_fd; |
|
|
|
|
|
pollfds[0].events = POLLIN; |
|
|
|
|
|
pollfds[1].events = POLLIN; |
|
|
|
|
|
|
|
|
|
|
|
if (poll(pollfds, 2, 200) > 0) |
|
|
|
|
|
{ |
|
|
|
|
|
if(pollfds[0].revents & POLLIN || pollfds[1].revents & POLLIN) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!connected && pollfds[0].revents & POLLIN) |
|
|
|
|
|
{ |
|
|
|
|
|
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) == -1) |
|
|
|
|
|
{ |
|
|
|
|
|
throw std::runtime_error("failed accepting connection"); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
pollfds[1].fd = new_socket; |
|
|
|
|
|
connected = true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else if (pollfds[1].revents & POLLIN) |
|
|
|
|
|
{ |
|
|
|
|
|
bytes_received = recv(new_socket, buffer, sizeof(buffer), 0); |
|
|
|
|
|
if (bytes_received > 0) |
|
|
|
|
|
{ |
|
|
|
|
|
received = true; |
|
|
|
|
|
std::copy(std::begin(buffer), std::end(buffer), std::begin(telegram)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
catch(std::exception const &ex) |
|
|
|
|
|
{ |
|
|
|
|
|
if(!cb(ex)) |
|
|
|
|
|
{ |
|
|
|
|
|
//callback returned false -> exception not handled -> exit |
|
|
|
|
|
exit(EXIT_FAILURE); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//Invoke the callback method (ListenerPair second -> ListenerCallback) |
|
|
|
|
|
if (received) |
|
|
|
|
|
{ |
|
|
|
|
|
for(auto &val : listeners) |
|
|
|
|
|
{ |
|
|
|
|
|
val.second(telegram); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(150)); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void LFR_Socket::startLoop() |
|
|
|
|
|
{ |
|
|
|
|
|
if(thread) |
|
|
|
|
|
{ |
|
|
|
|
|
//Restart thread if it is running |
|
|
|
|
|
setStop(true); |
|
|
|
|
|
thread->join(); |
|
|
|
|
|
setStop(false); |
|
|
|
|
|
} |
|
|
|
|
|
createThread(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void LFR_Socket::endLoop() |
|
|
|
|
|
{ |
|
|
|
|
|
setStop(true); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int main() |
|
|
int main() |
|
|
{ |
|
|
{ |
|
|
std::string line; |
|
|
|
|
|
boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" ); |
|
|
|
|
|
|
|
|
std::mutex mutex; |
|
|
|
|
|
LFR_Socket socket([&](std::exception const &ex) |
|
|
|
|
|
{ |
|
|
|
|
|
std::unique_lock<std::mutex> lock(mutex); |
|
|
|
|
|
std::cerr<<"socket exception:"<<ex.what()<<std::endl; |
|
|
|
|
|
return false; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
socket.addListener([&](LFR_Socket::LFR_Telegram telegram) |
|
|
|
|
|
{ |
|
|
|
|
|
std::unique_lock<std::mutex> lock(mutex); |
|
|
|
|
|
std::cout << telegram; |
|
|
|
|
|
}, &mutex); |
|
|
|
|
|
|
|
|
|
|
|
socket.startLoop(); |
|
|
|
|
|
|
|
|
while (std::cin) |
|
|
|
|
|
|
|
|
//send(new_socket, "Hello from the server", sizeof("Hello from the server"), 0); |
|
|
|
|
|
char input; |
|
|
|
|
|
std::cout << "press q to quit" << std::endl; |
|
|
|
|
|
std::cin >> input; |
|
|
|
|
|
std::cout << "cinned" << std::endl; |
|
|
|
|
|
while (input != 'q') |
|
|
{ |
|
|
{ |
|
|
std::getline(std::cin, line); |
|
|
|
|
|
boost::smatch matches; |
|
|
|
|
|
if (boost::regex_match(line, matches, pat)) |
|
|
|
|
|
std::cout << matches[2] << std::endl; |
|
|
|
|
|
|
|
|
std::cin >> input; |
|
|
|
|
|
std::cout << "cinned" << std::endl; |
|
|
} |
|
|
} |
|
|
|
|
|
std::cout << "im out" << std::endl; |
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |