summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/admin/ladmin.cpp2
-rw-r--r--src/char/char.cpp25
-rw-r--r--src/common/core.cpp2
-rw-r--r--src/common/iter.hpp97
-rw-r--r--src/common/iter_test.cpp82
-rw-r--r--src/common/socket.cpp181
-rw-r--r--src/common/socket.hpp30
-rw-r--r--src/common/utils2.hpp53
-rw-r--r--src/io/fd.cpp164
-rw-r--r--src/io/fd.hpp159
-rw-r--r--src/io/line.cpp6
-rw-r--r--src/io/line.hpp5
-rw-r--r--src/io/line_test.cpp20
-rw-r--r--src/io/lock.cpp41
-rw-r--r--src/io/read.cpp18
-rw-r--r--src/io/read.hpp5
-rw-r--r--src/io/read_test.cpp20
-rw-r--r--src/io/write.cpp36
-rw-r--r--src/io/write.hpp6
-rw-r--r--src/io/write_test.cpp19
-rw-r--r--src/map/atcommand.cpp82
-rw-r--r--src/map/chrif.cpp25
-rw-r--r--src/map/clif.cpp33
-rw-r--r--src/map/intif.cpp4
-rw-r--r--src/map/map.cpp43
-rw-r--r--src/map/mob.cpp7
-rw-r--r--src/map/party.cpp14
-rw-r--r--src/map/pc.cpp4
-rw-r--r--src/map/script.cpp14
-rw-r--r--src/monitor/main.cpp21
30 files changed, 851 insertions, 367 deletions
diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp
index 6b49f35..2c9382c 100644
--- a/src/admin/ladmin.cpp
+++ b/src/admin/ladmin.cpp
@@ -1778,7 +1778,7 @@ void prompt(void)
// get command and parameter
// TODO figure out a better way to do stdio
- static auto cin = make_unique<io::ReadFile>(dup(0));
+ static auto cin = make_unique<io::ReadFile>(io::FD::stdin().dup());
FString buf;
cin->getline(buf);
diff --git a/src/char/char.cpp b/src/char/char.cpp
index f98fc4b..fe9bf9a 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -1046,16 +1046,16 @@ static
int disconnect_player(int accound_id)
{
// disconnect player if online on char-server
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ if (!get_session(i))
continue;
- struct char_session_data *sd = static_cast<char_session_data *>(session[i]->session_data.get());
+ struct char_session_data *sd = static_cast<char_session_data *>(get_session(i)->session_data.get());
if (sd)
{
if (sd->account_id == accound_id)
{
- session[i]->eof = 1;
+ get_session(i)->eof = 1;
return 1;
}
}
@@ -1142,9 +1142,9 @@ void parse_tologin(Session *ls)
if (RFIFOREST(ls) < 51)
return;
// PRINTF("parse_tologin 2713 : %d\n", RFIFOB(fd,6));
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
sd = static_cast<char_session_data *>(s2->session_data.get());
@@ -1188,9 +1188,9 @@ void parse_tologin(Session *ls)
case 0x2717:
if (RFIFOREST(ls) < 50)
return;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
sd = static_cast<char_session_data *>(s2->session_data.get());
@@ -1464,13 +1464,12 @@ void parse_tologin(Session *ls)
if (RFIFOREST(ls) < 7)
return;
{
- int acc, status, i;
- acc = RFIFOL(ls, 2);
- status = RFIFOB(ls, 6);
+ int acc = RFIFOL(ls, 2);
+ int status = RFIFOB(ls, 6);
- for (i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
sd = static_cast<char_session_data *>(s2->session_data.get());
diff --git a/src/common/core.cpp b/src/common/core.cpp
index fe2f660..d57e970 100644
--- a/src/common/core.cpp
+++ b/src/common/core.cpp
@@ -78,8 +78,6 @@ void sig_proc(int)
*/
int main(int argc, char **argv)
{
- do_socket();
-
// ZString args[argc]; is (deliberately!) not supported by clang yet
ZString *args = static_cast<ZString *>(alloca(argc * sizeof(ZString)));
for (int i = 0; i < argc; ++i)
diff --git a/src/common/iter.hpp b/src/common/iter.hpp
new file mode 100644
index 0000000..5b39588
--- /dev/null
+++ b/src/common/iter.hpp
@@ -0,0 +1,97 @@
+#ifndef TMWA_COMMON_ITER_HPP
+#define TMWA_COMMON_ITER_HPP
+// iter.hpp - tools for dealing with iterators
+//
+// Copyright © 2012-2014 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# include "../sanity.hpp"
+
+# include <iterator>
+
+
+/// Simple class to use a pair of iterators with foreach
+template<class It>
+class IteratorPair
+{
+ It _b, _e;
+public:
+ IteratorPair(It b, It e)
+ : _b(b), _e(e)
+ {}
+
+ It begin() { return _b; }
+ It end() { return _e; }
+};
+
+template<class It>
+IteratorPair<It> iterator_pair(It b, It e)
+{
+ return {b, e};
+}
+
+template<class T>
+class PassthroughMath
+{
+public:
+ static
+ T inced(T v) { return ++v; }
+};
+
+// An iterator that just directly contains an integer-like value
+// TODO port this once the new integer API happens
+template<class T, class Math=PassthroughMath<T>>
+class ValueIterator
+{
+ T value;
+public:
+ typedef std::forward_iterator_tag iterator_category;
+ typedef void difference_type;
+ typedef T value_type;
+ typedef void reference;
+ typedef void pointer;
+public:
+ ValueIterator(T v)
+ : value(v)
+ {}
+
+ T operator *()
+ {
+ return value;
+ }
+ ValueIterator& operator++ ()
+ {
+ value = Math::inced(value);
+ return *this;
+ }
+ friend bool operator == (ValueIterator l, ValueIterator r)
+ {
+ return l.value == r.value;
+ }
+ friend bool operator != (ValueIterator l, ValueIterator r)
+ {
+ return !(l == r);
+ }
+};
+
+template<class T>
+IteratorPair<ValueIterator<T>> value_range(T b, T e)
+{
+ return {b, e};
+}
+
+#endif // TMWA_COMMON_ITER_HPP
diff --git a/src/common/iter_test.cpp b/src/common/iter_test.cpp
new file mode 100644
index 0000000..647ebf9
--- /dev/null
+++ b/src/common/iter_test.cpp
@@ -0,0 +1,82 @@
+#include "iter.hpp"
+
+#include <gtest/gtest.h>
+
+#include "../strings/xstring.hpp"
+
+TEST(iterpair, string)
+{
+ IteratorPair<ValueIterator<char>> pair = value_range('0', ':');
+ const char *str = "0123456789";
+ EXPECT_TRUE(std::equal(pair.begin(), pair.end(), str));
+}
+
+TEST(iterpair, signed8)
+{
+ IteratorPair<ValueIterator<int8_t>> pair = value_range(int8_t(-128), int8_t(127));
+ int8_t arr[255] =
+ {
+ -128, -127, -126, -125, -124, -123, -122, -121, -120,
+ -119, -118, -117, -116, -115, -114, -113, -112, -111, -110,
+ -109, -108, -107, -106, -105, -104, -103, -102, -101, -100,
+ -99, -98, -97, -96, -95, -94, -93, -92, -91, -90,
+ -89, -88, -87, -86, -85, -84, -83, -82, -81, -80,
+ -79, -78, -77, -76, -75, -74, -73, -72, -71, -70,
+ -69, -68, -67, -66, -65, -64, -63, -62, -61, -60,
+ -59, -58, -57, -56, -55, -54, -53, -52, -51, -50,
+ -49, -48, -47, -46, -45, -44, -43, -42, -41, -40,
+ -39, -38, -37, -36, -35, -34, -33, -32, -31, -30,
+ -29, -28, -27, -26, -25, -24, -23, -22, -21, -20,
+ -19, -18, -17, -16, -15, -14, -13, -12, -11, -10,
+ -9, -8, -7, -6, -5, -4, -3, -2, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126,
+ };
+ EXPECT_TRUE(std::equal(pair.begin(), pair.end(), arr + 0));
+}
+
+TEST(iterpair, unsigned8)
+{
+ IteratorPair<ValueIterator<uint8_t>> pair = value_range(uint8_t(0), uint8_t(255));
+ uint8_t arr[255] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+ 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+ 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+ 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+ 250, 251, 252, 253, 254,
+ };
+ EXPECT_TRUE(std::equal(pair.begin(), pair.end(), arr));
+}
diff --git a/src/common/socket.cpp b/src/common/socket.cpp
index 1c5bcbc..b5f6379 100644
--- a/src/common/socket.cpp
+++ b/src/common/socket.cpp
@@ -19,7 +19,8 @@
#include "../poison.hpp"
static
-fd_set readfds;
+io::FD_Set readfds;
+static
int fd_max;
static
@@ -29,9 +30,35 @@ const uint32_t WFIFO_SIZE = 65536;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
+static
std::array<std::unique_ptr<Session>, FD_SETSIZE> session;
#pragma GCC diagnostic pop
+void set_session(io::FD fd, std::unique_ptr<Session> sess)
+{
+ int f = fd.uncast_dammit();
+ assert (0 <= f && f < FD_SETSIZE);
+ session[f] = std::move(sess);
+}
+Session *get_session(io::FD fd)
+{
+ int f = fd.uncast_dammit();
+ if (0 <= f && f < FD_SETSIZE)
+ return session[f].get();
+ return nullptr;
+}
+void reset_session(io::FD fd)
+{
+ int f = fd.uncast_dammit();
+ assert (0 <= f && f < FD_SETSIZE);
+ session[f] = nullptr;
+}
+int get_fd_max() { return fd_max; }
+IteratorPair<ValueIterator<io::FD, IncrFD>> iter_fds()
+{
+ return {io::FD::cast_dammit(0), io::FD::cast_dammit(fd_max)};
+}
+
/// clean up by discarding handled bytes
inline
void RFIFOFLUSH(Session *s)
@@ -68,7 +95,7 @@ void recv_to_fifo(Session *s)
if (s->eof)
return;
- ssize_t len = read(s->fd, &s->rdata[s->rdata_size],
+ ssize_t len = s->fd.read(&s->rdata[s->rdata_size],
RFIFOSPACE(s));
if (len > 0)
@@ -88,7 +115,7 @@ void send_from_fifo(Session *s)
if (s->eof)
return;
- ssize_t len = write(s->fd, &s->wdata[0], s->wdata_size);
+ ssize_t len = s->fd.write(&s->wdata[0], s->wdata_size);
if (len > 0)
{
@@ -120,53 +147,50 @@ void connect_client(Session *ls)
struct sockaddr_in client_address;
socklen_t len = sizeof(client_address);
- int fd = accept(ls->fd, reinterpret_cast<struct sockaddr *>(&client_address), &len);
- if (fd == -1)
+ io::FD fd = ls->fd.accept(reinterpret_cast<struct sockaddr *>(&client_address), &len);
+ if (fd == io::FD())
{
perror("accept");
return;
}
- if (fd >= SOFT_LIMIT)
+ if (fd.uncast_dammit() >= SOFT_LIMIT)
{
- FPRINTF(stderr, "softlimit reached, disconnecting : %d\n", fd);
- shutdown(fd, SHUT_RDWR);
- close(fd);
+ FPRINTF(stderr, "softlimit reached, disconnecting : %d\n", fd.uncast_dammit());
+ fd.shutdown(SHUT_RDWR);
+ fd.close();
return;
}
- if (fd_max <= fd)
+ if (fd_max <= fd.uncast_dammit())
{
- fd_max = fd + 1;
+ fd_max = fd.uncast_dammit() + 1;
}
const int yes = 1;
/// Allow to bind() again after the server restarts.
// Since the socket is still in the TIME_WAIT, there's a possibility
// that formerly lost packets might be delivered and confuse the server.
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
+ fd.setsockopt(SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
/// Send packets as soon as possible
/// even if the kernel thinks there is too little for it to be worth it!
/// Testing shows this is indeed a good idea.
- setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
+ fd.setsockopt(IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
// Linux-ism: Set socket options to optimize for thin streams
// See http://lwn.net/Articles/308919/ and
// Documentation/networking/tcp-thin.txt .. Kernel 3.2+
#ifdef TCP_THIN_LINEAR_TIMEOUTS
- setsockopt(fd, IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS, &yes, sizeof yes);
+ fd.setsockopt(IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS, &yes, sizeof yes);
#endif
#ifdef TCP_THIN_DUPACK
- setsockopt(fd, IPPROTO_TCP, TCP_THIN_DUPACK, &yes, sizeof yes);
+ fd.setsockopt(IPPROTO_TCP, TCP_THIN_DUPACK, &yes, sizeof yes);
#endif
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
- FD_SET(fd, &readfds);
-#pragma GCC diagnostic pop
+ readfds.set(fd);
- fcntl(fd, F_SETFL, O_NONBLOCK);
+ fd.fcntl(F_SETFL, O_NONBLOCK);
- session[fd] = make_unique<Session>();
- Session *s = session[fd].get();
+ set_session(fd, make_unique<Session>());
+ Session *s = get_session(fd);
s->fd = fd;
s->rdata.new_(RFIFO_SIZE);
s->wdata.new_(WFIFO_SIZE);
@@ -184,27 +208,27 @@ void connect_client(Session *ls)
Session *make_listen_port(uint16_t port)
{
struct sockaddr_in server_address;
- int fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd == -1)
+ io::FD fd = io::FD::socket(AF_INET, SOCK_STREAM, 0);
+ if (fd == io::FD())
{
perror("socket");
return nullptr;
}
- if (fd_max <= fd)
- fd_max = fd + 1;
+ if (fd_max <= fd.uncast_dammit())
+ fd_max = fd.uncast_dammit() + 1;
- fcntl(fd, F_SETFL, O_NONBLOCK);
+ fd.fcntl(F_SETFL, O_NONBLOCK);
const int yes = 1;
/// Allow to bind() again after the server restarts.
// Since the socket is still in the TIME_WAIT, there's a possibility
// that formerly lost packets might be delivered and confuse the server.
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
+ fd.setsockopt(SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
/// Send packets as soon as possible
/// even if the kernel thinks there is too little for it to be worth it!
// I'm not convinced this is a good idea; although in minimizes the
// latency for an individual write, it increases traffic in general.
- setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
+ fd.setsockopt(IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
server_address.sin_family = AF_INET;
#pragma GCC diagnostic push
@@ -216,25 +240,22 @@ Session *make_listen_port(uint16_t port)
server_address.sin_port = htons(port);
#pragma GCC diagnostic pop
- if (bind(fd, reinterpret_cast<struct sockaddr *>(&server_address),
+ if (fd.bind(reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(server_address)) == -1)
{
perror("bind");
exit(1);
}
- if (listen(fd, 5) == -1)
+ if (fd.listen(5) == -1)
{ /* error */
perror("listen");
exit(1);
}
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
- FD_SET(fd, &readfds);
-#pragma GCC diagnostic pop
+ readfds.set(fd);
- session[fd] = make_unique<Session>();
- Session *s = session[fd].get();
+ set_session(fd, make_unique<Session>());
+ Session *s = get_session(fd);
s->fd = fd;
s->func_recv = connect_client;
@@ -247,25 +268,25 @@ Session *make_listen_port(uint16_t port)
Session *make_connection(IP4Address ip, uint16_t port)
{
struct sockaddr_in server_address;
- int fd = socket(AF_INET, SOCK_STREAM, 0);
- if (fd == -1)
+ io::FD fd = io::FD::socket(AF_INET, SOCK_STREAM, 0);
+ if (fd == io::FD())
{
perror("socket");
return nullptr;
}
- if (fd_max <= fd)
- fd_max = fd + 1;
+ if (fd_max <= fd.uncast_dammit())
+ fd_max = fd.uncast_dammit() + 1;
const int yes = 1;
/// Allow to bind() again after the server restarts.
// Since the socket is still in the TIME_WAIT, there's a possibility
// that formerly lost packets might be delivered and confuse the server.
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
+ fd.setsockopt(SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
/// Send packets as soon as possible
/// even if the kernel thinks there is too little for it to be worth it!
// I'm not convinced this is a good idea; although in minimizes the
// latency for an individual write, it increases traffic in general.
- setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
+ fd.setsockopt(IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes);
server_address.sin_family = AF_INET;
server_address.sin_addr = in_addr(ip);
@@ -277,20 +298,17 @@ Session *make_connection(IP4Address ip, uint16_t port)
server_address.sin_port = htons(port);
#pragma GCC diagnostic pop
- fcntl(fd, F_SETFL, O_NONBLOCK);
+ fd.fcntl(F_SETFL, O_NONBLOCK);
/// Errors not caught - we must not block
/// Let the main select() loop detect when we know the state
- connect(fd, reinterpret_cast<struct sockaddr *>(&server_address),
+ fd.connect(reinterpret_cast<struct sockaddr *>(&server_address),
sizeof(struct sockaddr_in));
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
- FD_SET(fd, &readfds);
-#pragma GCC diagnostic pop
+ readfds.set(fd);
- session[fd] = make_unique<Session>();
- Session *s = session[fd].get();
+ set_session(fd, make_unique<Session>());
+ Session *s = get_session(fd);
s->fd = fd;
s->rdata.new_(RFIFO_SIZE);
s->wdata.new_(WFIFO_SIZE);
@@ -311,26 +329,23 @@ void delete_session(Session *s)
if (!s)
return;
- int fd = s->fd;
+ io::FD fd = s->fd;
// If this was the highest fd, decrease it
// We could add a loop to decrement fd_max further for every null session,
// but this is cheap and good enough for the typical case
- if (fd == fd_max - 1)
+ if (fd.uncast_dammit() == fd_max - 1)
fd_max--;
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
- FD_CLR(fd, &readfds);
-#pragma GCC diagnostic pop
+ readfds.clr(fd);
{
s->rdata.delete_();
s->wdata.delete_();
s->session_data.reset();
- session[fd].reset();
+ reset_session(fd);
}
// just close() would try to keep sending buffers
- shutdown(fd, SHUT_RDWR);
- close(fd);
+ fd.shutdown(SHUT_RDWR);
+ fd.close();
}
void realloc_fifo(Session *s, size_t rfifo_size, size_t wfifo_size)
@@ -362,18 +377,12 @@ void WFIFOSET(Session *s, size_t len)
void do_sendrecv(interval_t next_ms)
{
- fd_set rfd = readfds, wfd;
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
- FD_ZERO(&wfd);
-#pragma GCC diagnostic pop
- for (int i = 0; i < fd_max; i++)
+ io::FD_Set rfd = readfds, wfd;
+ for (io::FD i : iter_fds())
{
- if (session[i] && session[i]->wdata_size)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
- FD_SET(i, &wfd);
-#pragma GCC diagnostic pop
+ Session *s = get_session(i);
+ if (s && s->wdata_size)
+ wfd.set(i);
}
struct timeval timeout;
{
@@ -382,26 +391,20 @@ void do_sendrecv(interval_t next_ms)
timeout.tv_sec = next_s.count();
timeout.tv_usec = next_us.count();
}
- if (select(fd_max, &rfd, &wfd, NULL, &timeout) <= 0)
+ if (io::FD_Set::select(fd_max, &rfd, &wfd, NULL, &timeout) <= 0)
return;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s = session[i].get();
+ Session *s = get_session(i);
if (!s)
continue;
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
- if (FD_ISSET(i, &wfd))
-#pragma GCC diagnostic pop
+ if (wfd.isset(i))
{
if (s->func_send)
//send_from_fifo(i);
s->func_send(s);
}
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
- if (FD_ISSET(i, &rfd))
-#pragma GCC diagnostic pop
+ if (rfd.isset(i))
{
if (s->func_recv)
//recv_to_fifo(i);
@@ -413,15 +416,15 @@ void do_sendrecv(interval_t next_ms)
void do_parsepacket(void)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s = session[i].get();
+ Session *s = get_session(i);
if (!s)
continue;
if (!s->connected
&& static_cast<time_t>(TimeT::now()) - static_cast<time_t>(s->created) > CONNECT_TIMEOUT)
{
- PRINTF("Session #%d timed out\n", i);
+ PRINTF("Session #%d timed out\n", s);
s->eof = 1;
}
if (!s->rdata_size && !s->eof)
@@ -438,14 +441,6 @@ void do_parsepacket(void)
}
}
-void do_socket(void)
-{
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wold-style-cast"
- FD_ZERO(&readfds);
-#pragma GCC diagnostic pop
-}
-
void RFIFOSKIP(Session *s, size_t len)
{
s->rdata_pos += len;
diff --git a/src/common/socket.hpp b/src/common/socket.hpp
index 4d51604..6d0ca01 100644
--- a/src/common/socket.hpp
+++ b/src/common/socket.hpp
@@ -13,6 +13,8 @@
# include "../strings/vstring.hpp"
# include "../strings/xstring.hpp"
+# include "../io/fd.hpp"
+
# include "dumb_ptr.hpp"
# include "ip.hpp"
# include "utils.hpp"
@@ -64,13 +66,13 @@ struct Session
/// Server-specific data type
std::unique_ptr<SessionData, SessionDeleter> session_data;
- int fd;
+ io::FD fd;
};
inline
int convert_for_printf(Session *s)
{
- return s->fd;
+ return s->fd.uncast_dammit();
}
// save file descriptors for important stuff
@@ -79,12 +81,23 @@ constexpr int SOFT_LIMIT = FD_SETSIZE - 50;
// socket timeout to establish a full connection in seconds
constexpr int CONNECT_TIMEOUT = 15;
-/// Everyone who has connected
-// note: call delete_session(i) to null out an element
-extern std::array<std::unique_ptr<Session>, FD_SETSIZE> session;
-/// Maximum used FD, +1
-extern int fd_max;
+void set_session(io::FD fd, std::unique_ptr<Session> sess);
+Session *get_session(io::FD fd);
+void reset_session(io::FD fd);
+int get_fd_max();
+
+class IncrFD
+{
+public:
+ static
+ io::FD inced(io::FD v)
+ {
+ return io::FD::cast_dammit(v.uncast_dammit() + 1);
+ }
+};
+IteratorPair<ValueIterator<io::FD, IncrFD>> iter_fds();
+
/// open a socket, bind, and listen. Return an fd, or -1 if socket() fails,
/// but exit if bind() or listen() fails
@@ -101,9 +114,6 @@ void do_sendrecv(interval_t next);
/// Call the parser function for every socket that has read data
void do_parsepacket(void);
-/// An init function
-void do_socket(void);
-
/// Change the default parser for newly connected clients
// typically called once per server, but individual clients may identify
// themselves as servers
diff --git a/src/common/utils2.hpp b/src/common/utils2.hpp
index 0f72aff..ac55a5a 100644
--- a/src/common/utils2.hpp
+++ b/src/common/utils2.hpp
@@ -9,6 +9,8 @@
# include <memory>
# include <type_traits>
+# include "iter.hpp"
+
# ifdef __clang__
# define FALLTHROUGH [[clang::fallthrough]]
# else
@@ -92,25 +94,6 @@ public:
}
};
-template<class It>
-class IteratorPair
-{
- It _b, _e;
-public:
- IteratorPair(It b, It e)
- : _b(b), _e(e)
- {}
-
- It begin() { return _b; }
- It end() { return _e; }
-};
-
-template<class It>
-IteratorPair<It> iterator_pair(It b, It e)
-{
- return {b, e};
-}
-
// std::underlying_type isn't supported until gcc 4.7
// this is a poor man's emulation
template<class E>
@@ -177,41 +160,19 @@ E operator ~ (E r) \
}
template<class E>
-class EnumValueIterator
+class EnumMath
{
typedef typename underlying_type<E>::type U;
- E value;
public:
- EnumValueIterator(E v)
- : value(v)
- {}
-
- E operator *()
- {
- return value;
- }
- EnumValueIterator& operator++ ()
- {
- value = E(U(value) + 1);
- return *this;
- }
- EnumValueIterator& operator-- ()
- {
- value = E(U(value) - 1);
- return *this;
- }
- friend bool operator == (EnumValueIterator l, EnumValueIterator r)
- {
- return l.value == r.value;
- }
- friend bool operator != (EnumValueIterator l, EnumValueIterator r)
+ static
+ E inced(E v)
{
- return !(l == r);
+ return E(U(v) + 1);
}
};
template<class E>
-IteratorPair<EnumValueIterator<E>> erange(E b, E e)
+IteratorPair<ValueIterator<E, EnumMath<E>>> erange(E b, E e)
{
return {b, e};
}
diff --git a/src/io/fd.cpp b/src/io/fd.cpp
new file mode 100644
index 0000000..87d3967
--- /dev/null
+++ b/src/io/fd.cpp
@@ -0,0 +1,164 @@
+#include "fd.hpp"
+// io/fd.cpp - typesafe (but not scopesafe) file descriptors
+//
+// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "../strings/zstring.hpp"
+
+
+namespace io
+{
+ FD FD::open(ZString path, int flags, int mode)
+ {
+ return FD(::open(path.c_str(), flags, mode));
+ }
+ FD FD::socket(int domain, int type, int protocol)
+ {
+ return FD(::socket(domain, type, protocol));
+ }
+ FD FD::accept(struct sockaddr *addr, socklen_t *addrlen)
+ {
+ return FD(::accept(fd, addr, addrlen));
+ }
+ int FD::pipe(FD& r, FD& w)
+ {
+ int tmp[2] = {-1, -1};
+ int rv = ::pipe(tmp);
+ r = FD(tmp[0]);
+ w = FD(tmp[1]);
+ return rv;
+ }
+ int FD::pipe2(FD& r, FD& w, int flags)
+ {
+ int tmp[2] = {-1, -1};
+ int rv = ::pipe2(tmp, flags);
+ r = FD(tmp[0]);
+ w = FD(tmp[1]);
+ return rv;
+ }
+ FD FD::sysconf_SC_OPEN_MAX()
+ {
+ return FD(::sysconf(_SC_OPEN_MAX));
+ }
+
+ ssize_t FD::read(void *buf, size_t count)
+ {
+ return ::read(fd, buf, count);
+ }
+ ssize_t FD::write(const void *buf, size_t count)
+ {
+ return ::write(fd, buf, count);
+ }
+ ssize_t FD::pread(void *buf, size_t count, off_t offset)
+ {
+ return ::pread(fd, buf, count, offset);
+ }
+ ssize_t FD::pwrite(const void *buf, size_t count, off_t offset)
+ {
+ return ::pwrite(fd, buf, count, offset);
+ }
+ ssize_t FD::readv(const struct iovec *iov, int iovcnt)
+ {
+ return ::readv(fd, iov, iovcnt);
+ }
+ ssize_t FD::writev(const struct iovec *iov, int iovcnt)
+ {
+ return ::writev(fd, iov, iovcnt);
+ }
+ ssize_t FD::preadv(const struct iovec *iov, int iovcnt, off_t offset)
+ {
+ return ::preadv(fd, iov, iovcnt, offset);
+ }
+ ssize_t FD::pwritev(const struct iovec *iov, int iovcnt, off_t offset)
+ {
+ return ::pwritev(fd, iov, iovcnt, offset);
+ }
+
+ int FD::close()
+ {
+ return ::close(fd);
+ }
+ int FD::shutdown(int how)
+ {
+ return ::shutdown(fd, how);
+ }
+ int FD::getsockopt(int level, int optname, void *optval, socklen_t *optlen)
+ {
+ return ::getsockopt(fd, level, optname, optval, optlen);
+ }
+ int FD::setsockopt(int level, int optname, const void *optval, socklen_t optlen)
+ {
+ return ::setsockopt(fd, level, optname, optval, optlen);
+ }
+ int FD::fcntl(int cmd)
+ {
+ return ::fcntl(fd, cmd);
+ }
+ int FD::fcntl(int cmd, int arg)
+ {
+ return ::fcntl(fd, cmd, arg);
+ }
+ int FD::fcntl(int cmd, void *arg)
+ {
+ return ::fcntl(fd, cmd, arg);
+ }
+ int FD::listen(int backlog)
+ {
+ return ::listen(fd, backlog);
+ }
+ int FD::bind(const struct sockaddr *addr, socklen_t addrlen)
+ {
+ return ::bind(fd, addr, addrlen);
+ }
+ int FD::connect(const struct sockaddr *addr, socklen_t addrlen)
+ {
+ return ::connect(fd, addr, addrlen);
+ }
+ FD FD::dup()
+ {
+ return FD(::dup(fd));
+ }
+ FD FD::dup2(FD newfd)
+ {
+ return FD(::dup2(fd, newfd.fd));
+ }
+ FD FD::dup3(FD newfd, int flags)
+ {
+ return FD(::dup3(fd, newfd.fd, flags));
+ }
+
+ int FD_Set::select(int nfds, FD_Set *readfds, FD_Set *writefds, FD_Set *exceptfds, struct timeval *timeout)
+ {
+ return ::select(nfds,
+ readfds ? &readfds->fds : nullptr,
+ writefds ? &writefds->fds : nullptr,
+ exceptfds ? &exceptfds->fds : nullptr,
+ timeout);
+ }
+ int FD_Set::pselect(int nfds, FD_Set *readfds, FD_Set *writefds, FD_Set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask)
+ {
+ return ::pselect(nfds,
+ readfds ? &readfds->fds : nullptr,
+ writefds ? &writefds->fds : nullptr,
+ exceptfds ? &exceptfds->fds : nullptr,
+ timeout, sigmask);
+ }
+} // namespace io
diff --git a/src/io/fd.hpp b/src/io/fd.hpp
new file mode 100644
index 0000000..e4bcff7
--- /dev/null
+++ b/src/io/fd.hpp
@@ -0,0 +1,159 @@
+#ifndef TMWA_IO_FD_HPP
+#define TMWA_IO_FD_HPP
+// io/fd.hpp - typesafe (but not scopesafe) file descriptors
+//
+// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# include "../sanity.hpp"
+
+# include <sys/select.h>
+# include <sys/socket.h>
+
+# include <unistd.h>
+
+# include "../strings/fwd.hpp"
+
+
+namespace io
+{
+ class FD
+ {
+ private:
+ int fd;
+
+ explicit
+ FD(int f)
+ : fd(f)
+ {}
+ public:
+ FD()
+ : fd(-1)
+ {}
+
+ int uncast_dammit() { return fd; }
+ static
+ FD cast_dammit(int f) { return FD(f); }
+
+ static
+ FD stdin() { return FD(0); }
+ static
+ FD stdout() { return FD(1); }
+ static
+ FD stderr() { return FD(2); }
+ static
+ FD open(ZString path, int flags, int mode=0666);
+ static
+ FD socket(int domain, int type, int protocol);
+ FD accept(struct sockaddr *addr, socklen_t *addrlen);
+ static
+ int pipe(FD& r, FD& w);
+ static
+ int pipe2(FD& r, FD& w, int flags);
+ static
+ FD sysconf_SC_OPEN_MAX();
+
+ FD next() { return FD(fd + 1); }
+ FD prev() { return FD(fd - 1); }
+
+ ssize_t read(void *buf, size_t count);
+ ssize_t write(const void *buf, size_t count);
+ ssize_t pread(void *buf, size_t count, off_t offset);
+ ssize_t pwrite(const void *buf, size_t count, off_t offset);
+ ssize_t readv(const struct iovec *iov, int iovcnt);
+ ssize_t writev(const struct iovec *iov, int iovcnt);
+ ssize_t preadv(const struct iovec *iov, int iovcnt, off_t offset);
+ ssize_t pwritev(const struct iovec *iov, int iovcnt, off_t offset);
+
+ int close();
+ int shutdown(int);
+ int getsockopt(int level, int optname, void *optval, socklen_t *optlen);
+ int setsockopt(int level, int optname, const void *optval, socklen_t optlen);
+ // ...
+ int fcntl(int cmd);
+ int fcntl(int cmd, int arg);
+ int fcntl(int cmd, void *arg);
+ int listen(int backlog);
+ int bind(const struct sockaddr *addr, socklen_t addrlen);
+ int connect(const struct sockaddr *addr, socklen_t addrlen);
+ FD dup();
+ FD dup2(FD newfd);
+ FD dup3(FD newfd, int flags);
+
+
+ friend
+ bool operator == (FD l, FD r)
+ {
+ return l.fd == r.fd;
+ }
+ friend
+ bool operator != (FD l, FD r)
+ {
+ return l.fd != r.fd;
+ }
+ friend
+ bool operator < (FD l, FD r)
+ {
+ return l.fd < r.fd;
+ }
+ friend
+ bool operator <= (FD l, FD r)
+ {
+ return l.fd <= r.fd;
+ }
+ friend
+ bool operator > (FD l, FD r)
+ {
+ return l.fd > r.fd;
+ }
+ friend
+ bool operator >= (FD l, FD r)
+ {
+ return l.fd >= r.fd;
+ }
+ };
+
+ class FD_Set
+ {
+ private:
+ fd_set fds;
+ public:
+ FD_Set()
+ {
+ FD_ZERO(&fds);
+ }
+ void clr(FD fd)
+ {
+ FD_CLR(fd.uncast_dammit(), &fds);
+ }
+ bool isset(FD fd)
+ {
+ return FD_ISSET(fd.uncast_dammit(), &fds);
+ }
+ void set(FD fd)
+ {
+ FD_SET(fd.uncast_dammit(), &fds);
+ }
+
+ static
+ int select(int nfds, FD_Set *readfds, FD_Set *writefds, FD_Set *exceptfds, struct timeval *timeout);
+ static
+ int pselect(int nfds, FD_Set *readfds, FD_Set *writefds, FD_Set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);
+ };
+} // namespace io
+
+#endif //TMWA_IO_FD_HPP
diff --git a/src/io/line.cpp b/src/io/line.cpp
index 09dd8fb..83f439d 100644
--- a/src/io/line.cpp
+++ b/src/io/line.cpp
@@ -25,7 +25,7 @@
#include "../strings/mstring.hpp"
#include "../strings/zstring.hpp"
-#include "../io/cxxstdio.hpp"
+#include "cxxstdio.hpp"
#include "../poison.hpp"
@@ -62,7 +62,7 @@ namespace io
: filename(name), line(0), column(0), rf(name)
{}
- LineReader::LineReader(ZString name, int fd)
+ LineReader::LineReader(ZString name, FD fd)
: filename(name), line(0), column(0), rf(fd)
{}
@@ -94,7 +94,7 @@ namespace io
}
// sigh, copy-paste
// in just a couple months I can drop support for gcc 4.6 though
- LineCharReader::LineCharReader(ZString name, int fd)
+ LineCharReader::LineCharReader(ZString name, FD fd)
: LineReader(name, fd)
{
column = 1; // not 0, not whole line
diff --git a/src/io/line.hpp b/src/io/line.hpp
index 6dccfd9..78e1d25 100644
--- a/src/io/line.hpp
+++ b/src/io/line.hpp
@@ -24,6 +24,7 @@
# include "../strings/fstring.hpp"
# include "../strings/zstring.hpp"
+# include "fd.hpp"
# include "read.hpp"
@@ -67,7 +68,7 @@ namespace io
LineReader(ZString name);
LineReader(LineReader&&) = delete;
// needed for unit tests
- LineReader(ZString name, int fd);
+ LineReader(ZString name, FD fd);
bool read_line(Line& l);
bool is_open();
@@ -80,7 +81,7 @@ namespace io
explicit
LineCharReader(ZString name);
LineCharReader(LineCharReader&&) = delete;
- LineCharReader(ZString name, int fd);
+ LineCharReader(ZString name, FD fd);
bool get(LineChar& c);
void adv();
diff --git a/src/io/line_test.cpp b/src/io/line_test.cpp
index 8df6bbc..ae316c6 100644
--- a/src/io/line_test.cpp
+++ b/src/io/line_test.cpp
@@ -5,19 +5,19 @@
#include "../strings/zstring.hpp"
static
-int string_pipe(ZString sz)
+io::FD string_pipe(ZString sz)
{
- int pfd[2];
- if (-1 == pipe(pfd))
- return -1;
- if (sz.size() != write(pfd[1], sz.c_str(), sz.size()))
+ io::FD rfd, wfd;
+ if (-1 == io::FD::pipe(rfd, wfd))
+ return io::FD();
+ if (sz.size() != wfd.write(sz.c_str(), sz.size()))
{
- close(pfd[0]);
- close(pfd[1]);
- return -1;
+ rfd.close();
+ wfd.close();
+ return io::FD();
}
- close(pfd[1]);
- return pfd[0];
+ wfd.close();
+ return rfd;
}
TEST(io, line1)
diff --git a/src/io/lock.cpp b/src/io/lock.cpp
index 823b168..c7cbda8 100644
--- a/src/io/lock.cpp
+++ b/src/io/lock.cpp
@@ -23,7 +23,8 @@
#include "../strings/zstring.hpp"
-#include "../io/cxxstdio.hpp"
+#include "cxxstdio.hpp"
+#include "fd.hpp"
#include "../poison.hpp"
@@ -35,29 +36,29 @@ const int backup_count = 10;
/// Protected file writing
/// (Until the file is closed, it keeps the old file)
-// Start writing a tmpfile
-static
-int get_lock_open(ZString filename, int *info)
+namespace io
{
- int fd;
- int no = getpid();
-
- // Get a filename that doesn't already exist
- FString newfile;
- do
+ // Start writing a tmpfile
+ static
+ FD get_lock_open(ZString filename, int *info)
{
- newfile = STRPRINTF("%s_%d.tmp", filename, no++);
- fd = open(newfile.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0666);
+ FD fd;
+ int no = getpid();
+
+ // Get a filename that doesn't already exist
+ FString newfile;
+ do
+ {
+ newfile = STRPRINTF("%s_%d.tmp", filename, no++);
+ fd = FD::open(newfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
+ }
+ while (fd == FD() && errno == EEXIST);
+ if (fd == FD())
+ abort();
+ *info = --no;
+ return fd;
}
- while (fd == -1 && errno == EEXIST);
- if (fd == -1)
- abort();
- *info = --no;
- return fd;
-}
-namespace io
-{
WriteLock::WriteLock(FString fn, bool linebuffered)
: WriteFile(get_lock_open(fn, &tmp_suffix), linebuffered), filename(fn)
{}
diff --git a/src/io/read.cpp b/src/io/read.cpp
index 146ba81..fe2c765 100644
--- a/src/io/read.cpp
+++ b/src/io/read.cpp
@@ -32,31 +32,31 @@
namespace io
{
- ReadFile::ReadFile(int f)
+ ReadFile::ReadFile(FD f)
: fd(f), start(0), end(0)
{
}
ReadFile::ReadFile(ZString name)
- : fd(open(name.c_str(), O_RDONLY | O_CLOEXEC)), start(0), end(0)
+ : fd(FD::open(name, O_RDONLY | O_CLOEXEC)), start(0), end(0)
{
}
ReadFile::~ReadFile()
{
- close(fd);
- fd = -1;
+ fd.close();
+ fd = FD();
}
bool ReadFile::get(char& c)
{
if (start == end)
{
- if (fd == -1)
+ if (fd == FD())
return false;
- ssize_t rv = read(fd, &buf, sizeof(buf));
+ ssize_t rv = fd.read(&buf, sizeof(buf));
if (rv == 0 || rv == -1)
{
- close(fd);
- fd = -1;
+ fd.close();
+ fd = FD();
return false;
}
start = 0;
@@ -117,6 +117,6 @@ namespace io
bool ReadFile::is_open()
{
- return fd != -1;
+ return fd != FD();
}
} // namespace io
diff --git a/src/io/read.hpp b/src/io/read.hpp
index 8b910b6..14283c5 100644
--- a/src/io/read.hpp
+++ b/src/io/read.hpp
@@ -23,18 +23,19 @@
# include "../strings/fwd.hpp"
+# include "fd.hpp"
namespace io
{
class ReadFile
{
private:
- int fd;
+ FD fd;
unsigned short start, end;
char buf[4096];
public:
explicit
- ReadFile(int fd);
+ ReadFile(FD fd);
explicit
ReadFile(ZString name);
ReadFile(ReadFile&&) = delete;
diff --git a/src/io/read_test.cpp b/src/io/read_test.cpp
index 8c459cbb..ebb20ca 100644
--- a/src/io/read_test.cpp
+++ b/src/io/read_test.cpp
@@ -5,19 +5,19 @@
#include "../strings/zstring.hpp"
static
-int string_pipe(ZString sz)
+io::FD string_pipe(ZString sz)
{
- int pfd[2];
- if (-1 == pipe(pfd))
- return -1;
- if (sz.size() != write(pfd[1], sz.c_str(), sz.size()))
+ io::FD rfd, wfd;
+ if (-1 == io::FD::pipe(rfd, wfd))
+ return io::FD();
+ if (sz.size() != wfd.write(sz.c_str(), sz.size()))
{
- close(pfd[0]);
- close(pfd[1]);
- return -1;
+ rfd.close();
+ wfd.close();
+ return io::FD();
}
- close(pfd[1]);
- return pfd[0];
+ wfd.close();
+ return rfd;
}
TEST(io, read1)
diff --git a/src/io/write.cpp b/src/io/write.cpp
index 71f05ae..5993a69 100644
--- a/src/io/write.cpp
+++ b/src/io/write.cpp
@@ -30,18 +30,20 @@
namespace io
{
- WriteFile::WriteFile(int f, bool linebuffered)
+ WriteFile::WriteFile(FD f, bool linebuffered)
: fd(f), lb(linebuffered), buflen(0)
{}
WriteFile::WriteFile(ZString name, bool linebuffered)
- : fd(open(name.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666)), lb(linebuffered), buflen(0)
+ : fd(FD::open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666)), lb(linebuffered), buflen(0)
{}
WriteFile::~WriteFile()
{
- if (fd != -1)
+ if (fd != FD())
{
- if (close() == -1)
+ if (!close())
+ {
abort();
+ }
}
}
@@ -69,7 +71,7 @@ namespace io
{buf + offset, buflen - offset},
{const_cast<char *>(dat), len},
};
- ssize_t rv = writev(fd, iov, 2);
+ ssize_t rv = fd.writev(iov, 2);
if (rv <= 0)
goto write_fail;
offset += rv;
@@ -81,7 +83,7 @@ namespace io
while (len > sizeof(buf))
{
- ssize_t rv = write(fd, dat, len);
+ ssize_t rv = fd.write(dat, len);
if (rv <= 0)
goto write_fail;
dat += rv;
@@ -102,7 +104,7 @@ namespace io
size_t remaining = rend - last_nl;
while (remaining)
{
- ssize_t rv = write(fd, buf + offset, remaining);
+ ssize_t rv = fd.write(buf + offset, remaining);
if (rv <= 0)
goto write_fail;
offset += rv;
@@ -115,8 +117,8 @@ namespace io
return;
write_fail:
- ::close(fd);
- fd = -1;
+ fd.close();
+ fd = FD();
return;
}
@@ -132,28 +134,28 @@ namespace io
size_t off = 0;
while (off < buflen)
{
- ssize_t rv = write(fd, buf + off, buflen - off);
+ ssize_t rv = fd.write(buf + off, buflen - off);
if (rv <= 0)
{
- ::close(fd);
- fd = -1;
+ fd.close();
+ fd = FD();
return false;
}
off += rv;
}
- int f = fd;
- fd = -1;
- return ::close(f) == 0;
+ FD f = fd;
+ fd = FD();
+ return f.close() == 0;
}
bool WriteFile::is_open()
{
- return fd != -1;
+ return fd != FD();
}
AppendFile::AppendFile(ZString name, bool linebuffered)
- : WriteFile(open(name.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666), linebuffered)
+ : WriteFile(FD::open(name, O_WRONLY | O_CREAT | O_APPEND, 0666), linebuffered)
{}
int do_vprint(WriteFile& out, const char *fmt, va_list ap)
diff --git a/src/io/write.hpp b/src/io/write.hpp
index 7134015..a52c176 100644
--- a/src/io/write.hpp
+++ b/src/io/write.hpp
@@ -25,19 +25,21 @@
# include "../strings/fwd.hpp"
+# include "fd.hpp"
+
namespace io
{
class WriteFile
{
private:
- int fd;
+ FD fd;
bool lb;
struct {} _unused;
unsigned short buflen;
char buf[4096];
public:
explicit
- WriteFile(int fd, bool linebuffered=false);
+ WriteFile(FD fd, bool linebuffered=false);
explicit
WriteFile(ZString name, bool linebuffered=false);
WriteFile(WriteFile&&) = delete;
diff --git a/src/io/write_test.cpp b/src/io/write_test.cpp
index 36ffe88..a9736b8 100644
--- a/src/io/write_test.cpp
+++ b/src/io/write_test.cpp
@@ -10,22 +10,21 @@
#include "../strings/xstring.hpp"
static
-int pipew(int& rfd)
+io::FD pipew(io::FD& rfd)
{
- int pfd[2];
- if (-1 == pipe2(pfd, O_NONBLOCK))
+ io::FD wfd;
+ if (-1 == io::FD::pipe2(rfd, wfd, O_NONBLOCK))
{
- rfd = -1;
- return -1;
+ rfd = io::FD();
+ return io::FD();
}
- rfd = pfd[0];
- return pfd[1];
+ return wfd;
}
class PipeWriter
{
private:
- int rfd;
+ io::FD rfd;
public:
io::WriteFile wf;
public:
@@ -34,7 +33,7 @@ public:
{}
~PipeWriter()
{
- close(rfd);
+ rfd.close();
}
FString slurp()
{
@@ -42,7 +41,7 @@ public:
char buf[4096];
while (true)
{
- ssize_t rv = read(rfd, buf, sizeof(buf));
+ ssize_t rv = rfd.read(buf, sizeof(buf));
if (rv == -1)
{
if (errno != EAGAIN)
diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp
index 931a4d0..f5deab8 100644
--- a/src/map/atcommand.cpp
+++ b/src/map/atcommand.cpp
@@ -715,9 +715,9 @@ ATCE atcommand_who(Session *s, dumb_ptr<map_session_data> sd,
count = 0;
GM_level = pc_isGM(sd);
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -778,9 +778,9 @@ ATCE atcommand_whogroup(Session *s, dumb_ptr<map_session_data> sd,
count = 0;
GM_level = pc_isGM(sd);
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -842,9 +842,9 @@ ATCE atcommand_whomap(Session *s, dumb_ptr<map_session_data> sd,
count = 0;
GM_level = pc_isGM(sd);
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -903,9 +903,9 @@ ATCE atcommand_whomapgroup(Session *s, dumb_ptr<map_session_data> sd,
count = 0;
GM_level = pc_isGM(sd);
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -963,9 +963,9 @@ ATCE atcommand_whogm(Session *s, dumb_ptr<map_session_data> sd,
count = 0;
GM_level = pc_isGM(sd);
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -1522,9 +1522,9 @@ ATCE atcommand_pvpoff(Session *s, dumb_ptr<map_session_data> sd,
if (sd->bl_m->flag.pvp)
{
sd->bl_m->flag.pvp = 0;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -1561,9 +1561,9 @@ ATCE atcommand_pvpon(Session *s, dumb_ptr<map_session_data> sd,
if (!sd->bl_m->flag.pvp && !sd->bl_m->flag.nopvp)
{
sd->bl_m->flag.pvp = 1;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -2155,9 +2155,9 @@ ATCE atcommand_character_stats_all(Session *s, dumb_ptr<map_session_data>,
int count;
count = 0;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -2395,9 +2395,9 @@ static
ATCE atcommand_doom(Session *s, dumb_ptr<map_session_data> sd,
ZString)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -2419,9 +2419,9 @@ static
ATCE atcommand_doommap(Session *s, dumb_ptr<map_session_data> sd,
ZString)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -2458,9 +2458,9 @@ static
ATCE atcommand_raise(Session *s, dumb_ptr<map_session_data>,
ZString)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -2475,9 +2475,9 @@ static
ATCE atcommand_raisemap(Session *s, dumb_ptr<map_session_data> sd,
ZString)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -2687,9 +2687,9 @@ static
ATCE atcommand_kickall(Session *s, dumb_ptr<map_session_data> sd,
ZString)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -2905,9 +2905,9 @@ static
ATCE atcommand_mapexit(Session *, dumb_ptr<map_session_data> sd,
ZString)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -3318,9 +3318,9 @@ ATCE atcommand_recallall(Session *s, dumb_ptr<map_session_data> sd,
}
count = 0;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -3374,9 +3374,9 @@ ATCE atcommand_partyrecall(Session *s, dumb_ptr<map_session_data> sd,
(p = party_search(atoi(message.c_str()))) != NULL)
{
count = 0;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -3475,9 +3475,9 @@ ATCE atcommand_mapinfo(Session *s, dumb_ptr<map_session_data> sd,
break;
case 1:
clif_displaymessage(s, "----- Players in Map -----");
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -3486,7 +3486,7 @@ ATCE atcommand_mapinfo(Session *s, dumb_ptr<map_session_data> sd,
{
output = STRPRINTF(
"Player '%s' (session #%d) | Location: %d,%d",
- pl_sd->status.name, i, pl_sd->bl_x, pl_sd->bl_y);
+ pl_sd->status.name, s2, pl_sd->bl_x, pl_sd->bl_y);
clif_displaymessage(s, output);
}
}
@@ -3797,9 +3797,9 @@ ATCE atcommand_effect(Session *s, dumb_ptr<map_session_data> sd,
}
else
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -5031,9 +5031,9 @@ ATCE atcommand_ipcheck(Session *s, dumb_ptr<map_session_data>,
// We now have the IP address of a character.
// Loop over all logged in sessions looking for matches.
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
@@ -5059,9 +5059,9 @@ static
ATCE atcommand_doomspot(Session *s, dumb_ptr<map_session_data> sd,
ZString)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp
index 959186c..ab67b5c 100644
--- a/src/map/chrif.cpp
+++ b/src/map/chrif.cpp
@@ -202,15 +202,15 @@ int chrif_changemapserver(dumb_ptr<map_session_data> sd,
nullpo_retr(-1, sd);
IP4Address s_ip;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s = session[i].get();
+ Session *s = get_session(i);
if (!s)
continue;
if (dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())) == sd)
{
assert (s == sd->sess);
- s_ip = session[i]->client_ip;
+ s_ip = s->client_ip;
break;
}
}
@@ -321,12 +321,12 @@ int chrif_authreq(dumb_ptr<map_session_data> sd)
if (!sd || !char_session || !sd->bl_id || !sd->login_id1)
return -1;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s = session[i].get();
+ Session *s = get_session(i);
if (!s)
continue;
- if (dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get())) == sd)
+ if (dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())) == sd)
{
assert (s == sd->sess);
WFIFOW(char_session, 0) = 0x2afc;
@@ -334,7 +334,7 @@ int chrif_authreq(dumb_ptr<map_session_data> sd)
WFIFOL(char_session, 6) = sd->char_id;
WFIFOL(char_session, 10) = sd->login_id1;
WFIFOL(char_session, 14) = sd->login_id2;
- WFIFOIP(char_session, 18) = session[i]->client_ip;
+ WFIFOIP(char_session, 18) = s->client_ip;
WFIFOSET(char_session, 22);
break;
}
@@ -355,9 +355,9 @@ int chrif_charselectreq(dumb_ptr<map_session_data> sd)
return -1;
IP4Address s_ip;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s = session[i].get();
+ Session *s = get_session(i);
if (!s)
continue;
if (dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get())) == sd)
@@ -1157,11 +1157,12 @@ void send_users_tochar(TimerData *, tick_t)
return;
WFIFOW(char_session, 0) = 0x2aff;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
+ dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
if (sd && sd->state.auth &&
!((battle_config.hide_GM_session
|| sd->state.shroud_active
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 0429600..61c47d9 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -165,11 +165,12 @@ int clif_countusers(void)
{
int users = 0;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
+ dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
if (sd && sd->state.auth && !(battle_config.hide_GM_session && pc_isGM(sd)))
users++;
}
@@ -182,11 +183,12 @@ int clif_countusers(void)
*/
int clif_foreachclient(std::function<void (dumb_ptr<map_session_data>)> func)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
+ dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
if (sd && sd->state.auth)
func(sd);
}
@@ -302,9 +304,9 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type
switch (type)
{
case SendWho::ALL_CLIENT: // 全クライアントに送信
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s = session[i].get();
+ Session *s = get_session(i);
if (!s)
continue;
dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
@@ -320,9 +322,9 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type
}
break;
case SendWho::ALL_SAMEMAP: // 同じマップの全クライアントに送信
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s = session[i].get();
+ Session *s = get_session(i);
if (!s)
continue;
dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
@@ -402,9 +404,9 @@ int clif_send(const uint8_t *buf, int len, dumb_ptr<block_list> bl, SendWho type
}
}
}
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s = session[i].get();
+ Session *s = get_session(i);
if (!s)
continue;
dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
@@ -3379,11 +3381,12 @@ int clif_specialeffect(dumb_ptr<block_list> bl, int type, int flag)
if (flag == 2)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
+ dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
if (sd && sd->state.auth && sd->bl_m == bl->bl_m)
clif_specialeffect(sd, type, 1);
}
diff --git a/src/map/intif.cpp b/src/map/intif.cpp
index 006be1c..7d699dd 100644
--- a/src/map/intif.cpp
+++ b/src/map/intif.cpp
@@ -315,9 +315,9 @@ void mapif_parse_WisToGM(Session *s)
CharName Wisp_name = stringish<CharName>(RFIFO_STRING<24>(s, 4));
FString message = RFIFO_STRING(s, 30, len);
// information is sended to all online GM
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- Session *s2 = session[i].get();
+ Session *s2 = get_session(i);
if (!s2)
continue;
dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s2->session_data.get()));
diff --git a/src/map/map.cpp b/src/map/map.cpp
index 3817422..2600412 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -871,13 +871,14 @@ dumb_ptr<map_session_data> map_id2sd(int id)
return (struct map_session_data*)bl;
return NULL;
*/
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- if (session[i]->session_data)
+ if (s->session_data)
{
- map_session_data *sd = static_cast<map_session_data *>(session[i]->session_data.get());
+ map_session_data *sd = static_cast<map_session_data *>(s->session_data.get());
if (sd->bl_id == id)
return dumb_ptr<map_session_data>(sd);
}
@@ -905,13 +906,13 @@ CharName map_charid2nick(int id)
/* [Fate] Operations to iterate over active map sessions */
static
-dumb_ptr<map_session_data> map_get_session(int i)
+dumb_ptr<map_session_data> map_get_session(io::FD i)
{
- if (i >= 0 && i < fd_max)
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
return nullptr;
- map_session_data *d = static_cast<map_session_data *>(session[i]->session_data.get());
+ map_session_data *d = static_cast<map_session_data *>(s->session_data.get());
if (d && d->state.auth)
return dumb_ptr<map_session_data>(d);
}
@@ -922,9 +923,9 @@ dumb_ptr<map_session_data> map_get_session(int i)
static
dumb_ptr<map_session_data> map_get_session_forward(int start)
{
- for (int i = start; i < fd_max; i++)
+ for (int i = start; i < get_fd_max(); i++)
{
- dumb_ptr<map_session_data> d = map_get_session(i);
+ dumb_ptr<map_session_data> d = map_get_session(io::FD::cast_dammit(i));
if (d)
return d;
}
@@ -935,10 +936,9 @@ dumb_ptr<map_session_data> map_get_session_forward(int start)
static
dumb_ptr<map_session_data> map_get_session_backward(int start)
{
- int i;
- for (i = start; i >= 0; i--)
+ for (int i = start; i >= 0; i--)
{
- dumb_ptr<map_session_data> d = map_get_session(i);
+ dumb_ptr<map_session_data> d = map_get_session(io::FD::cast_dammit(i));
if (d)
return d;
}
@@ -953,17 +953,17 @@ dumb_ptr<map_session_data> map_get_first_session(void)
dumb_ptr<map_session_data> map_get_next_session(dumb_ptr<map_session_data> d)
{
- return map_get_session_forward(d->sess->fd + 1);
+ return map_get_session_forward(d->sess->fd.uncast_dammit() + 1);
}
dumb_ptr<map_session_data> map_get_last_session(void)
{
- return map_get_session_backward(fd_max);
+ return map_get_session_backward(get_fd_max());
}
dumb_ptr<map_session_data> map_get_prev_session(dumb_ptr<map_session_data> d)
{
- return map_get_session_backward(d->sess->fd - 1);
+ return map_get_session_backward(d->sess->fd.uncast_dammit() - 1);
}
/*==========================================
@@ -974,11 +974,12 @@ dumb_ptr<map_session_data> map_get_prev_session(dumb_ptr<map_session_data> d)
*/
dumb_ptr<map_session_data> map_nick2sd(CharName nick)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- map_session_data *pl_sd = static_cast<map_session_data *>(session[i]->session_data.get());
+ map_session_data *pl_sd = static_cast<map_session_data *>(s->session_data.get());
if (pl_sd && pl_sd->state.auth)
{
{
@@ -1611,8 +1612,8 @@ void term_func(void)
BL::NUL);
}
- for (int i = 0; i < fd_max; i++)
- delete_session(session[i].get());
+ for (io::FD i : iter_fds())
+ delete_session(get_session(i));
map_removenpc();
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index d68c580..7a73df5 100644
--- a/src/map/mob.cpp
+++ b/src/map/mob.cpp
@@ -2652,11 +2652,12 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage,
sd = mvp_sd;
else
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- dumb_ptr<map_session_data> tmp_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
+ dumb_ptr<map_session_data> tmp_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
if (tmp_sd && tmp_sd->state.auth)
{
if (md->bl_m == tmp_sd->bl_m)
diff --git a/src/map/party.cpp b/src/map/party.cpp
index 09f103e..b2ce340 100644
--- a/src/map/party.cpp
+++ b/src/map/party.cpp
@@ -126,11 +126,12 @@ int party_check_member(struct party *p)
{
nullpo_ret(p);
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- map_session_data *sd = static_cast<map_session_data *>(session[i]->session_data.get());
+ map_session_data *sd = static_cast<map_session_data *>(s->session_data.get());
if (sd && sd->state.auth)
{
if (sd->status.party_id == p->party_id)
@@ -165,11 +166,12 @@ int party_check_member(struct party *p)
// 情報所得失敗(そのIDのキャラを全部未所属にする)
int party_recv_noinfo(int party_id)
{
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- map_session_data *sd = static_cast<map_session_data *>(session[i]->session_data.get());
+ map_session_data *sd = static_cast<map_session_data *>(s->session_data.get());
if (sd && sd->state.auth)
{
if (sd->status.party_id == party_id)
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 168d124..8d242ae 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -5201,13 +5201,13 @@ void pc_autosave_sub(dumb_ptr<map_session_data> sd)
{
nullpo_retv(sd);
- if (save_flag == 0 && sd->sess->fd > last_save_fd)
+ if (save_flag == 0 && sd->sess->fd.uncast_dammit() > last_save_fd)
{
pc_makesavestatus(sd);
chrif_save(sd);
save_flag = 1;
- last_save_fd = sd->sess->fd;
+ last_save_fd = sd->sess->fd.uncast_dammit();
}
}
diff --git a/src/map/script.cpp b/src/map/script.cpp
index 6bd4543..c154182 100644
--- a/src/map/script.cpp
+++ b/src/map/script.cpp
@@ -3367,11 +3367,12 @@ void builtin_pvpon(ScriptState *st)
if (battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris]
return;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- map_session_data *pl_sd = static_cast<map_session_data *>(session[i]->session_data.get());
+ map_session_data *pl_sd = static_cast<map_session_data *>(s->session_data.get());
if (pl_sd && pl_sd->state.auth)
{
if (m == pl_sd->bl_m && !pl_sd->pvp_timer)
@@ -3401,11 +3402,12 @@ void builtin_pvpoff(ScriptState *st)
if (battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris]
return;
- for (int i = 0; i < fd_max; i++)
+ for (io::FD i : iter_fds())
{
- if (!session[i])
+ Session *s = get_session(i);
+ if (!s)
continue;
- map_session_data *pl_sd = static_cast<map_session_data *>(session[i]->session_data.get());
+ map_session_data *pl_sd = static_cast<map_session_data *>(s->session_data.get());
if (pl_sd && pl_sd->state.auth)
{
if (m == pl_sd->bl_m)
diff --git a/src/monitor/main.cpp b/src/monitor/main.cpp
index 1bc9880..352b375 100644
--- a/src/monitor/main.cpp
+++ b/src/monitor/main.cpp
@@ -20,6 +20,7 @@
#include "../strings/xstring.hpp"
#include "../io/cxxstdio.hpp"
+#include "../io/fd.hpp"
#include "../io/read.hpp"
#include "../common/config_parse.hpp"
@@ -183,19 +184,21 @@ int main(int argc, char *argv[])
{
//make sure all possible file descriptors are free for use by the servers
//if there are file descriptors higher than the max open from before the limit dropped, that's not our problem
- int fd = sysconf(_SC_OPEN_MAX);
- while (--fd > 2)
- if (close(fd) == 0)
- FPRINTF(stderr, "close fd %d\n", fd);
- fd = open("/dev/null", O_RDWR);
- if (fd < 0)
+ io::FD fd = io::FD::sysconf_SC_OPEN_MAX();
+ while ((fd = fd.prev()) > io::FD::stderr())
+ {
+ if (fd.close() == 0)
+ FPRINTF(stderr, "close fd %d\n", fd.uncast_dammit());
+ }
+ fd = io::FD::open("/dev/null", O_RDWR);
+ if (fd == io::FD())
{
perror("open /dev/null");
exit(1);
}
- dup2(fd, 0);
- dup2(fd, 1);
- close(fd);
+ fd.dup2(io::FD::stdin());
+ fd.dup2(io::FD::stdout());
+ fd.close();
}
while (1)
{