18 #ifndef ORDER_ENTRY_CONNECTION_HPP
19 #define ORDER_ENTRY_CONNECTION_HPP
26 #include "exceptions.hpp"
27 #include "limit_order_book/limit_order_book.hpp"
28 #include "messages.hpp"
29 #include "authorizer.hpp"
30 #include "system_account.hpp"
38 class Connection :
public std::enable_shared_from_this<Connection> {
53 uint32_t output_buffer_size = 0;
57 asio::steady_timer timer;
66 asio::io_context& context,
69 ) : socket(context), authorizer(authorizer_), book(book_), timer(context) { }
74 if (account ==
nullptr)
return;
84 inline void write_buffer() {
88 [
this](
const std::error_code& error, std::size_t) {
90 std::cout <<
"OrderEntry::Connection::write_buffer - " << error << std::endl;
94 output_buffer.pop_front();
96 if (--output_buffer_size) write_buffer();
107 template <
class T,
typename ...Args>
108 inline void send(Args && ...args) {
110 output_buffer.emplace_back();
112 new (&output_buffer.back()) T{sequence++, std::forward<Args>(args)...};
115 if (++output_buffer_size == 1) write_buffer();
120 auto self(shared_from_this());
121 input_buffer.emplace_back();
125 [
this,
self](
const std::error_code& error, std::size_t) {
127 if (error == asio::error::eof) {
133 throw Exception(
"Server::read_buffer - " + error.message());
137 input_buffer.pop_front();
141 switch (
reinterpret_cast<Messages::Header&
>(message).uid) {
142 case Messages::MessageID::LoginRequest: { handle(
reinterpret_cast<Messages::LoginRequest&
>(message));
break; }
143 case Messages::MessageID::LogoutRequest: { handle(
reinterpret_cast<Messages::LogoutRequest&
>(message));
break; }
144 case Messages::MessageID::OrderRequest: { handle(
reinterpret_cast<Messages::OrderRequest&
>(message));
break; }
145 case Messages::MessageID::CancelRequest: { handle(
reinterpret_cast<Messages::CancelRequest&
>(message));
break; }
146 case Messages::MessageID::ReplaceRequest: { handle(
reinterpret_cast<Messages::ReplaceRequest&
>(message));
break; }
147 case Messages::MessageID::PurgeRequest: { handle(
reinterpret_cast<Messages::PurgeRequest&
>(message));
break; }
148 default: { handle(
reinterpret_cast<Messages::Header&
>(message));
break; }
158 void handle(
const Messages::LoginRequest& request) {
160 auto username = request.username_string();
161 auto password = request.password_string();
162 if (is_logged_in()) {
164 send<Messages::LoginResponse>(Messages::LoginResponseStatus::AlreadyAuthorized);
165 }
else if (not authorizer.is_valid(username, password)) {
167 send<Messages::LoginResponse>(Messages::LoginResponseStatus::NotAuthorized);
168 }
else if (authorizer.get_account(username)->is_connected) {
170 send<Messages::LoginResponse>(Messages::LoginResponseStatus::SessionInUse);
173 account = authorizer.get_account(username);
177 account->handler =
this;
180 account->is_connected =
true;
182 send<Messages::LoginResponse>(Messages::LoginResponseStatus::Accepted);
190 void handle(
const Messages::LogoutRequest& request) {
192 if (not is_logged_in()) {
193 send<Messages::LogoutResponse>(Messages::LogoutReason::ProtocolViolation);
198 send<Messages::LogoutResponse>(Messages::LogoutReason::UserRequested);
205 void handle(
const Messages::OrderRequest& request) {
206 if (not is_logged_in()) {
207 send<Messages::OrderResponse>(Messages::ORDER_ID_REJECTED, Messages::OrderStatus::Rejected);
211 if (request.price == Messages::ORDER_PRICE_MARKET) {
213 send<Messages::OrderResponse>(Messages::ORDER_ID_MARKET, Messages::OrderStatus::Accepted);
215 auto uid = book.limit(account,
side_to_LOB_side(request.side), request.quantity, request.price);
216 send<Messages::OrderResponse>(uid, Messages::OrderStatus::Accepted);
224 void handle(
const Messages::CancelRequest& request) {
226 if (not is_logged_in()) {
227 send<Messages::CancelResponse>(request.order_id, Messages::CancelStatus::Rejected);
231 if (not book.has(request.order_id)) {
232 send<Messages::CancelResponse>(request.order_id, Messages::CancelStatus::Rejected);
236 if (
static_cast<SystemAccount<Connection>*
>(book.get(request.order_id).account)->username.compare(account->username) != 0) {
237 send<Messages::CancelResponse>(request.order_id, Messages::CancelStatus::Rejected);
241 book.cancel(request.order_id);
242 send<Messages::CancelResponse>(request.order_id, Messages::CancelStatus::Accepted);
249 void handle(
const Messages::ReplaceRequest& request) {
251 if (not is_logged_in()) {
252 send<Messages::ReplaceResponse>(request.order_id, Messages::ORDER_ID_REJECTED, Messages::ReplaceStatus::Rejected);
256 OrderID canceled = Messages::ORDER_ID_REJECTED;
257 if (book.has(request.order_id)) {
259 if (
static_cast<SystemAccount<Connection>*
>(book.get(request.order_id).account)->username.compare(account->username) != 0) {
260 send<Messages::ReplaceResponse>(request.order_id, Messages::ORDER_ID_REJECTED, Messages::ReplaceStatus::Rejected);
264 book.cancel(request.order_id);
265 canceled = request.order_id;
268 OrderID uid = Messages::ORDER_ID_REJECTED;
269 switch (request.side) {
271 uid = book.limit_sell(account, request.quantity, request.price);
275 uid = book.limit_buy(account, request.quantity, request.price);
280 send<Messages::ReplaceResponse>(canceled, uid, Messages::ReplaceStatus::Accepted);
287 void handle(
const Messages::PurgeRequest& request) {
289 if (not is_logged_in()) {
290 send<Messages::PurgeResponse>(Messages::PurgeStatus::Rejected);
297 while (account->orders.size()) {
298 book.cancel((*account->orders.begin())->uid);
301 send<Messages::PurgeResponse>(Messages::PurgeStatus::Accepted);
308 void handle(
const Messages::Header& header) {
309 std::cout <<
"OrderEntry::Connection::handle(Header) - " << header << std::endl;
312 send<Messages::LogoutResponse>(Messages::LogoutReason::ProtocolViolation);
327 asio::io_context& context,
357 inline void start() { read_buffer(); }
373 ) { send<Messages::TradeResponse>(order_id, price, size, leaves_size, side); }
378 #endif // ORDER_ENTRY_CONNECTION_HPP