mirror of
https://github.com/data61/MP-SPDZ.git
synced 2026-01-09 13:37:58 -05:00
201 lines
6.6 KiB
C++
201 lines
6.6 KiB
C++
|
|
#include "sockets.h"
|
|
#include "Tools/Exceptions.h"
|
|
#include "Tools/time-func.h"
|
|
#include "Processor/OnlineOptions.h"
|
|
|
|
#include <iostream>
|
|
#include <fcntl.h>
|
|
using namespace std;
|
|
|
|
void error(const char *str, bool interrupted, size_t length)
|
|
{
|
|
int old_errno = errno;
|
|
char err[1000];
|
|
gethostname(err, 1000);
|
|
err[999] = 0;
|
|
string message = string() + "Fatal communication error on " + err + ": "
|
|
+ str + " (" + strerror(old_errno) + ")";
|
|
if (length)
|
|
message += " when sending " + to_string(length) + " bytes";
|
|
if (interrupted)
|
|
message += "\nThis is probably because another party encountered a problem.";
|
|
exit_error(message);
|
|
}
|
|
|
|
void set_up_client_socket(int& mysocket,const char* hostname,int Portnum)
|
|
{
|
|
struct addrinfo hints, *ai=NULL,*rp;
|
|
memset (&hints, 0, sizeof(hints));
|
|
hints.ai_family = AF_INET;
|
|
hints.ai_flags = AI_CANONNAME;
|
|
|
|
char my_name[512];
|
|
memset(my_name,0,512*sizeof(octet));
|
|
gethostname((char*)my_name,512);
|
|
|
|
int erp;
|
|
for (int i = 0; i < CONNECTION_TIMEOUT; i++)
|
|
{ erp=getaddrinfo (hostname, NULL, &hints, &ai);
|
|
if (erp == 0)
|
|
{ break; }
|
|
else
|
|
{ cerr << "getaddrinfo on " << my_name << " has returned '" << gai_strerror(erp) <<
|
|
"' for " << hostname << ", trying again in a second ..." << endl;
|
|
if (ai)
|
|
freeaddrinfo(ai);
|
|
sleep(1);
|
|
}
|
|
}
|
|
if (erp!=0)
|
|
{ error("set_up_socket:getaddrinfo"); }
|
|
|
|
bool success = false;
|
|
socklen_t len = 0;
|
|
const struct sockaddr* addr = 0;
|
|
for (rp=ai; rp!=NULL; rp=rp->ai_next)
|
|
{ addr = ai->ai_addr;
|
|
|
|
if (ai->ai_family == AF_INET)
|
|
{
|
|
len = ai->ai_addrlen;
|
|
success = true;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (not success)
|
|
{
|
|
for (rp = ai; rp != NULL; rp = rp->ai_next)
|
|
cerr << "Family on offer: " << ai->ai_family << endl;
|
|
exit_error(string("No AF_INET for ") + (char*)hostname + " on " + (char*)my_name);
|
|
}
|
|
|
|
|
|
Timer timer;
|
|
timer.start();
|
|
struct sockaddr_in* addr4 = (sockaddr_in*) addr;
|
|
addr4->sin_port = htons(Portnum); // set destination port number
|
|
#ifdef DEBUG_IPV4
|
|
cout << "connect to ip " << hex << addr4->sin_addr.s_addr << " port " << addr4->sin_port << dec << endl;
|
|
#endif
|
|
|
|
int attempts = 0;
|
|
long wait = 1;
|
|
int fl;
|
|
int connect_errno;
|
|
do
|
|
{
|
|
mysocket = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (mysocket < 0)
|
|
error("set_up_socket:socket");
|
|
|
|
fl = connect(mysocket, addr, len);
|
|
connect_errno = errno;
|
|
attempts++;
|
|
if (fl != 0)
|
|
{
|
|
close(mysocket);
|
|
usleep(wait < 1000 ? wait *= 2 : wait);
|
|
if (OnlineOptions::singleton.has_option("debug_networking"))
|
|
{
|
|
string msg = "Connecting to " + string(hostname) + ":"
|
|
+ to_string(Portnum) + " failed";
|
|
errno = connect_errno;
|
|
perror(msg.c_str());
|
|
}
|
|
}
|
|
errno = connect_errno;
|
|
}
|
|
while (fl == -1 &&
|
|
(errno == ECONNREFUSED || errno == ETIMEDOUT || errno == EINPROGRESS || errno == ECONNRESET) &&
|
|
timer.elapsed() < CONNECTION_TIMEOUT);
|
|
|
|
if (fl < 0)
|
|
{
|
|
exit_error(
|
|
string() + "cannot connect from " + my_name + " to " + hostname + ":"
|
|
+ to_string(Portnum) + " after " + to_string(attempts)
|
|
+ " attempts in " + to_string(CONNECTION_TIMEOUT)
|
|
+ " seconds because " + strerror(connect_errno) + ". "
|
|
"https://mp-spdz.readthedocs.io/en/latest/troubleshooting.html#"
|
|
"connection-failures has more information on port requirements.");
|
|
}
|
|
|
|
freeaddrinfo(ai);
|
|
|
|
if (OnlineOptions::singleton.has_option("time_connect"))
|
|
cerr << "Connection took " << timer.elapsed() << " seconds." << endl;
|
|
|
|
/* disable Nagle's algorithm */
|
|
int one=1;
|
|
fl= setsockopt(mysocket, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(int));
|
|
if (fl<0) { error("set_up_socket:setsockopt"); }
|
|
|
|
|
|
/*
|
|
* The following code block is either taken directly from or derived from the solutions posted at:
|
|
* https://stackoverflow.com/questions/20188718/configuring-tcp-keep-alive-with-boostasio
|
|
* https://stackoverflow.com/questions/23669005/tcp-keepalive-protocol-not-available
|
|
*/
|
|
unsigned int timeout_milli = 10000;
|
|
|
|
#if (defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT)
|
|
int32_t timeout = timeout_milli;
|
|
fl = setsockopt(mysocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
|
|
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_RCVTIMEO)"); }
|
|
|
|
fl = setsockopt(mysocket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout));
|
|
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_SNDTIMEO)"); }
|
|
|
|
#else
|
|
struct timeval tv;
|
|
tv.tv_sec = timeout_milli / 1000;
|
|
tv.tv_usec = (timeout_milli % 1000) * 1000;
|
|
|
|
fl = setsockopt(mysocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
|
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_RCVTIMEO)"); }
|
|
|
|
fl = setsockopt(mysocket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
|
|
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_RCVTIMEO)"); }
|
|
|
|
int enable_keepalive = 1;
|
|
int keepalive_strobe_interval_secs = 3;
|
|
int num_keepalive_strobes = 5;
|
|
|
|
fl = setsockopt(mysocket, SOL_SOCKET, SO_KEEPALIVE,(char *)&enable_keepalive, sizeof(enable_keepalive));
|
|
if (fl<0) { error("set_tcp_keepalive:setsockopt(SOL_SOCKET, SO_KEEPALIVE)"); }
|
|
|
|
#ifdef TCP_KEEPIDLE
|
|
int keepalive_idle_time_secs = 1;
|
|
fl = setsockopt(mysocket, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keepalive_idle_time_secs, sizeof(keepalive_idle_time_secs));
|
|
if (fl<0) { error("set_tcp_keepalive:setsockopt(IPPROTO_TCP, TCP_KEEPIDLE)"); }
|
|
#endif
|
|
|
|
fl = setsockopt(mysocket, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&keepalive_strobe_interval_secs, sizeof(keepalive_strobe_interval_secs));
|
|
if (fl<0) { error("set_tcp_keepalive:setsockopt(IPPROTO_TCP, TCP_KEEPINTVL)"); }
|
|
|
|
setsockopt(mysocket, IPPROTO_TCP, TCP_KEEPCNT, (char *)&num_keepalive_strobes, sizeof(num_keepalive_strobes));
|
|
if (fl<0) { error("set_tcp_keepalive:setsockopt(IPPROTO_TCP, TCP_KEEPCNT)"); }
|
|
|
|
#endif
|
|
/* End third-party code */
|
|
|
|
#ifdef __APPLE__
|
|
int flags = fcntl(mysocket, F_GETFL, 0);
|
|
fl = fcntl(mysocket, F_SETFL, O_NONBLOCK | flags);
|
|
if (fl < 0)
|
|
error("set non-blocking on client");
|
|
#endif
|
|
}
|
|
|
|
void close_client_socket(int socket)
|
|
{
|
|
if (close(socket))
|
|
{
|
|
char tmp[1000];
|
|
snprintf(tmp, 1000, "close(%d)", socket);
|
|
error(tmp);
|
|
}
|
|
}
|