Jump to content

FloppyDesk

Members
  • Content Count

    6
  • Joined

  • Last visited

Posts posted by FloppyDesk


  1. 1 hour ago, David Heffernan said:

    FWIW this is my spin lock

     

    
    TSpinLock = class
      private
        FLock: Integer;
      public
        procedure Acquire;
        procedure Release;
      end;
    
    procedure TSpinLock.Acquire;
    begin
      Assert(AlignedOn32bitBoundary(@FLock));
      while AtomicCmpExchange(FLock, 1, 0)<>0 do begin
        //signal to CPU that we are spinning; see, for example, http://msdn.microsoft.com/en-us/magazine/cc163726.aspx
        YieldProcessor;
      end;
    end;
    
    procedure TSpinLock.Release;
    begin
      AtomicExchange(FLock, 0);
    end;

     

    It's only useful on x86/x64 because Emba haven't provided an implementation of YieldProcessor for other processors!

     

    I suspect that professional spin locks use different yield methods depending on how long they have been spinning.

    David, can you please provide the code for AlignedOn32bitBoundary() func? 

    Thanks.

     


  2. 4 minutes ago, Angus Robertson said:

    I would first ensure none of your threads access any visual components and ideally don't use Synchronize atall.

    I use tthread.synchronize method, to update my "memo" for logging. I need replace the synchronization method?

     

    6 minutes ago, Angus Robertson said:

    I don't see a message loop anywhere in your thread, so nothing should work.

    What do you mean about message loop?

    I have "while" loop in main thread which loops until "tthread not terminated flag set".

    I use 10 threads and 10 instances of

    TSslHttpCli

    10 threads = 10 instances, each instance works on their own thread.

    9 minutes ago, Angus Robertson said:

    You can use blocking calls in a thread, since it's doing nothing else.  And a thread may be necessary if you are doing long processing like SQL database look-ups, although even then it's better to use a thread for only the SQL stuff and leave all ICS stuff in the main thread. 

    I use multiple threads for speed up the request sending and get result to the software.

    If you can, send please a demo or give me aiming on something what can help me.

     

    Thank you in advance Angus.


  3. Using 10 threads and after 100 iterations i got an exception.

    If i continue this exception, after 10 iterations it raises again, after VCL form frees and crashes.

     

    Quote

    First chance exception at $7B6D951C. Exception class $C0000005 with message 'access violation at 0x7b6d951c: read of address 0xfeeefeee'

    Capture.thumb.PNG.e6afce1e99b59464b6858f0e747550bb.PNG

     

    Quote

    First chance exception at $77101D6C. Exception class $C0000008 with message 'system exception (code 0xc0000008) at 0x6a5dfe8a'

     

    Capture111.thumb.PNG.707679cf51250bcbb38ac0565a315993.PNG

    Quote

    First chance exception at $7B6D951C. Exception class $C0000005 with message 'access violation at 0x7b6d951c: read of address 0xfeeefeee'

     

    Capture123124.thumb.PNG.446240dbc0a1893f241ae6ea52463f5d.PNG

    OnCreate Event Code:

      FHttpIcs := TSslHttpCli.Create(nil);
      FHttpIcs.MultiThreaded := True;
      FHttpIcs.SslContext := TSSLContext.Create(nil);
      FHttpIcs.ResponseNoException := True;
      FHttpIcs.FollowRelocation := True;
      FHttpIcs.LocationChangeMaxCount := 15;

     

    I tried to put

    FHttpIcs.SslContext := TSSLContext.Create(nil);

    in cycle (not onCreate event) but still no helps.

     

    Here is example of POST request, probably "same code" i have for GET requests.

    procedure TConnector.SubmitTokens;
    begin
      if (FThreadStatus = Terminated) then
        Exit;
    
      SetHeadersST();
      SetPostParamsST();
    
      FHttpIcs.RcvdStream := FResponseStream;
      FHttpIcs.Url := FUrl;
      try
    
        FHttpIcs.Post();
    
        if (FHttpIcs.StatusCode > cBadRequest) or (FIsErrorConnection) then
          raise Exception.Create('err connection');
    
        FHtmlResponse := FConnectorUtils.StreamToString(FResponseStream,
          TEncoding.UTF8);
    
        if (ContainsText(FHtmlResponse, 'true')) then
         // do some work
        else
          raise Exception.Create('err connection');
    
      except
        on e: Exception do
        begin
          ReCheck(TMethods.SubmitTokensM);
        end;
      end;
    
    end;

     


  4. 4 hours ago, Angus Robertson said:

    It is better to process the response in the onRequestDone event. 

     

    There is a new property added a year ago ResponseNoException which will help you.

     

    Angus

     

    Thank you so much  - Angus!

    Tried this property, all works!

     

    But this "OnRequestDone" event, i tried to write some code and i got stucked at one question.

    For example, we have error = 1 (which is bad connection) how i can reconnect same request with same headers/post parameters?

     

    I have much methods with requests, new headers, new post params, how i can handle this in this event?

     

    Thanks!


  5. 49 minutes ago, Angus Robertson said:

    Don't know what FConnectorUtils.StreamToString does, but you always have to seek to beginning of the stream before reading it. 

     

    There is a new function that convert an HTML page in the buffer to unicode string with the correct codepage:

    FResponseRaw := IcsHtmlToStr(FResponseStream, FContentType, true);

    Last boolean option converts HTML entries like &pound; and &#9741; to unicode. 

     

    That function is used in the new TSslHttpRest unit that hides a lot of the low level stuff you are doing returning Json.

     

    Angus

    Tried this code

    Quote

      const

       cAppFormUrlEnc = 'application/x-www-form-urlencoded';

     

    FHtmlResponse := IcsHtmlToStr(FResponseStream, cAppFormUrlEnc, True);

    But problem not solved, same result in txt files in folder.

     

    Here is FConnectorUtils.StreamToStringCode:

    function TConnectorUtils.StreamToString(const Stream: TStream;
      const Encoding: TEncoding): string;
    var
      StringBytes: TBytes;
    begin
      Stream.Position := 0;
      SetLength(StringBytes, Stream.Size);
    
      Stream.ReadBuffer(StringBytes[0], Stream.Size);
      Result := Encoding.GetString(StringBytes);
    end;

     

     

    UPD!!!: PROBLEM SOLVED

    Problem was in EXCEPT BLOCK:

     I tried to parse html only on TRY block, but not in except. (Result Code of response is 400)

     

    One more question, can i disable this function like in indy? If  responsecode > 400 then raise exception?

     


  6. Hello, i have a problem when i recieve response from only one response!

    I tried to analyze the request which i send from SOFT by "http analyzer/debugger" and analyzer shows me good !!!JSON!!! response which is:

    Quote

    {"error":"invalid_grant","error_description":"Invalid Grant"}

    But, if i write "rcvdstream" to a file for see the result i got ANOTHER result which is not JSON!

     

    Here is my code:

     

    1. Headers:

    procedure TConnector.SetHttpHeadersCFV;
    begin
    
      FHttpIcs.Agent := FUserAgent;
      FHttpIcs.ContentTypePost := cAppFormUrlEnc;
      FHttpIcs.Accept := ' application/json, text/javascript, */*; q=0.01';
      FHttpIcs.AcceptLanguage := 'en-US;q=0.5,en;q=0.3';
    
      FHeaders := '';
    
      AddHeader('X-CORRELATION-ID: ' + FColeractionId);
    
      AddHeader('x-via-hint_dca: ' + '1_MTM0Mw==');
      AddHeader('Origin: ' + 'https://cnn.com/');
      AddHeader('Referer: ' +
        'https://google.com');
      AddHeader('X-THMID: ' + FXtmId);
      AddHeader('dfpSessionID: ' + FSessionId);
      AddHeader('X-Requested-With: ' + 'XMLHttpRequest');
      AddHeader('Accept-Encoding: gzip, deflate');
    
      FHttpIcs.ExtraHeaders.Text := FHeaders;
    
    end;

    Note: about encoding, i tried to delete accept-encoding header, no helps...

     

    2. Sending request:

      // set post params
      // set headers
    
      // requesting....
      FHttpIcs.RcvdStream := FResponseStream;
      // url .. https://..../
      FHttpIcs.Url := Url;
      try
    
        FHttpIcs.Post();
    
        if (FHttpIcs.StatusCode = cTooManyReqCode) then
          raise Exception.Create('err connection');
    
        FHtmlResponse := FConnectorUtils.StreamToString(FResponseStream,
          TEncoding.Default);
    
        // !!!!! HTML RESPONSE IS INCORRECT !!!!! ////
        FConnectorUtils.LogToFile('htmlresponse_.txt', FHtmlResponse);
    
        // status code is correct!
        FConnectorUtils.LogToFile('statuscode_.txt', FHttpIcs.StatusCode.ToString);
        // phrase is correct!
        FConnectorUtils.LogToFile('phrase_.txt', FHttpIcs.ReasonPhrase);
        // last response is EMPTY!!!!
        FConnectorUtils.LogToFile('lastresponse_.txt', FHttpIcs.LastResponse);
      except
        // !!!!! HTML RESPONSE IS INCORRECT !!!!! ////
        FConnectorUtils.LogToFile('htmlresponse_.txt', FHtmlResponse);
    
        // status code is correct!
        FConnectorUtils.LogToFile('statuscode_.txt', FHttpIcs.StatusCode.ToString);
        // phrase is correct!
        FConnectorUtils.LogToFile('phrase_.txt', FHttpIcs.ReasonPhrase);
        // last response is EMPTY!!!!
        FConnectorUtils.LogToFile('lastresponse_.txt', FHttpIcs.LastResponse);
        ReCheck(TMethods.SendRequestM);
      end;

    Can someone help me please?

    thank you in advance!
×