IMA with asynchronous ReceiveHTTPMemory

Everything else that doesn't fall into one of the other PB categories.
dige
Addict
Addict
Posts: 1256
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

IMA with asynchronous ReceiveHTTPMemory

Post by dige »

With asynchronous, its very important to use the ReceiveHTTPMemory() function in the right way, otherwise there are happen sporadic IMA's and
its hard to debug the real error reason..

Unfortunately, the help example for HTTPProgress() shows only a one time asynchronous download and not what to do,
if the download fails or aborted..

Code: Select all

  ; PB help example for HTTPProgress()

  InitNetwork()

  Download = ReceiveHTTPMemory("http://www.purebasic.com/download/OgreAssimpConverter.zip", #PB_HTTP_Asynchronous)
  If Download
    Repeat
      Progress = HTTPProgress(Download)
      Select Progress
        Case #PB_Http_Success
          *Buffer = FinishHTTP(Download)
          Debug "Download finished (size: " + MemorySize(*Buffer) + ")"
          FreeMemory(*Buffer)
          End

        Case #PB_Http_Failed
          Debug "Download failed"
          End

        Case #PB_Http_Aborted
          Debug "Download aborted"
          End
          
        Default
          Debug "Current download: " + Progress
       
      EndSelect
      
      Delay(500) ; Don't stole the whole CPU
    ForEver
  Else
    Debug "Download error"
  EndIf
Please correct me if I'm wrong: Contrary to what the example suggests, it is very important to finish every download with FinishHTTP()
even if it is canceled or failed.

Code: Select all

Procedure.S ReceiveHTTPMemory_(Url.S, TimeOut.I = 0); No TimeOut = Synchron, TimeOut > 0 = Asynch
  Protected *mem, Result.S, Connection.I
  
  If TimeOut = 0
    
    *mem = ReceiveHTTPMemory(Url)
    If *mem <> 0
      Result = PeekS(*mem, MemorySize(*mem), #PB_Ascii)
      FreeMemory(*mem)
    EndIf
    
  Else
    
    TimeOut = ElapsedMilliseconds() + TimeOut
    Connection = ReceiveHTTPMemory(Url, #PB_HTTP_Asynchronous)
    If Connection
      
      Repeat
        Delay(100) 
        
        Select HTTPProgress(Connection)
          Case #PB_Http_Success
            Result = "[success]"
            Break
            
          Case #PB_Http_Failed, #PB_Http_Aborted 
            Result = "[failed]"
            Break
            
        EndSelect
        
        If ElapsedMilliseconds() > TimeOut
          Result = "[timeout]"
          AbortHTTP(Connection)
          Delay(100) ; give it some extra time
          Break
        EndIf
      ForEver
      
      *mem = FinishHTTP(Connection)
      If *mem <> 0
        Result = PeekS(*mem, MemorySize(*mem), #PB_Ascii)
        FreeMemory(*mem)
      EndIf   
      
    Else
      Result = "[no connection]"
    EndIf
    
  EndIf
  ProcedureReturn Result
EndProcedure

To reproduce the problem, here is the the extended example:

Code: Select all

InitNetwork()

Procedure Provoke_IMA()
  Download = ReceiveHTTPMemory("http://www.purebasic.com", #PB_HTTP_Asynchronous)
  If Download
    Repeat
      progress = HTTPProgress(Download)
      Select progress
        Case #PB_Http_Success
          *Buffer = FinishHTTP(Download)
          Debug "Download finished (size: " + MemorySize(*Buffer) + ")"
          FreeMemory(*Buffer)
          Break
          
        Case #PB_Http_Failed
          Debug "Download failed"
          Break
          
        Case #PB_Http_Aborted
          Debug "Download aborted"
          Break
          
        Default
          ;Debug "Current download: " + progress
          
      EndSelect
      
      Delay(1)
    ForEver
  Else
    Debug "Download error"
  EndIf
EndProcedure

For a = 1 To 20
  Provoke_IMA()
Next
"Daddy, I'll run faster, then it is not so far..."