diff --git a/src/Context.cc b/src/Context.cc index e50e1b85..080c0c88 100644 --- a/src/Context.cc +++ b/src/Context.cc @@ -185,6 +185,7 @@ Context::Context(bool standalone, // when none of network interface has IPv4 address. setDefaultAIFlags(0); } + SocketCore::setIpDscp(op->getAsInt(PREF_DSCP)); net::checkAddrconfig(); // Bind interface if(!op->get(PREF_INTERFACE).empty()) { diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 11f32620..a7ac5578 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -739,6 +739,15 @@ std::vector OptionHandlerFactory::createOptionHandlers() op->addTag(TAG_ADVANCED); handlers.push_back(op); } + { + OptionHandler* op(new NumberOptionHandler + (PREF_DSCP, + TEXT_DSCP, + "0", + 0)); + op->addTag(TAG_ADVANCED); + handlers.push_back(op); + } { OptionHandler* op(new BooleanOptionHandler (PREF_SELECT_LEAST_USED_HOST, diff --git a/src/PeerInitiateConnectionCommand.cc b/src/PeerInitiateConnectionCommand.cc index 384af239..4339d5de 100644 --- a/src/PeerInitiateConnectionCommand.cc +++ b/src/PeerInitiateConnectionCommand.cc @@ -83,6 +83,7 @@ bool PeerInitiateConnectionCommand::executeInternal() { createSocket(); getSocket()->establishConnection(getPeer()->getIPAddress(), getPeer()->getPort(), false); + getSocket()->applyIpDscp(); if(mseHandshakeEnabled_) { auto c = make_unique (getCuid(), requestGroup_, getPeer(), diff --git a/src/PeerListenCommand.cc b/src/PeerListenCommand.cc index 4c137e55..8bcd3f16 100644 --- a/src/PeerListenCommand.cc +++ b/src/PeerListenCommand.cc @@ -110,6 +110,7 @@ bool PeerListenCommand::execute() { std::shared_ptr peerSocket; try { peerSocket = socket_->acceptConnection(); + peerSocket->applyIpDscp(); std::pair peerInfo; peerSocket->getPeerInfo(peerInfo); diff --git a/src/SocketCore.cc b/src/SocketCore.cc index 74ebdb5c..fb78dc02 100644 --- a/src/SocketCore.cc +++ b/src/SocketCore.cc @@ -129,6 +129,7 @@ enum TlsState { } // namespace int SocketCore::protocolFamily_ = AF_UNSPEC; +int SocketCore::ipDscp_ = 0; std::vector > SocketCore::bindAddrs_; @@ -532,6 +533,11 @@ void SocketCore::setTcpNodelay(bool f) setSockOpt(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); } +void SocketCore::applyIpDscp() +{ + setSockOpt(IPPROTO_IP, IP_TOS, &ipDscp_, sizeof(ipDscp_)); +} + void SocketCore::setNonBlockingMode() { #ifdef __MINGW32__ diff --git a/src/SocketCore.h b/src/SocketCore.h index de7065d4..4442dc15 100644 --- a/src/SocketCore.h +++ b/src/SocketCore.h @@ -66,6 +66,7 @@ private: sock_t sockfd_; static int protocolFamily_; + static int ipDscp_; static std::vector > bindAddrs_; @@ -120,6 +121,14 @@ public: // Enables TCP_NODELAY socket option if f == true. void setTcpNodelay(bool f); + // Set DSCP byte + void applyIpDscp(); + static void setIpDscp(int ipDscp) + { + // Here we prepare DSCP value for IPTOS option, which sets whole DS field + ipDscp_ = ipDscp << 2; + } + void create(int family, int protocol = 0); void bindWithFamily(uint16_t port, int family, int flags = AI_PASSIVE); diff --git a/src/prefs.cc b/src/prefs.cc index b22286ff..2ffc976c 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -361,6 +361,8 @@ PrefPtr PREF_SAVE_SESSION_INTERVAL = makePref("save-session-interval"); PrefPtr PREF_ENABLE_COLOR = makePref("enable-color"); // value: string PrefPtr PREF_RPC_SECRET = makePref("rpc-secret"); +// values: 1*digit +PrefPtr PREF_DSCP = makePref("dscp"); /** * FTP related preferences diff --git a/src/prefs.h b/src/prefs.h index 76be3ee2..592bad9a 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -298,6 +298,8 @@ extern PrefPtr PREF_SAVE_SESSION_INTERVAL; extern PrefPtr PREF_ENABLE_COLOR; // value: string extern PrefPtr PREF_RPC_SECRET; +// values: 1*digit +extern PrefPtr PREF_DSCP; /** * FTP related preferences diff --git a/src/usage_text.h b/src/usage_text.h index facba928..3f22e555 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -966,3 +966,13 @@ _(" --enable-color[=true|false] Enable color output for a terminal.") #define TEXT_RPC_SECRET \ _(" --rpc-secret=TOKEN Set RPC secret authorization token.") +#define TEXT_DSCP \ + _(" --dscp=DSCP Set DSCP value in outgoing IP packets of\n" \ + " BitTorrent traffic for QoS. This parameter sets\n" \ + " only DSCP bits in TOS field of IP packets,\n" \ + " not the whole field. If you take values\n" \ + " from /usr/include/netinet/ip.h divide them by 4\n" \ + " (otherwise values would be incorrect, e.g. your CS1\n" \ + " class would turn into CS4). If you are take commonly\n" \ + " used values from RFC, network vendors' documentation,\n" \ + " Wikipedia or any other source, use them as they are.")