Jump to content

Remy Lebeau

Members
  • Content Count

    2322
  • Joined

  • Last visited

  • Days Won

    94

Everything posted by Remy Lebeau

  1. Remy Lebeau

    [Need help] Linux recv() timeout

    It has the public Receive() method inherited from TIdStack, but that takes only a socket handle and a TIdBytes as parameters. I assume you want access to the flags parameter of recv()? For that, you can use the protected TIdStackBSDBase.WSRecv() method. type TIdStackBSDBaseAccess = class(TIdStackBSDBase) end; TIdStackBSDBaseAccess(GBSDStack).WSRecv(AContext.Binding.Handle, buffer, length, MSG_PEEK);
  2. Remy Lebeau

    SSL connection

    https://github.com/IndySockets/Indy/issues/410
  3. Remy Lebeau

    [Need help] Linux recv() timeout

    Indy's TIdSocketHandle class does not have a SetSockOpt() overload for non-integer inputs, but its TIdStackBSDBase class does (for BSD-based socket stacks, like Linux and Windows): uses ..., IdStackBSDBase; GBSDStack.SetSocketOption(AContext.Binding.Handle, Id_SOL_SOCKET, Id_SO_RCVTIMEO, mTime, SizeOf(TTimeVal)); I probably need to update Indy to expose this overload in TIdSocketHandle and TIdStack for easier use.
  4. Remy Lebeau

    TIdMappedPortTCP not executing on Linux

    That's good to hear (not that you are tired, but that you got it working). FYI, if the mapped host/port is wrong and the connection can't be established, the TIdMappedPortTCP's OnException event will be triggered. On a side note: the way you are using TThread.Queue() is a potential crash waiting to happen. TThread.Queue() is asynchronous, and your anonymous procedures are capturing the local TIdContext variable, which points to an object that may or may not be valid anymore if the client disconnects before the Queue request is processed by the main thread. Instead, you should first save the desired values locally and then capture those variables instead, eg: procedure TMyClass.OnServerConnect(AContext: TIdContext); var lPeerIP: string; lPort: TIdPort; begin lPeerIP := AContext.Binding.PeerIP; lPort := AContext.Binding.Port; TThread.Queue(nil, procedure begin WriteLn('OnConnect from ' + lPeerIP + ' to ' + lPort.ToString); end ); end; procedure TMyClass.OnServerExecute(AContext: TIdContext); var lPeerIP: string; lPort: TIdPort; begin lPeerIP := AContext.Binding.PeerIP; lPort := AContext.Binding.Port; TThread.Queue(nil, procedure begin WriteLn('OnExecute from ' + lPeerIP + ' to ' + lPort.ToString); end ); end;
  5. That will only work if the email is entirely textual, no binary attachments. And also, only if the sender actually sends the text data as UTF-8, which is not a guarantee. Try this instead: var MsgEnd: Boolean; Decoder, NewDecoder: TIdMessageDecoder; Line, Boundary, BoundaryStart, BoundaryEnd: String; Dest: TStream; begin ... Boundary := ExtractHeaderSubItem(ARequestInfo.ContentType, 'boundary', QuoteHTTP); BoundaryStart := '--' + Boundary; BoundaryEnd := BoundaryStart + '--'; repeat Line := ReadLnFromStream(ARequestInfo.PostStream, -1, True); if Line = BoundaryEnd then Exit; until Line = BoundaryStart; Decoder := TIdMessageDecoderMIME.Create(nil); try MsgEnd := False; repeat TIdMessageDecoderMIME(Decoder).MIMEBoundary := Boundary; Decoder.SourceStream := ARequestInfo.PostStream; Decoder.FreeSourceStream := False; Decoder.ReadHeader; case Decoder.PartType of mcptText, mcptAttachment: begin Dest := TMemoryStream.Create; try NewDecoder := Decoder.ReadBody(Dest, MsgEnd); try // use Dest as needed... finally Decoder.Free; Decoder := NewDecoder; end; finally Dest.Free; end; end; mcptIgnore: begin FreeAndNil(Decoder); Decoder := TIdMessageDecoderMIME.Create(nil); end; mcptEOF: begin MsgEnd := True; end; end; until (Decoder = nil) or MsgEnd; finally Decoder.Free; end; end; What you SHOULD be doing is actually parsing the MIME data according to the official MIME RFC specifications.
  6. That is the basic jist of it, yes. Though, detecting a viable handshake is slightly more complex than just testing the first 2 bytes. I did write some code for this a long time ago, I'll have to look for it.
  7. That depends on how you are parsing it. TIdHTTPServer does not parse 'multipart/form-data' for you (that is on the todo list), so you have to parse the raw data yourself. What does your code look like for that? You can use Indy's TIdMessageDecoderMIME class to help you parse 'multipart/form-data' from the ARequestInfo.PostStream data.
  8. Remy Lebeau

    IOHandler.Write() problems with SocketError # 10053 exception

    First, that is a lot of code to go through, and blue text on black a background is very difficult to read. Second, there is no mention of this failing AddStr() method being called anywhere in those screenshots.
  9. There are countless examples of that online all over the place. Start with the TThread class, overriding its virtual Execute() method, and use its Synchronize() or Queue() method when you need to communicate with the main UI thread. Seems like you already know how to do that. So, what's stopping you from using that? That would be a perfectly valid approach. And? It still works. All that means is that code which touches VCL controls needs to run in the context of the main UI thread. There are many different way to do that. One way is TThread::Synchronize()/TThread::Queue(). Another way is using window messages (for example, wParam and lParam can hold pointers to data). Another way is using a thread-safe container and having the main thread poll it periodically, such as in a timer. Or any combination of these approaches (for example, putting data in a thread-safe container, then posting a message to poll the container). Are you planning on writing portable code in C++Builder only, or do you need to support other C++ compilers? If you stick with just C++Builder then there is no reason not to use what it provides, like TThread (which does run on all supported platforms). But, if you want to support other compilers, then you have to stick with only the standard C++ library and 3rd party cross-platform libraries. Those headers were introduced in C++11. Are you using one of the clang-enhanced C++ compilers that support C++11? The "classic" Borland compiler only supports a small subset of C++11 language features, but no C++ standard library features. So make sure you are using a compiler that supports what you want.
  10. Remy Lebeau

    TIdHTTP->Get UnicodeString trouble

    This issue has nothing to do with Unicode. You simply have a logic bug in your code. You are already doing it. You just have a mistake in your format string. BTW, you can get rid of the char[] array and use the (s)printf() method of AnsiString/UnicodeString instead, eg: AnsiString url; url.printf("http://%s/ajax.xml", ethTcp_ip); String us = IdHTTP1->Get(url); out << "Response" << endl << AnsiString(us).c_str() << endl; Memo1->Lines->Text = us; Another option, albeit a little heavier-handed, is to use Indy's TIdURI class, eg: #include <IdURI.hpp> #include <memory> std::unique_ptr<TIdURI> idUri(new TIdURI); // or: auto idUri = std::make_unique<TIdURI>(); idUri->Protocol = _D("http"); idUri->Host = ethTcp_ip; idUri->Path = _D("/"); idUri->Document = _D("ajax.xml"); String url = idUri->URI; Look VERY CAREFULLY at the two URLs you are passing to TIdHTTP::Get(). What do you see that is different between them? In the bad example, there is an extra erroneous '/' character in front of the filename: good: "http://192.168.1.123/ajax.xml" bad: "http://192.168.1.123//ajax.xml" ^ Fix your format string to remove the erroneous '/' character. https://www.indyproject.org/2021/02/10/links-to-old-indy-website-pages-are-currently-broken/ https://blogs.embarcadero.com/we-are-experiencing-a-hardware-outage/ https://ideasawakened.com/post/embarcadero-network-issues Yes, but you are not experiencing a Unicode problem, since your URL contains only ASCII characters. https://github.com/IndySockets/Indy/wiki/Documentation
  11. If you want to do this TLS handshake detection in TIdMappedPortTCP, the best place to handle this is in the OnBeforeConnect event, which is fired immediately after a new client is accepted by TIdMappedPortTCP and before its associated OutboundClient is connected to the next server. The OnExecute event is fired after the OutboundClient is connected to the next server and the accepted client has sent data which has been read into its InputBuffer. By then, its too late for the TLS detection since the connection is already receiving application data after the TLS session is established. No, you do not. You can't "undo" a socket read. Nor will doing so help you with detecting the TLS handshake, anyway. You have to peek the bytes directly from the socket itself, not from the InputBuffer that is on top of the socket.
  12. Then there IS a try..except involved, but its inside the VCL framework wrapping the call to the event handler (and most other events, for that matter). That is why, for example, if you raise an exception inside an OnClick event and don't catch it yourself, you will still see a default popup message appear. There is a default try..except inside the framework for handling UI errors.
  13. Remy Lebeau

    Quality Portal going to be moved

    I was just thinking the same thing! So many QC tickets were lost, and not linked/duplicated into QP tickets.
  14. Delphi 12 does not support Server 2008 or 2008 R2 as a deployment platform. The minimum supported Server version is 2019. Because Window 7 (SP1+) is a supported deployment platform. See: https://docwiki.embarcadero.com/RADStudio/Athens/en/Supported_Target_Platforms
  15. On a side note, you should not be passing an Owner to your thread. You are creating the TPing object inside your worker thread, so don't assign a component from the main thread as its Owner. Set the Owner to nil instead, and then Free() the object when you are done using it.
  16. Remy Lebeau

    Testing a Semaphore??

    Unfortunately, that does not work. The LastError property is set only if THandleObject.Wait() fails with an OS error. If a creation or acquisition/release fails, an exception is raised instead. If a creation succeeds with a non-zero error code, the LastError property is not set to reflect that. I have now opened a ticket for that feature: RSP-44312: THandleObject.LastError should be set during object creation
  17. @dan27125 I commented earlier on your same question on StackOverflow: https://stackoverflow.com/questions/77868076/collect-json-ajax-data-from-a-local-zigbee-web-server Now that I see this post, the StackOverflow post appears to be a direct copy/paste of this post? That would explain why it mentions "Attached is ajax.xml, debug.html" without actually providing those files. It is generally frowned upon by internet etiquette to post the same question in multiple forums at the same time. It shows a lack of patience on your part, and a disrespect for people who might take time out of their day to answer. That being said, now that I see the relevant data files are on this post and not the StackOverflow post, I can fill in some gaps from my StackOverflow comment. The HTML is running a client-side JavaScript that uses a timer to invoke the browser's built-in AJAX client at regular intervals to send an HTTP request to download the XML file, parse the XML, and inject the results into the HTML elements using the browser's DOM. There is no streaming involved at all, each data update is an independent HTTP request. In C++Builder, you would simply do the same thing. Run a timer that uses any HTTP client you want (TIdHTTP, T(Net)HTTPClient, libcurl, etc) to download the XML from the appropriate URL, and then you can use any XML library, such as (T|I)XMLDocument, to parse the XML and do what you need with the data values.
  18. It is "up", but it is not entirely stable. I was just using it a few minutes ago and still got a few errors on it. But yes, I could access pages.
  19. The parent list (https://stats.uptimerobot.com/3yP3quwNW) doesn't appear to include any GetIt servers for monitoring. Unless maybe they are listed under a different name (Downloads, perhaps?)
  20. Remy Lebeau

    TCP/IP Server with OpenSSL TLS 1.2

    In the short term, yes. But on the other hand, external links tend to break over time, which makes discussions harder to follow for future readers who may be looking for solutions to similar problems, if they can't see the code that is being discussed.
  21. Did you read the discussion I linked to earlier? You would have to modify the Registry directly. However... At the moment, not the online version, no. Several key systems, including GetIt, are completely down (and have been for over a week now!) due to a hardware outage: https://blogs.embarcadero.com/we-are-experiencing-a-hardware-outage/ If you really need access to GetIt right now, the best you could do is put GetIt into offline mode and let it work with its local cache/ISO, including any local packages you install into it manually.
  22. Remy Lebeau

    IOHandler.Write() problems with SocketError # 10053 exception

    You appear to be using TIdHTTPServer, so why are you using IOHandler.Write() directly at all? You should be using ResponseInfo.ContentText or ResponseInfo.ContentStream instead. Unless you are streaming data that is dynamically generated in chunks while the response is still being written to the client? That is not a common thing to do for HTML. Can you please show a more complete example of how exactly this AddStr() method is being used in relation to your server? How are you configuring the ResponseInfo before calling AddStr() the 1st time? Without more info, my guess is that you are probably violating the HTTP protocol in some way and the error is just a side effect. The error simply means the connection has been dropped on the server side, but that could happen for any number of reasons not directly related to your code.
  23. Remy Lebeau

    Could this be an Indy Error?

    That sounds more like a server-side issue, if it affects both components. Did you check if the requests are different in any way between Delphi 11 vs 12?
×