|
3 | 3 | #include <iostream> |
4 | 4 |
|
5 | 5 | #include <sys/eventfd.h> |
6 | | -#include <sys/epoll.h> |
| 6 | +#include <sys/select.h> |
7 | 7 |
|
8 | 8 | #include <errno.h> |
9 | 9 | #include <unistd.h> |
@@ -47,227 +47,136 @@ namespace simpleApp |
47 | 47 | return 0; |
48 | 48 | } |
49 | 49 |
|
50 | | - void cleanStdin() |
51 | | - { |
52 | | - // TODO |
53 | | - } |
54 | | - |
55 | | - int getFromStdin(char* buffer) |
56 | | - { |
57 | | - // TODO |
58 | | - return 0; |
59 | | - } |
60 | | - |
61 | 50 | int MainConsole::consoleLoop() |
62 | 51 | { |
63 | | - int epollfd = epoll_create1(0); |
64 | | - |
65 | | - if (epollfd == -1) |
| 52 | + if (this->breakEventFd == -1) |
66 | 53 | { |
67 | | - std::cout << "EPoll creation failed with code " << errno << std::endl << std::flush; |
68 | | - return -1; |
69 | | - } |
70 | | - |
71 | | - epoll_event setupEvent; |
72 | | - setupEvent.data.fd = this->breakEventFd; |
73 | | - setupEvent.events = EPOLLIN | EPOLLET; |
74 | | - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, this->breakEventFd, &setupEvent) == -1) |
75 | | - { |
76 | | - std::cout << "EPOLL_CTL_ADD of break event fd failed with code " << errno << std::endl << std::flush; |
77 | | - close(epollfd); |
| 54 | + std::cout << "Break event is not set" << std::endl; |
78 | 55 | return -1; |
79 | 56 | } |
80 | 57 |
|
81 | | - setupEvent.data.fd = STDIN_FILENO; |
82 | | - setupEvent.events = EPOLLIN | EPOLLET; |
83 | | - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, STDIN_FILENO, &setupEvent) == -1) |
84 | | - { |
85 | | - std::cout << "EPOLL_CTL_ADD of break event fd failed with code " << errno << std::endl << std::flush; |
86 | | - epoll_ctl(epollfd, EPOLL_CTL_DEL, this->breakEventFd, nullptr); |
87 | | - close(epollfd); |
88 | | - return -1; |
89 | | - } |
| 58 | + timeval tv; |
| 59 | + |
| 60 | + tv.tv_sec = 5; |
| 61 | + tv.tv_usec = 0; |
90 | 62 |
|
91 | 63 | bool isExit = false; |
92 | | - console_state currentState = console_state::protocol_selection; |
93 | | - SessionClient* currentSession = nullptr; |
| 64 | + SessionClient * currentSession = nullptr; |
| 65 | + console_state currentState; |
94 | 66 |
|
95 | | - std::cout << "Select protocol: [u]dp or [t]cp - or press Ctrl+C for exit" << std::endl << std::flush; |
96 | | - std::cout << " >> " << std::flush; |
| 67 | + auto switchState = [¤tState, ¤tSession, &isExit](console_state newState) |
| 68 | + { |
| 69 | + // TODO |
| 70 | + }; |
| 71 | + |
| 72 | + switchState(console_state::protocol_selection); |
97 | 73 |
|
98 | 74 | while (!isExit) |
99 | 75 | { |
100 | | - const size_t eventsSize = 4; |
101 | | - epoll_event events[eventsSize]; |
| 76 | + fd_set fd_in; |
| 77 | + FD_ZERO(&fd_in); |
102 | 78 |
|
103 | | - console_state nextState = console_state::none; |
| 79 | + FD_SET(this->breakEventFd, &fd_in); |
| 80 | + FD_SET(STDIN_FILENO, &fd_in); |
104 | 81 |
|
105 | | - int len = epoll_wait(epollfd, events, eventsSize, -1); |
106 | | - for(size_t i = 0; static_cast<int>(i) < len; i++) |
| 82 | + int largerFd = this->breakEventFd > STDIN_FILENO ? this->breakEventFd : STDIN_FILENO; |
| 83 | + if (currentSession != nullptr) |
107 | 84 | { |
108 | | - if (events[i].data.fd == this->breakEventFd) |
109 | | - { |
110 | | - switch (currentState) |
111 | | - { |
112 | | - case console_state::protocol_selection: |
113 | | - nextState = console_state::none; |
114 | | - isExit = true; |
115 | | - break; |
116 | | - |
117 | | - case console_state::msg_input: |
118 | | - case console_state::wait_result: |
119 | | - case console_state::connect_wait: |
120 | | - delete currentSession; |
121 | | - currentSession = nullptr; |
122 | | - case console_state::address_input: |
123 | | - nextState = console_state::protocol_selection; |
124 | | - break; |
125 | | - default: |
126 | | - break; |
127 | | - } |
128 | | - |
129 | | - cleanStdin(); |
| 85 | + auto sessionSocket = currentSession->getSocket(); |
| 86 | + largerFd = sessionSocket > largerFd ? sessionSocket : largerFd; |
| 87 | + } |
| 88 | + |
| 89 | + int selectResult = select(largerFd + 1, &fd_in, 0, 0, &tv); |
130 | 90 |
|
131 | | - break; |
132 | | - } |
| 91 | + if (selectResult == -1) |
| 92 | + { |
| 93 | + std::cout << "Select failed with code " << errno; |
| 94 | + if (currentSession != nullptr) |
| 95 | + delete currentSession; |
| 96 | + return -1; |
| 97 | + } |
133 | 98 |
|
134 | | - // Non-console event and have session |
135 | | - if (events[i].data.fd != STDIN_FILENO && currentSession != nullptr) |
| 99 | + if (currentSession != nullptr) |
| 100 | + { |
| 101 | + if (selectResult == 0) |
136 | 102 | { |
137 | | - //cleanStdin(); |
138 | | - |
139 | | - switch (currentState) |
| 103 | + auto result = currentSession->sendConnup(); |
| 104 | + if (result.status != session_status::connup_up && result.status != session_status::connup_not_req) |
140 | 105 | { |
141 | | - case console_state::msg_input: |
| 106 | + if (result.status == session_status::connup_timeout) |
| 107 | + std::cout << std::endl << "Server does not response"; |
| 108 | + else |
| 109 | + std::cout << std::endl << "Unknown error"; |
142 | 110 |
|
143 | | - break; |
144 | | - |
145 | | - default: |
146 | | - break; |
| 111 | + if (result.err != 0) |
| 112 | + std::cout << " with code " << result.err << std::endl << std::flush; |
| 113 | + else |
| 114 | + std::cout << std::endl << std::flush; |
| 115 | + |
| 116 | + switchState(console_state::address_input); |
| 117 | + |
| 118 | + continue; |
147 | 119 | } |
148 | | - // TODO |
149 | 120 | } |
150 | | - |
151 | | - // Console input |
152 | | - if (events[i].data.fd == STDIN_FILENO) |
| 121 | + |
| 122 | + // Something came to socket without request |
| 123 | + if (FD_ISSET(currentSession->getSocket(), &fd_in)) |
153 | 124 | { |
154 | | - char buffer[MESSAGE_MAX_BUFFER - sizeof(msg_headers)]; |
155 | | - auto len = getFromStdin(buffer); |
| 125 | + auto result = currentSession->proceed(); |
156 | 126 |
|
157 | | - if (len < 1) |
| 127 | + switch (result.status) |
158 | 128 | { |
159 | | - cleanStdin(); |
| 129 | + case session_status::proceed_msg_recv_fail: |
| 130 | + std::cout << "Message receiving failed"; |
160 | 131 | break; |
161 | | - } |
162 | | - |
163 | | - switch (currentState) |
164 | | - { |
165 | | - case console_state::protocol_selection: |
166 | | - if (buffer[0] == 't') |
167 | | - { |
168 | | - currentSession = new SessionTcp(epollfd); |
169 | | - nextState = console_state::address_input; |
170 | | - } |
171 | | - else if (buffer[0] == 'u') |
172 | | - { |
173 | | - currentSession = new SessionUdp(epollfd); |
174 | | - nextState = console_state::address_input; |
175 | | - } |
176 | | - else |
177 | | - { |
178 | | - std::cout << "Incorrect choice" << std::endl << std::flush; |
179 | | - } |
| 132 | + case session_status::proceed_disconnect: |
| 133 | + std::cout << "Session shutdown by server"; |
| 134 | + break; |
| 135 | + case session_status::recv_wrong_length: |
| 136 | + std::cout << "Message with wrong length received"; |
| 137 | + break; |
| 138 | + case session_status::proceed_server_error: |
| 139 | + std::cout << "Server error returned"; |
| 140 | + break; |
| 141 | + case session_status::proceed_server_timeout: |
| 142 | + std::cout << "Received server timeout"; |
180 | 143 | break; |
181 | | - |
182 | | - case console_state::address_input: |
183 | | - { |
184 | | - auto result = currentSession->init(std::string(buffer, len)); |
185 | | - switch (result.status) |
186 | | - { |
187 | | - case session_status::init_success: |
188 | | - nextState = console_state::msg_input; |
189 | | - break; |
190 | | - |
191 | | - case session_status::init_udp_conn_wait: |
192 | | - nextState = console_state::connect_wait; |
193 | | - break; |
194 | | - |
195 | | - default: |
196 | | - std::cout << "Connection error" << std::endl << std::flush; |
197 | | - delete currentSession; |
198 | | - currentSession = nullptr; |
199 | | - nextState = console_state::protocol_selection; |
200 | | - break; |
201 | | - } |
202 | | - break; |
203 | | - } |
204 | | - case console_state::msg_input: |
205 | | - { |
206 | | - auto result = currentSession->proceed(events[i].data.fd, buffer, len); |
207 | | - switch (result.status) |
208 | | - { |
209 | | - case session_status::proceed_msg_send: |
210 | | - |
211 | | - break; |
212 | | - |
213 | | - default: |
214 | | - break; |
215 | | - } |
216 | | - } |
217 | 144 | default: |
| 145 | + std::cout << "Unknown error"; |
218 | 146 | break; |
219 | 147 | } |
| 148 | + |
| 149 | + if (result.err != 0) |
| 150 | + std::cout << " with code " << result.err << std::endl << std::flush; |
| 151 | + else |
| 152 | + std::cout << std::endl << std::flush; |
| 153 | + |
| 154 | + switchState(console_state::protocol_selection); |
220 | 155 |
|
221 | | - cleanStdin(); |
222 | | - break; |
| 156 | + continue; |
223 | 157 | } |
224 | 158 | } |
225 | | - |
226 | | - // Switch state |
227 | | - switch (nextState) |
| 159 | + else if (selectResult == 0) |
228 | 160 | { |
229 | | - case console_state::protocol_selection: |
230 | | - { |
231 | | - std::cout << "Select protocol: [u]dp or [t]cp - or press Ctrl+C for exit" << std::endl << std::flush; |
232 | | - break; |
233 | | - } |
234 | | - |
235 | | - case console_state::address_input: |
236 | | - { |
237 | | - std::cout << "Input IP address of server. To change protocol press Ctrl+C" << std::endl << std::flush; |
238 | | - break; |
239 | | - } |
240 | | - |
241 | | - case console_state::msg_input: |
242 | | - { |
243 | | - std::cout << "Connected to server. For disconnect press Ctrl+C" << std::endl << std::flush; |
244 | | - break; |
245 | | - } |
246 | | - default: |
247 | | - break; |
| 161 | + continue; |
248 | 162 | } |
249 | 163 |
|
250 | | - if (nextState != console_state::none) |
251 | | - currentState = nextState; |
| 164 | + if (FD_ISSET(this->breakEventFd, &fd_in)) |
| 165 | + { |
| 166 | + if (currentState == console_state::protocol_selection) |
| 167 | + isExit = true; |
| 168 | + else |
| 169 | + switchState(console_state::protocol_selection); |
| 170 | + |
| 171 | + continue; |
| 172 | + } |
252 | 173 |
|
253 | | - switch (currentState) |
| 174 | + if (FD_ISSET(STDIN_FILENO, &fd_in)) |
254 | 175 | { |
255 | | - case console_state::protocol_selection: |
256 | | - case console_state::address_input: |
257 | | - case console_state::msg_input: |
258 | | - std::cout << " >> " << std::endl; |
259 | | - break; |
260 | | - default: |
261 | | - break; |
| 176 | + // TODO |
262 | 177 | } |
263 | 178 | } |
264 | 179 |
|
265 | | - if (currentSession != nullptr) |
266 | | - delete currentSession; |
267 | | - |
268 | | - epoll_ctl(epollfd, EPOLL_CTL_DEL, this->breakEventFd, 0); |
269 | | - close(epollfd); |
270 | | - |
271 | 180 | return 0; |
272 | 181 | } |
273 | 182 | } |
0 commit comments