@ -107,11 +107,21 @@ public extension LibSession {
guard
swarmSize > 0 ,
let cSwarm : UnsafeMutablePointer < network_service_node > = swarmPtr
else { return resolver ( Result . failure ( SnodeAPIError . unableToRetrieveSwarm ) ) }
else {
// D i s p a t c h a s y n c s o w e d o n ' t h o l d u p t h e l i b S e s s i o n t h r e a d ( w h i c h c a n b l o c k o t h e r r e q u e s t s )
DispatchQueue . global ( qos : . default ) . async {
resolver ( Result . failure ( SnodeAPIError . unableToRetrieveSwarm ) )
}
return
}
var nodes : Set < Snode > = [ ]
( 0. . < swarmSize ) . forEach { index in nodes . insert ( Snode ( cSwarm [ index ] ) ) }
resolver ( Result . success ( nodes ) )
// D i s p a t c h a s y n c s o w e d o n ' t h o l d u p t h e l i b S e s s i o n t h r e a d ( w h i c h c a n b l o c k o t h e r r e q u e s t s )
DispatchQueue . global ( qos : . default ) . async {
resolver ( Result . success ( nodes ) )
}
}
let cWrapperPtr : UnsafeMutableRawPointer = Unmanaged . passRetained ( callbackWrapper ) . toOpaque ( )
@ -134,11 +144,21 @@ public extension LibSession {
guard
nodesSize >= count ,
let cSwarm : UnsafeMutablePointer < network_service_node > = nodesPtr
else { return resolver ( Result . failure ( SnodeAPIError . unableToRetrieveSwarm ) ) }
else {
// D i s p a t c h a s y n c s o w e d o n ' t h o l d u p t h e l i b S e s s i o n t h r e a d ( w h i c h c a n b l o c k o t h e r r e q u e s t s )
DispatchQueue . global ( qos : . default ) . async {
resolver ( Result . failure ( SnodeAPIError . unableToRetrieveSwarm ) )
}
return
}
var nodes : Set < Snode > = [ ]
( 0. . < nodesSize ) . forEach { index in nodes . insert ( Snode ( cSwarm [ index ] ) ) }
resolver ( Result . success ( nodes ) )
// D i s p a t c h a s y n c s o w e d o n ' t h o l d u p t h e l i b S e s s i o n t h r e a d ( w h i c h c a n b l o c k o t h e r r e q u e s t s )
DispatchQueue . global ( qos : . default ) . async {
resolver ( Result . success ( nodes ) )
}
}
let cWrapperPtr : UnsafeMutableRawPointer = Unmanaged . passRetained ( callbackWrapper ) . toOpaque ( )
@ -179,9 +199,15 @@ public extension LibSession {
return Deferred {
Future < ( ResponseInfoType , Data ? ) , Error > { resolver in
let callbackWrapper : CWrapper < NetworkCallback > = CWrapper { success , timeout , statusCode , data in
switch processError ( success , timeout , statusCode , data , using : dependencies ) {
case . some ( let error ) : resolver ( Result . failure ( error ) )
case . none : resolver ( Result . success ( ( Network . ResponseInfo ( code : Int ( statusCode ) , headers : [ : ] ) , data ) ) )
let maybeError : Error ? = processError ( success , timeout , statusCode , data , using : dependencies )
// D i s p a t c h a s y n c s o w e d o n ' t h o l d u p t h e l i b S e s s i o n t h r e a d ( w h i c h c a n b l o c k o t h e r r e q u e s t s )
DispatchQueue . global ( qos : . default ) . async {
switch maybeError {
case . some ( let error ) : resolver ( Result . failure ( error ) )
case . none :
resolver ( Result . success ( ( Network . ResponseInfo ( code : Int ( statusCode ) , headers : [ : ] ) , data ) ) )
}
}
}
let cWrapperPtr : UnsafeMutableRawPointer = Unmanaged . passRetained ( callbackWrapper ) . toOpaque ( )
@ -191,7 +217,7 @@ public extension LibSession {
case . snode ( let snode ) :
let cSwarmPublicKey : UnsafePointer < CChar > ? = swarmPublicKey . map {
// Q u i c k w a y t o d r o p ' 0 5 ' p r e f i x i f p r e s e n t
$0 . suffix ( 64 ) . c Array. nullTerminated ( ) . unsafeCopy ( )
$0 . suffix ( 64 ) . c String( using : . utf8 ) ? . unsafeCopy ( )
}
callbackWrapper . addUnsafePointerToCleanup ( cSwarmPublicKey )
@ -211,30 +237,46 @@ public extension LibSession {
)
case . server ( let method , let scheme , let host , let endpoint , let port , let headers , let x25519PublicKey ) :
let headerInfo : [ ( key : String , value : String ) ] ? = headers ? . map { ( $0 . key , $0 . value ) }
// H a n d l e t h e m o r e c o m p l i c a t e d t y p e c o n v e r s i o n s f i r s t
let cHeaderKeysContent : [ UnsafePointer < CChar > ? ] = ( try ? ( ( headerInfo ? ? [ ] )
. map { $0 . key . cString ( using : . utf8 ) }
. unsafeCopyCStringArray ( ) ) )
. defaulting ( to : [ ] )
let cHeaderValuesContent : [ UnsafePointer < CChar > ? ] = ( try ? ( ( headerInfo ? ? [ ] )
. map { $0 . value . cString ( using : . utf8 ) }
. unsafeCopyCStringArray ( ) ) )
. defaulting ( to : [ ] )
guard
cHeaderKeysContent . count = = cHeaderValuesContent . count ,
cHeaderKeysContent . allSatisfy ( { $0 != nil } ) ,
cHeaderValuesContent . allSatisfy ( { $0 != nil } )
else {
cHeaderKeysContent . forEach { $0 ? . deallocate ( ) }
cHeaderValuesContent . forEach { $0 ? . deallocate ( ) }
cWrapperPtr . deallocate ( )
return resolver ( Result . failure ( LibSessionError . invalidCConversion ) )
}
// C o n v e r t t h e o t h e r t y p e s
let targetScheme : String = ( scheme ? ? " https " )
let cMethod : UnsafePointer < CChar > ? = ( method ? ? " GET " ) . cArray
. nullTerminated ( )
let cMethod : UnsafePointer < CChar > ? = ( method ? ? " GET " )
. cString( using : . utf8 ) ?
. unsafeCopy ( )
let cTargetScheme : UnsafePointer < CChar > ? = targetScheme . cArray
. nullTerminated ( )
let cTargetScheme : UnsafePointer < CChar > ? = targetScheme
. cString( using : . utf8 ) ?
. unsafeCopy ( )
let cHost : UnsafePointer < CChar > ? = host . cArray
. nullTerminated ( )
let cHost : UnsafePointer < CChar > ? = host
. cString( using : . utf8 ) ?
. unsafeCopy ( )
let cEndpoint : UnsafePointer < CChar > ? = endpoint . cArray
. nullTerminated ( )
let cEndpoint : UnsafePointer < CChar > ? = endpoint
. cString( using : . utf8 ) ?
. unsafeCopy ( )
let cX25519Pubkey : UnsafePointer < CChar > ? = x25519PublicKey
. suffix ( 64 ) // Q u i c k w a y t o d r o p ' 0 5 ' p r e f i x i f p r e s e n t
. cArray
. nullTerminated ( )
. unsafeCopy ( )
let headerInfo : [ ( key : String , value : String ) ] ? = headers ? . map { ( $0 . key , $0 . value ) }
let cHeaderKeysContent : [ UnsafePointer < CChar > ? ] = ( headerInfo ? ? [ ] )
. map { $0 . key . cArray . nullTerminated ( ) }
. unsafeCopy ( )
let cHeaderValuesContent : [ UnsafePointer < CChar > ? ] = ( headerInfo ? ? [ ] )
. map { $0 . value . cArray . nullTerminated ( ) }
. cString ( using : . utf8 ) ?
. unsafeCopy ( )
let cHeaderKeys : UnsafeMutablePointer < UnsafePointer < CChar > ? >? = cHeaderKeysContent
. unsafeCopy ( )
@ -304,10 +346,14 @@ public extension LibSession {
// O t h e r w i s e c r e a t e a n e w n e t w o r k
var error : [ CChar ] = [ CChar ] ( repeating : 0 , count : 256 )
var network : UnsafeMutablePointer < network_object > ?
let cCachePath : [ CChar ] = snodeCachePath . cArray . nullTerminated ( )
guard let cCachePath : [ CChar ] = snodeCachePath . cString ( using : . utf8 ) else {
Log . error ( " [LibQuic] Unable to create network object: \( LibSessionError . invalidCConversion ) " )
return nil
}
guard network_init ( & network , cCachePath , Features . useTestnet , true , & error ) else {
SNLog ( " [LibQuic Error] Unable to create network object: \( String ( cString : error ) ) " )
Log. error ( " [LibQuic ] Unable to create network object: \( String ( cString : error ) ) " )
return nil
}
@ -336,12 +382,15 @@ public extension LibSession {
private static func updateNetworkStatus ( cStatus : CONNECTION_STATUS ) {
let status : NetworkStatus = NetworkStatus ( status : cStatus )
SNLog ( " Network status changed to: \( status ) " )
lastNetworkStatus . mutate { lastNetworkStatus in
lastNetworkStatus = status
// D i s p a t c h a s y n c s o w e d o n ' t h o l d u p t h e l i b S e s s i o n t h r e a d t h a t t r i g g e r e d t h e u p d a t e
DispatchQueue . global ( qos : . default ) . async {
Log . info ( " Network status changed to: \( status ) " )
lastNetworkStatus . mutate { lastNetworkStatus in
lastNetworkStatus = status
networkStatusCallbacks . wrappedValue . forEach { _ , callback in
callback ( status )
networkStatusCallbacks . wrappedValue . forEach { _ , callback in
callback ( status )
}
}
}
}
@ -374,11 +423,14 @@ public extension LibSession {
// N e e d t o f r e e t h e c P a t h s P t r a s w e a r e t h e o w n e r
cPathsPtr ? . deallocate ( )
lastPaths . mutate { lastPaths in
lastPaths = paths
// D i s p a t c h a s y n c s o w e d o n ' t h o l d u p t h e l i b S e s s i o n t h r e a d t h a t t r i g g e r e d t h e u p d a t e
DispatchQueue . global ( qos : . default ) . async {
lastPaths . mutate { lastPaths in
lastPaths = paths
pathsChangedCallbacks . wrappedValue . forEach { id , callback in
callback ( paths , id )
pathsChangedCallbacks . wrappedValue . forEach { id , callback in
callback ( paths , id )
}
}
}
}
@ -401,14 +453,14 @@ public extension LibSession {
case ( 400 , . some ( let responseString ) ) : return NetworkError . badRequest ( error : responseString , rawData : data )
case ( 401 , _ ) :
SN Log( " Unauthorised (Failed to verify the signature). " )
Log. warn ( " Unauthorised (Failed to verify the signature). " )
return NetworkError . unauthorised
case ( 404 , _ ) : return NetworkError . notFound
// / A s n o d e w i l l r e t u r n a ` 4 0 6 ` b u t o n i o n r e q u e s t s v 4 s e e m s t o r e t u r n ` 4 2 5 ` s o h a n d l e b o t h
case ( 406 , _ ) , ( 425 , _ ) :
SN Log( " The user's clock is out of sync with the service node network. " )
Log. warn ( " The user's clock is out of sync with the service node network. " )
return SnodeAPIError . clockOutOfSync
case ( 421 , _ ) : return SnodeAPIError . unassociatedPubkey