LOG_INFO("FD(%d) connected\n", fd);
close_on_exec(fd);
disable_tcp_nagle(fd);
+ keep_alive(fd, 1, SDB_KEEPALIVE_CNT, SDB_KEEPALIVE_IDLE, SDB_KEEPALIVE_INTVL);
char serial[100];
snprintf(serial, sizeof(serial), "%s:%d", host, port);
if (fd >= 0) {
D("connected on remote on fd '%d', port '%d'\n", fd, sdb_port);
+ keep_alive(fd, 1, SDB_KEEPALIVE_CNT, SDB_KEEPALIVE_IDLE, SDB_KEEPALIVE_INTVL);
close_on_exec(fd);
disable_tcp_nagle(fd);
return utils_backend->close_on_exec(fd);
}
+void keep_alive(int fd, int onoff, int cnt, int idle, int interval) {
+ return utils_backend->keep_alive(fd, onoff, cnt, idle, interval);
+}
+
int sdb_socket_accept(int serverfd) {
LOG_INFO("FD(%d)\n");
return utils_backend->sdb_socket_accept(serverfd);
int unix_unlink(const char* path);
int sdb_mkdir(const char* path, int mode);
void close_on_exec(int fd);
+void keep_alive(int fd, int onoff, int cnt, int idle, int interval);
int sdb_socket_accept(int serverfd);
int sdb_socketpair(int sv[2]);
void sdb_sleep_ms(int mseconds);
int sdb_getpeername(int fd, struct sockaddr *addr, int *sockaddr_len);
// sockets
-#define LISTEN_BACKLOG 4
+#define LISTEN_BACKLOG (4)
#define SDB_MAX_CONNECT_TIMEOUT (10.0f)
#define SDB_DEFAULT_CONNECT_TIMEOUT (1.0f)
+#define SDB_KEEPALIVE_CNT (9)
+#define SDB_KEEPALIVE_IDLE (1)
+#define SDB_KEEPALIVE_INTVL (1)
int sdb_host_connect(const char *host, int port, int type);
int sdb_host_connect_timeout(const char *host, int port, int type, double timeout);
int (*sdb_close)(int fd);
int (*sdb_mkdir)(const char* path, int mode);
void (*close_on_exec)(int fd);
+ void (*keep_alive)(int fd, int onoff, int cnt, int idle, int interval);
int (*sdb_socket_accept)(int serverfd);
int (*sdb_socketpair)(int sv[2]);
void (*sdb_sleep_ms)(int mseconds);
LOG_ERROR("failed to set the file descriptor '%d': %s",fd ,strerror(errno));
}
+static void _keep_alive(int fd, int onoff, int cnt, int idle, int interval)
+{
+ int ret = -1;
+
+ ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof(onoff));
+ if (ret == -1) {
+ LOG_ERROR("failed to set keep alive option. FD(%d), error=%s\n", fd, strerror(errno));
+ return;
+ }
+
+ /* override /proc/sys/net/ipv4/tcp_keepalive_probes */
+ ret = setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));
+ if (ret == -1) {
+ LOG_ERROR("failed to set keep count option. FD(%d), error=%s\n", fd, strerror(errno));
+ return;
+ }
+
+ /* override /proc/sys/net/ipv4/tcp_keepalive_time */
+ ret = setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &idle, sizeof(idle));
+ if (ret == -1) {
+ LOG_ERROR("failed to set keep idle option. FD(%d), error=%s\n", fd, strerror(errno));
+ return;
+ }
+
+ /* override /proc/sys/net/ipv4/tcp_keepalive_intvl */
+ ret = setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
+ if (ret == -1) {
+ LOG_ERROR("failed to set keep interval option. FD(%d), error=%s\n", fd, strerror(errno));
+ return;
+ }
+
+ LOG_INFO("Success to set keep alive option. FD(%d), onoff=%d, cnt=%d, idle=%d(sec), interval=%d(sec)\n", onoff, cnt, idle, interval);
+}
+
static int _sdb_open( const char* pathname, int options )
{
int fd = open( pathname, options );
.sdb_transport_close = _sdb_close,
.sdb_close = _sdb_close,
.close_on_exec = _close_on_exec,
+ .keep_alive = _keep_alive,
.sdb_mkdir = _sdb_mkdir,
.sdb_socket_accept = _sdb_socket_accept,
.sdb_socketpair = _sdb_socketpair,
/* nothing really */
}
+/* XXX: Include the mstcpip.h.
+ * Defines tcp_keepalive structure and SIO_KEEPALIVE_VALS manually,
+ * because mstcpip.h is not supported in mingw32. */
+struct tcp_keepalive {
+ u_long onoff;
+ u_long keepalivetime;
+ u_long keepaliveinterval;
+};
+#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
+
+static void _keep_alive(int fd, int onoff, int cnt, int idle, int interval) {
+ SDB_HANDLE* sdb_handle = sdb_handle_map_get(fd);
+ SOCKET s;
+ struct tcp_keepalive keep_alive, out_keep_alive;
+ DWORD outBytes;
+ int ret = 0;
+
+ if (sdb_handle == NULL) {
+ LOG_ERROR("FD(%d) not exists\n", fd);
+ return;
+ }
+ s = sdb_handle->u.socket;
+
+ keep_alive.onoff = onoff;
+ /* specifies the timeout in milliseconds,
+ * with no activity until the first keep-alive packet is sent. */
+ keep_alive.keepalivetime = idle * 1000;
+ /* specifies the interval in milliseconds,
+ * between when successive keep-alive packet are sent if no acknowledgment is received. */
+ keep_alive.keepaliveinterval = interval * 1000;
+
+ ret = WSAIoctl(s, SIO_KEEPALIVE_VALS, &keep_alive, sizeof(keep_alive),
+ &out_keep_alive, sizeof(out_keep_alive), &outBytes, NULL, NULL);
+ if (ret == SOCKET_ERROR) {
+ LOG_ERROR("Failed to set keep alive option. FD(%d), GetLastError=%ld\n", fd, WSAGetLastError());
+ return;
+ }
+
+ LOG_INFO("Success to set keep alive option. FD(%d), onoff=%d, idle=%d(sec), interval=%d(sec)\n", onoff, idle, interval);
+}
+
static void _sdb_sleep_ms(int mseconds) {
Sleep(mseconds);
}
.sdb_transport_close = _sdb_transport_close,
.sdb_close = _sdb_close,
.close_on_exec = _close_on_exec,
+ .keep_alive = _keep_alive,
.sdb_mkdir = _sdb_mkdir,
.sdb_socket_accept = _sdb_socket_accept,
.sdb_socketpair = _sdb_socketpair,