summaryrefslogtreecommitdiff
path: root/support/dktools/dk4sock16.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk4sock16.ctr
Initial commit
Diffstat (limited to 'support/dktools/dk4sock16.ctr')
-rw-r--r--support/dktools/dk4sock16.ctr274
1 files changed, 274 insertions, 0 deletions
diff --git a/support/dktools/dk4sock16.ctr b/support/dktools/dk4sock16.ctr
new file mode 100644
index 0000000000..ebac56871b
--- /dev/null
+++ b/support/dktools/dk4sock16.ctr
@@ -0,0 +1,274 @@
+%% options
+
+copyright owner = Dirk Krause
+copyright year = 2015-xxxx
+license = bsd
+
+
+%% module
+
+#include "dk4sock.h"
+
+#include <stdio.h>
+
+#if !DK4_ON_WINDOWS
+#if DK4_HAVE_FCNTL_H
+#ifndef FCNTL_H_INCLUDED
+#include <fcntl.h>
+#define FCNTL_H_INCLUDED 1
+#endif
+#endif
+#endif
+
+#if DK4_HAVE_ERRNO_H
+#ifndef ERRNO_H_INCLUDED
+#include <errno.h>
+#define ERRNO_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_UNISTD_H
+#ifndef UNISTD_H_INCLUDED
+#include <unistd.h>
+#define UNISTD_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_IO_H
+#ifndef IO_H_INCLUDED
+#include <io.h>
+#define IO_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_STRING_H
+#ifndef STRING_H_INCLUDED
+#include <string.h>
+#define STRING_H_INCLUDED 1
+#endif
+#endif
+
+$!trace-include
+
+
+
+static
+dk4_socket_t
+dk4socket_tcp_client_cleanup_socket(
+ dk4_socket_t sock,
+ int level,
+ struct sockaddr *pAddr,
+ size_t szAddr
+)
+{
+#if 0
+ /* Setting SO_REUSEADDR or SO_REUSEPORT must follow socket()
+ immediately.
+ */
+ if ((0 < level) || ((NULL != pAddr) && (0 < szAddr))) {
+ (void)dk4socket_option_set_reuse(sock, 1, NULL);
+ }
+#endif
+
+#if DK4_ON_WINDOWS
+ closesocket(sock);
+#else
+ close(sock);
+#endif
+ return (INVALID_SOCKET);
+}
+
+
+
+static
+dk4_socket_t
+dk4socket_tcp_client_connect_attempt(
+ dk4_socket_t back,
+ struct sockaddr *pAddr,
+ size_t szAddr,
+ struct sockaddr *pLoAddr,
+ size_t szLoAddr,
+ long secs,
+ long usecs,
+ dk4_er_t *erp
+)
+{
+ fd_set wfds;
+ struct timeval to;
+#if (!DK4_ON_WINDOWS) && (DK4_HAVE_SETSOCKOPT) \
+ && defined(SOL_SOCKET) && defined(SO_ERROR)
+#if DK4_HAVE_SOCKLEN_T
+ socklen_t slo;
+#else
+ int slo;
+#endif
+ int err;
+#endif
+ int res;
+ $? "+ dk4socket_tcp_client_connect_attempt"
+ $? ". remote = PTR=%d %lu", TR_IPTR(pAddr), (unsigned long)szAddr
+ res = dk4socket_connect(back, pAddr, szAddr, erp);
+ switch (res) {
+ case DK4_SOCKET_RESULT_SUCCESS : { $? ". connected"
+ /* do nothing */
+ } break;
+ case DK4_SOCKET_RESULT_IN_PROGRESS : { $? ". in progress"
+ FD_ZERO(&wfds);
+ FD_SET(back, &wfds);
+ to.tv_sec = secs;
+ to.tv_usec = usecs;
+ dk4socket_error_reset();
+ res = select((((int)back) + 1), NULL, &wfds, NULL, &to);
+ if (0 < res) { $? ". select"
+ if (FD_ISSET(back, &wfds)) { $? ". in write set"
+#if (!DK4_ON_WINDOWS) && (DK4_HAVE_SETSOCKOPT) \
+ && defined(SOL_SOCKET) && defined(SO_ERROR)
+ err = 0;
+ slo = sizeof(err);
+ dk4socket_error_reset();
+ res = getsockopt(back, SOL_SOCKET, SO_ERROR, &err, &slo);
+ if (0 == res) { $? ". getsockopt ok"
+ if (0 != dk4socket_non_null_getsockopt(err, slo)) {
+ $? "! non-null from getsockopt"
+ dk4error_set_idetails(erp, DK4_E_SOCKET_CONNECT, err);
+ back = dk4socket_tcp_client_cleanup_socket(
+ back, 1, pLoAddr, szLoAddr
+ );
+ }
+#if VERSION_BEFORE_20160415
+ if (sizeof(int) != slo) {
+ if (0 != err) { $? "! error from getsockopt"
+ dk4error_set_idetails(erp, DK4_E_SOCKET_CONNECT, err);
+ back = dk4socket_tcp_client_cleanup_socket(
+ back, 1, pLoAddr, szLoAddr
+ );
+ }
+ } else { $? "! getsockopt (size)"
+ dk4socket_error_report(erp, DK4_E_SOCKET_GETSOCKOPT);
+ back = dk4socket_tcp_client_cleanup_socket(
+ back, 1, pLoAddr, szLoAddr
+ );
+ }
+#endif
+ } else { $? "! getsockopt"
+ dk4socket_error_report(erp, DK4_E_SOCKET_GETSOCKOPT);
+ back = dk4socket_tcp_client_cleanup_socket(back,1,pLoAddr,szLoAddr);
+ }
+#endif
+ } else { $? "! timeout (not in list)"
+ dk4error_set_simple_error_code(erp, DK4_E_SOCKET_TIMEOUT);
+ back = dk4socket_tcp_client_cleanup_socket(back,0,pLoAddr,szLoAddr);
+ }
+ } else {
+ if (0 > res) { $? "! select"
+ dk4socket_error_report(erp, DK4_E_SOCKET_SELECT);
+ } else { $? "! timeout (from select)"
+ dk4error_set_simple_error_code(erp, DK4_E_SOCKET_TIMEOUT);
+ }
+ back = dk4socket_tcp_client_cleanup_socket(back,0,pLoAddr,szLoAddr);
+ }
+ } break;
+ default : { $? "! failed"
+ back = dk4socket_tcp_client_cleanup_socket(back, 0, pLoAddr, szLoAddr);
+ } break;
+ }
+ $? "- dk4socket_tcp_client_connect_attempt %d", (int)back
+ return back;
+}
+
+
+
+dk4_socket_t
+dk4socket_tcp_client_for_addr(
+ int protfam,
+ struct sockaddr *pRemoteAddr,
+ size_t szRemoteAddr,
+ struct sockaddr *pLocalAddr,
+ size_t szLocalAddr,
+ long seconds,
+ long microSeconds,
+ dk4_er_t *erp
+)
+{
+ dk4_socket_t back = INVALID_SOCKET;
+ int res;
+#if DK4_HAVE_SETSOCKOPT && (defined(SO_REUSEPORT) || defined(SO_REUSEADDR))
+ int opt = 0;
+#endif
+ $? "+ dk4socket_tcp_client_for_addr"
+ if ((NULL != pRemoteAddr) && (0 < szRemoteAddr)) { $? ". args ok"
+ $? ". remote = PTR=%d %lu",TR_IPTR(pRemoteAddr),(unsigned long)szRemoteAddr
+ back = dk4socket_open(protfam, SOCK_STREAM, 0, erp);
+ if (INVALID_SOCKET != back) { $? ". socket"
+ if ((NULL != pLocalAddr) && (0 < szLocalAddr)) { $? ". must bind"
+#if DK4_HAVE_SETSOCKOPT && defined(SO_REUSEPORT)
+ $? ". SO_REUSEPORT"
+ dk4socket_set_one_bytes(&opt, sizeof(opt));
+ res = setsockopt(
+ back, SOL_SOCKET,
+ SO_REUSEPORT, (void *)(&opt), sizeof(opt)
+ );
+ if (0 != res) { $? "! failed to reuse port number"
+ }
+#else
+#if DK4_HAVE_SETSOCKOPT && defined(SO_REUSEADDR)
+ $? ". SO_REUSEADDR"
+ dk4socket_set_one_bytes(&opt, sizeof(opt));
+ res = setsockopt(
+ back, SOL_SOCKET,
+ SO_REUSEADDR, (void *)(&opt), sizeof(opt)
+ );
+ if (0 != res) { $? "! failed to reuse address"
+ }
+#else
+ $? ". neither SO_REUSEPORT nor SO_REUSEADDR"
+#endif
+#endif
+ res = dk4socket_bind(back, pLocalAddr, szLocalAddr, erp);
+ if (DK4_SOCKET_RESULT_FAILED == res) { $? "! bind"
+ back = dk4socket_tcp_client_cleanup_socket(
+ back, 0, pLocalAddr, szLocalAddr
+ );
+ }
+ }
+ if (INVALID_SOCKET != back) {
+ if ((0L != seconds) || (0L != microSeconds)) { $? ". use timeout"
+ res = dk4socket_option_set_nonblock(back, 1, erp);
+ if (DK4_SOCKET_RESULT_SUCCESS == res) { $? ". non-blocking"
+ back = dk4socket_tcp_client_connect_attempt(
+ back, pRemoteAddr, szRemoteAddr, pLocalAddr, szLocalAddr,
+ seconds, microSeconds, erp
+ );
+ if (INVALID_SOCKET != back) {
+ res = dk4socket_option_set_nonblock(back, 0, erp);
+ if (DK4_SOCKET_RESULT_SUCCESS != res) { $? "! back blocking"
+ back = dk4socket_tcp_client_cleanup_socket(
+ back, 1, pLocalAddr, szLocalAddr
+ );
+ }
+ }
+ } else { $? "! non-blocking"
+ back = dk4socket_tcp_client_cleanup_socket(
+ back, 0, pLocalAddr, szLocalAddr
+ );
+ }
+ } else { $? ". no timeout"
+ back = dk4socket_tcp_client_connect_attempt(
+ back, pRemoteAddr, szRemoteAddr, pLocalAddr, szLocalAddr,
+ 0L, 0L, erp
+ );
+ }
+ }
+ } else { $? "! socket"
+ $? "! errno=%d", errno
+ }
+ } else { $? "! args"
+ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
+ }
+ $? "- dk4socket_tcp_client_for_addr %d", (int)back
+ return back;
+}
+
+
+
+