More work on client and server
This commit is contained in:
@@ -7,20 +7,20 @@
|
||||
#include "printbuffer.hpp"
|
||||
#include <memory>
|
||||
|
||||
class ServerClient {
|
||||
class Client {
|
||||
public:
|
||||
int64_t actor_id_;
|
||||
UniqueChannel channel_;
|
||||
UniqueWorld sync_;
|
||||
};
|
||||
using UniqueServerClient = std::unique_ptr<ServerClient>;
|
||||
using ServerClientVector = std::vector<UniqueServerClient>;
|
||||
using UniqueClient = std::unique_ptr<Client>;
|
||||
using ClientVector = std::vector<UniqueClient>;
|
||||
|
||||
class LpxServer : public DrivenEngine {
|
||||
public:
|
||||
UniqueWorld master_;
|
||||
LuaConsole console_;
|
||||
ServerClientVector clients_;
|
||||
ClientVector clients_;
|
||||
PrintChanneler print_channeler_;
|
||||
int64_t admin_id_;
|
||||
|
||||
@@ -79,10 +79,53 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_invocation(ServerClient *sclient) {
|
||||
return false;
|
||||
void delete_client(UniqueClient &client) {
|
||||
stdostream() << "Client closed: actor id=" << client->actor_id_ << std::endl;
|
||||
client.reset();
|
||||
}
|
||||
|
||||
void send_diffs(UniqueClient &client) {
|
||||
StreamBuffer *sb = client->channel_->out();
|
||||
sb->write_uint8(util::MSG_DIFF);
|
||||
sb->write_uint32(0);
|
||||
int64_t tw_1 = sb->total_writes();
|
||||
stdostream() << "Sending diffs to client " << client->actor_id_ << std::endl;
|
||||
client->sync_->diff_everything(client->actor_id_, master_.get(), sb);
|
||||
int64_t tw_2 = sb->total_writes();
|
||||
sb->overwrite_int32(tw_1, tw_2 - tw_1);
|
||||
}
|
||||
|
||||
bool handle_invocation(UniqueClient &client) {
|
||||
StreamBuffer *sb = client->channel_->in();
|
||||
int64_t tr_before = sb->total_reads();
|
||||
Invocation inv;
|
||||
try {
|
||||
uint8_t msg_type = sb->read_uint8();
|
||||
if (msg_type != util::MSG_INVOKE) {
|
||||
delete_client(client);
|
||||
return false;
|
||||
}
|
||||
inv.deserialize(sb);
|
||||
} catch (const StreamEof &seof) {
|
||||
sb->unread_to(tr_before);
|
||||
return false;
|
||||
} catch (const StreamCorruption &scorr) {
|
||||
delete_client(client);
|
||||
return false;
|
||||
}
|
||||
if (inv.actor() != client->actor_id_) {
|
||||
stdostream() << "Ignoring invoke with wrong actor ID " << inv.actor() << std::endl;
|
||||
return true;
|
||||
}
|
||||
stdostream() << "Invoking: " << inv.debug_string() << std::endl;
|
||||
master_->invoke(inv);
|
||||
client->channel_->out()->write_uint8(util::MSG_ACK);
|
||||
client->channel_->out()->write_uint32(0);
|
||||
client->sync_->invoke(inv);
|
||||
send_diffs(client);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void event_update() {
|
||||
// Check for keyboard input on stdin.
|
||||
while (true) {
|
||||
@@ -102,28 +145,27 @@ public:
|
||||
while (true) {
|
||||
UniqueChannel chan = new_incoming_channel();
|
||||
if (chan == nullptr) break;
|
||||
ServerClient *client = new ServerClient;
|
||||
Client *client = new Client;
|
||||
client->actor_id_ = master_->create_login_actor();
|
||||
client->channel_ = std::move(chan);
|
||||
client->sync_.reset(new World(util::WORLD_TYPE_S_SYNC));
|
||||
client->sync_->create_login_actor();
|
||||
clients_.emplace_back(client);
|
||||
stdostream() << "New client: actor id=" << client->actor_id_ << std::endl;
|
||||
send_diffs(clients_.back());
|
||||
}
|
||||
|
||||
// Traverse all existing channels, process any communication.
|
||||
ServerClientVector keep;
|
||||
for (UniqueServerClient &client : clients_) {
|
||||
for (UniqueClient &client : clients_) {
|
||||
if (client->channel_->closed()) {
|
||||
stdostream() << "Client closed: actor id=" << client->actor_id_ << std::endl;
|
||||
delete_client(client);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for received invocations.
|
||||
while (handle_invocation(client.get()));
|
||||
// Transfer the client to the keep vector.
|
||||
keep.emplace_back(std::move(client));
|
||||
while (handle_invocation(client));
|
||||
}
|
||||
clients_ = std::move(keep);
|
||||
util::remove_nullptrs(clients_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user