|
|
nono 0.1.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
#include "header.h"
#include "config.h"
#include "console.h"
#include <netdb.h>
#include <sys/socket.h>
//
// TCP コンソール
//
// コンストラクタ
ConsoleTCP::ConsoleTCP()
{
ls = -1;
sock = -1;
// editline は使えないようだ...
//use_editline = true;
}
// デストラクタ
ConsoleTCP::~ConsoleTCP()
{
if (res) {
freeaddrinfo(res);
res = NULL;
}
if (sock != -1) {
close(sock);
sock = -1;
}
if (ls != -1) {
close(ls);
ls = -1;
}
}
// 初期化
bool
ConsoleTCP::Init()
{
struct addrinfo hints;
int r;
int on = 1;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
const char *host = "::1";
const ConfigItem& item = gConfig->Find("debugger-port");
const std::string& port = item.AsString();
int portnum = atoi(port.c_str());
if (portnum < 0 || portnum > 65535) {
item.Err();
return false;
}
// 0 なら待ち受けしない
if (portnum == 0) {
return false;
}
r = getaddrinfo(host, port.c_str(), &hints, &res);
if (r != 0) {
const char *errmsg;
if (r == EAI_SYSTEM) {
errmsg = strerror(errno);
} else {
errmsg = gai_strerror(r);
}
warnx("getaddrinfo: %s: %s", host, errmsg);
return false;
}
if (res == NULL) {
warnx("getaddrinfo: %s: no address found", host);
return false;
}
// res を順番に試して成功したらそれで待ち受ける
ls = -1;
for (ai = res; ai && ls == -1; ai = ai->ai_next) {
ls = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (ls == -1) {
warn("socket");
continue;
}
if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) {
warn("setsockopt(SO_REUSEADDR)");
close(ls);
continue;
}
if (setsockopt(ls, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) {
warn("setsockopt(SO_REUSEPORT)");
close(ls);
continue;
}
if (bind(ls, ai->ai_addr, ai->ai_addrlen) == -1) {
warn("bind");
close(ls);
continue;
}
if (listen(ls, 0) == -1) {
warn("listen");
close(ls);
continue;
}
// ここまで来たら成功
break;
}
if (ls == -1) {
return false;
}
return true;
}
// 受け付ける
bool
ConsoleTCP::Accept()
{
for (;;) {
sock = accept(ls, ai->ai_addr, &ai->ai_addrlen);
if (sock == -1) {
if (errno == EINTR) {
continue;
}
warn("accept");
return false;
}
break;
}
inp.fd = dup(sock);
out.fd = dup(sock);
FDOpen();
// editline(3) を使う場合、出力側がフルバッファリングだと内部バッファが
// 一杯になったか何かのタイミングでしか出力されなくなるので、少なくとも
// 行バッファリングにはしないといけない。
setlinebuf(out.file);
// バッファリングなしにしてもプロンプトは表示されない...
//setvbuf(out.file, NULL, _IONBF, 0);
return true;
}
void
ConsoleTCP::Close()
{
inherited::Close();
if (sock != -1) {
close(sock);
sock = -1;
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.