]> git.localhorst.tv Git - blank.git/blob - src/shared/net.cpp
17b2e8d1ea2066b27f27870254b33e201d26bb6d
[blank.git] / src / shared / net.cpp
1 #include "CommandService.hpp"
2
3 #include "CLI.hpp"
4 #include "CommandBuffer.hpp"
5
6 #include <algorithm>
7 #include <iostream>
8
9 using namespace std;
10
11
12 namespace blank {
13
14 CommandService::CommandService(CLI &cli, unsigned short port)
15 : cli(cli)
16 , pool() {
17         pool.AddConnection(tcp::Socket(port), this);
18         cout << "listening on TCP port " << port << endl;
19 }
20
21 CommandService::~CommandService() {
22
23 }
24
25
26 void CommandService::Wait(int timeout) noexcept {
27         pool.Check(timeout);
28 }
29
30 bool CommandService::Ready() noexcept {
31         return pool.Check(0);
32 }
33
34 void CommandService::Handle() {
35         pool.Receive();
36 }
37
38 void CommandService::Send() {
39         pool.Send();
40 }
41
42 void CommandService::OnRecv(tcp::Socket &serv) {
43         for (tcp::Socket client = serv.Accept(); client; client = serv.Accept()) {
44                 pool.AddConnection(move(client), new CommandBuffer(cli));
45         }
46 }
47
48
49 CommandBuffer::CommandBuffer(CLI &cli)
50 : cli(cli)
51 , write_buffer()
52 , read_buffer(1440, '\0')
53 , head(0) {
54
55 }
56
57 CommandBuffer::~CommandBuffer() {
58
59 }
60
61
62 void CommandBuffer::Error(const string &msg) {
63         write_buffer += " ! ";
64         write_buffer += msg;
65         write_buffer += '\n';
66 }
67
68 void CommandBuffer::Message(const string &msg) {
69         write_buffer += " > ";
70         write_buffer += msg;
71         write_buffer += '\n';
72 }
73
74 void CommandBuffer::Broadcast(const string &msg) {
75         // TODO: broadcast should be an operation of the
76         // environment, not the singular context
77         write_buffer += " @ ";
78         write_buffer += msg;
79         write_buffer += '\n';
80 }
81
82
83 void CommandBuffer::OnSend(tcp::Socket &sock) {
84         if (write_buffer.empty()) {
85                 return;
86         }
87         size_t len = sock.Send(write_buffer.data(), write_buffer.size());
88         write_buffer.erase(0, len);
89 }
90
91 void CommandBuffer::OnRecv(tcp::Socket &sock) {
92         size_t len = sock.Recv(&read_buffer[0], read_buffer.size() - head);
93         head += len;
94         // scan for lines
95         string::iterator begin = read_buffer.begin();
96         string::iterator end = begin + head;
97         string::iterator handled = begin;
98         for (
99                 string::iterator i = find(handled, end, '\n');
100                 i != end;
101                 i = find(handled, end, '\n')
102         ) {
103                 string line(handled, i);
104                 cli.Execute(*this, line);
105                 handled = ++i;
106         }
107         if (handled == end) {
108                 // guzzled it all
109                 head = 0;
110         } else if (handled != begin) {
111                 // half a line remaining, move it to the start of the buffer
112                 move(handled, end, begin);
113                 head = distance(handled, end);
114         }
115 }
116
117 void CommandBuffer::OnRemove(tcp::Socket &) noexcept {
118         delete this;
119 }
120
121 }