2014-11-20 13:21:19 +00:00
/ *
* Copyright ( C ) 2010 - 2014 Laurent CLOUET
* Author Laurent CLOUET < laurent . clouet @nopnop.net >
*
2020-05-28 13:28:42 +02:00
* This program is free software ; you can redistribute it and / or
2014-11-20 13:21:19 +00:00
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; version 2
* of the License .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
* /
package com.sheepit.client ;
import java.io.File ;
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.io.InputStream ;
2020-06-01 19:15:44 +10:00
import java.io.OutputStream ;
2015-04-30 20:40:03 +01:00
import java.io.PrintWriter ;
2014-11-20 13:21:19 +00:00
import java.io.StringWriter ;
import java.io.UnsupportedEncodingException ;
2022-03-24 13:49:17 +00:00
import java.nio.file.Files ;
2020-06-01 19:15:44 +10:00
import java.net.* ;
2020-09-12 10:00:24 +10:00
import java.time.Duration ;
import java.time.LocalDateTime ;
2019-09-03 20:15:46 +02:00
import java.util.ArrayList ;
2014-11-20 13:21:19 +00:00
import java.util.Date ;
import java.util.List ;
2020-06-01 19:15:44 +10:00
import java.util.Objects ;
import java.util.concurrent.TimeUnit ;
2021-11-15 14:09:41 +00:00
import java.util.stream.Collectors ;
2014-11-20 13:21:19 +00:00
2021-11-15 14:09:41 +00:00
import com.sheepit.client.datamodel.SpeedTestTarget ;
import com.sheepit.client.datamodel.SpeedTestResult ;
import com.sheepit.client.datamodel.SpeedTestTargetResult ;
2023-01-28 11:45:20 +00:00
import com.sheepit.client.exception.SheepItExceptionSessionDisabledDenoisingNotSupported ;
2022-01-04 17:25:41 +00:00
import com.sheepit.client.hardware.hwid.HWIdentifier ;
2021-11-16 14:51:53 +00:00
import com.sheepit.client.os.Windows ;
2020-06-01 19:15:44 +10:00
import lombok.Getter ;
import org.simpleframework.xml.core.Persister ;
2014-11-20 13:21:19 +00:00
2020-06-01 19:15:44 +10:00
import okhttp3.Call ;
import okhttp3.FormBody ;
import okhttp3.HttpUrl ;
import okhttp3.MediaType ;
import okhttp3.MultipartBody ;
import okhttp3.OkHttpClient ;
import okhttp3.Request ;
import okhttp3.RequestBody ;
import okhttp3.Response ;
import okhttp3.JavaNetCookieJar ;
2021-07-07 16:18:45 +00:00
import com.sheepit.client.hardware.cpu.CPU ;
2020-06-01 19:15:44 +10:00
import com.sheepit.client.Configuration.ComputeType ;
import com.sheepit.client.Error.ServerCode ;
2019-09-03 20:15:46 +02:00
import com.sheepit.client.datamodel.CacheFileMD5 ;
import com.sheepit.client.datamodel.FileMD5 ;
import com.sheepit.client.datamodel.HeartBeatInfos ;
import com.sheepit.client.datamodel.JobInfos ;
import com.sheepit.client.datamodel.JobValidation ;
2020-01-12 14:37:30 +01:00
import com.sheepit.client.datamodel.RequestEndPoint ;
2019-09-03 20:15:46 +02:00
import com.sheepit.client.datamodel.ServerConfig ;
2023-01-28 11:45:20 +00:00
import com.sheepit.client.exception.SheepItException ;
import com.sheepit.client.exception.SheepItExceptionBadResponseFromServer ;
import com.sheepit.client.exception.SheepItExceptionNoRendererAvailable ;
import com.sheepit.client.exception.SheepItExceptionNoRightToRender ;
import com.sheepit.client.exception.SheepItExceptionNoSession ;
import com.sheepit.client.exception.SheepItExceptionNoSpaceLeftOnDevice ;
import com.sheepit.client.exception.SheepItExceptionPathInvalid ;
import com.sheepit.client.exception.SheepItExceptionNoWritePermission ;
import com.sheepit.client.exception.SheepItExceptionServerInMaintenance ;
import com.sheepit.client.exception.SheepItExceptionServerOverloaded ;
import com.sheepit.client.exception.SheepItExceptionSessionDisabled ;
import com.sheepit.client.exception.SheepItServerDown ;
2014-11-20 13:21:19 +00:00
import com.sheepit.client.os.OS ;
2020-06-01 19:15:44 +10:00
public class Server extends Thread {
2021-11-15 14:09:41 +00:00
private static final int NUMBER_OF_SPEEDTEST_RESULTS = 3 ;
2020-06-21 02:33:59 +10:00
final private String HTTP_USER_AGENT = " Java/ " + System . getProperty ( " java.version " ) ;
2014-11-20 13:21:19 +00:00
private String base_url ;
2020-06-01 19:15:44 +10:00
private final OkHttpClient httpClient ;
2020-05-28 13:28:42 +02:00
@Getter private ServerConfig serverConfig ;
2014-11-20 13:21:19 +00:00
private Configuration user_config ;
private Client client ;
private Log log ;
private long lastRequestTime ;
2014-12-11 00:06:55 +01:00
private int keepmealive_duration ; // time in ms
2014-11-20 13:21:19 +00:00
2020-09-12 10:00:24 +10:00
private TransferStats dlStats = new TransferStats ( ) ;
private TransferStats ulStats = new TransferStats ( ) ;
2014-11-20 13:21:19 +00:00
public Server ( String url_ , Configuration user_config_ , Client client_ ) {
super ( ) ;
this . base_url = url_ ;
this . user_config = user_config_ ;
this . client = client_ ;
this . log = Log . getInstance ( this . user_config ) ;
this . lastRequestTime = 0 ;
this . keepmealive_duration = 15 * 60 * 1000 ; // default 15min
2018-12-01 15:29:42 +01:00
2020-06-01 19:15:44 +10:00
// OkHttp performs best when we create a single OkHttpClient instance and reuse it for all of the HTTP calls. This is because each client holds its own
// connection pool and thread pools.Reusing connections and threads reduces latency and saves memory. Conversely, creating a client for each request
// wastes resources on idle pools.
this . httpClient = getOkHttpClient ( ) ;
2014-11-20 13:21:19 +00:00
}
2024-06-07 14:30:24 +00:00
@Override
2014-11-20 13:21:19 +00:00
public void run ( ) {
this . stayAlive ( ) ;
}
public void stayAlive ( ) {
while ( true ) {
long current_time = new Date ( ) . getTime ( ) ;
if ( ( current_time - this . lastRequestTime ) > this . keepmealive_duration ) {
try {
2020-06-01 19:15:44 +10:00
HttpUrl . Builder urlBuilder = Objects . requireNonNull ( HttpUrl . parse ( this . getPage ( " keepmealive " ) ) ) . newBuilder ( ) ;
2022-10-19 16:45:31 +00:00
urlBuilder . addQueryParameter ( " paused " , String . valueOf ( this . client . isSuspended ( ) ) ) ;
2020-06-01 19:15:44 +10:00
2014-11-20 13:21:19 +00:00
if ( this . client ! = null & & this . client . getRenderingJob ( ) ! = null ) {
2020-06-01 19:15:44 +10:00
Job job = this . client . getRenderingJob ( ) ;
urlBuilder . addQueryParameter ( " frame " , job . getFrameNumber ( ) ) . addQueryParameter ( " job " , job . getId ( ) ) ;
RenderProcess process = job . getProcessRender ( ) ;
if ( process ! = null ) {
urlBuilder . addQueryParameter ( " rendertime " , String . valueOf ( process . getDuration ( ) ) )
. addQueryParameter ( " remainingtime " , String . valueOf ( process . getRemainingDuration ( ) ) ) ;
2015-04-27 20:35:44 +01:00
}
2014-11-20 13:21:19 +00:00
}
2020-06-01 19:15:44 +10:00
Response response = this . HTTPRequest ( urlBuilder ) ;
2014-11-20 13:21:19 +00:00
2020-06-01 19:15:44 +10:00
if ( response . code ( ) = = HttpURLConnection . HTTP_OK & & response . body ( ) . contentType ( ) . toString ( ) . startsWith ( " text/xml " ) ) {
String in = response . body ( ) . string ( ) ;
2014-11-20 13:21:19 +00:00
try {
2021-11-15 14:09:41 +00:00
HeartBeatInfos heartBeatInfos = new Persister ( ) . read ( HeartBeatInfos . class , in ) ;
ServerCode serverCode = ServerCode . fromInt ( heartBeatInfos . getStatus ( ) ) ;
2019-09-03 20:15:46 +02:00
if ( serverCode = = ServerCode . KEEPMEALIVE_STOP_RENDERING ) {
2017-03-05 22:39:40 +01:00
this . log . debug ( " Server::stayAlive server asked to kill local render process " ) ;
2014-11-20 13:21:19 +00:00
// kill the current process, it will generate an error but it's okay
2020-06-21 02:36:55 +10:00
if ( this . client ! = null & & this . client . getRenderingJob ( ) ! = null ) {
2016-11-01 19:44:09 +01:00
this . client . getRenderingJob ( ) . setServerBlockJob ( true ) ;
2020-06-21 02:36:55 +10:00
if ( this . client . getRenderingJob ( ) . getProcessRender ( ) . getProcess ( ) ! = null ) {
this . client . getRenderingJob ( ) . setAskForRendererKill ( true ) ;
2023-07-15 14:49:03 +00:00
this . client . getRenderingJob ( ) . getProcessRender ( ) . kill ( ) ;
2020-06-21 02:36:55 +10:00
}
2014-11-20 13:21:19 +00:00
}
}
}
2019-09-03 20:15:46 +02:00
catch ( Exception e ) { // for the read
this . log . debug ( " Server::stayAlive Exception " + e ) ;
2014-11-20 13:21:19 +00:00
}
}
}
2015-07-08 19:44:38 +01:00
catch ( NoRouteToHostException e ) {
2017-03-05 22:39:40 +01:00
this . log . debug ( " Server::stayAlive can not connect to server " ) ;
2015-07-08 19:44:38 +01:00
}
2014-11-20 13:21:19 +00:00
catch ( IOException e ) {
2017-04-19 21:23:12 +02:00
StringWriter sw = new StringWriter ( ) ;
PrintWriter pw = new PrintWriter ( sw ) ;
e . printStackTrace ( pw ) ;
this . log . debug ( " Server::stayAlive IOException " + e + " stacktrace: " + sw . toString ( ) ) ;
2014-11-20 13:21:19 +00:00
}
}
try {
2024-06-10 16:34:12 +00:00
sleep ( 60 * 1000 ) ; // 1min
2014-11-20 13:21:19 +00:00
}
catch ( InterruptedException e ) {
return ;
}
catch ( Exception e ) {
2017-04-19 21:23:12 +02:00
StringWriter sw = new StringWriter ( ) ;
PrintWriter pw = new PrintWriter ( sw ) ;
e . printStackTrace ( pw ) ;
this . log . debug ( " Server::stayAlive Exception " + e + " stacktrace: " + sw . toString ( ) ) ;
2014-11-20 13:21:19 +00:00
}
}
}
2024-06-07 14:30:24 +00:00
@Override public String toString ( ) {
2019-09-03 20:15:46 +02:00
return String . format ( " Server (base_url '%s', user_config %s " , this . base_url , this . user_config ) ;
2014-11-20 13:21:19 +00:00
}
public Error . Type getConfiguration ( ) {
OS os = OS . getOS ( ) ;
2024-06-06 01:05:27 +00:00
String publickey ;
2014-11-20 13:21:19 +00:00
try {
2020-06-01 19:15:44 +10:00
HttpUrl . Builder remoteURL = Objects . requireNonNull ( HttpUrl . parse ( this . base_url + " /server/config.php " ) ) . newBuilder ( ) ;
FormBody formBody = new FormBody . Builder ( )
. add ( " login " , user_config . getLogin ( ) )
. add ( " password " , user_config . getPassword ( ) )
2023-10-16 18:05:29 +00:00
. add ( " cpu_family " , os . getCPU ( ) . getFamily ( ) )
. add ( " cpu_model " , os . getCPU ( ) . getModel ( ) )
. add ( " cpu_model_name " , os . getCPU ( ) . getName ( ) )
2021-07-07 16:18:45 +00:00
. add ( " cpu_cores " , String . valueOf ( user_config . getNbCores ( ) = = - 1 ? os . getCPU ( ) . cores ( ) : Math . max ( CPU . MIN_CORES , user_config . getNbCores ( ) ) ) )
2020-06-01 19:15:44 +10:00
. add ( " os " , os . name ( ) )
2021-06-24 10:36:25 +02:00
. add ( " os_version " , os . getVersion ( ) )
2021-11-16 14:51:53 +00:00
. add ( " ram " , String . valueOf ( os . getTotalMemory ( ) ) )
2023-10-16 18:05:29 +00:00
. add ( " bits " , os . getCPU ( ) . getArch ( ) )
2021-12-30 17:46:20 +00:00
. add ( " version " , Configuration . jarVersion )
2020-06-01 19:15:44 +10:00
. add ( " hostname " , user_config . getHostname ( ) )
. add ( " ui " , client . getGui ( ) . getClass ( ) . getSimpleName ( ) )
. add ( " extras " , user_config . getExtras ( ) )
2021-07-16 23:37:24 +00:00
. add ( " headless " , java . awt . GraphicsEnvironment . isHeadless ( ) ? " 1 " : ( user_config . isHeadless ( ) ? " 1 " : " 0 " ) )
2022-01-04 17:25:41 +00:00
. add ( " hwid " , new HWIdentifier ( log ) . getHardwareHash ( ) )
2024-03-26 14:08:46 +00:00
. add ( " disable_large_downloads " , user_config . isDisableLargeDownloads ( ) ? " 1 " : " 0 " )
2020-06-01 19:15:44 +10:00
. build ( ) ;
this . log . debug ( " Server::getConfiguration url " + remoteURL . build ( ) . toString ( ) ) ;
2022-06-09 12:26:38 +00:00
Response response = this . HTTPRequest ( remoteURL , formBody , false ) ;
2020-06-01 19:15:44 +10:00
int r = response . code ( ) ;
String contentType = response . body ( ) . contentType ( ) . toString ( ) ;
2022-02-19 02:42:33 +01:00
if ( r ! = HttpURLConnection . HTTP_OK | | contentType . startsWith ( " text/xml " ) = = false ) {
return Error . Type . ERROR_BAD_SERVER_RESPONSE ;
2014-11-20 13:21:19 +00:00
}
2022-06-09 12:26:38 +00:00
else if ( r = = HttpURLConnection . HTTP_NOT_FOUND ) {
// most likely the server instance is down but not the frontend proxy (traefik)
return Error . Type . SERVER_DOWN ;
}
2022-02-19 02:42:33 +01:00
String in = response . body ( ) . string ( ) ;
serverConfig = new Persister ( ) . read ( ServerConfig . class , in ) ;
if ( ServerCode . fromInt ( serverConfig . getStatus ( ) ) ! = ServerCode . OK ) {
return Error . ServerCodeToType ( ServerCode . fromInt ( serverConfig . getStatus ( ) ) ) ;
}
2024-06-06 01:05:27 +00:00
2022-02-19 02:42:33 +01:00
publickey = serverConfig . getPublickey ( ) ;
2024-06-06 01:05:27 +00:00
if ( publickey . isEmpty ( ) = = false ) {
2022-02-19 02:42:33 +01:00
this . user_config . setPassword ( publickey ) ;
}
2014-11-20 13:21:19 +00:00
}
catch ( ConnectException e ) {
this . log . error ( " Server::getConfiguration error ConnectException " + e ) ;
return Error . Type . NETWORK_ISSUE ;
}
2019-07-12 17:46:57 +02:00
catch ( UnknownHostException e ) {
this . log . error ( " Server::getConfiguration: exception UnknownHostException " + e ) ;
return Error . Type . NETWORK_ISSUE ;
}
2016-02-18 18:30:05 +01:00
catch ( UnsupportedEncodingException e ) {
this . log . error ( " Server::getConfiguration: exception UnsupportedEncodingException " + e ) ;
return Error . Type . UNKNOWN ;
}
catch ( IOException e ) {
this . log . error ( " Server::getConfiguration: exception IOException " + e ) ;
2014-11-20 13:21:19 +00:00
return Error . Type . UNKNOWN ;
}
2019-09-03 20:15:46 +02:00
catch ( Exception e ) {
this . log . error ( " Server::getConfiguration: exception Exception " + e ) ;
return Error . Type . UNKNOWN ;
}
2019-08-22 21:35:26 +02:00
2021-11-15 14:09:41 +00:00
if ( serverConfig . getSpeedTestTargets ( ) ! = null & & serverConfig . getSpeedTestTargets ( ) . isEmpty ( ) = = false ) {
try {
2021-11-28 21:51:04 +01:00
client . getGui ( ) . status ( " Checking mirror connection speeds " ) ;
2021-11-15 14:09:41 +00:00
Speedtest speedtest = new Speedtest ( log ) ;
List < SpeedTestTarget > bestSpeedTestTargets = speedtest . doSpeedtests ( serverConfig . getSpeedTestTargets ( ) . stream ( ) . map ( m - > m . getUrl ( ) ) . collect ( Collectors . toList ( ) ) ,
NUMBER_OF_SPEEDTEST_RESULTS ) ;
SpeedTestResult result = new SpeedTestResult ( ) ;
result . setResults ( bestSpeedTestTargets . stream ( ) . map ( m - > {
SpeedTestTargetResult targetResult = new SpeedTestTargetResult ( ) ;
targetResult . setTarget ( m . getUrl ( ) ) ;
targetResult . setSpeed ( m . getSpeedtest ( ) ) ;
targetResult . setPing ( ( int ) ( m . getPing ( ) . getAverage ( ) ) ) ;
return targetResult ;
} ) . collect ( Collectors . toList ( ) ) ) ;
final Persister persister = new Persister ( ) ;
try ( StringWriter writer = new StringWriter ( ) ) {
persister . write ( result , writer ) ;
HttpUrl . Builder urlBuilder = Objects . requireNonNull ( HttpUrl . parse ( this . getPage ( " speedtest-answer " ) ) ) . newBuilder ( ) ;
Response response = this . HTTPRequest ( urlBuilder , RequestBody . create ( MediaType . parse ( " application/xml " ) , writer . toString ( ) ) ) ;
if ( response . code ( ) ! = HttpURLConnection . HTTP_OK ) {
2022-02-19 02:42:33 +01:00
this . log . error ( " Server::getConfiguration Speedtest unexpected response " ) ;
return Error . Type . ERROR_BAD_SERVER_RESPONSE ;
2021-11-15 14:09:41 +00:00
}
}
catch ( final Exception e ) {
throw new IOException ( " Server::getConfiguration Speedtest failed to generate payload " ) ;
}
}
catch ( IOException e ) {
this . log . error ( " Server::getConfiguration Speedtest failed: " + e ) ;
return Error . Type . NETWORK_ISSUE ;
}
}
2021-07-16 23:37:24 +00:00
client . setSessionStarted ( true ) ;
2019-08-22 21:35:26 +02:00
this . client . getGui ( ) . successfulAuthenticationEvent ( publickey ) ;
2014-11-20 13:21:19 +00:00
return Error . Type . OK ;
}
2023-01-28 11:45:20 +00:00
public Job requestJob ( ) throws SheepItException {
2014-11-20 13:21:19 +00:00
this . log . debug ( " Server::requestJob " ) ;
try {
2015-06-09 20:16:12 +01:00
OS os = OS . getOS ( ) ;
2021-11-16 14:51:53 +00:00
long maxMemory = this . user_config . getMaxAllowedMemory ( ) ;
long freeMemory = os . getFreeMemory ( ) - 1024 ^ 2 /*One gigabyte*/ * ( os instanceof Windows ? 2 : 1 ) ; //Make RAM to reserve 2GB on Windows
2018-08-10 17:33:50 +02:00
if ( maxMemory < 0 ) {
maxMemory = freeMemory ;
}
else if ( freeMemory > 0 & & maxMemory > 0 ) {
maxMemory = Math . min ( maxMemory , freeMemory ) ;
}
2014-11-20 13:21:19 +00:00
2020-06-01 19:15:44 +10:00
HttpUrl . Builder urlBuilder = Objects . requireNonNull ( HttpUrl . parse ( this . getPage ( " request-job " ) ) ) . newBuilder ( )
. addQueryParameter ( " computemethod " , String . valueOf ( user_config . computeMethodToInt ( ) ) )
2021-06-22 16:10:35 +02:00
. addQueryParameter ( " network_dl " , String . valueOf ( dlStats . getRawAverageSessionSpeed ( ) ) )
. addQueryParameter ( " network_up " , String . valueOf ( ulStats . getRawAverageSessionSpeed ( ) ) )
2021-07-07 16:18:45 +00:00
. addQueryParameter ( " cpu_cores " , String . valueOf ( user_config . getNbCores ( ) = = - 1 ? os . getCPU ( ) . cores ( ) :
( Math . max ( user_config . getNbCores ( ) , CPU . MIN_CORES ) ) ) )
2020-06-01 19:15:44 +10:00
. addQueryParameter ( " ram_max " , String . valueOf ( maxMemory ) )
. addQueryParameter ( " rendertime_max " , String . valueOf ( user_config . getMaxRenderTime ( ) ) ) ;
2014-11-20 13:21:19 +00:00
2020-06-01 19:15:44 +10:00
if ( user_config . getComputeMethod ( ) ! = ComputeType . CPU & & user_config . getGPUDevice ( ) ! = null ) {
urlBuilder . addQueryParameter ( " gpu_model " , user_config . getGPUDevice ( ) . getModel ( ) )
. addQueryParameter ( " gpu_ram " , String . valueOf ( user_config . getGPUDevice ( ) . getMemory ( ) ) )
. addQueryParameter ( " gpu_type " , user_config . getGPUDevice ( ) . getType ( ) ) ;
}
2021-06-22 16:10:35 +02:00
2021-11-19 16:05:55 +00:00
Response response = this . HTTPRequest ( urlBuilder , RequestBody . create ( this . generateXMLForMD5cache ( ) , MediaType . parse ( " application/xml " ) ) ) ;
2020-06-01 19:15:44 +10:00
int r = response . code ( ) ;
2022-02-19 02:42:33 +01:00
if ( r = = HttpURLConnection . HTTP_UNAVAILABLE | | r = = HttpURLConnection . HTTP_CLIENT_TIMEOUT ) {
this . log . error ( " Server::requestJob server unavailable or down: " + response ) ;
2023-01-28 11:45:20 +00:00
throw new SheepItServerDown ( ) ;
2014-11-20 13:21:19 +00:00
}
2022-02-19 02:42:33 +01:00
else if ( response . body ( ) . contentType ( ) . toString ( ) . startsWith ( " text/xml " ) = = false ) {
this . log . error ( " Server::requestJob bad contentType received: " + response ) ;
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionBadResponseFromServer ( ) ;
2022-02-19 02:42:33 +01:00
}
else if ( r ! = HttpURLConnection . HTTP_OK ) {
this . log . error ( " Server::requestJob unexpected response " + response ) ;
2023-01-28 11:45:20 +00:00
throw new SheepItException ( ) ;
2022-02-19 02:42:33 +01:00
}
String in = response . body ( ) . string ( ) ;
JobInfos jobData = new Persister ( ) . read ( JobInfos . class , in ) ;
handleFileMD5DeleteDocument ( jobData . getFileMD5s ( ) ) ;
if ( jobData . getSessionStats ( ) ! = null ) {
this . client . getGui ( ) . displayStats (
new Stats ( jobData . getSessionStats ( ) . getRemainingFrames ( ) , jobData . getSessionStats ( ) . getPointsEarnedByUser ( ) ,
jobData . getSessionStats ( ) . getPointsEarnedOnSession ( ) , jobData . getSessionStats ( ) . getRenderableProjects ( ) ,
jobData . getSessionStats ( ) . getWaitingProjects ( ) , jobData . getSessionStats ( ) . getConnectedMachines ( ) ) ) ;
}
ServerCode serverCode = ServerCode . fromInt ( jobData . getStatus ( ) ) ;
if ( serverCode ! = ServerCode . OK ) {
switch ( serverCode ) {
case JOB_REQUEST_NOJOB :
return null ;
case JOB_REQUEST_ERROR_NO_RENDERING_RIGHT :
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionNoRightToRender ( ) ;
2022-02-19 02:42:33 +01:00
case JOB_REQUEST_ERROR_DEAD_SESSION :
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionNoSession ( ) ;
2022-02-19 02:42:33 +01:00
case JOB_REQUEST_ERROR_SESSION_DISABLED :
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionSessionDisabled ( ) ;
2022-07-29 17:13:29 +00:00
case JOB_REQUEST_ERROR_SESSION_DISABLED_DENOISING_NOT_SUPPORTED :
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionSessionDisabledDenoisingNotSupported ( ) ;
2022-02-19 02:42:33 +01:00
case JOB_REQUEST_ERROR_INTERNAL_ERROR :
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionBadResponseFromServer ( ) ;
2022-02-19 02:42:33 +01:00
case JOB_REQUEST_ERROR_RENDERER_NOT_AVAILABLE :
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionNoRendererAvailable ( ) ;
2022-02-19 02:42:33 +01:00
case JOB_REQUEST_SERVER_IN_MAINTENANCE :
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionServerInMaintenance ( ) ;
2022-02-19 02:42:33 +01:00
case JOB_REQUEST_SERVER_OVERLOADED :
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionServerOverloaded ( ) ;
2022-02-19 02:42:33 +01:00
default :
2023-01-28 11:45:20 +00:00
throw new SheepItException ( " error requestJob: status is not ok (it's " + serverCode + " ) " ) ;
2016-09-11 13:46:12 +02:00
}
2014-11-20 13:21:19 +00:00
}
2022-02-19 02:42:33 +01:00
String validationUrl = URLDecoder . decode ( jobData . getRenderTask ( ) . getValidationUrl ( ) , " UTF-8 " ) ;
2024-11-20 16:57:43 +00:00
DownloadItem projectDownload = new DownloadItem (
jobData . getRenderTask ( ) . getChunks ( ) ,
jobData . getRenderTask ( ) . getSize ( ) ,
jobData . getRenderTask ( ) . getMd5 ( ) ) ;
DownloadItem rendererDownload = new DownloadItem (
jobData . getRenderTask ( ) . getRendererInfos ( ) . getChunks ( ) ,
jobData . getRenderTask ( ) . getRendererInfos ( ) . getSize ( ) ,
jobData . getRenderTask ( ) . getRendererInfos ( ) . getMd5 ( ) ) ;
2022-02-19 02:42:33 +01:00
return new Job ( this . user_config , this . client . getGui ( ) , this . client . getLog ( ) , jobData . getRenderTask ( ) . getId ( ) ,
jobData . getRenderTask ( ) . getFrame ( ) , jobData . getRenderTask ( ) . getPath ( ) . replace ( " / " , File . separator ) ,
jobData . getRenderTask ( ) . getUseGpu ( ) = = 1 , jobData . getRenderTask ( ) . getRendererInfos ( ) . getCommandline ( ) , validationUrl ,
2024-11-20 16:57:43 +00:00
jobData . getRenderTask ( ) . getScript ( ) , projectDownload , rendererDownload ,
jobData . getRenderTask ( ) . getName ( ) , jobData . getRenderTask ( ) . getPassword ( ) ,
2024-06-07 14:35:47 +00:00
" 1 " . equals ( jobData . getRenderTask ( ) . getSynchronousUpload ( ) ) , jobData . getRenderTask ( ) . getRendererInfos ( ) . getUpdateMethod ( ) ) ;
2014-11-20 13:21:19 +00:00
}
2023-01-28 11:45:20 +00:00
catch ( SheepItException e ) {
2015-03-04 18:59:16 +00:00
throw e ;
2014-11-20 13:21:19 +00:00
}
2015-07-08 19:44:38 +01:00
catch ( NoRouteToHostException e ) {
2023-01-28 11:45:20 +00:00
throw new SheepItServerDown ( ) ;
2015-07-08 19:44:38 +01:00
}
2019-07-12 17:46:57 +02:00
catch ( UnknownHostException e ) {
2023-01-28 11:45:20 +00:00
throw new SheepItServerDown ( ) ;
2019-07-12 17:46:57 +02:00
}
2014-11-20 13:21:19 +00:00
catch ( Exception e ) {
2015-06-10 19:24:42 +01:00
StringWriter sw = new StringWriter ( ) ;
PrintWriter pw = new PrintWriter ( sw ) ;
2015-07-20 17:45:38 +01:00
e . printStackTrace ( pw ) ;
2023-01-28 11:45:20 +00:00
throw new SheepItException ( " error requestJob: unknown exception " + e + " stacktrace: " + sw . toString ( ) ) ;
2014-11-20 13:21:19 +00:00
}
}
2020-05-28 13:28:42 +02:00
2020-06-01 19:15:44 +10:00
public Response HTTPRequest ( String url ) throws IOException {
HttpUrl . Builder httpUrlBuilder = Objects . requireNonNull ( HttpUrl . parse ( url ) ) . newBuilder ( ) ;
return this . HTTPRequest ( httpUrlBuilder , null ) ;
2014-11-20 13:21:19 +00:00
}
2020-06-01 19:15:44 +10:00
public Response HTTPRequest ( HttpUrl . Builder httpUrlBuilder ) throws IOException {
return this . HTTPRequest ( httpUrlBuilder , null ) ;
}
public Response HTTPRequest ( HttpUrl . Builder httpUrlBuilder , RequestBody data_ ) throws IOException {
String url = httpUrlBuilder . build ( ) . toString ( ) ;
2020-06-21 02:33:59 +10:00
Request . Builder builder = new Request . Builder ( ) . addHeader ( " User-Agent " , HTTP_USER_AGENT ) . url ( url ) ;
2014-11-20 13:21:19 +00:00
2020-06-01 19:15:44 +10:00
this . log . debug ( " Server::HTTPRequest url( " + url + " ) " ) ;
2014-11-20 13:21:19 +00:00
if ( data_ ! = null ) {
2020-06-01 19:15:44 +10:00
builder . post ( data_ ) ;
2014-11-20 13:21:19 +00:00
}
2020-06-01 19:15:44 +10:00
Request request = builder . build ( ) ;
2014-11-20 13:21:19 +00:00
2020-06-01 19:15:44 +10:00
try {
2024-06-06 01:05:27 +00:00
Response response = httpClient . newCall ( request ) . execute ( ) ;
2020-06-01 19:15:44 +10:00
2024-06-06 01:05:27 +00:00
if ( response . isSuccessful ( ) = = false ) {
2022-02-19 02:42:33 +01:00
this . log . error ( " Received unsuccessful HTTP response " + response ) ;
2022-06-09 12:26:38 +00:00
}
this . lastRequestTime = new Date ( ) . getTime ( ) ;
return response ;
}
catch ( IOException e ) {
throw new IOException ( " Unexpected response from HTTP Stack " + e . getMessage ( ) ) ;
}
}
public Response HTTPRequest ( HttpUrl . Builder httpUrlBuilder , RequestBody data_ , boolean checkIsSuccessful ) throws IOException {
String url = httpUrlBuilder . build ( ) . toString ( ) ;
Request . Builder builder = new Request . Builder ( ) . addHeader ( " User-Agent " , HTTP_USER_AGENT ) . url ( url ) ;
this . log . debug ( " Server::HTTPRequest url( " + url + " ) " ) ;
if ( data_ ! = null ) {
builder . post ( data_ ) ;
}
Request request = builder . build ( ) ;
2024-06-06 01:05:27 +00:00
2022-06-09 12:26:38 +00:00
try {
2024-06-06 01:05:27 +00:00
Response response = httpClient . newCall ( request ) . execute ( ) ;
2022-06-09 12:26:38 +00:00
if ( checkIsSuccessful & & ! response . isSuccessful ( ) ) {
2020-06-01 19:15:44 +10:00
throw new IOException ( " Unexpected code " + response ) ;
}
this . lastRequestTime = new Date ( ) . getTime ( ) ;
return response ;
}
2023-09-16 09:08:13 +02:00
catch ( ConnectException e ) {
throw new ConnectException ( " Unexpected response from HTTP Stack " + e . getMessage ( ) ) ;
}
2020-06-01 19:15:44 +10:00
catch ( IOException e ) {
throw new IOException ( " Unexpected response from HTTP Stack " + e . getMessage ( ) ) ;
}
2014-11-20 13:21:19 +00:00
}
2024-04-11 15:24:50 +00:00
public Error . Type HTTPGetFile ( String url_ , String destination_ , Gui gui_ ) throws SheepItException {
2023-09-19 17:14:49 +00:00
this . log . debug ( " Server::HTTPGetFile destination: " + destination_ ) ;
2020-06-21 02:36:55 +10:00
InputStream is = null ;
OutputStream output = null ;
2014-11-20 13:21:19 +00:00
try {
2020-06-01 19:15:44 +10:00
Response response = this . HTTPRequest ( url_ ) ;
2014-11-20 13:21:19 +00:00
2020-06-01 19:15:44 +10:00
if ( response . code ( ) ! = HttpURLConnection . HTTP_OK ) {
this . log . error ( " Server::HTTPGetFile( " + url_ + " , ...) HTTP code is not " + HttpURLConnection . HTTP_OK + " it's " + response . code ( ) ) ;
2020-06-21 02:36:55 +10:00
return Error . Type . DOWNLOAD_FILE ;
2014-11-20 13:21:19 +00:00
}
2020-06-01 19:15:44 +10:00
2020-06-21 02:36:55 +10:00
is = response . body ( ) . byteStream ( ) ;
2020-10-21 22:03:09 +11:00
output = new FileOutputStream ( destination_ + " .partial " ) ;
2014-11-20 13:21:19 +00:00
2020-06-01 19:15:44 +10:00
long size = response . body ( ) . contentLength ( ) ;
2024-04-11 15:24:50 +00:00
// only update the gui every 1MB
byte [ ] buffer = new byte [ 1024 * 1024 ] ;
2024-06-06 01:05:27 +00:00
int len ;
2015-01-18 16:50:28 +01:00
long written = 0 ;
2024-04-11 15:24:50 +00:00
2023-07-14 13:17:19 +02:00
this . log . debug ( " Downloading file from " + response . request ( ) . url ( ) . host ( ) ) ;
2020-09-12 10:00:24 +10:00
LocalDateTime startRequestTime = LocalDateTime . now ( ) ;
2020-06-01 19:15:44 +10:00
while ( ( len = is . read ( buffer ) ) ! = - 1 ) {
2020-06-21 02:36:55 +10:00
if ( this . client . getRenderingJob ( ) . isServerBlockJob ( ) ) {
return Error . Type . RENDERER_KILLED_BY_SERVER ;
}
else if ( this . client . getRenderingJob ( ) . isUserBlockJob ( ) ) {
return Error . Type . RENDERER_KILLED_BY_USER ;
}
2020-06-01 19:15:44 +10:00
output . write ( buffer , 0 , len ) ;
written + = len ;
2024-04-11 15:24:50 +00:00
gui_ . getDownloadProgress ( ) . addProgress ( len ) ;
2014-11-20 13:21:19 +00:00
}
2020-06-01 19:15:44 +10:00
2020-09-12 10:00:24 +10:00
LocalDateTime endRequestTime = LocalDateTime . now ( ) ;
Duration duration = Duration . between ( startRequestTime , endRequestTime ) ;
this . dlStats . calc ( written , ( ( duration . getSeconds ( ) * 1000 ) + ( duration . getNano ( ) / 1000000 ) ) ) ;
gui_ . displayTransferStats ( dlStats , ulStats ) ;
2020-06-01 19:15:44 +10:00
2023-09-09 10:40:19 +00:00
this . log . debug ( String . format ( " File downloaded at %s/s, written %d bytes " , new TransferStats ( size , duration . toMillis ( ) + 1 ) . getAverageSessionSpeed ( ) , written ) ) ;
2020-09-12 11:12:54 +02:00
2014-11-20 13:21:19 +00:00
this . lastRequestTime = new Date ( ) . getTime ( ) ;
2020-06-21 02:36:55 +10:00
return Error . Type . OK ;
2014-11-20 13:21:19 +00:00
}
catch ( Exception e ) {
2022-03-11 14:02:22 +00:00
File destFile = new File ( destination_ ) ;
2022-03-24 13:49:17 +00:00
if ( Files . isWritable ( destFile . getParentFile ( ) . toPath ( ) ) = = false ) {
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionNoWritePermission ( ) ;
2022-03-11 14:02:22 +00:00
}
2022-03-24 13:49:17 +00:00
else if ( destFile . getParentFile ( ) . isDirectory ( ) = = false ) {
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionPathInvalid ( ) ;
2022-03-24 13:49:17 +00:00
}
2022-03-11 14:02:22 +00:00
else if ( Utils . noFreeSpaceOnDisk ( destFile . getParent ( ) , log ) ) {
2023-01-28 11:45:20 +00:00
throw new SheepItExceptionNoSpaceLeftOnDevice ( ) ;
2016-06-25 13:45:09 +02:00
}
2015-04-30 20:40:03 +01:00
StringWriter sw = new StringWriter ( ) ;
e . printStackTrace ( new PrintWriter ( sw ) ) ;
2017-04-19 21:23:12 +02:00
this . log . error ( " Server::HTTPGetFile Exception " + e + " stacktrace " + sw . toString ( ) ) ;
2014-11-20 13:21:19 +00:00
}
2020-06-21 02:36:55 +10:00
finally {
try {
2020-07-07 23:38:23 +10:00
if ( output ! = null ) {
output . flush ( ) ;
output . close ( ) ;
}
2020-10-21 22:03:09 +11:00
File downloadedFile = new File ( destination_ + " .partial " ) ;
if ( downloadedFile . exists ( ) ) {
// Rename file (or directory)
boolean success = downloadedFile . renameTo ( new File ( destination_ ) ) ;
if ( ! success ) {
this . log . debug ( String . format ( " Server::HTTPGetFile Error trying to rename the downloaded file to final name (%s) " , destination_ ) ) ;
}
}
2020-07-07 23:38:23 +10:00
if ( is ! = null ) {
is . close ( ) ;
}
2020-06-21 02:36:55 +10:00
}
2020-07-07 23:38:23 +10:00
catch ( Exception e ) {
2020-06-21 02:36:55 +10:00
this . log . debug ( String . format ( " Server::HTTPGetFile Error trying to close the open streams (%s) " , e . getMessage ( ) ) ) ;
}
}
2020-06-01 19:15:44 +10:00
this . log . debug ( String . format ( " Server::HTTPGetFile(%s) did fail " , url_ ) ) ;
2020-06-21 02:36:55 +10:00
return Error . Type . DOWNLOAD_FILE ;
2014-11-20 13:21:19 +00:00
}
2020-09-12 10:00:24 +10:00
public ServerCode HTTPSendFile ( String surl , String file1 , int checkpoint , Gui gui ) {
2020-06-18 21:57:52 +10:00
this . log . debug ( checkpoint , " Server::HTTPSendFile( " + surl + " , " + file1 + " ) " ) ;
2014-11-20 13:21:19 +00:00
try {
2020-07-07 15:37:15 +02:00
String fileMimeType = Utils . findMimeType ( file1 ) ;
2020-09-12 10:00:24 +10:00
File fileHandler = new File ( file1 ) ;
2020-07-07 15:37:15 +02:00
2020-06-17 18:19:29 +10:00
MediaType MEDIA_TYPE = MediaType . parse ( fileMimeType ) ; // e.g. "image/png"
2014-11-20 13:21:19 +00:00
2020-06-01 19:15:44 +10:00
RequestBody uploadContent = new MultipartBody . Builder ( ) . setType ( MultipartBody . FORM )
2020-09-12 10:00:24 +10:00
. addFormDataPart ( " file " , fileHandler . getName ( ) , RequestBody . create ( fileHandler , MEDIA_TYPE ) ) . build ( ) ;
2014-11-20 13:21:19 +00:00
2020-06-21 02:33:59 +10:00
Request request = new Request . Builder ( ) . addHeader ( " User-Agent " , HTTP_USER_AGENT ) . url ( surl ) . post ( uploadContent ) . build ( ) ;
2020-06-01 19:15:44 +10:00
2020-09-12 10:00:24 +10:00
LocalDateTime startRequestTime = LocalDateTime . now ( ) ;
2020-06-01 19:15:44 +10:00
Call call = httpClient . newCall ( request ) ;
Response response = call . execute ( ) ;
2020-09-12 10:00:24 +10:00
LocalDateTime endRequestTime = LocalDateTime . now ( ) ;
Duration duration = Duration . between ( startRequestTime , endRequestTime ) ;
this . ulStats . calc ( fileHandler . length ( ) , ( ( duration . getSeconds ( ) * 1000 ) + ( duration . getNano ( ) / 1000000 ) ) ) ;
gui . displayTransferStats ( dlStats , ulStats ) ;
2023-09-09 10:40:19 +00:00
this . log . debug ( String . format ( " File uploaded at %s/s, uploaded %d bytes " , new TransferStats ( fileHandler . length ( ) , duration . toMillis ( ) + 1 ) . getAverageSessionSpeed ( ) , fileHandler . length ( ) ) ) ;
2020-09-12 10:00:24 +10:00
2020-06-01 19:15:44 +10:00
int r = response . code ( ) ;
String contentType = response . body ( ) . contentType ( ) . toString ( ) ;
if ( r = = HttpURLConnection . HTTP_OK & & contentType . startsWith ( " text/xml " ) ) {
2014-11-20 13:21:19 +00:00
try {
2020-06-01 19:15:44 +10:00
String in = response . body ( ) . string ( ) ;
JobValidation jobValidation = new Persister ( ) . read ( JobValidation . class , in ) ;
2020-05-28 13:28:42 +02:00
2020-06-01 19:15:44 +10:00
this . lastRequestTime = new Date ( ) . getTime ( ) ;
2020-05-28 13:28:42 +02:00
2020-06-01 19:15:44 +10:00
ServerCode serverCode = ServerCode . fromInt ( jobValidation . getStatus ( ) ) ;
if ( serverCode ! = ServerCode . OK ) {
2020-06-18 21:57:52 +10:00
this . log . error ( checkpoint , " Server::HTTPSendFile wrong status (is " + serverCode + " ) " ) ;
2020-06-01 19:15:44 +10:00
return serverCode ;
2014-11-20 13:21:19 +00:00
}
}
2020-06-01 19:15:44 +10:00
catch ( Exception e ) { // for the .read
e . printStackTrace ( ) ;
}
return ServerCode . OK ;
2014-11-20 13:21:19 +00:00
}
2020-06-01 19:15:44 +10:00
else if ( r = = HttpURLConnection . HTTP_OK & & contentType . startsWith ( " text/html " ) ) {
return ServerCode . ERROR_BAD_RESPONSE ;
}
2020-06-21 02:42:20 +10:00
// We don't check all the HTTP 4xx but the 413 in particular, we can always find a huge image larger than whatever configuration we have in the
// server and it's worth to send the error back to the server if this happen
else if ( r = = HttpURLConnection . HTTP_ENTITY_TOO_LARGE ) {
this . log . error ( response . body ( ) . string ( ) ) ;
return ServerCode . JOB_VALIDATION_IMAGE_TOO_LARGE ;
}
2022-07-17 11:40:01 +02:00
else if ( r = = HttpURLConnection . HTTP_INTERNAL_ERROR ) {
return ServerCode . ERROR_BAD_RESPONSE ;
}
2020-06-01 19:15:44 +10:00
else {
2020-06-16 23:22:21 +10:00
this . log . error ( String . format ( " Server::HTTPSendFile Unknown response received from server: %s " , response . body ( ) . string ( ) ) ) ;
2014-11-20 13:21:19 +00:00
}
return ServerCode . UNKNOWN ;
}
2022-08-30 18:11:17 +00:00
catch ( ConnectException e ) {
StringWriter sw = new StringWriter ( ) ;
PrintWriter pw = new PrintWriter ( sw ) ;
e . printStackTrace ( pw ) ;
this . log . error ( checkpoint , String . format ( " Server::HTTPSendFile Error in upload process. Exception %s stacktrace " , e . getMessage ( ) ) + sw . toString ( ) ) ;
return ServerCode . SERVER_CONNECTION_FAILED ;
}
2017-04-19 21:23:12 +02:00
catch ( IOException e ) {
StringWriter sw = new StringWriter ( ) ;
PrintWriter pw = new PrintWriter ( sw ) ;
e . printStackTrace ( pw ) ;
2020-07-26 08:05:07 -04:00
this . log . error ( checkpoint , String . format ( " Server::HTTPSendFile Error in upload process. Exception %s stacktrace " , e . getMessage ( ) ) + sw . toString ( ) ) ;
2014-11-20 13:21:19 +00:00
return ServerCode . UNKNOWN ;
}
2017-04-19 21:23:12 +02:00
catch ( OutOfMemoryError e ) {
StringWriter sw = new StringWriter ( ) ;
PrintWriter pw = new PrintWriter ( sw ) ;
e . printStackTrace ( pw ) ;
2020-06-18 21:57:52 +10:00
this . log . error ( checkpoint , " Server::HTTPSendFile, OutOfMemoryError " + e + " stacktrace " + sw . toString ( ) ) ;
2017-03-18 17:05:54 +01:00
return ServerCode . JOB_VALIDATION_ERROR_UPLOAD_FAILED ;
}
2017-04-19 21:23:12 +02:00
catch ( Exception e ) {
StringWriter sw = new StringWriter ( ) ;
PrintWriter pw = new PrintWriter ( sw ) ;
e . printStackTrace ( pw ) ;
2020-06-18 21:57:52 +10:00
this . log . error ( checkpoint , " Server::HTTPSendFile, Exception " + e + " stacktrace " + sw . toString ( ) ) ;
2017-04-19 21:23:12 +02:00
return ServerCode . UNKNOWN ;
}
2014-11-20 13:21:19 +00:00
}
private String generateXMLForMD5cache ( ) {
2019-09-03 20:15:46 +02:00
List < FileMD5 > md5s = new ArrayList < > ( ) ;
for ( File local_file : this . user_config . getLocalCacheFiles ( ) ) {
try {
String extension = local_file . getName ( ) . substring ( local_file . getName ( ) . lastIndexOf ( '.' ) ) . toLowerCase ( ) ;
String name = local_file . getName ( ) . substring ( 0 , local_file . getName ( ) . length ( ) - 1 * extension . length ( ) ) ;
2024-11-20 13:05:20 +00:00
if ( " .wool " . equals ( extension ) ) {
2019-09-03 20:15:46 +02:00
// node_file.setAttribute("md5", name);
FileMD5 fileMD5 = new FileMD5 ( ) ;
fileMD5 . setMd5 ( name ) ;
md5s . add ( fileMD5 ) ;
2014-11-20 13:21:19 +00:00
}
}
2019-09-03 20:15:46 +02:00
catch ( StringIndexOutOfBoundsException e ) { // because the file does not have an . its path
}
2014-11-20 13:21:19 +00:00
}
2020-05-28 13:28:42 +02:00
2019-09-03 20:15:46 +02:00
CacheFileMD5 cache = new CacheFileMD5 ( ) ;
cache . setMd5s ( md5s ) ;
2020-05-28 13:28:42 +02:00
2019-09-03 20:15:46 +02:00
final Persister persister = new Persister ( ) ;
try ( StringWriter writer = new StringWriter ( ) ) {
persister . write ( cache , writer ) ;
return writer . toString ( ) ;
2014-11-20 13:21:19 +00:00
}
2019-09-03 20:15:46 +02:00
catch ( final Exception e ) {
log . debug ( " Failed to dump md5s " + e ) ;
return " " ;
2014-11-20 13:21:19 +00:00
}
}
2020-05-28 13:28:42 +02:00
2019-09-03 20:15:46 +02:00
private void handleFileMD5DeleteDocument ( List < FileMD5 > fileMD5s ) {
if ( fileMD5s ! = null & & fileMD5s . isEmpty ( ) = = false ) {
2020-05-28 13:28:42 +02:00
for ( FileMD5 fileMD5 : fileMD5s ) {
2019-09-03 20:15:46 +02:00
if ( " delete " . equals ( fileMD5 . getAction ( ) ) & & fileMD5 . getMd5 ( ) ! = null & & fileMD5 . getMd5 ( ) . isEmpty ( ) = = false ) {
2023-09-19 17:14:49 +00:00
List < String > paths = new ArrayList < > ( ) ;
2024-10-31 13:30:37 +00:00
paths . add ( this . user_config . getWoolCacheDirectory ( ) . getAbsolutePath ( ) + File . separator + fileMD5 . getMd5 ( ) ) ;
2023-06-03 19:00:12 +00:00
2020-10-21 22:03:09 +11:00
// If we are using a shared downloads directory, then delete the file from the shared downloads directory as well :)
if ( this . user_config . getSharedDownloadsDirectory ( ) ! = null ) {
2023-09-19 17:14:49 +00:00
paths . add ( this . user_config . getSharedDownloadsDirectory ( ) . getAbsolutePath ( ) + File . separator + fileMD5 . getMd5 ( ) ) ;
}
for ( String path : paths ) {
new File ( path + " .wool " ) . delete ( ) ;
Utils . delete ( new File ( path ) ) ;
2020-10-21 22:03:09 +11:00
}
2014-11-20 13:21:19 +00:00
}
}
}
}
public String getPage ( String key ) {
2019-09-03 20:15:46 +02:00
if ( this . serverConfig ! = null ) {
2020-01-12 14:37:30 +01:00
RequestEndPoint endpoint = this . serverConfig . getRequestEndPoint ( key ) ;
if ( endpoint ! = null ) {
return this . base_url + endpoint . getPath ( ) ;
}
2014-11-20 13:21:19 +00:00
}
return " " ;
}
2020-06-01 19:15:44 +10:00
private OkHttpClient getOkHttpClient ( ) {
try {
OkHttpClient . Builder builder = new OkHttpClient . Builder ( ) ;
CookieManager cookieManager = new CookieManager ( ) ;
cookieManager . setCookiePolicy ( CookiePolicy . ACCEPT_ALL ) ;
builder . cookieJar ( new JavaNetCookieJar ( cookieManager ) ) ; // Cookie store to maintain the session across calls
builder . connectTimeout ( 30 , TimeUnit . SECONDS ) ; // Cancel the HTTP Request if the connection to server takes more than 10 seconds
builder . writeTimeout ( 60 , TimeUnit . SECONDS ) ; // Cancel the upload if the client cannot send any byte in 60 seconds
// If the user has selected a proxy, then we must increase the download timeout. Reason being the way proxies work. To download a large file (i.e.
// a 500MB job), the proxy must first download the file to the proxy cache and then the information is sent fast to the SheepIt client. From a client
// viewpoint, the HTTP connection will make the CONNECT step really fast but then the time until the fist byte is received (the time measured by
// readTimeout) will be really long (minutes). Without a proxy in the middle, a connection that does receive nothing in 60 seconds might be
// considered a dead connection.
if ( this . user_config . getProxy ( ) ! = null ) {
builder . readTimeout ( 10 , TimeUnit . MINUTES ) ; // Proxy enabled - 10 minutes
}
else {
2024-10-25 13:06:35 +02:00
builder . readTimeout ( 60 , TimeUnit . SECONDS ) ; // No proxy - 60 seconds max
2020-06-01 19:15:44 +10:00
}
return builder . build ( ) ;
}
catch ( Exception e ) {
throw new RuntimeException ( e ) ;
}
2014-11-20 13:21:19 +00:00
}
}