...and close-unix-server-socket.
}
Tchannel
-OS_server_connection_accept (Tchannel channel,
+OS_tcp_server_connection_accept (Tchannel channel,
void * peer_host, unsigned int * peer_port)
{
static struct sockaddr_in address;
}
Tchannel
-OS_server_connection_accept (Tchannel channel,
+OS_tcp_server_connection_accept (Tchannel channel,
void * peer_host, unsigned int * peer_port)
{
static struct sockaddr_in address;
channel_type_unix_fifo,
channel_type_terminal,
channel_type_unix_pty_master,
+ channel_type_unix_server_socket,
channel_type_unix_stream_socket,
channel_type_tcp_stream_socket,
channel_type_tcp_server_socket,
}
static Tchannel
-arg_server_socket (unsigned int arg)
+arg_tcp_server_socket (unsigned int arg)
{
Tchannel server_socket = (arg_nonnegative_integer (arg));
if ((OS_channel_type (server_socket)) != channel_type_tcp_server_socket)
return (server_socket);
}
+#ifdef HAVE_UNIX_SOCKETS
+static Tchannel
+arg_unix_server_socket (unsigned int arg)
+{
+ Tchannel server_socket = (arg_nonnegative_integer (arg));
+ if ((OS_channel_type (server_socket)) != channel_type_unix_server_socket)
+ error_bad_range_arg (arg);
+ return (server_socket);
+}
+#endif /* HAVE_UNIX_SOCKETS */
+
#else /* not HAVE_SOCKETS */
#define SOCKET_CODE(code) \
});
}
+DEFINE_PRIMITIVE ("CREATE-UNIX-SERVER-SOCKET", Prim_create_unix_server_socket, 2, 2, 0)
+{
+ PRIMITIVE_HEADER (2);
+ CHECK_ARG (2, WEAK_PAIR_P);
+#ifdef HAVE_UNIX_SOCKETS
+ {
+ Tchannel channel = OS_create_unix_server_socket (STRING_ARG (1));
+ if (channel == NO_CHANNEL)
+ PRIMITIVE_RETURN (SHARP_F);
+ SET_PAIR_CDR ((ARG_REF (2)), (long_to_integer (channel)));
+ PRIMITIVE_RETURN (SHARP_T);
+ }
+#else
+ signal_error_from_primitive (ERR_UNIMPLEMENTED_PRIMITIVE);
+ PRIMITIVE_RETURN (UNSPECIFIC);
+#endif
+}
+
DEFINE_PRIMITIVE ("BIND-TCP-SERVER-SOCKET", Prim_bind_tcp_server_socket, 3, 3, 0)
{
PRIMITIVE_HEADER (3);
SOCKET_CODE
({
- OS_bind_tcp_server_socket ((arg_server_socket (1)),
+ OS_bind_tcp_server_socket ((arg_tcp_server_socket (1)),
(arg_host (2)),
(arg_nonnegative_integer (3)));
PRIMITIVE_RETURN (UNSPECIFIC);
PRIMITIVE_HEADER (1);
SOCKET_CODE
({
- OS_listen_tcp_server_socket (arg_server_socket (1));
+ OS_listen_tcp_server_socket (arg_tcp_server_socket (1));
PRIMITIVE_RETURN (UNSPECIFIC);
});
}
CHECK_ARG (3, WEAK_PAIR_P);
SOCKET_CODE
({
- Tchannel server_socket = (arg_server_socket (1));
+ Tchannel server_socket = (arg_tcp_server_socket (1));
void * peer_host = (((ARG_REF (2)) == SHARP_F) ? 0 : (arg_host (2)));
Tchannel connection =
- (OS_server_connection_accept (server_socket, peer_host, 0));
+ (OS_tcp_server_connection_accept (server_socket, peer_host, 0));
if (connection == NO_CHANNEL)
PRIMITIVE_RETURN (SHARP_F);
SET_PAIR_CDR ((ARG_REF (3)), (long_to_integer (connection)));
PRIMITIVE_RETURN (SHARP_T);
});
}
+
+DEFINE_PRIMITIVE ("NEW-UNIX-SERVER-CONNECTION-ACCEPT",
+ Prim_new_unix_server_connection_accept, 2, 2,
+ "Poll SERVER-SOCKET for a connection.\n\
+If a connection is available, it is opened and #T is returned;\n\
+the opened socket is stored in the cdr of WEAK-PAIR.\n\
+Otherwise, if SERVER-SOCKET is non-blocking, returns #F.")
+{
+ PRIMITIVE_HEADER (2);
+ CHECK_ARG (2, WEAK_PAIR_P);
+#ifdef HAVE_UNIX_SOCKETS
+ {
+ Tchannel server_socket = (arg_unix_server_socket (1));
+ Tchannel connection =
+ (OS_unix_server_connection_accept (server_socket));
+ if (connection == NO_CHANNEL)
+ PRIMITIVE_RETURN (SHARP_F);
+ SET_PAIR_CDR ((ARG_REF (2)), (long_to_integer (connection)));
+ PRIMITIVE_RETURN (SHARP_T);
+ }
+#else
+ signal_error_from_primitive (ERR_UNIMPLEMENTED_PRIMITIVE);
+ PRIMITIVE_RETURN (UNSPECIFIC);
+#endif
+}
(syscall_listen,
(UX_listen ((CHANNEL_DESCRIPTOR (channel)), SOCKET_LISTEN_BACKLOG)));
}
-\f
+
+#ifdef HAVE_UNIX_SOCKETS
+Tchannel
+OS_create_unix_server_socket (const char * filename)
+{
+ int s;
+ Tchannel channel;
+
+ transaction_begin ();
+ STD_FD_SYSTEM_CALL
+ (syscall_socket, s, (UX_socket (AF_UNIX, SOCK_STREAM, 0)));
+ MAKE_CHANNEL (s, channel_type_unix_server_socket, channel =);
+ OS_channel_close_on_abort (channel);
+ {
+ struct sockaddr_un address;
+ memset((&address), 0, (sizeof (address)));
+ (address . sun_family) = AF_UNIX;
+ strncpy ((address . sun_path), filename, (sizeof (address . sun_path)));
+ STD_VOID_SYSTEM_CALL
+ (syscall_bind,
+ (UX_bind ((CHANNEL_DESCRIPTOR (channel)),
+ ((struct sockaddr *) (&address)),
+ (sizeof (struct sockaddr_un)))));
+ STD_VOID_SYSTEM_CALL
+ (syscall_listen,
+ (UX_listen ((CHANNEL_DESCRIPTOR (channel)), SOCKET_LISTEN_BACKLOG)));
+ }
+ transaction_commit ();
+ return (channel);
+}
+#endif /* HAVE_UNIX_SOCKETS */
+
Tchannel
-OS_server_connection_accept (Tchannel channel,
- void * peer_host,
- unsigned int * peer_port)
+OS_tcp_server_connection_accept (Tchannel channel,
+ void * peer_host,
+ unsigned int * peer_port)
{
static struct sockaddr_in address;
socklen_t address_length = (sizeof (struct sockaddr_in));
MAKE_CHANNEL (s, channel_type_tcp_stream_socket, return);
}
-#endif /* not HAVE_SOCKETS */
+#ifdef HAVE_UNIX_SOCKETS
+Tchannel
+OS_unix_server_connection_accept (Tchannel channel)
+{
+ int s;
+ while (1)
+ {
+ s = (UX_accept ((CHANNEL_DESCRIPTOR (channel)), NULL, NULL));
+ if (s >= 0)
+ break;
+#ifdef EAGAIN
+ if (errno == EAGAIN)
+ return (NO_CHANNEL);
+#endif
+#ifdef EWOULDBLOCK
+ if (errno == EWOULDBLOCK)
+ return (NO_CHANNEL);
+#endif
+ UX_prim_check_fd_errno (syscall_accept);
+ }
+ UX_out_of_files_p = false;
+ MAKE_CHANNEL (s, channel_type_unix_stream_socket, return);
+}
+#endif /* HAVE_UNIX_SOCKETS */
+
+#endif /* HAVE_SOCKETS */
extern void OS_host_address_loopback (void *);
#ifdef HAVE_UNIX_SOCKETS
- extern Tchannel OS_open_unix_stream_socket (const char *);
+ extern Tchannel OS_open_unix_stream_socket (const char *);
+ extern Tchannel OS_create_unix_server_socket (const char *);
+ extern Tchannel OS_unix_server_connection_accept (Tchannel);
#endif
extern Tchannel OS_create_tcp_server_socket (void);
extern void OS_bind_tcp_server_socket (Tchannel, void *, unsigned int);
extern void OS_listen_tcp_server_socket (Tchannel);
-extern Tchannel OS_server_connection_accept (Tchannel, void *, unsigned int *);
+extern Tchannel OS_tcp_server_connection_accept (Tchannel, void *, unsigned int *);
#endif /* SCM_UXSOCK_H */
bind-tcp-server-socket
canonical-host-name
close-tcp-server-socket
+ close-unix-server-socket
create-tcp-server-socket
get-host-by-address
get-host-by-name
open-tcp-server-socket
open-tcp-stream-socket
open-tcp-stream-socket-channel
+ open-unix-server-socket
open-unix-stream-socket
open-unix-stream-socket-channel
os/hostname
- tcp-server-connection-accept)
+ tcp-server-connection-accept
+ unix-server-connection-accept)
(initialization (initialize-package!)))
(define-package (runtime subprocess)
((ucode-primitive get-service-by-number 1) service)
((ucode-primitive get-service-by-name 2) service "tcp")))
+(define (open-unix-server-socket pathname)
+ (open-channel
+ (lambda (p)
+ ((ucode-primitive create-unix-server-socket 2) (->namestring pathname) p)
+ #t)))
+
(define (close-tcp-server-socket server-socket)
(channel-close server-socket))
+(define (close-unix-server-socket server-socket)
+ (channel-close server-socket))
+
(define (tcp-server-connection-accept server-socket block? peer-address)
+ (connection-accept (ucode-primitive new-tcp-server-connection-accept 3)
+ server-socket block? peer-address))
+
+(define (unix-server-connection-accept server-socket block?)
+ (connection-accept (named-lambda (new-unix-server-connection-accept
+ socket peer pair)
+ (declare (ignore peer))
+ ((ucode-primitive new-unix-server-connection-accept 2)
+ socket pair))
+ server-socket block? #f))
+
+(define (connection-accept accept! server-socket block? peer-address)
(let ((channel
(with-thread-events-blocked
(lambda ()
(lambda (p)
(with-thread-timer-stopped
(lambda ()
- ((ucode-primitive
- new-tcp-server-connection-accept
- 3)
+ (accept!
(channel-descriptor server-socket)
peer-address
p))))))