Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for an external signature server #4772

Merged
merged 11 commits into from
Aug 13, 2024
30 changes: 14 additions & 16 deletions config/config.example.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#########################################
#
# Database configuration
# Database and other external servers
#
#########################################

Expand Down Expand Up @@ -41,6 +41,19 @@ db:
#check_tables: false


##
## Path to an external signature resolver, used to emulate
## the Youtube client's Javascript. If no such server is
## available, some videos will not be playable.
##
## When this setting is commented out, no external
## resolver will be used.
##
## Accepted values: a path to a UNIX socket or "<IP>:<Port>"
## Default: <none>
##
#signature_server:


#########################################
#
Expand Down Expand Up @@ -343,21 +356,6 @@ full_refresh: false
##
feed_threads: 1

##
## Enable/Disable the polling job that keeps the decryption
## function (for "secured" videos) up to date.
##
## Note: This part of the code generate a small amount of data every minute.
## This may not be desired if you have bandwidth limits set by your ISP.
##
## Note 2: This part of the code is currently broken, so changing
## this setting has no impact.
##
## Accepted values: true, false
## Default: false
##
#decrypt_polling: false


jobs:

Expand Down
14 changes: 9 additions & 5 deletions src/invidious.cr
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ Invidious::Database.check_integrity(CONFIG)
{% puts "\nDone checking player dependencies, now compiling Invidious...\n" %}
{% end %}

# Misc

DECRYPT_FUNCTION =
if sig_helper_address = CONFIG.signature_server.presence
IV::DecryptFunction.new(sig_helper_address)
else
nil
end

# Start jobs

if CONFIG.channel_threads > 0
Expand All @@ -163,11 +172,6 @@ if CONFIG.feed_threads > 0
Invidious::Jobs.register Invidious::Jobs::RefreshFeedsJob.new(PG_DB)
end

DECRYPT_FUNCTION = DecryptFunction.new(CONFIG.decrypt_polling)
if CONFIG.decrypt_polling
Invidious::Jobs.register Invidious::Jobs::UpdateDecryptFunctionJob.new
end

if CONFIG.statistics_enabled
Invidious::Jobs.register Invidious::Jobs::StatisticsRefreshJob.new(PG_DB, SOFTWARE)
end
Expand Down
6 changes: 4 additions & 2 deletions src/invidious/config.cr
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ class Config
# Database configuration using 12-Factor "Database URL" syntax
@[YAML::Field(converter: Preferences::URIConverter)]
property database_url : URI = URI.parse("")
# Use polling to keep decryption function up to date
property decrypt_polling : Bool = false
# Used for crawling channels: threads should check all videos uploaded by a channel
property full_refresh : Bool = false

Expand Down Expand Up @@ -120,6 +118,10 @@ class Config
# Connect to YouTube over 'ipv6', 'ipv4'. Will sometimes resolve fix issues with rate-limiting (see https://github.com/ytdl-org/youtube-dl/issues/21729)
@[YAML::Field(converter: Preferences::FamilyConverter)]
property force_resolve : Socket::Family = Socket::Family::UNSPEC

# External signature solver server socket (either a path to a UNIX domain socket or "<IP>:<Port>")
property signature_server : String? = nil

# Port to listen for connections (overridden by command line argument)
property port : Int32 = 3000
# Host to bind (overridden by command line argument)
Expand Down
8 changes: 4 additions & 4 deletions src/invidious/helpers/crystal_class_overrides.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
# IPv6 addresses.
#
class TCPSocket
def initialize(host : String, port, dns_timeout = nil, connect_timeout = nil, family = Socket::Family::UNSPEC)
def initialize(host, port, dns_timeout = nil, connect_timeout = nil, blocking = false, family = Socket::Family::UNSPEC)
Addrinfo.tcp(host, port, timeout: dns_timeout, family: family) do |addrinfo|
super(addrinfo.family, addrinfo.type, addrinfo.protocol)
super(addrinfo.family, addrinfo.type, addrinfo.protocol, blocking)
connect(addrinfo, timeout: connect_timeout) do |error|
close
error
Expand All @@ -26,7 +26,7 @@ class HTTP::Client
end

hostname = @host.starts_with?('[') && @host.ends_with?(']') ? @host[1..-2] : @host
io = TCPSocket.new hostname, @port, @dns_timeout, @connect_timeout, @family
io = TCPSocket.new hostname, @port, @dns_timeout, @connect_timeout, family: @family
io.read_timeout = @read_timeout if @read_timeout
io.write_timeout = @write_timeout if @write_timeout
io.sync = false
Expand All @@ -35,7 +35,7 @@ class HTTP::Client
if tls = @tls
tcp_socket = io
begin
io = OpenSSL::SSL::Socket::Client.new(tcp_socket, context: tls, sync_close: true, hostname: @host)
io = OpenSSL::SSL::Socket::Client.new(tcp_socket, context: tls, sync_close: true, hostname: @host.rchop('.'))
rescue exc
# don't leak the TCP socket when the SSL connection failed
tcp_socket.close
Expand Down
Loading
Loading