📄 socket.cpp
字号:
/***************************************************************************//* *//* Copyright (c) 2005, 2006 2X Software Ltd, http://www.2X.com., NoMachine *//* *//* NXPROXY, NX protocol compression and NX extensions to this software *//* are copyright of Nomachine. Redistribution and use of the present *//* software is allowed according to terms specified in the file LICENSE *//* which comes in the source distribution. *//* *//* NX and NoMachine are trademarks of Medialogic S.p.A. *//* *//* 2X is a trademark of 2X Software Ltd. *//* *//* All rights reserved. *//* *//***************************************************************************/#include <sys/ioctl.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/utsname.h>#if defined(__CYGWIN32__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)#include <netinet/in_systm.h>#endif#ifdef __sun#include <unistd.h>#include <stropts.h>#include <sys/filio.h>#include <sys/termios.h>#endif#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/tcp.h>#include <arpa/inet.h>#include <netdb.h>#include <fcntl.h>//// System specific defines.//#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)#define SOL_IP IPPROTO_IP#endif#ifdef __sun#define INADDR_NONE ((unsigned int) -1)#endif//// The TIOCOUTQ ioctl is not implemented on Cygwin.// Note also that TIOCOUTQ and IPTOS_LOWDELAY are// disabled when running on MacOS/X.//#ifdef __CYGWIN32__#define TIOCOUTQ ((unsigned int) -1)#endif//// NX includes.//#include "Misc.h"#include "Socket.h"//// Set verbosity level.//#undef PANIC#undef WARNING#undef TEST#undef DEBUG//// Set this only once by querying OS details.//static int _kernelStep = -1;int GetKernelStep(){ if (_kernelStep < 0) { // // At the moment only NX clients run on Win32 // and MacOS/X so we are not really interested // in the relevant OS dependent functions. // #if defined(__CYGWIN32__) || defined(__APPLE__) _kernelStep = 0; #else struct utsname buffer; if (uname(&buffer) < 0) { #ifdef WARNING *logofs << "Socket: WARNING! Failed to get system info. Error is " << EGET() << " '" << ESTR() << "'.\n" << logofs_flush; *logofs << "Socket: WARNING! Assuming lowest system support.\n" << logofs_flush; #endif cerr << "Warning" << ": Failed to get system info. Error is " << EGET() << " '" << ESTR() << "'.\n"; cerr << "Warning" << ": Assuming lowest system support.\n"; _kernelStep = 0; } else { #ifdef TEST *logofs << "Socket: System is '" << buffer.sysname << "' nodename '" << buffer.nodename << "' release '" << buffer.release << "'.\n" << logofs_flush; *logofs << "Socket: Version is '" << buffer.version << "' machine '" << buffer.machine << "'.\n" << logofs_flush; #endif // // Should test support on other operating systems. // if (strcmp(buffer.sysname, "Linux") == 0) { if (strncmp(buffer.release, "2.0.", 4) == 0 || strncmp(buffer.release, "2.2.", 4) == 0) { #ifdef TEST *logofs << "Socket: Assuming level 2 system support.\n" << logofs_flush; #endif _kernelStep = 2; } else { #ifdef TEST *logofs << "Socket: Assuming level 3 system support.\n" << logofs_flush; #endif _kernelStep = 3; } } else if (strcmp(buffer.sysname, "SunOS") == 0) { #ifdef TEST *logofs << "Socket: Assuming level 1 system support.\n" << logofs_flush; #endif _kernelStep = 1; } else { #ifdef TEST *logofs << "Socket: Assuming level 0 system support.\n" << logofs_flush; #endif _kernelStep = 0; } } #endif /* #if defined(__CYGWIN32__) || defined(__APPLE__) */ } return _kernelStep;} int SetReuseAddress(int fd){ int flag = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(flag)) < 0) { #ifdef PANIC *logofs << "Socket: PANIC! Failed to set SO_REUSEADDR flag on FD#" << fd << ". Error is " << EGET() << " '" << ESTR() << "'.\n" << logofs_flush; #endif cerr << "Error" << ": Failed to set SO_REUSEADDR flag on FD#" << fd << ". Error is " << EGET() << " '" << ESTR() << "'.\n"; return -1; } #ifdef TEST else { *logofs << "Socket: Set SO_REUSEADDR flag on FD#" << fd << ".\n" << logofs_flush; } #endif return 1;}int SetNonBlocking(int fd, int value){ int flags = fcntl(fd, F_GETFL); if (flags >= 0) { if (value == 0) { flags &= ~O_NONBLOCK; } else { flags |= O_NONBLOCK; } } if (flags < 0 || fcntl(fd, F_SETFL, flags) < 0) { #ifdef PANIC *logofs << "Socket: PANIC! Failed to set O_NONBLOCK flag on FD#" << fd << " to " << value << ". Error is " << EGET() << " '" << ESTR() << "'.\n" << logofs_flush; #endif cerr << "Error" << ": Failed to set O_NONBLOCK flag on FD#" << fd << " to " << value << ". Error is " << EGET() << " '" << ESTR() << "'.\n"; return -1; } #ifdef TEST else { *logofs << "Socket: Set O_NONBLOCK flag on FD#" << fd << " to " << value << ".\n" << logofs_flush; } #endif return 1;}int SetLingerTimeout(int fd, int timeout){ struct linger linger_value; linger_value.l_onoff = 1; linger_value.l_linger = timeout; if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger_value, sizeof(linger_value)) < 0) { #ifdef PANIC *logofs << "Socket: PANIC! Failed to set SO_LINGER values to " << linger_value.l_onoff << " and " << linger_value.l_linger << " on FD#" << fd << ". Error is " << EGET() << " '" << ESTR() << "'.\n" << logofs_flush; #endif cerr << "Error" << ": Failed to set SO_LINGER values to " << linger_value.l_onoff << " and " << linger_value.l_linger << " on FD#" << fd << ". Error is " << EGET() << " '" << ESTR() << "'.\n"; return -1; } #ifdef TEST else { *logofs << "Socket: Set SO_LINGER values to " << linger_value.l_onoff << " and " << linger_value.l_linger << " on FD#" << fd << ".\n" << logofs_flush; } #endif return 1;}int SetSendBuffer(int fd, int size){ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0) { #ifdef PANIC *logofs << "Socket: PANIC! Failed to set SO_SNDBUF size to " << size << " on FD#" << fd << ". Error is " << EGET() << " '" << ESTR() << "'.\n" << logofs_flush; #endif cerr << "Error" << ": Failed to set SO_SNDBUF size to " << size << " on FD#" << fd << ". Error is " << EGET() << " '" << ESTR() << "'.\n"; return -1; } #ifdef TEST else { *logofs << "Socket: Set SO_SNDBUF on FD#" << fd << " to " << size << " bytes.\n" << logofs_flush; } #endif return 1;}int SetReceiveBuffer(int fd, int size){ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0) { #ifdef PANIC *logofs << "Socket: PANIC! Failed to set SO_RCVBUF size to " << size << " on FD#" << fd << ". Error is " << EGET() << " '" << ESTR() << "'.\n" << logofs_flush; #endif cerr << "Error" << ": Failed to set SO_RCVBUF size to " << size << " on FD#" << fd << ". Error is " << EGET() << " '" << ESTR() << "'.\n"; return -1; } #ifdef TEST else { *logofs << "Socket: Set SO_RCVBUF on FD#" << fd << " to " << size << " bytes.\n" << logofs_flush; } #endif return 1;}int SetNoDelay(int fd, int value){ int result = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value)); if (result == 0) { result = 1; } else if (result < 0) { #if defined(__APPLE__) || defined(__sun) if (EGET() == ENOPROTOOPT) { result = 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -