From 948eff1374dec4bd763eb8d5e0da21a9c4f1105d Mon Sep 17 00:00:00 2001
From: "Wesley W. Terpstra" <w.terpstra@gsi.de>
Date: Thu, 23 Feb 2012 11:09:36 +0000
Subject: [PATCH] Add an accept method for TCP support

---
 api/transport/posix-ip.h   | 12 ++++++++----
 api/transport/posix-tcp.c  | 30 ++++++++++++++++++++++++++++++
 api/transport/posix-tcp.h  |  1 +
 api/transport/posix-udp.c  |  5 +++++
 api/transport/posix-udp.h  |  1 +
 api/transport/ssh.c        |  5 +++++
 api/transport/ssh.h        |  1 +
 api/transport/transport.h  |  4 +++-
 api/transport/transports.c |  9 ++++++---
 9 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/api/transport/posix-ip.h b/api/transport/posix-ip.h
index 195ac25..b70c2f1 100644
--- a/api/transport/posix-ip.h
+++ b/api/transport/posix-ip.h
@@ -28,8 +28,6 @@
 #ifndef EB_POSIX_IP_H
 #define EB_POSIX_IP_H
 
-#include "../etherbone.h"
-
 #ifdef __WIN32
 #define _WIN32_WINNT 0x0501
 #include <winsock2.h>
@@ -38,6 +36,7 @@
 typedef int socklen_t;
 typedef SOCKET eb_posix_sock_t;
 #else
+#define _GNU_SOURCE
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
@@ -46,14 +45,19 @@ typedef SOCKET eb_posix_sock_t;
 #include <netinet/in.h>
 #include <netdb.h>
 #include <unistd.h>
-typedef eb_descriptor_t eb_posix_sock_t;
 #endif
 
-#ifdef MSG_DONTWAIT
+#include "../etherbone.h"
+
+typedef eb_descriptor_t eb_posix_sock_t;
+
+#if defined(MSG_DONTWAIT) && defined(SOCK_NONBLOCK)
 #define EB_POSIX_IP_NON_BLOCKING_NOOP
 #else
+#ifndef MSG_DONTWAIT
 #define MSG_DONTWAIT 0
 #endif
+#endif
 
 EB_PRIVATE void eb_posix_ip_close(eb_posix_sock_t sock);
 EB_PRIVATE eb_posix_sock_t eb_posix_ip_open(int type, const char* port);
diff --git a/api/transport/posix-tcp.c b/api/transport/posix-tcp.c
index 32166c4..8eebfd7 100644
--- a/api/transport/posix-tcp.c
+++ b/api/transport/posix-tcp.c
@@ -45,6 +45,8 @@ eb_status_t eb_posix_tcp_open(struct eb_transport* transportp, const char* port)
     eb_posix_ip_close(sock);
     return EB_ADDRESS; 
   }
+
+    eb_posix_ip_non_blocking(sock, 1);
   
   transport = (struct eb_posix_tcp_transport*)transportp;
   transport->port = sock;
@@ -150,3 +152,31 @@ void eb_posix_tcp_send(struct eb_transport* transportp, struct eb_link* linkp, u
 
   send(link->socket, (const char*)buf, len, 0);
 }
+
+int eb_posix_tcp_accept(struct eb_transport* transportp, struct eb_link* result_linkp) {
+  struct eb_posix_tcp_transport* transport;
+  struct eb_posix_tcp_link* result_link;
+  eb_posix_sock_t sock;
+  
+  transport = (struct eb_posix_tcp_transport*)transportp;
+  
+#ifdef EB_POSIX_IP_NON_BLOCKING_NOOP
+  sock = accept4(transport->port, 0, 0, SOCK_NONBLOCK);
+#else
+  sock = accept(transport->port, 0, 0);
+#endif
+
+  if (sock == -1) {
+    if (errno != EAGAIN) return -1;
+    return 0;
+  }
+  
+  if (result_linkp != 0) {
+    result_link = (struct eb_posix_tcp_link*)result_linkp;
+    result_link->socket = sock;
+    return 1;
+  } else {
+    eb_posix_ip_close(sock);
+    return 0;
+  }
+}
diff --git a/api/transport/posix-tcp.h b/api/transport/posix-tcp.h
index 5a19d1b..589472e 100644
--- a/api/transport/posix-tcp.h
+++ b/api/transport/posix-tcp.h
@@ -42,6 +42,7 @@ EB_PRIVATE eb_descriptor_t eb_posix_tcp_fdes(struct eb_transport*, struct eb_lin
 EB_PRIVATE int eb_posix_tcp_poll(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
 EB_PRIVATE int eb_posix_tcp_recv(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
 EB_PRIVATE void eb_posix_tcp_send(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
+EB_PRIVATE int eb_posix_tcp_accept(struct eb_transport*, struct eb_link* result_link);
 
 struct eb_posix_tcp_transport {
   /* Contents must fit in 9 bytes */
diff --git a/api/transport/posix-udp.c b/api/transport/posix-udp.c
index 145305f..12e1f56 100644
--- a/api/transport/posix-udp.c
+++ b/api/transport/posix-udp.c
@@ -148,3 +148,8 @@ void eb_posix_udp_send(struct eb_transport* transportp, struct eb_link* linkp, u
   else
     sendto(transport->socket, (const char*)buf, len, 0, (struct sockaddr*)link->sa, link->sa_len);
 }
+
+int eb_posix_udp_accept(struct eb_transport* transportp, struct eb_link* result_linkp) {
+  /* UDP does not make child connections */
+  return 0;
+}
diff --git a/api/transport/posix-udp.h b/api/transport/posix-udp.h
index 75f0858..d883b0f 100644
--- a/api/transport/posix-udp.h
+++ b/api/transport/posix-udp.h
@@ -42,6 +42,7 @@ EB_PRIVATE eb_descriptor_t eb_posix_udp_fdes(struct eb_transport*, struct eb_lin
 EB_PRIVATE int eb_posix_udp_poll(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
 EB_PRIVATE int eb_posix_udp_recv(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
 EB_PRIVATE void eb_posix_udp_send(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
+EB_PRIVATE int eb_posix_udp_accept(struct eb_transport*, struct eb_link* result_link);
 
 struct eb_posix_udp_transport {
   /* Contents must fit in 9 bytes */
diff --git a/api/transport/ssh.c b/api/transport/ssh.c
index 193d7b2..728cf34 100644
--- a/api/transport/ssh.c
+++ b/api/transport/ssh.c
@@ -161,3 +161,8 @@ void eb_ssh_send(struct eb_transport* transportp, struct eb_link* linkp, uint8_t
 
   send(link->socket, (const char*)buf, len, 0);
 }
+
+int eb_ssh_accept(struct eb_transport* transportp, struct eb_link* result_linkp) {
+  /* SSH does not make child connections */
+  return 0;
+}
diff --git a/api/transport/ssh.h b/api/transport/ssh.h
index 1933fdb..5b60470 100644
--- a/api/transport/ssh.h
+++ b/api/transport/ssh.h
@@ -40,6 +40,7 @@ EB_PRIVATE eb_descriptor_t eb_ssh_fdes(struct eb_transport* transportp, struct e
 EB_PRIVATE int eb_ssh_poll(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
 EB_PRIVATE int eb_ssh_recv(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
 EB_PRIVATE void eb_ssh_send(struct eb_transport* transportp, struct eb_link* linkp, uint8_t* buf, int len);
+EB_PRIVATE int eb_ssh_accept(struct eb_transport*, struct eb_link* result_link);
 
 struct eb_ssh_transport {
 };
diff --git a/api/transport/transport.h b/api/transport/transport.h
index c1abd62..7ef8e4b 100644
--- a/api/transport/transport.h
+++ b/api/transport/transport.h
@@ -61,9 +61,11 @@ struct eb_transport_ops {
    eb_descriptor_t (*fdes)(struct eb_transport*, struct eb_link* link);
    
    /* IO functions. -1 means close link. 0 means no data at the moment. */
-   int  (*poll)(struct eb_transport*, struct eb_link* link, uint8_t* buf, int len); /* !!! somehow create device */
+   int  (*poll)(struct eb_transport*, struct eb_link* link, uint8_t* buf, int len);
    int  (*recv)(struct eb_transport*, struct eb_link* link, uint8_t* buf, int len);
    void (*send)(struct eb_transport*, struct eb_link* link, uint8_t* buf, int len);
+   
+   int  (*accept)(struct eb_transport*, struct eb_link* result_link);
 };
 
 /* The table of all supported transports */
diff --git a/api/transport/transports.c b/api/transport/transports.c
index b4ed89f..b9c94b9 100644
--- a/api/transport/transports.c
+++ b/api/transport/transports.c
@@ -42,7 +42,8 @@ struct eb_transport_ops eb_transports[] = {
     eb_posix_udp_fdes,
     eb_posix_udp_poll,
     eb_posix_udp_recv,
-    eb_posix_udp_send
+    eb_posix_udp_send,
+    eb_posix_udp_accept
   },
   {
     EB_POSIX_TCP_MTU,
@@ -53,7 +54,8 @@ struct eb_transport_ops eb_transports[] = {
     eb_posix_tcp_fdes,
     eb_posix_tcp_poll,
     eb_posix_tcp_recv,
-    eb_posix_tcp_send
+    eb_posix_tcp_send,
+    eb_posix_tcp_accept
   },
   {
     EB_SSH_MTU,
@@ -64,7 +66,8 @@ struct eb_transport_ops eb_transports[] = {
     eb_ssh_fdes,
     eb_ssh_poll,
     eb_ssh_recv,
-    eb_ssh_send
+    eb_ssh_send,
+    eb_ssh_accept
   }
 };
 
-- 
GitLab