2017-06-28 20:23:21 +00:00
import ClientConstants as CC
2017-10-04 17:51:58 +00:00
import ClientNetworkingDomain
2017-06-07 22:05:15 +00:00
import collections
2017-06-28 20:23:21 +00:00
import cPickle
2017-06-21 21:15:59 +00:00
import cStringIO
2015-10-21 21:53:10 +00:00
import HydrusConstants as HC
2017-10-25 21:45:15 +00:00
import HydrusData
2015-10-21 21:53:10 +00:00
import HydrusExceptions
2017-10-25 21:45:15 +00:00
import HydrusGlobals as HG
2017-03-02 02:14:56 +00:00
import HydrusNetwork
2017-06-07 22:05:15 +00:00
import HydrusNetworking
2015-11-04 22:30:28 +00:00
import HydrusPaths
2015-10-21 21:53:10 +00:00
import HydrusSerialisable
2017-10-25 21:45:15 +00:00
import itertools
2015-10-21 21:53:10 +00:00
import os
2017-06-21 21:15:59 +00:00
import random
2016-02-24 21:42:54 +00:00
import requests
2017-06-21 21:15:59 +00:00
import urllib3
from urllib3 . exceptions import InsecureRequestWarning
2015-10-21 21:53:10 +00:00
import threading
import time
2017-06-21 21:15:59 +00:00
import traceback
2015-10-21 21:53:10 +00:00
import urllib
import urlparse
import yaml
2017-06-21 21:15:59 +00:00
urllib3 . disable_warnings ( InsecureRequestWarning )
2017-01-25 22:56:55 +00:00
2017-09-06 20:18:20 +00:00
def CombineGETURLWithParameters ( url , params_dict ) :
def make_safe ( text ) :
# convert unicode to raw bytes
# quote that to be url-safe, ignoring the default '/' 'safe' character
return urllib . quote ( HydrusData . ToByteString ( text ) , ' ' )
2017-10-25 21:45:15 +00:00
request_string = ' & ' . join ( ( make_safe ( key ) + ' = ' + make_safe ( value ) for ( key , value ) in params_dict . items ( ) ) )
return url + ' ? ' + request_string
def ConvertStatusCodeAndDataIntoExceptionInfo ( status_code , data , is_hydrus_service = False ) :
error_text = data
if len ( error_text ) > 1024 :
2016-09-07 20:01:05 +00:00
2017-10-25 21:45:15 +00:00
large_chunk = error_text [ : 4096 ]
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
smaller_chunk = large_chunk [ : 256 ]
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
HydrusData . DebugPrint ( large_chunk )
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
error_text = ' The server \' s error text was too long to display. The first part follows, while a larger chunk has been written to the log. '
error_text + = os . linesep
error_text + = smaller_chunk
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
if status_code == 304 :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . NotModifiedException
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
elif status_code == 401 :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . PermissionException
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
elif status_code == 403 :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . ForbiddenException
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
elif status_code == 404 :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . NotFoundException
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
elif status_code == 419 :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . SessionException
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
elif status_code == 426 :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . NetworkVersionException
elif status_code == 509 :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . BandwidthException
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
elif status_code > = 500 :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
if is_hydrus_service and status_code == 503 :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . ServerBusyException
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
else :
2017-05-31 21:50:53 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . ServerException
2017-05-31 21:50:53 +00:00
2017-10-25 21:45:15 +00:00
else :
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
eclass = HydrusExceptions . NetworkException
2015-10-21 21:53:10 +00:00
2017-10-25 21:45:15 +00:00
e = eclass ( error_text )
return ( e , error_text )
2015-10-21 21:53:10 +00:00
2017-06-28 20:23:21 +00:00
class NetworkBandwidthManager ( HydrusSerialisable . SerialisableBase ) :
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
SERIALISABLE_TYPE = HydrusSerialisable . SERIALISABLE_TYPE_NETWORK_BANDWIDTH_MANAGER
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = ' Bandwidth Manager '
2017-06-07 22:05:15 +00:00
SERIALISABLE_VERSION = 1
def __init__ ( self ) :
HydrusSerialisable . SerialisableBase . __init__ ( self )
2017-06-28 20:23:21 +00:00
self . engine = None
2017-07-05 21:09:28 +00:00
self . _dirty = False
2017-06-07 22:05:15 +00:00
self . _lock = threading . Lock ( )
2017-06-28 20:23:21 +00:00
self . _network_contexts_to_bandwidth_trackers = collections . defaultdict ( HydrusNetworking . BandwidthTracker )
2017-07-12 20:03:45 +00:00
self . _network_contexts_to_bandwidth_rules = collections . defaultdict ( HydrusNetworking . BandwidthRules )
2017-06-07 22:05:15 +00:00
2017-07-19 21:21:41 +00:00
for context_type in [ CC . NETWORK_CONTEXT_GLOBAL , CC . NETWORK_CONTEXT_HYDRUS , CC . NETWORK_CONTEXT_DOMAIN , CC . NETWORK_CONTEXT_DOWNLOADER , CC . NETWORK_CONTEXT_DOWNLOADER_QUERY , CC . NETWORK_CONTEXT_SUBSCRIPTION , CC . NETWORK_CONTEXT_THREAD_WATCHER_THREAD ] :
2017-06-28 20:23:21 +00:00
self . _network_contexts_to_bandwidth_rules [ NetworkContext ( context_type ) ] = HydrusNetworking . BandwidthRules ( )
2017-06-07 22:05:15 +00:00
2017-08-16 21:58:06 +00:00
def _CanStartRequest ( self , network_contexts ) :
for network_context in network_contexts :
bandwidth_rules = self . _GetRules ( network_context )
bandwidth_tracker = self . _network_contexts_to_bandwidth_trackers [ network_context ]
if not bandwidth_rules . CanStartRequest ( bandwidth_tracker ) :
return False
return True
2017-06-28 20:23:21 +00:00
def _GetRules ( self , network_context ) :
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
if network_context not in self . _network_contexts_to_bandwidth_rules :
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
network_context = NetworkContext ( network_context . context_type ) # i.e. the default
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
return self . _network_contexts_to_bandwidth_rules [ network_context ]
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
def _GetSerialisableInfo ( self ) :
2017-07-19 21:21:41 +00:00
# note this discards ephemeral network contexts, which have page_key-specific identifiers and are temporary, not meant to be hung onto forever, and are generally invisible to the user
all_serialisable_trackers = [ ( network_context . GetSerialisableTuple ( ) , tracker . GetSerialisableTuple ( ) ) for ( network_context , tracker ) in self . _network_contexts_to_bandwidth_trackers . items ( ) if not network_context . IsEphemeral ( ) ]
2017-07-05 21:09:28 +00:00
all_serialisable_rules = [ ( network_context . GetSerialisableTuple ( ) , rules . GetSerialisableTuple ( ) ) for ( network_context , rules ) in self . _network_contexts_to_bandwidth_rules . items ( ) ]
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
return ( all_serialisable_trackers , all_serialisable_rules )
2017-06-21 21:15:59 +00:00
def _InitialiseFromSerialisableInfo ( self , serialisable_info ) :
2017-07-05 21:09:28 +00:00
( all_serialisable_trackers , all_serialisable_rules ) = serialisable_info
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
for ( serialisable_network_context , serialisable_tracker ) in all_serialisable_trackers :
network_context = HydrusSerialisable . CreateFromSerialisableTuple ( serialisable_network_context )
tracker = HydrusSerialisable . CreateFromSerialisableTuple ( serialisable_tracker )
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
self . _network_contexts_to_bandwidth_trackers [ network_context ] = tracker
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
for ( serialisable_network_context , serialisable_rules ) in all_serialisable_rules :
network_context = HydrusSerialisable . CreateFromSerialisableTuple ( serialisable_network_context )
rules = HydrusSerialisable . CreateFromSerialisableTuple ( serialisable_rules )
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
self . _network_contexts_to_bandwidth_rules [ network_context ] = rules
2017-06-21 21:15:59 +00:00
2017-08-16 21:58:06 +00:00
def _ReportRequestUsed ( self , network_contexts ) :
for network_context in network_contexts :
self . _network_contexts_to_bandwidth_trackers [ network_context ] . ReportRequestUsed ( )
self . _SetDirty ( )
2017-07-05 21:09:28 +00:00
def _SetDirty ( self ) :
self . _dirty = True
2017-07-27 00:47:13 +00:00
def CanContinueDownload ( self , network_contexts ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
with self . _lock :
for network_context in network_contexts :
bandwidth_rules = self . _GetRules ( network_context )
bandwidth_tracker = self . _network_contexts_to_bandwidth_trackers [ network_context ]
2017-07-27 00:47:13 +00:00
if not bandwidth_rules . CanContinueDownload ( bandwidth_tracker ) :
2017-06-28 20:23:21 +00:00
return False
return True
2017-06-21 21:15:59 +00:00
2018-02-07 23:40:33 +00:00
def CanDoWork ( self , network_contexts , expected_requests = 3 , expected_bytes = 1048576 , threshold = 30 ) :
2017-06-21 21:15:59 +00:00
with self . _lock :
2017-06-28 20:23:21 +00:00
for network_context in network_contexts :
bandwidth_rules = self . _GetRules ( network_context )
bandwidth_tracker = self . _network_contexts_to_bandwidth_trackers [ network_context ]
2017-06-21 21:15:59 +00:00
2018-02-07 23:40:33 +00:00
if not bandwidth_rules . CanDoWork ( bandwidth_tracker , expected_requests = expected_requests , expected_bytes = expected_bytes , threshold = threshold ) :
2017-07-27 00:47:13 +00:00
return False
return True
def CanStartRequest ( self , network_contexts ) :
with self . _lock :
2017-08-16 21:58:06 +00:00
return self . _CanStartRequest ( network_contexts )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
def DeleteRules ( self , network_context ) :
with self . _lock :
2017-07-19 21:21:41 +00:00
if network_context . context_data is None :
2017-06-28 20:23:21 +00:00
return # can't delete 'default' network contexts
else :
if network_context in self . _network_contexts_to_bandwidth_rules :
del self . _network_contexts_to_bandwidth_rules [ network_context ]
2017-07-05 21:09:28 +00:00
self . _SetDirty ( )
2017-06-21 21:15:59 +00:00
2017-07-19 21:21:41 +00:00
def DeleteHistory ( self , network_contexts ) :
with self . _lock :
for network_context in network_contexts :
if network_context in self . _network_contexts_to_bandwidth_trackers :
del self . _network_contexts_to_bandwidth_trackers [ network_context ]
if network_context == GLOBAL_NETWORK_CONTEXT :
# just to reset it, so we have a 0 global context at all times
self . _network_contexts_to_bandwidth_trackers [ GLOBAL_NETWORK_CONTEXT ] = HydrusNetworking . BandwidthTracker ( )
self . _SetDirty ( )
def GetDefaultRules ( self ) :
with self . _lock :
result = [ ]
for ( network_context , bandwidth_rules ) in self . _network_contexts_to_bandwidth_rules . items ( ) :
if network_context . IsDefault ( ) :
result . append ( ( network_context , bandwidth_rules ) )
return result
2017-10-25 21:45:15 +00:00
def GetCurrentMonthSummary ( self , network_context ) :
with self . _lock :
bandwidth_tracker = self . _network_contexts_to_bandwidth_trackers [ network_context ]
return bandwidth_tracker . GetCurrentMonthSummary ( )
def GetBandwidthStringsAndGaugeTuples ( self , network_context ) :
with self . _lock :
bandwidth_rules = self . _GetRules ( network_context )
bandwidth_tracker = self . _network_contexts_to_bandwidth_trackers [ network_context ]
return bandwidth_rules . GetBandwidthStringsAndGaugeTuples ( bandwidth_tracker )
2017-08-02 21:32:54 +00:00
def GetNetworkContextsForUser ( self , history_time_delta_threshold = None ) :
2017-07-12 20:03:45 +00:00
with self . _lock :
2017-08-16 21:58:06 +00:00
result = set ( )
2017-07-12 20:03:45 +00:00
for ( network_context , bandwidth_tracker ) in self . _network_contexts_to_bandwidth_trackers . items ( ) :
2017-07-19 21:21:41 +00:00
if network_context . IsDefault ( ) or network_context . IsEphemeral ( ) :
2017-07-12 20:03:45 +00:00
continue
2017-07-19 21:21:41 +00:00
if network_context != GLOBAL_NETWORK_CONTEXT and history_time_delta_threshold is not None :
2017-07-12 20:03:45 +00:00
2017-07-19 21:21:41 +00:00
if bandwidth_tracker . GetUsage ( HC . BANDWIDTH_TYPE_REQUESTS , history_time_delta_threshold ) == 0 :
continue
2017-07-12 20:03:45 +00:00
2017-08-16 21:58:06 +00:00
result . add ( network_context )
2017-07-19 21:21:41 +00:00
2017-07-12 20:03:45 +00:00
return result
2017-07-19 21:21:41 +00:00
def GetRules ( self , network_context ) :
with self . _lock :
return self . _GetRules ( network_context )
2017-06-28 20:23:21 +00:00
def GetTracker ( self , network_context ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
with self . _lock :
2017-07-19 21:21:41 +00:00
if network_context in self . _network_contexts_to_bandwidth_trackers :
return self . _network_contexts_to_bandwidth_trackers [ network_context ]
else :
return HydrusNetworking . BandwidthTracker ( )
2017-06-28 20:23:21 +00:00
2017-06-21 21:15:59 +00:00
2017-08-09 21:33:51 +00:00
def GetWaitingEstimate ( self , network_contexts ) :
with self . _lock :
estimates = [ ]
for network_context in network_contexts :
bandwidth_rules = self . _GetRules ( network_context )
bandwidth_tracker = self . _network_contexts_to_bandwidth_trackers [ network_context ]
estimates . append ( bandwidth_rules . GetWaitingEstimate ( bandwidth_tracker ) )
if len ( estimates ) == 0 :
return 0
else :
return max ( estimates )
2017-07-05 21:09:28 +00:00
def IsDirty ( self ) :
with self . _lock :
return self . _dirty
2017-06-28 20:23:21 +00:00
def ReportDataUsed ( self , network_contexts , num_bytes ) :
2017-06-07 22:05:15 +00:00
with self . _lock :
2017-06-28 20:23:21 +00:00
for network_context in network_contexts :
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
self . _network_contexts_to_bandwidth_trackers [ network_context ] . ReportDataUsed ( num_bytes )
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
self . _SetDirty ( )
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
def ReportRequestUsed ( self , network_contexts ) :
2017-06-07 22:05:15 +00:00
with self . _lock :
2017-08-16 21:58:06 +00:00
self . _ReportRequestUsed ( network_contexts )
2017-07-05 21:09:28 +00:00
def SetClean ( self ) :
with self . _lock :
self . _dirty = False
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
def SetRules ( self , network_context , bandwidth_rules ) :
2017-06-07 22:05:15 +00:00
with self . _lock :
2017-07-19 21:21:41 +00:00
if len ( bandwidth_rules . GetRules ( ) ) == 0 :
if network_context in self . _network_contexts_to_bandwidth_rules :
del self . _network_contexts_to_bandwidth_rules [ network_context ]
else :
self . _network_contexts_to_bandwidth_rules [ network_context ] = bandwidth_rules
self . _SetDirty ( )
2017-08-16 21:58:06 +00:00
def TryToStartRequest ( self , network_contexts ) :
# this wraps canstart and reportrequest in one transaction to stop 5/1 rq/s happening due to race condition
with self . _lock :
if not self . _CanStartRequest ( network_contexts ) :
return False
self . _ReportRequestUsed ( network_contexts )
return True
2017-07-19 21:21:41 +00:00
def UsesDefaultRules ( self , network_context ) :
with self . _lock :
return network_context not in self . _network_contexts_to_bandwidth_rules
2017-06-28 20:23:21 +00:00
2017-07-05 21:09:28 +00:00
HydrusSerialisable . SERIALISABLE_TYPES_TO_OBJECT_TYPES [ HydrusSerialisable . SERIALISABLE_TYPE_NETWORK_BANDWIDTH_MANAGER ] = NetworkBandwidthManager
2017-06-28 20:23:21 +00:00
class NetworkContext ( HydrusSerialisable . SerialisableBase ) :
SERIALISABLE_TYPE = HydrusSerialisable . SERIALISABLE_TYPE_NETWORK_CONTEXT
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = ' Network Context '
2017-08-02 21:32:54 +00:00
SERIALISABLE_VERSION = 2
2017-06-28 20:23:21 +00:00
def __init__ ( self , context_type = None , context_data = None ) :
HydrusSerialisable . SerialisableBase . __init__ ( self )
self . context_type = context_type
self . context_data = context_data
def __eq__ ( self , other ) :
return self . __hash__ ( ) == other . __hash__ ( )
def __hash__ ( self ) :
return ( self . context_type , self . context_data ) . __hash__ ( )
def __ne__ ( self , other ) :
return self . __hash__ ( ) != other . __hash__ ( )
2017-07-12 20:03:45 +00:00
def __repr__ ( self ) :
return self . ToUnicode ( )
2017-06-28 20:23:21 +00:00
def _GetSerialisableInfo ( self ) :
if self . context_data is None :
2017-07-05 21:09:28 +00:00
serialisable_context_data = self . context_data
2017-06-28 20:23:21 +00:00
else :
2017-08-02 21:32:54 +00:00
if self . context_type in ( CC . NETWORK_CONTEXT_DOMAIN , CC . NETWORK_CONTEXT_SUBSCRIPTION ) :
serialisable_context_data = self . context_data
else :
serialisable_context_data = self . context_data . encode ( ' hex ' )
2017-06-28 20:23:21 +00:00
2017-07-05 21:09:28 +00:00
return ( self . context_type , serialisable_context_data )
2017-06-28 20:23:21 +00:00
def _InitialiseFromSerialisableInfo ( self , serialisable_info ) :
( self . context_type , serialisable_context_data ) = serialisable_info
if serialisable_context_data is None :
self . context_data = serialisable_context_data
else :
2017-08-02 21:32:54 +00:00
if self . context_type in ( CC . NETWORK_CONTEXT_DOMAIN , CC . NETWORK_CONTEXT_SUBSCRIPTION ) :
self . context_data = serialisable_context_data
else :
self . context_data = serialisable_context_data . decode ( ' hex ' )
def _UpdateSerialisableInfo ( self , version , old_serialisable_info ) :
if version == 1 :
( context_type , serialisable_context_data ) = old_serialisable_info
if serialisable_context_data is not None :
# unicode subscription names were erroring on the hex call
if context_type in ( CC . NETWORK_CONTEXT_DOMAIN , CC . NETWORK_CONTEXT_SUBSCRIPTION ) :
context_data = serialisable_context_data . decode ( ' hex ' )
serialisable_context_data = context_data
new_serialisable_info = ( context_type , serialisable_context_data )
return ( 2 , new_serialisable_info )
2017-06-07 22:05:15 +00:00
2017-07-19 21:21:41 +00:00
def IsDefault ( self ) :
return self . context_data is None and self . context_type != CC . NETWORK_CONTEXT_GLOBAL
def IsEphemeral ( self ) :
return self . context_type in ( CC . NETWORK_CONTEXT_DOWNLOADER_QUERY , CC . NETWORK_CONTEXT_THREAD_WATCHER_THREAD )
2017-07-12 20:03:45 +00:00
def ToUnicode ( self ) :
if self . context_data is None :
2017-07-19 21:21:41 +00:00
if self . context_type == CC . NETWORK_CONTEXT_GLOBAL :
return ' global '
else :
return CC . network_context_type_string_lookup [ self . context_type ] + ' default '
2017-07-12 20:03:45 +00:00
else :
2017-10-25 21:45:15 +00:00
if self . context_type == CC . NETWORK_CONTEXT_HYDRUS :
service_key = self . context_data
services_manager = HG . client_controller . services_manager
if services_manager . ServiceExists ( service_key ) :
name = HG . client_controller . services_manager . GetName ( service_key )
else :
name = ' unknown service--probably deleted or an unusual test '
else :
name = HydrusData . ToUnicode ( self . context_data )
return CC . network_context_type_string_lookup [ self . context_type ] + ' : ' + name
2017-07-12 20:03:45 +00:00
2017-06-28 20:23:21 +00:00
HydrusSerialisable . SERIALISABLE_TYPES_TO_OBJECT_TYPES [ HydrusSerialisable . SERIALISABLE_TYPE_NETWORK_CONTEXT ] = NetworkContext
GLOBAL_NETWORK_CONTEXT = NetworkContext ( CC . NETWORK_CONTEXT_GLOBAL )
2017-06-07 22:05:15 +00:00
class NetworkEngine ( object ) :
2017-06-21 21:15:59 +00:00
MAX_JOBS = 10 # turn this into an option
2017-10-04 17:51:58 +00:00
def __init__ ( self , controller , bandwidth_manager , session_manager , domain_manager , login_manager ) :
2017-06-28 20:23:21 +00:00
self . controller = controller
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
self . bandwidth_manager = bandwidth_manager
self . session_manager = session_manager
2017-10-04 17:51:58 +00:00
self . domain_manager = domain_manager
2017-06-28 20:23:21 +00:00
self . login_manager = login_manager
self . bandwidth_manager . engine = self
self . session_manager . engine = self
2017-10-04 17:51:58 +00:00
self . domain_manager . engine = self
2017-06-28 20:23:21 +00:00
self . login_manager . engine = self
2017-06-07 22:05:15 +00:00
self . _lock = threading . Lock ( )
self . _new_work_to_do = threading . Event ( )
2017-10-04 17:51:58 +00:00
self . _jobs_awaiting_validity = [ ]
self . _current_validation_process = None
2017-06-21 21:15:59 +00:00
self . _jobs_bandwidth_throttled = [ ]
self . _jobs_login_throttled = [ ]
self . _current_login_process = None
self . _jobs_ready_to_start = [ ]
self . _jobs_downloading = [ ]
2017-06-07 22:05:15 +00:00
2018-03-14 21:01:02 +00:00
self . _pause_all_new_network_traffic = self . controller . new_options . GetBoolean ( ' pause_all_new_network_traffic ' )
2017-06-28 20:23:21 +00:00
self . _is_running = False
self . _is_shutdown = False
2017-06-07 22:05:15 +00:00
self . _local_shutdown = False
def AddJob ( self , job ) :
with self . _lock :
2017-06-28 20:23:21 +00:00
job . engine = self
2017-10-04 17:51:58 +00:00
self . _jobs_awaiting_validity . append ( job )
2017-06-07 22:05:15 +00:00
self . _new_work_to_do . set ( )
2017-06-28 20:23:21 +00:00
def IsRunning ( self ) :
with self . _lock :
return self . _is_running
def IsShutdown ( self ) :
with self . _lock :
return self . _is_shutdown
2017-06-07 22:05:15 +00:00
def MainLoop ( self ) :
2017-10-04 17:51:58 +00:00
def ProcessValidationJob ( job ) :
if job . IsDone ( ) :
return False
elif job . IsAsleep ( ) :
return True
elif not job . IsValid ( ) :
if job . CanValidateInPopup ( ) :
if self . _current_validation_process is None :
2017-10-11 17:38:14 +00:00
validation_process = job . GenerateValidationPopupProcess ( )
2017-10-04 17:51:58 +00:00
2017-10-11 17:38:14 +00:00
self . controller . CallToThread ( validation_process . Start )
2017-10-04 17:51:58 +00:00
self . _current_validation_process = validation_process
job . SetStatus ( u ' validation presented to user \u2026 ' )
else :
2017-10-25 21:45:15 +00:00
job . SetStatus ( u ' waiting in user validation queue \u2026 ' )
2017-10-04 17:51:58 +00:00
job . Sleep ( 5 )
2017-10-25 21:45:15 +00:00
return True
2017-10-04 17:51:58 +00:00
else :
2017-10-25 21:45:15 +00:00
error_text = u ' network context not currently valid! '
2017-10-04 17:51:58 +00:00
2017-10-25 21:45:15 +00:00
job . SetError ( HydrusExceptions . ValidationException ( error_text ) , error_text )
return False
2017-10-04 17:51:58 +00:00
else :
self . _jobs_bandwidth_throttled . append ( job )
return False
def ProcessCurrentValidationJob ( ) :
if self . _current_validation_process is not None :
if self . _current_validation_process . IsDone ( ) :
self . _current_validation_process = None
2017-07-27 00:47:13 +00:00
def ProcessBandwidthJob ( job ) :
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
if job . IsDone ( ) :
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
return False
elif job . IsAsleep ( ) :
return True
elif not job . BandwidthOK ( ) :
return True
else :
self . _jobs_login_throttled . append ( job )
return False
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
def ProcessLoginJob ( job ) :
if job . IsDone ( ) :
2017-06-21 21:15:59 +00:00
2017-07-27 00:47:13 +00:00
return False
elif job . IsAsleep ( ) :
return True
elif job . NeedsLogin ( ) :
2018-02-28 22:30:36 +00:00
try :
2017-06-21 21:15:59 +00:00
2018-02-28 22:30:36 +00:00
job . CheckCanLogin ( )
2017-06-21 21:15:59 +00:00
2018-02-28 22:30:36 +00:00
except Exception as e :
2017-10-25 21:45:15 +00:00
2018-02-28 22:30:36 +00:00
job . SetError ( e , HydrusData . ToUnicode ( e ) )
2017-06-21 21:15:59 +00:00
2018-02-28 22:30:36 +00:00
return False
2017-06-21 21:15:59 +00:00
2018-02-28 22:30:36 +00:00
if self . _current_login_process is None :
2017-10-25 21:45:15 +00:00
2018-02-28 22:30:36 +00:00
login_process = job . GenerateLoginProcess ( )
self . controller . CallToThread ( login_process . Start )
self . _current_login_process = login_process
job . SetStatus ( u ' logging in \u2026 ' )
else :
job . SetStatus ( u ' waiting in login queue \u2026 ' )
job . Sleep ( 5 )
2017-06-21 21:15:59 +00:00
2017-07-27 00:47:13 +00:00
2018-02-28 22:30:36 +00:00
return True
2017-07-27 00:47:13 +00:00
else :
self . _jobs_ready_to_start . append ( job )
return False
def ProcessCurrentLoginJob ( ) :
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
if self . _current_login_process is not None :
2017-06-21 21:15:59 +00:00
2017-07-27 00:47:13 +00:00
if self . _current_login_process . IsDone ( ) :
2017-06-21 21:15:59 +00:00
2017-07-27 00:47:13 +00:00
self . _current_login_process = None
2017-06-21 21:15:59 +00:00
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
def ProcessReadyJob ( job ) :
if job . IsDone ( ) :
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
return False
elif len ( self . _jobs_downloading ) < self . MAX_JOBS :
2017-06-07 22:05:15 +00:00
2018-03-14 21:01:02 +00:00
if self . _pause_all_new_network_traffic :
job . SetStatus ( u ' all new network traffic is paused \u2026 ' )
return True
else :
self . controller . CallToThread ( job . Start )
self . _jobs_downloading . append ( job )
return False
2017-07-27 00:47:13 +00:00
else :
2017-08-16 21:58:06 +00:00
job . SetStatus ( u ' waiting for download slot \u2026 ' )
2017-07-27 00:47:13 +00:00
return True
def ProcessDownloadingJob ( job ) :
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
if job . IsDone ( ) :
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
return False
else :
return True
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
self . _is_running = True
while not ( self . _local_shutdown or self . controller . ModelIsShutdown ( ) ) :
2017-06-21 21:15:59 +00:00
with self . _lock :
2017-10-04 17:51:58 +00:00
self . _jobs_awaiting_validity = filter ( ProcessValidationJob , self . _jobs_awaiting_validity )
ProcessCurrentValidationJob ( )
2017-06-21 21:15:59 +00:00
self . _jobs_bandwidth_throttled = filter ( ProcessBandwidthJob , self . _jobs_bandwidth_throttled )
self . _jobs_login_throttled = filter ( ProcessLoginJob , self . _jobs_login_throttled )
ProcessCurrentLoginJob ( )
self . _jobs_ready_to_start = filter ( ProcessReadyJob , self . _jobs_ready_to_start )
self . _jobs_downloading = filter ( ProcessDownloadingJob , self . _jobs_downloading )
2017-06-07 22:05:15 +00:00
2017-08-23 21:34:25 +00:00
# we want to catch the rollover of the second for bandwidth jobs
now_with_subsecond = time . time ( )
subsecond_part = now_with_subsecond % 1
time_until_next_second = 1.0 - subsecond_part
self . _new_work_to_do . wait ( time_until_next_second )
2017-06-07 22:05:15 +00:00
self . _new_work_to_do . clear ( )
2017-06-28 20:23:21 +00:00
self . _is_running = False
self . _is_shutdown = True
2018-03-14 21:01:02 +00:00
def PausePlayNewJobs ( self ) :
self . _pause_all_new_network_traffic = not self . _pause_all_new_network_traffic
self . controller . new_options . SetBoolean ( ' pause_all_new_network_traffic ' , self . _pause_all_new_network_traffic )
2017-06-07 22:05:15 +00:00
def Shutdown ( self ) :
self . _local_shutdown = True
2017-06-28 20:23:21 +00:00
self . _new_work_to_do . set ( )
2017-06-07 22:05:15 +00:00
class NetworkJob ( object ) :
2017-10-25 21:45:15 +00:00
IS_HYDRUS_SERVICE = False
def __init__ ( self , method , url , body = None , referral_url = None , temp_path = None ) :
2017-06-28 20:23:21 +00:00
2017-08-16 21:58:06 +00:00
if HG . network_report_mode :
HydrusData . ShowText ( ' Network Job: ' + method + ' ' + url )
2017-06-28 20:23:21 +00:00
self . engine = None
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
self . _lock = threading . Lock ( )
2017-06-07 22:05:15 +00:00
self . _method = method
self . _url = url
self . _body = body
self . _referral_url = referral_url
self . _temp_path = temp_path
2017-09-06 20:18:20 +00:00
2017-10-25 21:45:15 +00:00
self . _files = None
2017-09-06 20:18:20 +00:00
self . _for_login = False
2017-09-20 19:47:31 +00:00
self . _current_connection_attempt_number = 1
2017-09-06 20:18:20 +00:00
self . _additional_headers = { }
2017-06-07 22:05:15 +00:00
2017-08-16 21:58:06 +00:00
self . _creation_time = HydrusData . GetNow ( )
2017-06-21 21:15:59 +00:00
self . _bandwidth_tracker = HydrusNetworking . BandwidthTracker ( )
self . _wake_time = 0
2017-06-07 22:05:15 +00:00
2017-10-25 21:45:15 +00:00
self . _content_type = None
2017-06-21 21:15:59 +00:00
self . _stream_io = cStringIO . StringIO ( )
2017-06-07 22:05:15 +00:00
2017-12-20 22:55:48 +00:00
self . _error_exception = Exception ( ' Exception not initialised. ' ) # PyLint hint, wew
2017-06-21 21:15:59 +00:00
self . _error_exception = None
self . _error_text = None
2017-09-06 20:18:20 +00:00
self . _is_done_event = threading . Event ( )
2017-06-07 22:05:15 +00:00
self . _is_done = False
self . _is_cancelled = False
2017-06-28 20:23:21 +00:00
self . _bandwidth_manual_override = False
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
self . _last_time_ongoing_bandwidth_failed = 0
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
self . _status_text = u ' initialising \u2026 '
self . _num_bytes_read = 0
2017-07-05 21:09:28 +00:00
self . _num_bytes_to_read = 1
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
self . _network_contexts = self . _GenerateNetworkContexts ( )
2017-11-01 20:37:39 +00:00
( self . _session_network_context , self . _login_network_context ) = self . _GenerateSpecificNetworkContexts ( )
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
def _CanReattemptRequest ( self ) :
if self . _method == ' GET ' :
max_attempts_allowed = 5
elif self . _method == ' POST ' :
max_attempts_allowed = 1
return self . _current_connection_attempt_number < = max_attempts_allowed
2017-06-28 20:23:21 +00:00
def _GenerateNetworkContexts ( self ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
network_contexts = [ ]
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
network_contexts . append ( GLOBAL_NETWORK_CONTEXT )
2017-06-21 21:15:59 +00:00
2017-10-04 17:51:58 +00:00
domain = ClientNetworkingDomain . ConvertURLIntoDomain ( self . _url )
domains = ClientNetworkingDomain . ConvertDomainIntoAllApplicableDomains ( domain )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
network_contexts . extend ( ( NetworkContext ( CC . NETWORK_CONTEXT_DOMAIN , domain ) for domain in domains ) )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
return network_contexts
2017-06-21 21:15:59 +00:00
2017-11-01 20:37:39 +00:00
def _GenerateSpecificNetworkContexts ( self ) :
# we always store cookies in the larger session
# but we can login to a specific subdomain
domain = ClientNetworkingDomain . ConvertURLIntoDomain ( self . _url )
domains = ClientNetworkingDomain . ConvertDomainIntoAllApplicableDomains ( domain )
session_network_context = NetworkContext ( CC . NETWORK_CONTEXT_DOMAIN , domains [ - 1 ] )
login_network_context = NetworkContext ( CC . NETWORK_CONTEXT_DOMAIN , domain )
return ( session_network_context , login_network_context )
2017-07-27 00:47:13 +00:00
def _SendRequestAndGetResponse ( self ) :
with self . _lock :
session = self . _GetSession ( )
method = self . _method
url = self . _url
data = self . _body
2017-09-06 20:18:20 +00:00
files = self . _files
2017-07-27 00:47:13 +00:00
2017-10-11 17:38:14 +00:00
headers = self . engine . domain_manager . GetHeaders ( self . _network_contexts )
2017-07-27 00:47:13 +00:00
2017-10-25 21:45:15 +00:00
if self . IS_HYDRUS_SERVICE :
headers [ ' User-Agent ' ] = ' hydrus client/ ' + str ( HC . NETWORK_VERSION )
2017-07-27 00:47:13 +00:00
if self . _referral_url is not None :
2017-10-11 17:38:14 +00:00
headers [ ' referer ' ] = self . _referral_url
2017-07-27 00:47:13 +00:00
2017-09-06 20:18:20 +00:00
for ( key , value ) in self . _additional_headers . items ( ) :
headers [ key ] = value
2017-09-20 19:47:31 +00:00
self . _status_text = u ' sending request \u2026 '
2017-07-27 00:47:13 +00:00
2017-12-06 22:06:56 +00:00
connect_timeout = HG . client_controller . new_options . GetInteger ( ' network_timeout ' )
2017-07-27 00:47:13 +00:00
2017-11-01 20:37:39 +00:00
read_timeout = connect_timeout * 6
response = session . request ( method , url , data = data , files = files , headers = headers , stream = True , timeout = ( connect_timeout , read_timeout ) )
2017-07-27 00:47:13 +00:00
return response
2017-06-21 21:15:59 +00:00
def _GetSession ( self ) :
2017-11-01 20:37:39 +00:00
return self . engine . session_manager . GetSession ( self . _session_network_context )
2017-06-07 22:05:15 +00:00
def _IsCancelled ( self ) :
if self . _is_cancelled :
return True
2017-06-28 20:23:21 +00:00
if self . engine . controller . ModelIsShutdown ( ) :
2017-06-07 22:05:15 +00:00
return True
return False
2017-06-28 20:23:21 +00:00
def _IsDone ( self ) :
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
if self . _is_done :
return True
if self . engine . controller . ModelIsShutdown ( ) :
return True
return False
def _ObeysBandwidth ( self ) :
2017-11-01 20:37:39 +00:00
return not ( self . _method == ' POST ' or self . _bandwidth_manual_override or self . _for_login )
2017-06-28 20:23:21 +00:00
def _OngoingBandwidthOK ( self ) :
2017-07-05 21:09:28 +00:00
now = HydrusData . GetNow ( )
if now == self . _last_time_ongoing_bandwidth_failed : # it won't have changed, so no point spending any cpu checking
2017-06-28 20:23:21 +00:00
2017-07-05 21:09:28 +00:00
return False
2017-06-28 20:23:21 +00:00
else :
2017-07-27 00:47:13 +00:00
result = self . engine . bandwidth_manager . CanContinueDownload ( self . _network_contexts )
2017-07-05 21:09:28 +00:00
if not result :
self . _last_time_ongoing_bandwidth_failed = now
return result
2017-06-28 20:23:21 +00:00
2017-06-07 22:05:15 +00:00
2017-11-08 22:07:12 +00:00
def _ReadResponse ( self , response , stream_dest , max_allowed = None ) :
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
with self . _lock :
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
if ' content-length ' in response . headers :
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
self . _num_bytes_to_read = int ( response . headers [ ' content-length ' ] )
2017-06-07 22:05:15 +00:00
2017-11-08 22:07:12 +00:00
if max_allowed is not None and self . _num_bytes_to_read > max_allowed :
raise HydrusExceptions . NetworkException ( ' The url ' + self . _url + ' looks too large! ' )
2017-07-05 21:09:28 +00:00
else :
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
self . _num_bytes_to_read = None
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
for chunk in response . iter_content ( chunk_size = 65536 ) :
if self . _IsCancelled ( ) :
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
return
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
stream_dest . write ( chunk )
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
chunk_length = len ( chunk )
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
with self . _lock :
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
self . _num_bytes_read + = chunk_length
2017-06-21 21:15:59 +00:00
2017-11-08 22:07:12 +00:00
if max_allowed is not None and self . _num_bytes_read > max_allowed :
raise HydrusExceptions . NetworkException ( ' The url ' + self . _url + ' was too large! ' )
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
self . _ReportDataUsed ( chunk_length )
self . _WaitOnOngoingBandwidth ( )
2017-09-06 20:18:20 +00:00
if HG . view_shutdown :
raise HydrusExceptions . ShutdownException ( )
2017-06-07 22:05:15 +00:00
2018-01-10 22:41:51 +00:00
if self . _num_bytes_to_read is not None and self . _num_bytes_read < self . _num_bytes_to_read * 0.8 :
raise HydrusExceptions . NetworkException ( ' Did not read enough data! Was expecting ' + HydrusData . ConvertIntToBytes ( self . _num_bytes_to_read ) + ' but only got ' + HydrusData . ConvertIntToBytes ( self . _num_bytes_read ) + ' . ' )
2017-06-21 21:15:59 +00:00
def _ReportDataUsed ( self , num_bytes ) :
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
self . _bandwidth_tracker . ReportDataUsed ( num_bytes )
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
self . engine . bandwidth_manager . ReportDataUsed ( self . _network_contexts , num_bytes )
2017-06-21 21:15:59 +00:00
def _SetCancelled ( self ) :
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
self . _is_cancelled = True
self . _SetDone ( )
def _SetError ( self , e , error ) :
self . _error_exception = e
self . _error_text = error
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
self . _SetDone ( )
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
def _SetDone ( self ) :
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
self . _is_done = True
2017-09-06 20:18:20 +00:00
self . _is_done_event . set ( )
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
def _Sleep ( self , seconds ) :
self . _wake_time = HydrusData . GetNow ( ) + seconds
2017-06-28 20:23:21 +00:00
def _WaitOnOngoingBandwidth ( self ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
while not self . _OngoingBandwidthOK ( ) and not self . _IsCancelled ( ) :
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
time . sleep ( 0.1 )
2017-06-21 21:15:59 +00:00
2017-09-06 20:18:20 +00:00
def AddAdditionalHeader ( self , key , value ) :
with self . _lock :
self . _additional_headers [ key ] = value
2017-06-21 21:15:59 +00:00
def BandwidthOK ( self ) :
with self . _lock :
2017-07-05 21:09:28 +00:00
if self . _ObeysBandwidth ( ) :
2017-08-16 21:58:06 +00:00
result = self . engine . bandwidth_manager . TryToStartRequest ( self . _network_contexts )
2017-07-05 21:09:28 +00:00
2017-08-16 21:58:06 +00:00
if result :
self . _bandwidth_tracker . ReportRequestUsed ( )
else :
2017-07-05 21:09:28 +00:00
2017-08-09 21:33:51 +00:00
waiting_duration = self . engine . bandwidth_manager . GetWaitingEstimate ( self . _network_contexts )
2017-08-23 21:34:25 +00:00
if waiting_duration < 2 :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
self . _status_text = u ' bandwidth free imminently \u2026 '
2017-08-09 21:33:51 +00:00
else :
pending_timestamp = HydrusData . GetNow ( ) + waiting_duration
waiting_str = HydrusData . ConvertTimestampToPrettyPending ( pending_timestamp )
2017-11-15 22:35:49 +00:00
self . _status_text = u ' bandwidth free in ' + waiting_str + u ' \u2026 '
2017-08-09 21:33:51 +00:00
2017-07-05 21:09:28 +00:00
2017-08-09 21:33:51 +00:00
if waiting_duration > 1200 :
self . _Sleep ( 30 )
elif waiting_duration > 120 :
self . _Sleep ( 10 )
elif waiting_duration > 10 :
self . _Sleep ( 1 )
2017-07-05 21:09:28 +00:00
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
return result
2017-06-21 21:15:59 +00:00
else :
2017-08-16 21:58:06 +00:00
self . _bandwidth_tracker . ReportRequestUsed ( )
self . engine . bandwidth_manager . ReportRequestUsed ( self . _network_contexts )
2017-06-28 20:23:21 +00:00
return True
2017-06-21 21:15:59 +00:00
2017-06-07 22:05:15 +00:00
def Cancel ( self ) :
2017-06-21 21:15:59 +00:00
with self . _lock :
self . _status_text = ' cancelled! '
self . _SetCancelled ( )
2018-02-28 22:30:36 +00:00
def CanValidateInPopup ( self ) :
2017-06-28 20:23:21 +00:00
with self . _lock :
2018-02-28 22:30:36 +00:00
return self . engine . domain_manager . CanValidateInPopup ( self . _network_contexts )
2017-06-28 20:23:21 +00:00
2018-02-28 22:30:36 +00:00
def CheckCanLogin ( self ) :
2017-10-04 17:51:58 +00:00
with self . _lock :
2018-02-28 22:30:36 +00:00
if self . _for_login :
raise HydrusExceptions . LoginException ( ' Login jobs should not be asked if they can login! ' )
else :
return self . engine . login_manager . CheckCanLogin ( self . _login_network_context )
2017-10-04 17:51:58 +00:00
2017-06-21 21:15:59 +00:00
def GenerateLoginProcess ( self ) :
with self . _lock :
2017-06-28 20:23:21 +00:00
if self . _for_login :
raise Exception ( ' Login jobs should not be asked to generate login processes! ' )
else :
2017-11-01 20:37:39 +00:00
return self . engine . login_manager . GenerateLoginProcess ( self . _login_network_context )
2017-06-28 20:23:21 +00:00
2017-06-21 21:15:59 +00:00
2017-06-07 22:05:15 +00:00
2017-10-04 17:51:58 +00:00
def GenerateValidationPopupProcess ( self ) :
with self . _lock :
return self . engine . domain_manager . GenerateValidationPopupProcess ( self . _network_contexts )
2017-06-07 22:05:15 +00:00
def GetContent ( self ) :
2017-06-21 21:15:59 +00:00
with self . _lock :
self . _stream_io . seek ( 0 )
return self . _stream_io . read ( )
2017-06-07 22:05:15 +00:00
2017-10-25 21:45:15 +00:00
def GetContentType ( self ) :
with self . _lock :
return self . _content_type
2017-08-16 21:58:06 +00:00
def GetCreationTime ( self ) :
with self . _lock :
return self . _creation_time
2017-06-21 21:15:59 +00:00
def GetErrorException ( self ) :
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
with self . _lock :
return self . _error_exception
def GetErrorText ( self ) :
with self . _lock :
return self . _error_text
2017-06-07 22:05:15 +00:00
2017-07-27 00:47:13 +00:00
def GetNetworkContexts ( self ) :
with self . _lock :
return list ( self . _network_contexts )
2017-06-07 22:05:15 +00:00
def GetStatus ( self ) :
with self . _lock :
2017-06-21 21:15:59 +00:00
return ( self . _status_text , self . _bandwidth_tracker . GetUsage ( HC . BANDWIDTH_TYPE_DATA , 1 ) , self . _num_bytes_read , self . _num_bytes_to_read )
2017-06-07 22:05:15 +00:00
2017-10-25 21:45:15 +00:00
def GetTotalDataUsed ( self ) :
with self . _lock :
return self . _bandwidth_tracker . GetUsage ( HC . BANDWIDTH_TYPE_DATA , None )
2017-06-07 22:05:15 +00:00
def HasError ( self ) :
2017-06-21 21:15:59 +00:00
with self . _lock :
2017-07-05 21:09:28 +00:00
return self . _error_exception is not None
2017-06-21 21:15:59 +00:00
def IsAsleep ( self ) :
with self . _lock :
2017-06-28 20:23:21 +00:00
return not HydrusData . TimeHasPassed ( self . _wake_time )
2017-06-21 21:15:59 +00:00
2017-06-07 22:05:15 +00:00
def IsCancelled ( self ) :
2017-06-21 21:15:59 +00:00
with self . _lock :
return self . _IsCancelled ( )
2017-06-07 22:05:15 +00:00
def IsDone ( self ) :
2017-06-21 21:15:59 +00:00
with self . _lock :
2017-06-28 20:23:21 +00:00
return self . _IsDone ( )
2017-06-21 21:15:59 +00:00
2017-06-07 22:05:15 +00:00
2017-10-04 17:51:58 +00:00
def IsValid ( self ) :
with self . _lock :
return self . engine . domain_manager . IsValid ( self . _network_contexts )
2017-06-21 21:15:59 +00:00
def NeedsLogin ( self ) :
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
with self . _lock :
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
if self . _for_login :
return False
else :
2017-11-01 20:37:39 +00:00
return self . engine . login_manager . NeedsLogin ( self . _login_network_context )
2017-06-28 20:23:21 +00:00
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
2017-07-27 00:47:13 +00:00
def NoEngineYet ( self ) :
return self . engine is None
2017-08-16 21:58:06 +00:00
def ObeysBandwidth ( self ) :
return self . _ObeysBandwidth ( )
2017-06-21 21:15:59 +00:00
def OverrideBandwidth ( self ) :
with self . _lock :
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
self . _bandwidth_manual_override = True
2017-06-07 22:05:15 +00:00
2017-07-05 21:09:28 +00:00
self . _wake_time = 0
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
2017-10-25 21:45:15 +00:00
def SetError ( self , e , error ) :
with self . _lock :
self . _SetError ( e , error )
def SetFiles ( self , files ) :
with self . _lock :
self . _files = files
2017-09-06 20:18:20 +00:00
def SetForLogin ( self , for_login ) :
with self . _lock :
self . _for_login = for_login
2017-06-21 21:15:59 +00:00
def SetStatus ( self , text ) :
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
with self . _lock :
self . _status_text = text
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
def Sleep ( self , seconds ) :
2017-06-07 22:05:15 +00:00
with self . _lock :
2017-07-05 21:09:28 +00:00
self . _Sleep ( seconds )
2017-06-07 22:05:15 +00:00
def Start ( self ) :
2017-06-21 21:15:59 +00:00
try :
2017-09-20 19:47:31 +00:00
request_completed = False
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
while not request_completed :
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
try :
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
response = self . _SendRequestAndGetResponse ( )
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
with self . _lock :
if self . _body is not None :
self . _ReportDataUsed ( len ( self . _body ) )
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
if response . ok :
with self . _lock :
self . _status_text = u ' downloading \u2026 '
if self . _temp_path is None :
2017-11-08 22:07:12 +00:00
self . _ReadResponse ( response , self . _stream_io , 104857600 )
2017-09-20 19:47:31 +00:00
else :
with open ( self . _temp_path , ' wb ' ) as f :
self . _ReadResponse ( response , f )
with self . _lock :
self . _status_text = ' done! '
else :
with self . _lock :
self . _status_text = str ( response . status_code ) + ' - ' + str ( response . reason )
self . _ReadResponse ( response , self . _stream_io )
with self . _lock :
self . _stream_io . seek ( 0 )
data = self . _stream_io . read ( )
2017-10-25 21:45:15 +00:00
( e , error_text ) = ConvertStatusCodeAndDataIntoExceptionInfo ( response . status_code , data , self . IS_HYDRUS_SERVICE )
2017-09-20 19:47:31 +00:00
self . _SetError ( e , error_text )
2017-06-21 21:15:59 +00:00
2017-10-25 21:45:15 +00:00
if ' Content-Type ' in response . headers :
self . _content_type = response . headers [ ' Content-Type ' ]
2017-09-20 19:47:31 +00:00
request_completed = True
2017-06-21 21:15:59 +00:00
2018-01-10 22:41:51 +00:00
except requests . exceptions . ChunkedEncodingError :
self . _current_connection_attempt_number + = 1
if not self . _CanReattemptRequest ( ) :
raise HydrusExceptions . ConnectionException ( ' Unable to complete request--it broke mid-way! ' )
with self . _lock :
self . _status_text = u ' connection broke mid-request--retrying '
time . sleep ( 3 )
2017-09-20 19:47:31 +00:00
except requests . exceptions . ConnectionError , requests . exceptions . ConnectTimeout :
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
self . _current_connection_attempt_number + = 1
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
if not self . _CanReattemptRequest ( ) :
2017-06-21 21:15:59 +00:00
2017-12-06 22:06:56 +00:00
raise HydrusExceptions . ConnectionException ( ' Could not connect! ' )
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
with self . _lock :
self . _status_text = u ' connection failed--retrying '
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
time . sleep ( 3 )
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
except requests . exceptions . ReadTimeout :
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
self . _current_connection_attempt_number + = 1
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
if not self . _CanReattemptRequest ( ) :
2017-12-06 22:06:56 +00:00
raise HydrusExceptions . ConnectionException ( ' Connection successful, but reading response timed out! ' )
2017-09-20 19:47:31 +00:00
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
with self . _lock :
self . _status_text = u ' read timed out--retrying '
2017-06-21 21:15:59 +00:00
2017-09-20 19:47:31 +00:00
time . sleep ( 3 )
2017-06-21 21:15:59 +00:00
except Exception as e :
with self . _lock :
self . _status_text = ' unexpected error! '
trace = traceback . format_exc ( )
2017-07-27 00:47:13 +00:00
HydrusData . Print ( trace )
2017-06-21 21:15:59 +00:00
self . _SetError ( e , trace )
finally :
with self . _lock :
self . _SetDone ( )
2017-06-07 22:05:15 +00:00
2017-06-21 21:15:59 +00:00
2017-09-06 20:18:20 +00:00
def WaitUntilDone ( self ) :
2017-09-27 21:52:54 +00:00
while True :
self . _is_done_event . wait ( 5 )
if self . IsDone ( ) :
break
2017-09-06 20:18:20 +00:00
with self . _lock :
if self . engine . controller . ModelIsShutdown ( ) :
raise HydrusExceptions . ShutdownException ( )
elif self . _error_exception is not None :
2017-09-13 20:50:41 +00:00
if isinstance ( self . _error_exception , Exception ) :
raise self . _error_exception
else :
raise Exception ( ' Problem in network error handling. ' )
2017-09-06 20:18:20 +00:00
elif self . _IsCancelled ( ) :
if self . _method == ' POST ' :
message = ' Upload cancelled! '
else :
message = ' Download cancelled! '
raise HydrusExceptions . CancelledException ( message )
2017-06-28 20:23:21 +00:00
class NetworkJobDownloader ( NetworkJob ) :
2017-06-21 21:15:59 +00:00
2017-09-06 20:18:20 +00:00
def __init__ ( self , downloader_key , method , url , body = None , referral_url = None , temp_path = None ) :
2017-06-07 22:05:15 +00:00
2017-06-28 20:23:21 +00:00
self . _downloader_key = downloader_key
2017-06-07 22:05:15 +00:00
2017-09-06 20:18:20 +00:00
NetworkJob . __init__ ( self , method , url , body = body , referral_url = referral_url , temp_path = temp_path )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
def _GenerateNetworkContexts ( self ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
network_contexts = NetworkJob . _GenerateNetworkContexts ( self )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
network_contexts . append ( NetworkContext ( CC . NETWORK_CONTEXT_DOWNLOADER , self . _downloader_key ) )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
return network_contexts
2017-07-05 21:09:28 +00:00
class NetworkJobDownloaderQuery ( NetworkJobDownloader ) :
2017-09-06 20:18:20 +00:00
def __init__ ( self , downloader_page_key , downloader_key , method , url , body = None , referral_url = None , temp_path = None ) :
2017-07-27 00:47:13 +00:00
self . _downloader_page_key = downloader_page_key
2017-09-06 20:18:20 +00:00
NetworkJobDownloader . __init__ ( self , downloader_key , method , url , body = body , referral_url = referral_url , temp_path = temp_path )
2017-07-27 00:47:13 +00:00
def _GenerateNetworkContexts ( self ) :
network_contexts = NetworkJob . _GenerateNetworkContexts ( self )
network_contexts . append ( NetworkContext ( CC . NETWORK_CONTEXT_DOWNLOADER_QUERY , self . _downloader_page_key ) )
return network_contexts
class NetworkJobDownloaderQueryTemporary ( NetworkJob ) :
2017-09-06 20:18:20 +00:00
def __init__ ( self , downloader_page_key , method , url , body = None , referral_url = None , temp_path = None ) :
2017-07-05 21:09:28 +00:00
self . _downloader_page_key = downloader_page_key
2017-09-06 20:18:20 +00:00
NetworkJob . __init__ ( self , method , url , body = body , referral_url = referral_url , temp_path = temp_path )
2017-07-05 21:09:28 +00:00
def _GenerateNetworkContexts ( self ) :
network_contexts = NetworkJob . _GenerateNetworkContexts ( self )
network_contexts . append ( NetworkContext ( CC . NETWORK_CONTEXT_DOWNLOADER_QUERY , self . _downloader_page_key ) )
return network_contexts
2017-06-28 20:23:21 +00:00
class NetworkJobSubscription ( NetworkJobDownloader ) :
2017-06-21 21:15:59 +00:00
2017-09-06 20:18:20 +00:00
def __init__ ( self , subscription_key , downloader_key , method , url , body = None , referral_url = None , temp_path = None ) :
2017-07-27 00:47:13 +00:00
self . _subscription_key = subscription_key
2017-09-06 20:18:20 +00:00
NetworkJobDownloader . __init__ ( self , downloader_key , method , url , body = body , referral_url = referral_url , temp_path = temp_path )
2017-07-27 00:47:13 +00:00
def _GenerateNetworkContexts ( self ) :
network_contexts = NetworkJob . _GenerateNetworkContexts ( self )
network_contexts . append ( NetworkContext ( CC . NETWORK_CONTEXT_SUBSCRIPTION , self . _subscription_key ) )
return network_contexts
class NetworkJobSubscriptionTemporary ( NetworkJob ) :
2017-11-29 21:48:23 +00:00
# temporary because we will move to the downloader_key stuff when that is available
2017-09-06 20:18:20 +00:00
def __init__ ( self , subscription_key , method , url , body = None , referral_url = None , temp_path = None ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
self . _subscription_key = subscription_key
2017-06-21 21:15:59 +00:00
2017-09-06 20:18:20 +00:00
NetworkJob . __init__ ( self , method , url , body = body , referral_url = referral_url , temp_path = temp_path )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
def _GenerateNetworkContexts ( self ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
network_contexts = NetworkJob . _GenerateNetworkContexts ( self )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
network_contexts . append ( NetworkContext ( CC . NETWORK_CONTEXT_SUBSCRIPTION , self . _subscription_key ) )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
return network_contexts
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
class NetworkJobHydrus ( NetworkJob ) :
2017-10-25 21:45:15 +00:00
IS_HYDRUS_SERVICE = True
2017-09-06 20:18:20 +00:00
def __init__ ( self , service_key , method , url , body = None , referral_url = None , temp_path = None ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
self . _service_key = service_key
2017-06-21 21:15:59 +00:00
2017-09-06 20:18:20 +00:00
NetworkJob . __init__ ( self , method , url , body = body , referral_url = referral_url , temp_path = temp_path )
2017-06-21 21:15:59 +00:00
2017-10-25 21:45:15 +00:00
def _CheckHydrusVersion ( self , service_type , response ) :
service_string = HC . service_string_lookup [ service_type ]
headers = response . headers
if ' server ' not in headers or service_string not in headers [ ' server ' ] :
raise HydrusExceptions . WrongServiceTypeException ( ' Target was not a ' + service_string + ' ! ' )
server_header = headers [ ' server ' ]
( service_string_gumpf , network_version ) = server_header . split ( ' / ' )
network_version = int ( network_version )
if network_version != HC . NETWORK_VERSION :
if network_version > HC . NETWORK_VERSION :
message = ' Your client is out of date; please download the latest release. '
else :
message = ' The server is out of date; please ask its admin to update to the latest release. '
raise HydrusExceptions . NetworkVersionException ( ' Network version mismatch! The server \' s network version was ' + str ( network_version ) + ' , whereas your client \' s is ' + str ( HC . NETWORK_VERSION ) + ' ! ' + message )
2017-06-28 20:23:21 +00:00
def _GenerateNetworkContexts ( self ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
network_contexts = NetworkJob . _GenerateNetworkContexts ( self )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
network_contexts . append ( NetworkContext ( CC . NETWORK_CONTEXT_HYDRUS , self . _service_key ) )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
return network_contexts
2017-06-21 21:15:59 +00:00
2017-11-01 20:37:39 +00:00
def _GenerateSpecificNetworkContexts ( self ) :
# we store cookies on and login to the same hydrus-specific context
session_network_context = NetworkContext ( CC . NETWORK_CONTEXT_HYDRUS , self . _service_key )
login_network_context = session_network_context
return ( session_network_context , login_network_context )
2017-10-25 21:45:15 +00:00
def _ReportDataUsed ( self , num_bytes ) :
service = self . engine . controller . services_manager . GetService ( self . _service_key )
service_type = service . GetServiceType ( )
if service_type in HC . RESTRICTED_SERVICES :
account = service . GetAccount ( )
account . ReportDataUsed ( num_bytes )
NetworkJob . _ReportDataUsed ( self , num_bytes )
def _SendRequestAndGetResponse ( self ) :
service = self . engine . controller . services_manager . GetService ( self . _service_key )
service_type = service . GetServiceType ( )
if service_type in HC . RESTRICTED_SERVICES :
account = service . GetAccount ( )
account . ReportRequestUsed ( )
response = NetworkJob . _SendRequestAndGetResponse ( self )
if service_type in HC . RESTRICTED_SERVICES :
self . _CheckHydrusVersion ( service_type , response )
return response
2017-07-19 21:21:41 +00:00
class NetworkJobThreadWatcher ( NetworkJob ) :
2017-09-06 20:18:20 +00:00
def __init__ ( self , thread_key , method , url , body = None , referral_url = None , temp_path = None ) :
2017-07-19 21:21:41 +00:00
self . _thread_key = thread_key
2017-09-06 20:18:20 +00:00
NetworkJob . __init__ ( self , method , url , body = body , referral_url = referral_url , temp_path = temp_path )
2017-07-19 21:21:41 +00:00
def _GenerateNetworkContexts ( self ) :
network_contexts = NetworkJob . _GenerateNetworkContexts ( self )
network_contexts . append ( NetworkContext ( CC . NETWORK_CONTEXT_THREAD_WATCHER_THREAD , self . _thread_key ) )
return network_contexts
2017-06-28 20:23:21 +00:00
class NetworkSessionManager ( HydrusSerialisable . SerialisableBase ) :
SERIALISABLE_TYPE = HydrusSerialisable . SERIALISABLE_TYPE_NETWORK_SESSION_MANAGER
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = ' Session Manager '
2017-06-28 20:23:21 +00:00
SERIALISABLE_VERSION = 1
2017-10-25 21:45:15 +00:00
SESSION_TIMEOUT = 60 * 60
2017-06-28 20:23:21 +00:00
def __init__ ( self ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
HydrusSerialisable . SerialisableBase . __init__ ( self )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
self . engine = None
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
self . _dirty = False
2017-06-28 20:23:21 +00:00
self . _lock = threading . Lock ( )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
self . _network_contexts_to_sessions = { }
2017-06-21 21:15:59 +00:00
2017-10-25 21:45:15 +00:00
self . _network_contexts_to_session_timeouts = { }
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
def _GenerateSession ( self , network_context ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
session = requests . Session ( )
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
if network_context . context_type == CC . NETWORK_CONTEXT_HYDRUS :
session . verify = False
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
return session
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
def _GetSerialisableInfo ( self ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
serialisable_network_contexts_to_sessions = [ ( network_context . GetSerialisableTuple ( ) , cPickle . dumps ( session ) ) for ( network_context , session ) in self . _network_contexts_to_sessions . items ( ) ]
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
return serialisable_network_contexts_to_sessions
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
def _InitialiseFromSerialisableInfo ( self , serialisable_info ) :
serialisable_network_contexts_to_sessions = serialisable_info
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
for ( serialisable_network_context , pickled_session ) in serialisable_network_contexts_to_sessions :
network_context = HydrusSerialisable . CreateFromSerialisableTuple ( serialisable_network_context )
2017-07-05 21:09:28 +00:00
session = cPickle . loads ( str ( pickled_session ) )
2017-06-28 20:23:21 +00:00
2017-07-27 00:47:13 +00:00
session . cookies . clear_session_cookies ( )
2017-06-28 20:23:21 +00:00
self . _network_contexts_to_sessions [ network_context ] = session
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
def _SetDirty ( self ) :
self . _dirty = True
2017-06-28 20:23:21 +00:00
def ClearSession ( self , network_context ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
with self . _lock :
if network_context in self . _network_contexts_to_sessions :
del self . _network_contexts_to_sessions [ network_context ]
2017-10-18 19:41:25 +00:00
self . _SetDirty ( )
2017-06-28 20:23:21 +00:00
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
def GetSession ( self , network_context ) :
2017-06-21 21:15:59 +00:00
2017-06-28 20:23:21 +00:00
with self . _lock :
2017-11-01 20:37:39 +00:00
# just in case one of these slips through somehow
if network_context . context_type == CC . NETWORK_CONTEXT_DOMAIN :
second_level_domain = ClientNetworkingDomain . ConvertDomainIntoSecondLevelDomain ( network_context . context_data )
network_context = NetworkContext ( CC . NETWORK_CONTEXT_DOMAIN , second_level_domain )
2017-06-28 20:23:21 +00:00
if network_context not in self . _network_contexts_to_sessions :
self . _network_contexts_to_sessions [ network_context ] = self . _GenerateSession ( network_context )
2017-10-25 21:45:15 +00:00
session = self . _network_contexts_to_sessions [ network_context ]
#
if network_context not in self . _network_contexts_to_session_timeouts :
self . _network_contexts_to_session_timeouts [ network_context ] = 0
if HydrusData . TimeHasPassed ( self . _network_contexts_to_session_timeouts [ network_context ] ) :
session . cookies . clear_session_cookies ( )
self . _network_contexts_to_session_timeouts [ network_context ] = HydrusData . GetNow ( ) + self . SESSION_TIMEOUT
#
2017-10-18 19:41:25 +00:00
# tumblr can't into ssl for some reason, and the data subdomain they use has weird cert properties, looking like amazon S3
# perhaps it is inward-facing somehow? whatever the case, let's just say fuck it for tumblr
if network_context . context_type == CC . NETWORK_CONTEXT_DOMAIN and network_context . context_data == ' tumblr.com ' :
2017-10-25 21:45:15 +00:00
session . verify = False
2017-10-18 19:41:25 +00:00
2017-10-25 21:45:15 +00:00
#
2017-07-05 21:09:28 +00:00
self . _SetDirty ( )
2017-10-25 21:45:15 +00:00
return session
2017-06-28 20:23:21 +00:00
2017-06-21 21:15:59 +00:00
2017-07-05 21:09:28 +00:00
def IsDirty ( self ) :
with self . _lock :
return self . _dirty
def SetClean ( self ) :
with self . _lock :
self . _dirty = False
2017-06-28 20:23:21 +00:00
HydrusSerialisable . SERIALISABLE_TYPES_TO_OBJECT_TYPES [ HydrusSerialisable . SERIALISABLE_TYPE_NETWORK_SESSION_MANAGER ] = NetworkSessionManager