Skip to content

Commit 4223249

Browse files
committed
Implemented "init" methods on ClientSession classes.
Start of implementing MainConsole
1 parent 977ad27 commit 4223249

File tree

18 files changed

+655
-32
lines changed

18 files changed

+655
-32
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ add_executable(${PROJECT_NAME} client/main.cpp)
2929

3030
target_sources(${PROJECT_NAME} PRIVATE client/MainConsole.cpp client/MainConsole.hpp)
3131
target_sources(${PROJECT_NAME} PRIVATE client/SessionClient.cpp client/SessionClient.hpp)
32+
target_sources(${PROJECT_NAME} PRIVATE client/SessionTcp.cpp client/SessionTcp.hpp)
33+
target_sources(${PROJECT_NAME} PRIVATE client/SessionUdp.cpp client/SessionUdp.hpp)
3234

3335
target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDE_PATH})
3436
target_link_libraries(${PROJECT_NAME} simple_lib)

client/MainConsole.cpp

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
#include "MainConsole.hpp"
22

3+
#include <iostream>
4+
35
#include <sys/eventfd.h>
6+
#include <sys/epoll.h>
47

58
#include <errno.h>
69
#include <unistd.h>
710

11+
#include "SessionClient.hpp"
12+
#include "SessionTcp.hpp"
13+
#include "SessionUdp.hpp"
14+
#include "console_state.h"
15+
816
namespace simpleApp
917
{
1018
MainConsole::MainConsole()
@@ -39,8 +47,227 @@ namespace simpleApp
3947
return 0;
4048
}
4149

50+
void cleanStdin()
51+
{
52+
// TODO
53+
}
54+
55+
int getFromStdin(char* buffer)
56+
{
57+
// TODO
58+
return 0;
59+
}
60+
4261
int MainConsole::consoleLoop()
4362
{
63+
int epollfd = epoll_create1(0);
64+
65+
if (epollfd == -1)
66+
{
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);
78+
return -1;
79+
}
80+
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+
}
90+
91+
bool isExit = false;
92+
console_state currentState = console_state::protocol_selection;
93+
SessionClient* currentSession = nullptr;
94+
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;
97+
98+
while (!isExit)
99+
{
100+
const size_t eventsSize = 4;
101+
epoll_event events[eventsSize];
102+
103+
console_state nextState = console_state::none;
104+
105+
int len = epoll_wait(epollfd, events, eventsSize, -1);
106+
for(size_t i = 0; static_cast<int>(i) < len; i++)
107+
{
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();
130+
131+
break;
132+
}
133+
134+
// Non-console event and have session
135+
if (events[i].data.fd != STDIN_FILENO && currentSession != nullptr)
136+
{
137+
//cleanStdin();
138+
139+
switch (currentState)
140+
{
141+
case console_state::msg_input:
142+
/* code */
143+
break;
144+
145+
default:
146+
break;
147+
}
148+
// TODO
149+
}
150+
151+
// Console input
152+
if (events[i].data.fd == STDIN_FILENO)
153+
{
154+
char buffer[MESSAGE_MAX_BUFFER - sizeof(msg_headers)];
155+
auto len = getFromStdin(buffer);
156+
157+
if (len < 1)
158+
{
159+
cleanStdin();
160+
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+
}
180+
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+
default:
218+
break;
219+
}
220+
221+
cleanStdin();
222+
break;
223+
}
224+
}
225+
226+
// Switch state
227+
switch (nextState)
228+
{
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;
248+
}
249+
250+
if (nextState != console_state::none)
251+
currentState = nextState;
252+
253+
switch (currentState)
254+
{
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;
262+
}
263+
}
264+
265+
if (currentSession != nullptr)
266+
delete currentSession;
267+
268+
epoll_ctl(epollfd, EPOLL_CTL_DEL, this->breakEventFd, 0);
269+
close(epollfd);
270+
44271
return 0;
45272
}
46273
}

client/SessionClient.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22

33
#include <sys/socket.h>
44
#include <sys/epoll.h>
5+
#include <arpa/inet.h>
6+
7+
#include <strings.h>
58

69
#include <unistd.h>
710

11+
#include <simple_lib/common.h>
12+
813
namespace simpleApp
914
{
1015
SessionClient::SessionClient(int epollfd) : Session(epollfd)
@@ -16,4 +21,61 @@ namespace simpleApp
1621
{
1722

1823
}
24+
25+
in_addr_t SessionClient::toInetAddress(std::string addressLine)
26+
{
27+
return inet_addr(addressLine.c_str());
28+
}
29+
30+
session_result SessionClient::connectSocket(std::string address, int sockType)
31+
{
32+
auto convertedAddr = SessionClient::toInetAddress(address);
33+
if (convertedAddr == INADDR_NONE)
34+
{
35+
return session_result(session_status::init_not_address, errno);
36+
}
37+
38+
this->_socket = socket(AF_INET, sockType, 0);
39+
if (this->_socket == -1)
40+
{
41+
return session_result(session_status::init_socket_fail, errno);
42+
}
43+
44+
if (set_nonblock(this->_socket) == -1)
45+
{
46+
auto result = session_result(session_status::init_socket_fail, errno);
47+
close(this->_socket);
48+
this->_socket = -1;
49+
return result;
50+
}
51+
52+
sockaddr_in addrStruct;
53+
bzero(&addrStruct, sizeof(addrStruct));
54+
addrStruct.sin_addr.s_addr = convertedAddr;
55+
addrStruct.sin_port = htons(PUBLIC_PORT);
56+
addrStruct.sin_family = AF_INET;
57+
58+
if (connect(this->_socket, (sockaddr *)&addrStruct, sizeof(addrStruct)) == -1)
59+
{
60+
auto result = session_result(session_status::init_connection_fail, errno);
61+
close(this->_socket);
62+
this->_socket = -1;
63+
return result;
64+
}
65+
66+
epoll_event socketEvent;
67+
socketEvent.data.fd = this->_socket;
68+
socketEvent.events = EPOLLET | EPOLLIN;
69+
70+
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, this->_socket, &socketEvent) == -1)
71+
{
72+
auto result = session_result(session_status::init_epoll_add_fail, errno);
73+
shutdown(this->_socket, SHUT_RDWR);
74+
close(this->_socket);
75+
this->_socket = -1;
76+
return result;
77+
}
78+
79+
return session_result(session_status::init_success);
80+
}
1981
}

client/SessionClient.hpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
#pragma once
22

3+
#include <string>
4+
35
#include <simple_lib/common.h>
46
#include <simple_lib/Session.hpp>
57

8+
#include "session_result.h"
9+
10+
#include <netinet/in.h>
11+
612
namespace simpleApp
713
{
814
class SessionClient : public Session
915
{
1016
public:
1117
virtual ~SessionClient();
1218

13-
virtual int init() = 0;
14-
virtual int proceed(int fd) = 0;
19+
virtual session_result init(std::string address) = 0;
20+
virtual session_result proceed(int fd, char* sendMsg = nullptr, size_t msgSize = 0) = 0;
1521

1622
protected:
1723
SessionClient(int epollfd);
24+
25+
static in_addr_t toInetAddress(std::string addressLine);
26+
27+
session_result connectSocket(std::string address, int sockType);
1828
};
1929
}

0 commit comments

Comments
 (0)