]> git.localhorst.tv Git - blank.git/blob - shared/net.cpp
new gcc version
[blank.git] / 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         // TODO: prefix each line in message/error/broadcast
64         write_buffer += " ! ";
65         write_buffer += msg;
66         write_buffer += '\n';
67 }
68
69 void CommandBuffer::Message(const string &msg) {
70         write_buffer += " > ";
71         write_buffer += msg;
72         write_buffer += '\n';
73 }
74
75 void CommandBuffer::Broadcast(const string &msg) {
76         // TODO: broadcast should be an operation of the
77         // environment, not the singular context
78         write_buffer += " @ ";
79         write_buffer += msg;
80         write_buffer += '\n';
81 }
82
83
84 void CommandBuffer::OnSend(tcp::Socket &sock) {
85         if (write_buffer.empty()) {
86                 return;
87         }
88         size_t len = sock.Send(write_buffer.data(), write_buffer.size());
89         write_buffer.erase(0, len);
90 }
91
92 void CommandBuffer::OnRecv(tcp::Socket &sock) {
93         size_t len = sock.Recv(&read_buffer[0], read_buffer.size() - head);
94         head += len;
95         // scan for lines
96         string::iterator begin = read_buffer.begin();
97         string::iterator end = begin + head;
98         string::iterator handled = begin;
99         for (
100                 string::iterator i = find(handled, end, '\n');
101                 i != end;
102                 i = find(handled, end, '\n')
103         ) {
104                 string line(handled, i);
105                 cli.Execute(*this, line);
106                 handled = ++i;
107         }
108         if (handled == end) {
109                 // guzzled it all
110                 head = 0;
111         } else if (handled != begin) {
112                 // half a line remaining, move it to the start of the buffer
113                 move(handled, end, begin);
114                 head = distance(handled, end);
115         }
116 }
117
118 void CommandBuffer::OnRemove(tcp::Socket &) noexcept {
119         delete this;
120 }
121
122 }