Jump to content

Remy Lebeau

Members
  • Content Count

    2985
  • Joined

  • Last visited

  • Days Won

    134

Posts posted by Remy Lebeau


  1. On 9/28/2023 at 12:35 PM, DelphiUdIT said:

    I haven't seen any blogs or public news about Rad 12 Beta (Yukon) yet (except directly from Embarcadero).

    https://delphiworlds.com/2023/09/yukon-is-coming/

    https://dalijap.blogspot.com/2023/09/coming-in-delphi-12-disabled-floating.html

    https://blog.marcocantu.com/blog/2023-09-yukonbeta-stringliterals.html

     

    MVPs were given permission to start blogging just a few days ago, but they have to be approved by Embarcadero before they're published. so I'm sure there will be more blog posts coming soon.

    • Like 2
    • Thanks 1

  2. On 9/29/2023 at 3:51 AM, DelphiUdIT said:

    In the server connect event you must add:

     

    
    procedure TFTPServer.ServerConnect(AContext: TIdContext);
    begin
      If AContext.Connection.IOHandler is TIdSSLIOHandlerSocketBase then
        TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler).PassThrough := (UseTLS = utNoTLSSupport); //This function must be set to false for it to handle SSL/TLS functionality.
    end;

     

    This approach is incorrect.  This forces ALL connections to use SSL/TLS implicitly at connect-time.  But clients may want to use SSL/TLS explicitly instead, ie via an AUTH or CCC command.

     

    The CORRECT way to handle the PassThrough is to let TIdFTPServer manage it for you.  You should not be setting it manually yourself at all.

     

    If TIdFTPServer.UseTLS is set to utNoTLSSupport then TIdFTPServer will not touch PassThrough at all, and neither should you.

     

    If TIdFTPServer.UseTLS is set to utUseRequireTLS or utUseExplicitTLS then TIdFTPServer will set PassThrough according to client commands. You don't need to do anything extra for this.  The difference between them is that utUseExplicitTLS allows the client to decide whether SSL/TLS is used, whereas utUseRequireTLS will reject various operations if the client doesn't use SSL/TLS.

     

    If TIdFTPServer.UseTLS is set to utUseImplicitTLS than you need to use the TIdFTPServer.OnQuerySSLPort event to tell the server which port(s) are to use SSL/TLS implicitly (ie, to set PassThrough at connect-time),


  3. 24 minutes ago, Aztec said:

    Where can I find those .so files though?

    There are some at https://github.com/IndySockets/OpenSSL-Binaries, though those might be for Android not Linux (though Android runs on top of Linux). Otherwise you'll have to look around.

    Quote

    Does this require an installation on linux or can I simply place them in the same location as my module?

    You can simply put them in your app's folder, or anywhere else you want. If needed, Indy has an IdOpenSSLSetLibPath() function in the IdSSLOpenSSLHeaders unit.

    Quote

    Will indy support the latest SSLlib in Delphi 12?

    I don't know at this time.

     

    I have discussed this matter with Marco Cantu and others, so they are certainly interested in a resolution, and are aware of the PR on GitHub.

     

    They are likely going to ship an up-to-date version of Indy's main code with Delphi 12 (see disclaimer below!), but whether they include the PR code in some form is unclear at this time. It is a pretty big PR, and is not incorporated into the main code.

     

    I suggested maybe putting the PR code into a new package. Marco suggested maybe providing it as an optional add-on via GetIt, but that is something they would have to setup on their end, if at all.

     

    Disclaimer: This blog post is based on a pre-release version of the RAD Studio software and it has been written with specific permission by Embarcadero. No feature is committed until the product GA release.


  4. 34 minutes ago, Aztec said:

    he actual inner error is General Exception: Could not load SSL library.

    Hmm, that should say EIdOSSLCouldNotLoadSSLLibrary instead of General Exception. But at least the root cause is now known.

    Quote

    I did a search in here and it seems that everyone is talking about Windows, but could not find anything related to Linux.

    Indy dynamically loads OpenSSL at runtime on most platforms, including Linux. You are seeing the error when Indy is not able to load OpenSSL at runtime. 

    Quote

    Looking in the configs, it does seem that the various SSL versions can be allowed or rejected (See screen shot). I have allowed them all for now, but that makes no difference.

    In one of those screens, I see libssl.so.3 and libcrypto.so.3 shown. Those are the OpenSSL libs, but are they for OpenSSL v3.0? If so, that version is not compatible with TIdSSLIOHandlerSocketOpenSSL.

     

    By default, Indy loads unversioned .so files before loading versioned files. If those unversioned files are symlinks that map to newer versions, you could get the load error.

     

    On 'Nix platforms, Indy has IdOpenSSLSetCanLoadSymLinks() and IdOpenSSLSetLoadSymLinksFirst() functions in the IdSSLOpenSSLHeaders unit. You can set them to False at runtime before using Indy, that way it load the versioned .so files first/only, and then you can deploy OpenSSL v1.0.2 .so files with your app that are currently compatible with Indy.

     

    If that is not an option, then you can try this WIP SSLIOHandler for newer OpenSSL versions (not sure if it supports v3.0 or Linux, though) instead of TIdSSLIOHandlerSocketOpenSSL.

     

    In any case, one way to handle this error condition a little better in TIdSSLIOHandlerSocketOpenSSL is to call Indy's LoadOpenSSLLibrary() function from the IdSSLOpenSSL unit during your app's startup. If it fails, you can use Indy's WhichFailedToLoad() function from the IdSSLOpenSSLHeaders unit to help diagnose why it failed.


  5. 10 hours ago, Aztec said:

    However when we try and send email we get the following error
    [ EIdTLSClientTLSHandShakeFailed ] SSL negotiation failed

    EIdTLSClientTLSHandShakeFailed is an outer exception raised when an earlier exception is caught during the TLS handshake.  What does its InnerException say was the initial error?

    10 hours ago, Aztec said:

    the parameters I am assigning are correct

    What are the actual values you are using?  In particular, which Port are you TRYING to connect to, and which Port is it ACTUALLY connecting to?  I notice that you are assigning the Port first, then assigning the IOHandler and UseTLS after.  Depending on the particular Port value, the UseTLS setter MIGHT be changing the Port to a different value.  Try setting the Port after setting UseTLS, to make sure you are actually using the Port you are expecting.

     

    Aside from that, does the server in question still support TLS 1.1/1.2?  Some servers have made the jump to requiring TLS 1.3 nowadays.


  6. 11 hours ago, sBsaidus said:

    Can someone tel me what's wrong with the code.

    There is quite a lot wrong with the server code you have shown.

     

    TIdTCPServer is a multi-threaded component.  The listening ports are managed in worker threads. Each connected client is handled in its own worker thread.

     

    Your management of your f_CClients list is not thread-safe, or even accurate in places.  It is also redundant, as TIdTCPServer already has a thread-safe list of connected clients in its Contexts property.  You should just get rid of your f_CClients list altogether and use the Contexts list by itself.  You can store your tCClient objects in the TIdContext.Data property, or you can derive it from TIdServerContext and then set it to the TIdTCPServer.ContextClass property before activating the server.

     

    You are accessing your TMemo and TListView directly in the context of each client worker thread.  Any access to the UI from a worker thread must be synchronized with the main UI thread, which you are not doing at all.  Use TThread.Synchronize() or TThread.Queue() (or Indy's TIdSync or TIdNotify) for that purpose.  Do be careful with TThread.Synchronize()/TIdSync, though.  Since they are synchronous, if you deactivate the server in the main UI thread, and then try to sync with the UI thread, you will deadlock the server.  So, don't sync synchronously while deactivating the server, or do the deactivation in a separate thread so the main UI thread remains free to process sync requests.

     

    You are directly sending your QUIT commands to clients from the context of the main UI thread.  In this example, you are not sending anything else to the clients, but if you were, you would potentially be overlapping any sends those clients' threads may happen to be performing at the same time, which would corrupt your communications.  You must serialize access to a client's socket when sending to it across thread boundaries.  It is generally best to keep your socket I/O with a given client in that client's worker thread as much as possible.

     

    In short, your server code needs a good amount of rewriting to operate safely in a multi-threaded environment.


  7. Indy uses blocking sockets and synchronous I/O. The client's OnDisconnected event is fired when the *client* disconnects on its end. If the server disconnects first, there is no real-time notification of that. The client will notify your code only when the client tries to access the connection and gets an error from the OS, at which time it will raise an exception to your code, such as EIdConnClosedGracefully, etc. So, if you want timely notification of a remote disconnect, you need to actively send/read data. If your code is not using the connection for lengths of time, use a timer  to poll for incoming data periodically. Or use a reading loop in a worker thread.

    • Like 1

  8. 23 minutes ago, rvk said:

    Why is the date of the files on Fulgan updated each night?

    I don't know, I thought they were done maintaining a copy, but I guess not.

    23 minutes ago, rvk said:

    Maybe a readme file there pointing to the new official spot (or at least stating it is decommissioned) would make that more clear.

    The readme on that mirror says:

    Quote

    As of January 2020, the Indz source code is not available from this mirror anymore:

     

    The indy source control system has been migrated to github. There is therefore no need for extra tools in order to download the latest snapshot.

     

    All source code can be accessed from https://github.com/IndySockets

     

    The Indy SSL libraries will remain here for the time being.

     


  9. On 9/17/2023 at 4:07 AM, PeterBelow said:

    Btw.: TeamB was a group of users offering support to other users on the old Borland newsgroups. As recognition they received goodies like free product licences, a bit like the current Embarcadero MVP program, and we had dedicated support partners at Borland. All that slowly died off after Codegear took over, unfortunately.

    But at least we get some of that back via Embarcadero MVP! :classic_biggrin:


  10. 4 hours ago, domus said:

    Would anyone know if it's allowed to install a Community Edition of Delphi on two separate PCs simultaneously? (PC and laptop)

    Yes, per the EULA:

    Quote

    INSTALLATION AND USE RIGHTS. You may install and use any number of copies of the software on your devices.

    The EULA explains several restrictions on the Community Edition, but this is not one of them.

    • Like 1

  11. 4 hours ago, alank2 said:

    sometimes I have a synchronous process and I want to make sure some VCL elements are updated beforehand.  This always worked fine in bcb6.

    BCB6 predates Visual Styles and VCL Styles and basically most modern UI practices.

    4 hours ago, alank2 said:

    What could cause the Enabled change to _not_ create an immediate pending message?

    For example, when UI changes are animated by the OS or Styles, it would thus take multiple paint cycles to fully animate the complete state change, and ProcessMessages() or Update() may not (likely will not) catch all of the paint cycles in a single call.

    51 minutes ago, alank2 said:

    I realize that putting the "seconds to run" is more ideal in a thread, but that adds creating and managing a thread which I don't want to have to do for every process that takes a few seconds.

    You can mitigate that somewhat by using thread pools, for instance.

    51 minutes ago, alank2 said:

    Essentially I am looking for a function that will make sure the UI is fully updated before a period of time where it won't be updated.

    There is nothing in UI programming that says like "state change is finished and the UI for it is fully drawn".  Not even back in BCB6's day.  Although back then, drawing was much simpler, and usually completed in 1 paint cycle.  That may not be the case anymore in modern UIs.

    51 minutes ago, alank2 said:

    I tried using calling Repaint for all 3 buttons before a ProcessMessages, but it didn't work.

    Whatever is different between versions, perhaps changing a property from true to false takes a number of things to occur in sequence that rely on each other?

    That is not really a factor of the property itself, but in the UI rendering behind the scenes, so more oriented to differ between OS versions rather than compiler/VCL versions.

    13 minutes ago, alank2 said:

    DelphiUdIT - I tried the below (with and without the processmessages calls) and it still has the issue

    Update() only processes paint messages that are already pending in the message queue.  But you also need Invaliidate() to generate those messages in the first place, if they are not already generated for you.  So that is where Repaint() comes into play, to signal that a new paint cycle is needed if it hasn't already been signaled.

    • Like 2

  12. 6 hours ago, alank2 said:

    I think ProcessMessages was supposed to process all messages, right?

    Yes, it does.  But it can only handle messages that are already in the message queue (or synthetically generated by the queue) at the moment it is called.  It does not process future messages.  And the behavior you describe sounds like the actions are being delayed such that ProcessMessages() doesn't see all of them right away, which is why calling ProcessMessages() multiple times produces better results.

     

    You really should not be using ProcessMessages() in this manner in the first place.  Break up your code logic using TThread::ForceQueue() or a TTimer or equivalent to allow control to flow back into the main message loop so it can continue to process new messages while your desired time interval is waiting to elapse.

     

    For example, using TThread::ForceQueue():

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      Button1->Enabled = false;
      Button2->Enabled = false;
      Button3->Enabled = false;
      TThread::ForceQueue(nullptr, &Step2, 3000);
    }
    
    void __fastcall TForm1::Step2()
    {
      Button1->Enabled = true;
      Button2->Enabled = true;
      Button3->Enabled = true;
      TThread::ForceQueue(&Step3, 3000);
    }
    
    void __fastcall TForm1::Step3()
    {
      //...
    }
    
    // alternatively
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      Button1->Enabled = false;
      Button2->Enabled = false;
      Button3->Enabled = false;
      TThread::ForceQueue(nullptr,
                          [this](){
                            Button1->Enabled = true;
                            Button2->Enabled = true;
                            Button3->Enabled = true;
                            TThread::ForceQueue(nullpr,
                                                [](){
                                                  //...
                                                },
                                                3000);
                          },
                          3000);
    }

    Or, using TTimer:

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      Button1->Enabled = false;
      Button2->Enabled = false;
      Button3->Enabled = false;
      //Timer1->Interval = 3000;
      Timer1->Tag = 1;
      Timer1->Enabled = true;
    }
    
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
      if (Timer1->Tag == 1)
      {
        Button1->Enabled = true;
        Button2->Enabled = true;
        Button3->Enabled = true;
        //Timer1->Interval = 3000;
        Timer1->Tag = 2;
      }
      else
      {
        //...
        Timer1->Enabled = false;
        Timer1->Tag = 0;
      }
    }
    
    // alternatively...
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      Button1->Enabled = false;
      Button2->Enabled = false;
      Button3->Enabled = false;
      //Timer1->Interval = 3000;
      Timer1->OnTimer = Step2;
      Timer1->Enabled = true;
    }
    
    void __fastcall TForm1::Step2(TObject *Sender)
    {
      Button1->Enabled = true;
      Button2->Enabled = true;
      Button3->Enabled = true;
      //Timer1->Interval = 3000;
      Timer1->OnTimer = Step3;
    }
    
    void __fastcall TForm1::Step3(TObject *Sender)
    {
      //...
      Timer1->Enabled = false;
      Timer1->OnTimer = nullptr;
    }

     

     

    • Like 3

  13. 2 hours ago, WalkingAway said:

    Is it possible to get / set through RTTI non standard type value?

    I tries, but always got something like 'invalid tapecast' error.

    Can you show the actual code you are having trouble with?

    2 hours ago, WalkingAway said:

    What I want - to unified opportunity to set / get "Meta" value ,

    it can be FirstFrame.Meta, SecondFrame.Meta, ...

    What is "Meta" defined as?

    2 hours ago, WalkingAway said:

    Now I have to write

    if FirstFrame.Meta is AccountFrame then ...

    else if FirstFrame.Meta is ReportFrame

    What is it you are trying to do with "Meta", exactly?  We can't really help you without more detail.

    2 hours ago, WalkingAway said:

    If I have 50 frames it is too boring. RTTI may help me

    Or maybe mnthere some libraries for that

    Or maybe just re-think your design?  Perhaps interfaces are more suitable?  Hard to say without seeing what you are actually trying to do.

    2 hours ago, WalkingAway said:

    Also I want to link that kind of link to "Meta" to listview (TValue.From) for same purpose. With no success also so far...

    I'm sure there are ways to accomplish that, but again, it really depends on what your data looks like and how you are using it.


  14. 57 minutes ago, Todd Grigsby said:

    I downloaded the latest Indy available on github two nights ago -- 10.6.2 -- and it does not work with TLS 1.3

    Did you download only the main code, or did you also download the PR #299 code on top of it?

    57 minutes ago, Todd Grigsby said:

    Any idea when the TLS 1.3 branch will get merged into main?

    No ETA at this time. My understanding is that the code works as-is, but still needs to be updated/finalized to include design-time support, added to all of the supported packages, etc.

    • Like 2

  15. 3 hours ago, aehimself said:

    A ComboBox suffers from the same 2-click issue

    What, 1 click to open the list, and 1 click to select?  I really don't think that is much of an issue.  But if it is, then just use TRadioGroup/3xTRadioButton instead.

×