-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
/
PipeServer.jl
93 lines (80 loc) · 2.7 KB
/
PipeServer.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# This file is a part of Julia. License is MIT: https://julialang.org/license
mutable struct PipeServer <: LibuvServer
handle::Ptr{Cvoid}
status::Int
connectnotify::Condition
closenotify::Condition
function PipeServer(handle::Ptr{Cvoid}, status)
p = new(handle,
status,
Condition(),
Condition())
associate_julia_struct(p.handle, p)
finalizer(uvfinalize, p)
return p
end
end
function PipeServer()
pipe = PipeServer(Libc.malloc(Base._sizeof_uv_named_pipe), StatusUninit)
err = ccall(:uv_pipe_init, Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Cint), eventloop(), pipe.handle, 0)
uv_error("failed to create pipe server", err)
pipe.status = StatusInit
return pipe
end
## server functions ##
accept(server::PipeServer) = accept(server, PipeEndpoint())
function accept_nonblock(server::PipeServer, client::PipeEndpoint)
if client.status != StatusInit
error("client is already in use or has been closed")
end
err = ccall(:uv_accept, Int32, (Ptr{Cvoid}, Ptr{Cvoid}), server.handle, client.handle)
if err == 0
client.status = StatusOpen
end
return err
end
function accept_nonblock(server::PipeServer)
client = PipeEndpoint()
uv_error("accept", accept_nonblock(server, client) != 0)
return client
end
function bind(server::PipeServer, name::AbstractString)
@assert server.status == StatusInit
err = ccall(:uv_pipe_bind, Int32, (Ptr{Cvoid}, Cstring),
server, name)
if err != 0
if err != UV_EADDRINUSE && err != UV_EACCES
#TODO: this codepath is currently not tested
throw(_UVError("bind",err))
else
return false
end
end
server.status = StatusOpen
return true
end
"""
listen(path::AbstractString) -> PipeServer
Create and listen on a named pipe / UNIX domain socket.
"""
function listen(path::AbstractString)
sock = PipeServer()
bind(sock, path) || throw(ArgumentError("could not listen on path $path"))
return listen(sock)
end
function connect!(sock::PipeEndpoint, path::AbstractString)
@assert sock.status == StatusInit
req = Libc.malloc(Base._sizeof_uv_connect)
uv_req_set_data(req, C_NULL)
ccall(:uv_pipe_connect, Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}), req, sock.handle, path,
uv_jl_connectcb::Ptr{Cvoid})
sock.status = StatusConnecting
return sock
end
# Libuv will internally reset read/writability, which is uses to
# mark that this is an invalid pipe.
"""
connect(path::AbstractString) -> PipeEndpoint
Connect to the named pipe / UNIX domain socket at `path`.
"""
connect(path::AbstractString) = connect(PipeEndpoint(), path)