port.cc | port.cc | |||
---|---|---|---|---|
skipping to change at line 37 | skipping to change at line 37 | |||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
* | * | |||
*/ | */ | |||
#include <config.h> | #include "mem_config.h" | |||
#include <libtest/common.h> | #include <libtest/common.h> | |||
#include <cassert> | #include <cassert> | |||
#include <cstdlib> | #include <cstdlib> | |||
#include <cstring> | #include <cstring> | |||
#include <ctime> | #include <ctime> | |||
#include <fnmatch.h> | #include <fnmatch.h> | |||
#include <iostream> | #include <iostream> | |||
#include <sys/socket.h> | #include <sys/socket.h> | |||
#include <sys/stat.h> | #include <sys/stat.h> | |||
skipping to change at line 60 | skipping to change at line 60 | |||
#include <sys/wait.h> | #include <sys/wait.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#include <utility> | #include <utility> | |||
#include <vector> | #include <vector> | |||
#include <signal.h> | #include <signal.h> | |||
#include <libtest/signal.h> | #include <libtest/signal.h> | |||
#ifndef SOCK_CLOEXEC | ||||
# define SOCK_CLOEXEC 0 | ||||
#endif | ||||
#ifndef SOCK_NONBLOCK | ||||
# define SOCK_NONBLOCK 0 | ||||
#endif | ||||
#ifndef FD_CLOEXEC | ||||
# define FD_CLOEXEC 0 | ||||
#endif | ||||
#ifndef __INTEL_COMPILER | #ifndef __INTEL_COMPILER | |||
#pragma GCC diagnostic ignored "-Wold-style-cast" | #pragma GCC diagnostic ignored "-Wold-style-cast" | |||
#endif | #endif | |||
using namespace libtest; | using namespace libtest; | |||
struct socket_st { | struct socket_st { | |||
typedef std::vector< std::pair< int, in_port_t> > socket_port_t; | typedef std::vector< std::pair< int, in_port_t> > socket_port_t; | |||
socket_port_t _pair; | socket_port_t _pair; | |||
in_port_t last_port; | ||||
socket_st(): | ||||
last_port(0) | ||||
{ } | ||||
void release(in_port_t _arg) | void release(in_port_t _arg) | |||
{ | { | |||
for (socket_port_t::iterator iter= _pair.begin(); | for (socket_port_t::iterator iter= _pair.begin(); | |||
iter != _pair.end(); | iter != _pair.end(); | |||
++iter) | ++iter) | |||
{ | { | |||
if ((*iter).second == _arg) | if ((*iter).second == _arg) | |||
{ | { | |||
shutdown((*iter).first, SHUT_RDWR); | shutdown((*iter).first, SHUT_RDWR); | |||
skipping to change at line 119 | skipping to change at line 136 | |||
return global_port; | return global_port; | |||
} | } | |||
void release_port(in_port_t arg) | void release_port(in_port_t arg) | |||
{ | { | |||
all_socket_fd.release(arg); | all_socket_fd.release(arg); | |||
} | } | |||
in_port_t get_free_port() | in_port_t get_free_port() | |||
{ | { | |||
in_port_t ret_port= in_port_t(0); | const in_port_t default_port= in_port_t(-1); | |||
int retries= 1024; | int retries= 1024; | |||
in_port_t ret_port; | ||||
while (--retries) | while (--retries) | |||
{ | { | |||
ret_port= default_port; | ||||
int sd; | int sd; | |||
if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != -1) | if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != -1) | |||
{ | { | |||
int optval= 1; | int optval= 1; | |||
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != -1) | if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != -1) | |||
{ | { | |||
struct sockaddr_in sin; | struct sockaddr_in sin; | |||
sin.sin_port= 0; | sin.sin_port= 0; | |||
sin.sin_addr.s_addr= 0; | sin.sin_addr.s_addr= 0; | |||
sin.sin_addr.s_addr= INADDR_ANY; | sin.sin_addr.s_addr= INADDR_ANY; | |||
sin.sin_family= AF_INET; | sin.sin_family= AF_INET; | |||
if (bind(sd, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) ) ! | int bind_ret; | |||
= -1) | do | |||
{ | { | |||
socklen_t addrlen= sizeof(sin); | if ((bind_ret= bind(sd, (struct sockaddr *)&sin, sizeof(struct so | |||
ckaddr_in) )) != -1) | ||||
{ | ||||
socklen_t addrlen= sizeof(sin); | ||||
if (getsockname(sd, (struct sockaddr *)&sin, &addrlen) != -1) | if (getsockname(sd, (struct sockaddr *)&sin, &addrlen) != -1) | |||
{ | ||||
ret_port= sin.sin_port; | ||||
} | ||||
} | ||||
else | ||||
{ | { | |||
ret_port= sin.sin_port; | if (errno != EADDRINUSE) | |||
{ | ||||
Error << strerror(errno); | ||||
} | ||||
} | } | |||
} | ||||
} | ||||
all_socket_fd._pair.push_back(std::make_pair(sd, ret_port)); | if (errno == EADDRINUSE) | |||
{ | ||||
libtest::dream(2, 0); | ||||
} | ||||
} while (bind_ret == -1 and errno == EADDRINUSE); | ||||
all_socket_fd._pair.push_back(std::make_pair(sd, ret_port)); | ||||
} | ||||
else | ||||
{ | ||||
Error << strerror(errno); | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
Error << strerror(errno); | ||||
} | } | |||
if (ret_port > 1024) | if (ret_port == default_port) | |||
{ | ||||
Error << "no ret_port set:" << strerror(errno); | ||||
} | ||||
else if (ret_port > 1024 and ret_port != all_socket_fd.last_port) | ||||
{ | { | |||
break; | break; | |||
} | } | |||
} | } | |||
// We handle the case where if we max out retries, we still abort. | // We handle the case where if we max out retries, we still abort. | |||
if (retries == 0) | if (retries == 0) | |||
{ | { | |||
fatal_message("No port could be found, exhausted retry"); | fatal_message("No port could be found, exhausted retry"); | |||
} | } | |||
if (ret_port == 0) | if (ret_port == 0) | |||
{ | { | |||
fatal_message("No port could be found"); | fatal_message("No port could be found"); | |||
} | } | |||
if (ret_port == default_port) | ||||
{ | ||||
fatal_message("No port could be found"); | ||||
} | ||||
if (ret_port <= 1024) | if (ret_port <= 1024) | |||
{ | { | |||
fatal_message("No port could be found, though some where available belo w or at 1024"); | fatal_message("No port could be found, though some where available belo w or at 1024"); | |||
} | } | |||
all_socket_fd.last_port= ret_port; | ||||
release_port(ret_port); | ||||
return ret_port; | return ret_port; | |||
} | } | |||
} // namespace libtest | } // namespace libtest | |||
End of changes. 15 change blocks. | ||||
11 lines changed or deleted | 66 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |