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