]> git.tdb.fi Git - xinema.git/blob - source/networkinterface.cpp
Avoid crashing due to network exceptions
[xinema.git] / source / networkinterface.cpp
1 #include <msp/io/print.h>
2 #include <msp/net/inet6.h>
3 #include <msp/net/resolve.h>
4 #include "client.h"
5 #include "networkinterface.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 NetworkInterface::NetworkInterface(Xinema &x):
11         xinema(x)
12 {
13         Net::SockAddr *addr = Net::resolve("::", "34588", Net::INET6);
14         server_sock = new Net::StreamServerSocket(addr->get_family());
15         server_sock->listen(*addr);
16         discover_sock = new Net::DatagramSocket(addr->get_family());
17         discover_sock->bind(*addr);
18         delete addr;
19
20         server_sock->signal_data_available.connect(sigc::mem_fun(this, &NetworkInterface::connection_available));
21         discover_sock->signal_data_available.connect(sigc::mem_fun(this, &NetworkInterface::discover_request));
22
23         event_disp.add(*server_sock);
24         event_disp.add(*discover_sock);
25
26         thread = new NetworkThread(*this);
27 }
28
29 NetworkInterface::~NetworkInterface()
30 {
31         thread->terminate();
32         delete thread;
33         delete server_sock;
34 }
35
36 void NetworkInterface::connection_available()
37 {
38         Net::StreamSocket *sock = server_sock->accept();
39         event_disp.add(*sock);
40         clients.push_back(new Client(xinema, sock));
41 }
42
43 void NetworkInterface::discover_request()
44 {
45         Net::SockAddr *peer_addr;
46         char rbuf[1024];
47         discover_sock->recvfrom(rbuf, sizeof(rbuf), peer_addr);
48         discover_sock->sendto("xinema", 6, *peer_addr);
49         delete peer_addr;
50 }
51
52
53 NetworkInterface::NetworkThread::NetworkThread(NetworkInterface &n):
54         network(n),
55         done(false)
56 {
57         network.event_disp.add(wakeup_pipe);
58         launch();
59 }
60
61 void NetworkInterface::NetworkThread::terminate()
62 {
63         done = true;
64         wakeup_pipe.put('w');
65         join();
66 }
67
68 void NetworkInterface::NetworkThread::main()
69 {
70         while(!done)
71         {
72                 try
73                 {
74                         network.event_disp.tick();
75                 }
76                 catch(const std::exception &e)
77                 {
78                         IO::print(IO::cerr, "Unhandled exception in network thread: %s\n", e.what());
79                 }
80
81                 for(list<Client *>::iterator i=network.clients.begin(); i!=network.clients.end(); )
82                 {
83                         if((*i)->is_stale())
84                         {
85                                 delete *i;
86                                 network.clients.erase(i++);
87                         }
88                         else
89                                 ++i;
90                 }
91         }
92 }