Skip to content

viticm/plain

Repository files navigation

Plain

The plain framework, a framework based on c++ for net applictions.

Build Status

img

The core is SFE, that is the safe and fast and easy.

What's i can do:

  1. Safe

You can use it for safe soket connection, more safe interface protect your appliction.

  1. Fast

The very many useful interfaces let develop start become soon, just use default environment file run your appliction, also can get the high performance with multithreading.

  1. Easy

All interfaces use very easy and coupling light, You can start with a environment file. If you want some diffrent then can write owner plugins.


How to start with plain framework?

On Linux, use the command build and run, make sure installed g++ and cmake:

git clone --recursive https://github.com/viticm/plain && cd plain
cd cmake && cmake ./ && sudo make install

On windows(vs 2022+ can build with cmake directly).

Update all submodule.

git submodule update --remote --recursive

Customize your network.

#include "plain/all.h"

using namespace plain::net;

std::shared_ptr<Listener> listener;
std::shared_ptr<Connector> connector;

// The packet decode function.
// Return a packet shared pointer or error.
plain::error_or_t<std::shared_ptr<packet::Basic>>
line_decode(
  stream::Basic *input, const packet::limit_t &packet_limit) {
  using namespace plain;
  if (!input) return Error{ErrorCode::RunTime};
  bytes_t bytes;
  bytes.reserve(packet_limit.max_length);
  auto readed = input->peek(bytes.data(), bytes.capacity());
  if (readed == 0) return ErrorCode{ErrorCode::NetPacketNeedRecv};
  std::string_view str{reinterpret_cast<char *>(bytes.data()), readed};
  auto pos = str.find('\n');
  if (pos == std::string::npos) {
    if (readed == packet_limit.max_length )
      return Error{ErrorCode::RunTime};
    else
      return Error{ErrorCode::NetPacketNeedRecv};
  }
  input->remove(pos + 1); // remove readed line.
  if (pos > 0 && str[pos - 1] == '\r') {
    pos -= 1;
  }
  auto p = std::make_shared<packet::Basic>();
  if (pos > 0) {
    p->set_writeable(true);
    p->write(bytes.data(), pos);
    p->set_writeable(false);
  }
  p->set_readable(true);
  return p;
}

// The packet encode function.
// Return a byte string.
plain::bytes_t line_encode(std::shared_ptr<packet::Basic> packet) {
  auto d = packet->data();
  return {d.data(), d.size()};
}

bool start_listener() {

  setting_t setting;
  setting.max_count = 512; // The connection max count
  setting.default_count = 32; // The connection object default created
  // The mode can be: select/epoll/iocp/iouring/kqueue
  // select is default mode(all platform can be supported).
  // epoll just active on linux.
  // iocp just active on windows.
  // iouring just active on linux kernel 5.0+.
  // kqueue just active on macos.
  setting.mode = Mode::Select; 
  setting.socket_type = socket::Type::Tcp; // Tcp/Udp
  setting.address = ":2001"; // Just active with Listener(empty system divide a port)
  setting.name = "listener"; // Empty kernel will divide a unknown name
  // The max packet id(if you custom packet handler this need check by yourself)
  setting.packet_limit.max_id = 65535;
  // The max packet length
  // (if you custom packet handler this need check by yourself)
  setting.packet_limit.max_length = 200 * 1024;

  // The executor for execute net handlers(send/recv/packet)
  // * default: WorkerThread(one thread)
  // * also can use: Inline/Manual/Thread/ThreadPool
  // *! executor module implement by concurrencpp
  auto executor = std::make_shared<plain::concurrency::executor::WorkerThread>();

  listener = std::make_shared<Listener>(setting, executor);

  // The codec handlers.
  listener->set_codec({.encode = line_encode, .decode = line_decode});

  // Set the packet dispachter.
  listener->set_dispatcher([](
    connection::Basic *conn, std::shared_ptr<packet::Basic> packet) {
    std::cout << conn->name() << ": " <<
      reinterpret_cast<const char *>(packet->data().data()) << std::endl;
    return true;
  });

  // Set the callback on connected.
  listener->set_connect_callback([](connection::Basic *conn) {
    std::cout << conn->name() << " connected" << std::endl;
  });

  // Set the callback on disconnected.
  listener->set_disconnect_callback([](connection::Basic *conn) {
    std::cout << conn->name() << " disconnected" << std::endl;
  });

  return listener->start();
}

void start_connector() {
  
  // The connector setting same as listener(but not active with address).
  // Also it can be set executor with construct.

  connector = std::make_shared<Connector>(); // Using default setting.
  connector->set_codec({.encode = line_encode, .decode = line_decode});
  connector->set_dispatcher([](
    connection::Basic *conn, std::shared_ptr<packet::Basic> packet) {
    std::cout << conn->name() << ": " <<
      reinterpret_cast<const char *>(packet->data().data()) << std::endl;
    return true;
  });

  connector->set_connect_callback([](connection::Basic *conn) {
    std::cout << conn->name() << " connected" << std::endl;
  });

  connector->set_disconnect_callback([](connection::Basic *conn) {
    std::cout << conn->name() << " disconnected" << std::endl;
  });

  if (!connector->start()) return;

  auto pack = std::make_shared<packet::Basic>();
  pack->set_writeable(true);
  std::string line{"hello world\n"};
  pack->write(reinterpret_cast<std::byte *>(line.data()), line.size());
  std::string line1{"plain\n"};
  pack->write(reinterpret_cast<std::byte *>(line1.data()), line1.size());
  auto conn = connector->connect(":2001");
  
  if (static_cast<bool>(conn)) {
    conn->send(pack);
  }
}

int32_t main(int32_t argc, char **argv) {
  using namespace std::chrono_literals;
  
  // Start console, param empty then listen a random port.
  if (!ENGINE->enable_console(":3001"))
    return 1;
  if (!start_listener())
    return 1;
  start_connector();

  // Wait exit.
  while (listener->running()) {
    std::this_thread::sleep_for(100ms);
  }
  return 0;
}

Simple project.

Many developers will confused use this framework, this project will tech you quick start.

The project url:

https://github.com/viticm/plain-simple

About

New plain framework, a socket framework use any applictions.

Resources

License

Stars

Watchers

Forks

Packages

No packages published