-
Content Count
2684 -
Joined
-
Last visited
-
Days Won
113
Everything posted by Remy Lebeau
-
Clearly it is, since the user is seeing an Indy error message. Which function are you referring to? The failing code is calling LocaleCharsFromUnicode(), which is an RTL system function.
-
I didn't write TIdHL7 and I'm not familiar with how the HL7 protocol works. I'll have to look into what is going on. I've opened a ticket on Indy's GitHub: https://github.com/IndySockets/Indy/issues/501
-
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.
-
indy Indy FTP Server with TLS/SSL
Remy Lebeau replied to shineworld's topic in Network, Cloud and Web
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), -
[ EIdTLSClientTLSHandShakeFailed ] SSL negotiation failed
Remy Lebeau replied to Aztec's topic in Indy
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. 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. 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. -
[ EIdTLSClientTLSHandShakeFailed ] SSL negotiation failed
Remy Lebeau replied to Aztec's topic in Indy
Hmm, that should say EIdOSSLCouldNotLoadSSLLibrary instead of General Exception. But at least the root cause is now known. 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. 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. -
[ EIdTLSClientTLSHandShakeFailed ] SSL negotiation failed
Remy Lebeau replied to Aztec's topic in Indy
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? 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. -
XE4 was released 10 years ago. And TIdHL7 specifically got a major revamp from its original author a year ago. So, you should upgrade to the latest Indy (if not to a modern Delphi) and see if the problem still occurs.
-
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.
-
Migrate an old app in Delphi 2009 to modren C++
Remy Lebeau replied to Alkanium's topic in General Help
You should be able to, as it should have the command-line Delphi compiler available, so that 3rd party components can still be compiled and installed into the IDE for C++Builder to use. -
Indy TIdTCPClient do not detect Disconnections.
Remy Lebeau replied to sBsaidus's topic in Network, Cloud and Web
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. -
Per the CE FAQ: https://www.embarcadero.com/products/delphi/starter/faq
-
I don't know, I thought they were done maintaining a copy, but I guess not. The readme on that mirror says:
-
Influenced by C# (like several features in Delphi have been): https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/raw-string-literal
-
Streams - Writing and Reading data or text from
Remy Lebeau replied to JohnLM's topic in Algorithms, Data Structures and Class Design
It is working fine for me. Yes. My hosting provider did perform maintenance on my site's server yesterday, so maybe they messed something up, or have already resolved the issue. -
OK, well... The fulgan mirror has been decommissioned for some time now, the GitHub repo is the official spot now.
-
Streams - Writing and Reading data or text from
Remy Lebeau replied to JohnLM's topic in Algorithms, Data Structures and Class Design
But at least we get some of that back via Embarcadero MVP! -
Those are the same DLLs that used to be on the indy.fulgan.com site.
-
Yes, per the EULA: The EULA explains several restrictions on the Community Edition, but this is not one of them.
-
The Delay option was added in 10.4 Sydney, so it is a relatively recent addition (2020).
-
BCB6 predates Visual Styles and VCL Styles and basically most modern UI practices. 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. You can mitigate that somewhat by using thread pools, for instance. 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. 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. 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.
-
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; }
-
Can you show the actual code you are having trouble with? What is "Meta" defined as? What is it you are trying to do with "Meta", exactly? We can't really help you without more detail. Or maybe just re-think your design? Perhaps interfaces are more suitable? Hard to say without seeing what you are actually trying to do. 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.
-
What @DelphiUdIT said. Indy 10 does have .dpk package files for Delphi 7, namely: IndySystem70.dpk IndyCore70.dpk IndyProtocols70.dpk dclIndyCore70.dpk dclIndyProtocols70.dpk
-
Did you download only the main code, or did you also download the PR #299 code on top of it? 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.