]> git.tdb.fi Git - libs/net.git/blob - examples/netcat.cpp
Add ClientSocket and ServerSocket abstractions
[libs/net.git] / examples / netcat.cpp
1 #include <msp/core/application.h>
2 #include <msp/core/getopt.h>
3 #include <msp/core/refptr.h>
4 #include <msp/io/console.h>
5 #include <msp/io/eventdispatcher.h>
6 #include <msp/net/streamserversocket.h>
7 #include <msp/net/streamsocket.h>
8 #include <msp/net/resolve.h>
9
10 using namespace std;
11 using namespace Msp;
12
13 class NetCat: public RegisteredApplication<NetCat>
14 {
15 private:
16         bool ipv6;
17         bool listen;
18         Net::StreamServerSocket *server_sock;
19         Net::StreamSocket *sock;
20         IO::EventDispatcher event_disp;
21
22 public:
23         NetCat(int, char **);
24
25 private:
26         virtual void tick();
27         void net_data_available();
28         void console_data_available();
29 };
30
31 NetCat::NetCat(int argc, char **argv):
32         ipv6(false),
33         listen(false),
34         server_sock(0),
35         sock(0)
36 {
37         GetOpt getopt;
38         getopt.add_option('6', "ipv6",   ipv6,   GetOpt::NO_ARG);
39         getopt.add_option('l', "listen", listen, GetOpt::NO_ARG);
40         getopt(argc, argv);
41
42         const vector<string> &args = getopt.get_args();
43         if(args.empty())
44                 throw usage_error("host argument missing");
45
46         RefPtr<Net::SockAddr> addr = Net::resolve(args.front(), (ipv6 ? Net::INET6 : Net::INET));
47         if(!listen)
48         {
49                 sock = new Net::StreamSocket(addr->get_family());
50                 sock->connect(*addr);
51                 event_disp.add(*sock);
52                 sock->signal_data_available.connect(sigc::mem_fun(this, &NetCat::net_data_available));
53         }
54         else
55         {
56                 server_sock = new Net::StreamServerSocket(addr->get_family());
57                 server_sock->listen(*addr);
58                 event_disp.add(*server_sock);
59                 server_sock->signal_data_available.connect(sigc::mem_fun(this, &NetCat::net_data_available));
60         }
61
62         event_disp.add(IO::cin);
63         IO::cin.signal_data_available.connect(sigc::mem_fun(this, &NetCat::console_data_available));
64 }
65
66 void NetCat::tick()
67 {
68         event_disp.tick();
69         if(server_sock && sock)
70         {
71                 delete server_sock;
72                 server_sock = 0;
73         }
74 }
75
76 void NetCat::net_data_available()
77 {
78         if(server_sock)
79         {
80                 sock = server_sock->accept();
81                 event_disp.add(*sock);
82                 sock->signal_data_available.connect(sigc::mem_fun(this, &NetCat::net_data_available));
83         }
84         else
85         {
86                 char buf[1024];
87                 unsigned len = sock->read(buf, sizeof(buf));
88                 IO::cout.write(buf, len);
89         }
90 }
91
92 void NetCat::console_data_available()
93 {
94         char buf[1024];
95         unsigned len = IO::cin.read(buf, sizeof(buf));
96         if(sock)
97                 sock->write(buf, len);
98 }