28 #include <arpa/inet.h>
30 #include <netinet/tcp.h>
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
34 #define OPTYPE (void *)
40 using namespace basis;
50 #define LOG(to_print) CLASS_EMERGENCY_LOG(program_wide_logger::get(), to_print)
57 class fd_set_wrapper :
public fd_set {};
80 raw_socket::raw_socket()
106 if (existing.
t()) existing +=
" | ";
107 existing += addition;
119 if (!interest)
combine(to_return,
"NORMAL");
126 return ::ioctl(socket, request, argp);
143 int curr_flags = fcntl(socket, F_GETFL, 0);
144 if (fcntl(socket, F_SETFL, curr_flags | O_NONBLOCK) < 0)
return false;
146 int arg = int(non_blocking);
148 LOG(
a_sprintf(
"Could not set non-blocking (FIONBIO) option on raw_socket %u.", socket));
157 FUNCDEF(
"set_nagle_algorithm");
158 int arg = int(!use_nagle);
159 if (
negative(setsockopt(socket, IPPROTO_TCP, TCP_NODELAY,
OPTYPE &arg,
161 LOG(
a_sprintf(
"Could not change nagle coalescing mode on %u.", socket));
170 int arg = int(broadcasting);
171 if (
negative(setsockopt(socket, SOL_SOCKET, SO_BROADCAST,
OPTYPE &arg,
173 LOG(
a_sprintf(
"Could not change broadcast mode on %u.", socket));
182 int arg = int(reuse);
183 if (
negative(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR,
OPTYPE &arg,
185 LOG(
a_sprintf(
"Could not set reuse address mode on %u.", socket));
194 int arg = int(keep_alive);
195 if (
negative(setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE,
OPTYPE &arg,
197 LOG(
a_sprintf(
"Could not set keep alive mode on %u.", socket));
207 fd_set_wrapper read_list, write_list, exceps;
208 int ret = inner_select(socket, mode, timeout, read_list, write_list, exceps);
215 int raw_socket::inner_select(
basis::un_int socket,
int mode,
int timeout,
216 fd_set_wrapper &read_list, fd_set_wrapper &write_list,
217 fd_set_wrapper &exceptions)
const
222 FD_ZERO(&read_list); FD_SET(socket, &read_list);
223 FD_ZERO(&write_list); FD_SET(socket, &write_list);
224 FD_ZERO(&exceptions); FD_SET(socket, &exceptions);
226 timeval base_time_out;
227 time_stamp::fill_timeval_ms(base_time_out, timeout);
230 timeval *time_out = &base_time_out;
244 &exceptions, time_out);
245 int error = critical_events::system_error();
265 #ifdef DEBUG_RAW_SOCKET
266 LOG(
"got to weird case, in progress or zero.");
270 #ifdef DEBUG_RAW_SOCKET
286 LOG(
astring(astring::SPRINTF,
"socket %u had ioctl error: %s.",
296 fd_set_wrapper &read_list, fd_set_wrapper &write_list,
297 fd_set_wrapper &exceptions)
const
299 #ifdef DEBUG_RAW_SOCKET
300 FUNCDEF(
"analyze_select_result");
305 if (FD_ISSET(socket, &exceptions)) {
306 #ifdef DEBUG_RAW_SOCKET
307 LOG(
astring(astring::SPRINTF,
"exception seen for socket %u!", socket));
316 int readable = test_readability(socket);
325 bool really_disconnected =
true;
327 fd_set_wrapper read_list, write_list, exceps;
335 really_disconnected =
false;
341 really_disconnected =
true;
345 if (!FD_ISSET(socket, &read_list)) {
348 really_disconnected =
false;
354 readable = test_readability(socket);
357 really_disconnected =
false;
361 if (really_disconnected) {
362 #ifdef DEBUG_RAW_SOCKET
363 LOG(
a_sprintf(
"connection closed on socket %u.", socket));
381 #ifdef DEBUG_RAW_SOCKET
391 fd_set_wrapper read_list; FD_ZERO(&read_list);
392 fd_set_wrapper write_list; FD_ZERO(&write_list);
393 fd_set_wrapper exceptions; FD_ZERO(&exceptions);
397 for (i = 0; i < read_sox.
length(); i++) {
399 if (sock > highest) highest = sock;
400 FD_SET(sock, &read_list);
402 for (i = 0; i < write_sox.
length(); i++) {
404 if (sock > highest) highest = sock;
405 FD_SET(sock, &write_list);
408 timeval base_time_out;
409 time_stamp::fill_timeval_ms(base_time_out, timeout);
412 timeval *time_out = &base_time_out;
425 &exceptions, time_out);
426 int error = critical_events::system_error();
445 #ifdef DEBUG_RAW_SOCKET
446 LOG(
"got to weird case, in progress or zero.");
453 #ifdef DEBUG_RAW_SOCKET
470 for (
int k = 0; k < read_sox.
length(); k++) {
473 write_list, exceptions);
480 to_return |= interim;
482 for (
int p = 0; p < write_sox.
length(); p++) {
485 write_list, exceptions);
492 to_return |= interim;
a_sprintf is a specialization of astring that provides printf style support.
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
int length() const
Returns the current reported length of the allocated C array.
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
Provides a dynamically resizable ASCII character string.
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
bool t() const
t() is a shortcut for the string being "true", as in non-empty.
A simple object that wraps a templated array of ints.
bool set_nagle_algorithm(basis::un_int socket, bool use_nagle=true)
int close(basis::un_int &socket)
int select(basis::un_int socket, int selection_mode, int timeout=0) const
int analyze_select_result(basis::un_int socket, int mode, fd_set_wrapper &read_list, fd_set_wrapper &write_list, fd_set_wrapper &exceptions) const
bool set_reuse_address(basis::un_int socket, bool reuse=true)
int ioctl(basis::un_int socket, int request, void *argp) const
bool set_keep_alive(basis::un_int socket, bool keep_alive=true)
static basis::astring interest_name(int to_name)
bool set_broadcast(basis::un_int socket, bool broadcasting=true)
bool set_non_blocking(basis::un_int socket, bool non_blocking=true)
Helpful functions for interacting with TCP/IP stacks.
static basis::astring tcpip_error_name(int error_value)
#define NULL_POINTER
The value representing a pointer to nothing.
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
The guards collection helps in testing preconditions and reporting errors.
bool positive(const type &a)
positive returns true if "a" is greater than zero, or false otherwise.
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
unsigned int un_int
Abbreviated name for unsigned integers.
bool negative(const type &a)
negative returns true if "a" is less than zero.
A logger that sends to the console screen using the standard output device.
Provides access to the operating system's socket methods.
const basis::un_int IOCTL_READ
const int MULTIPLE_DISCONNECT_CHECKS
void combine(astring &existing, const astring &addition)
const basis::un_int NON_BLOCKING