![]() |
libzmq master
The Intelligent Transport Layer
|
00001 /* 00002 Copyright (c) 2010-2011 250bpm s.r.o. 00003 Copyright (c) 2007-2009 iMatix Corporation 00004 Copyright (c) 2007-2011 Other contributors as noted in the AUTHORS file 00005 00006 This file is part of 0MQ. 00007 00008 0MQ is free software; you can redistribute it and/or modify it under 00009 the terms of the GNU Lesser General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 0MQ is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU Lesser General Public License for more details. 00017 00018 You should have received a copy of the GNU Lesser General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. 00020 */ 00021 00022 #include "ip.hpp" 00023 #include "err.hpp" 00024 #include "platform.hpp" 00025 00026 #if defined ZMQ_HAVE_WINDOWS 00027 #include "windows.hpp" 00028 #else 00029 #include <fcntl.h> 00030 #include <sys/types.h> 00031 #include <sys/socket.h> 00032 #include <netinet/in.h> 00033 #include <netinet/tcp.h> 00034 #endif 00035 00036 #if defined ZMQ_HAVE_OPENVMS 00037 #include <ioctl.h> 00038 #endif 00039 00040 zmq::fd_t zmq::open_socket (int domain_, int type_, int protocol_) 00041 { 00042 // Setting this option result in sane behaviour when exec() functions 00043 // are used. Old sockets are closed and don't block TCP ports etc. 00044 #if defined ZMQ_HAVE_SOCK_CLOEXEC 00045 type_ |= SOCK_CLOEXEC; 00046 #endif 00047 00048 fd_t s = socket (domain_, type_, protocol_); 00049 if (s == retired_fd) 00050 return retired_fd; 00051 00052 // If there's no SOCK_CLOEXEC, let's try the second best option. Note that 00053 // race condition can cause socket not to be closed (if fork happens 00054 // between socket creation and this point). 00055 #if !defined ZMQ_HAVE_SOCK_CLOEXEC && defined FD_CLOEXEC 00056 int rc = fcntl (s, F_SETFD, FD_CLOEXEC); 00057 errno_assert (rc != -1); 00058 #endif 00059 00060 return s; 00061 } 00062 00063 void zmq::tune_tcp_socket (fd_t s_) 00064 { 00065 // Disable Nagle's algorithm. We are doing data batching on 0MQ level, 00066 // so using Nagle wouldn't improve throughput in anyway, but it would 00067 // hurt latency. 00068 int nodelay = 1; 00069 int rc = setsockopt (s_, IPPROTO_TCP, TCP_NODELAY, (char*) &nodelay, 00070 sizeof (int)); 00071 #ifdef ZMQ_HAVE_WINDOWS 00072 wsa_assert (rc != SOCKET_ERROR); 00073 #else 00074 errno_assert (rc == 0); 00075 #endif 00076 00077 #ifdef ZMQ_HAVE_OPENVMS 00078 // Disable delayed acknowledgements as they hurt latency is serious manner. 00079 int nodelack = 1; 00080 rc = setsockopt (s_, IPPROTO_TCP, TCP_NODELACK, (char*) &nodelack, 00081 sizeof (int)); 00082 errno_assert (rc != SOCKET_ERROR); 00083 #endif 00084 } 00085 00086 void zmq::unblock_socket (fd_t s_) 00087 { 00088 #ifdef ZMQ_HAVE_WINDOWS 00089 u_long nonblock = 1; 00090 int rc = ioctlsocket (s_, FIONBIO, &nonblock); 00091 wsa_assert (rc != SOCKET_ERROR); 00092 #elif ZMQ_HAVE_OPENVMS 00093 int nonblock = 1; 00094 int rc = ioctl (s_, FIONBIO, &nonblock); 00095 errno_assert (rc != -1); 00096 #else 00097 int flags = fcntl (s_, F_GETFL, 0); 00098 if (flags == -1) 00099 flags = 0; 00100 int rc = fcntl (s_, F_SETFL, flags | O_NONBLOCK); 00101 errno_assert (rc != -1); 00102 #endif 00103 } 00104 00105 void zmq::enable_ipv4_mapping (fd_t s_) 00106 { 00107 #ifdef IPV6_V6ONLY 00108 #ifdef ZMQ_HAVE_WINDOWS 00109 DWORD flag = 0; 00110 #else 00111 int flag = 0; 00112 #endif 00113 int rc = setsockopt (s_, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &flag, 00114 sizeof (flag)); 00115 #ifdef ZMQ_HAVE_WINDOWS 00116 wsa_assert (rc != SOCKET_ERROR); 00117 #else 00118 errno_assert (rc == 0); 00119 #endif 00120 #endif 00121 } 00122