#include "rio.h"
#include "structs.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h> // for TCP_NODELAY
#include <iostream>
#include <thread>
#include <algorithm>
#include <cstring>
// #include "spdlog/fmt/bundled/ostream.h"
// #include "spdlog/fmt/fmt.h"
#include "spdlog/spdlog.h"
using namespace std;
void do_write(int clientfd);
void write_packet(int clientfd, int n, int extra_ints = 1, int sleep_ms = 20);
const int MAXBUF = 1024;
int main(int argc, char** argv) {
// SmallPacket packet = SmallPacket::new_packet();
// cout << sizeof(packet) << endl;
// cout << packet.to_string() << endl;
const char* host = "127.0.0.1";
int port = 5556;
if (argc > 1) {
host = argv[1];
}
if (argc > 2) {
port = atoi(argv[2]);
}
int clientfd = rio::open_clientfd(host, port);
if (clientfd < 0) {
spdlog::error("failed to connect host: {}:{}", host, port);
return -1;
}
int opt_val = 0;
int opt_len = sizeof(opt_val);
opt_val = 0;
// rio::Setsockopt(clientfd, IPPROTO_TCP, TCP_QUICKACK, &opt_val, opt_len);
// rio::Getsockopt(clientfd, IPPROTO_TCP, TCP_QUICKACK, &opt_val, opt_len);
// spdlog::info("TCP_QUICKACK: {}", opt_val);
// opt_val = 1;
// rio::Setsockopt(clientfd, SOL_SOCKET, SO_KEEPALIVE, &opt_val, opt_len);
// rio::Getsockopt(clientfd, SOL_SOCKET, SO_KEEPALIVE, &opt_val, opt_len);
// spdlog::info("SO_KEEPALIVE: {}", opt_val);
opt_val = 0;
rio::Setsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY, &opt_val, opt_len);
rio::Getsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY, &opt_val, opt_len);
spdlog::info("NODELAY: {}", opt_val);
write_packet(clientfd, 50, 1, 10);
close(clientfd);
return 0;
}
void write_packet(int clientfd, int n, int extra_ints, int sleep_ms) {
char buf[MAXBUF];
int content_bytes = sizeof(SmallPacket) + sizeof(int32_t) * extra_ints;
int total_bytes = sizeof(int32_t) + content_bytes;
spdlog::info("content_bytes: {}", content_bytes);
if (total_bytes > MAXBUF) {
throw std::invalid_argument("total_bytes exceed MAXBUF");
}
for (int i = 0; i < n; ++i) {
SmallPacket packet = SmallPacket::new_packet();
char* p_buf = buf;
memcpy(p_buf, &content_bytes, sizeof(content_bytes));
p_buf += sizeof(content_bytes);
memcpy(p_buf, &packet, sizeof(packet));
p_buf += sizeof(packet);
// fill with packet.seq
std::fill_n(reinterpret_cast<std::int32_t*>(p_buf), extra_ints, packet.seq);
int nwriten = rio::rio_writen(clientfd, buf, total_bytes);
dump_bytes(buf + sizeof(content_bytes), content_bytes);
if (nwriten != total_bytes) {
spdlog::error("failed to write, nwriten = {}", nwriten);
return;
}
spdlog::info("send: {}", packet.to_string());
// if (i % 3 == 0) {
// std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
usleep(sleep_ms * 1000);
// }
}
}