Skip to content

Instantly share code, notes, and snippets.

@carlhoerberg
Created June 27, 2023 11:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlhoerberg/0d031f876918fc725f4cfb1b5d23d3b3 to your computer and use it in GitHub Desktop.
Save carlhoerberg/0d031f876918fc725f4cfb1b5d23d3b3 to your computer and use it in GitHub Desktop.
sendfile implementation for crystal
require "socket"
lib LibC
{% if flag?(:linux) %}
fun sendfile(fd_out : Int, fd_in : Int, offset : OffT*, count : SizeT) : SSizeT
TCP_CORK = 3
{% else %}
struct SendfileHeader
headers : IoVec*
hdr_cnt : Int
trailers : IoVec*
trl_cnt : Int
end
fun sendfile(fd : Int, s : Int, offset : OffT*, len : OffT*, hdtr : SendfileHeader*, flags : Int) : Int
{% end %}
end
class Socket
# Zero-copy implementation of sending *length* bytes of *file*
# to the socket
# Returns the number of bytes sent
def sendfile(file_fd : Int32, offset : Int64, length : Int64) : Int32
flush
evented_sendfile(length, "sendfile") do |remaining|
offs = pointerof(offset)
{% if flag?(:linux) %}
LibC.sendfile(fd, file_fd, offs, remaining)
{% else %}
len = pointerof(remaining)
LibC.sendfile(file_fd, fd, offs, len, nil, 0)
len.value
{% end %}
end
end
def cork(&)
setsockopt_bool LibC::TCP_CORK, true, level: Protocol::TCP
yield
setsockopt_bool LibC::TCP_CORK, false, level: Protocol::TCP
end
def cork
setsockopt_bool LibC::TCP_CORK, true, level: Protocol::TCP
end
def uncork
setsockopt_bool LibC::TCP_CORK, false, level: Protocol::TCP
end
end
module IO::Evented
def evented_sendfile(limit : Int64, errno_msg : String, & : Int32 -> Int64) : Int32
limit = limit.to_i32
remaining = limit
loop do
bytes_written = (yield remaining).to_i32
case bytes_written
when -1
if Errno.value == Errno::EAGAIN
wait_writable
else
raise Socket::Error.from_errno(errno_msg)
end
when 0
break
else
remaining -= bytes_written
break if remaining.zero?
end
end
limit - remaining
ensure
resume_pending_writers
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment