Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Dec 02 17:36
    rlebeau edited #392
  • Dec 01 19:05
    rlebeau opened #392
  • Dec 01 19:05
    rlebeau labeled #392
  • Dec 01 19:05
    rlebeau milestoned #392
  • Dec 01 19:05
    rlebeau labeled #392
  • Dec 01 01:43
    rlebeau edited #181
  • Nov 30 15:37
    webaddicto commented #390
  • Nov 30 15:27
    webaddicto commented #390
  • Nov 30 14:10
    dhewg commented #299
  • Nov 30 13:32
    mezen synchronize #299
  • Nov 29 19:27
    rlebeau edited #391
  • Nov 29 19:27
    rlebeau labeled #391
  • Nov 29 19:27
    rlebeau labeled #391
  • Nov 29 19:27
    rlebeau opened #391
  • Nov 29 18:59
    rlebeau closed #377
  • Nov 29 18:58
    rlebeau commented #377
  • Nov 29 18:50

    rlebeau on master

    Fix #301 broke IdFTP in Active … Merge pull request #389 from Da… (compare)

  • Nov 29 18:50
    rlebeau closed #389
  • Nov 29 18:48
    rlebeau commented #390
  • Nov 29 18:47
    rlebeau commented #390
Chad Adams
@chadeadams_gitlab
And that procedure is written as:
procedure RunIRC(AContext: TIdContext);
Remy Lebeau
@rlebeau

@chadeadams_gitlab what is with that try..finally? That is useless in that context. In any case, don't call StartListening manually, the Active setter handles that internally. Second, RunIRC would need to be a class method for that code to work as-is.
Otherwise, if you want to use a standalone procedure instead, you must use a TMethod to assign it, eg:

var
  M: TMethod;
M.Data := ...;
M.Code := @RunIRC;
ccIRCD.OnExecute := TIdServerThreadEvent(M);

Or

var
  E: TIdServerThreadEvent;
TMethod(E).Data := ..;
TMethod(E).Code := @RunIRC;
ccIRCD.OnExecute := E;

Either way, you would also need to add an explicit Self parameter to the procedure (DON'T do that with a class method):

procedure RunIRC(ASelf: Pointer; AContext: TIdContext);
Chad Adams
@chadeadams_gitlab
thats what i had wrong, iwrote this as a class last time.
Chad Adams
@chadeadams_gitlab
@rlebeau so it compiles and runs and then exists. I am assuming I need a loop here after calling Active?
Remy Lebeau
@rlebeau
@chadeadams_gitlab obviously, you would need to keep your program alive while the server is running. If you are doing this in a console app, then yes, after activating the server you would need a loop or a signal wait or something, and then deactivate the server once that loop/signal/something is done waiting.
UlissesV
@UlissesV
Dear mezen, you saved me, I just put the DLLs in my application folder and it worked, thank you all for your collaboration and help. strong hugs
Chad Adams
@chadeadams_gitlab
@rlebeau When using the TCPCustomClient, do you need the same handler for OnConnect as the server?

//Start The Client Functions
class procedure cc_ClientEvent.StartClient();
begin

cc_Client := TIdTCPClientCustom.Create();
cc_Client.OnConnected := @OnConnected;

end;

Chad Adams
@chadeadams_gitlab
And one more question: with the client class, how can I tell if the port is not available? Can you point me in the right direction. Right now, it just gives an error on connect.
Remy Lebeau
@rlebeau
@chadeadams_gitlab you should not be using TIdTCPClientCustom directly, use TIdTCPClient instead (or, since you are writing an IRC server, perhaps use TIdIRC for the client). But yes, you can assign event handlers to a client in the same manner as the server. You are not required to use any event handlers with a TCP client, though, since it uses synchronous operations (well, except in the case of TIdIRC, which has extra events to handle server packets since IRC is an asynchronous protocol). Any code you want to put in the OnConnected event could alternatively be placed immediately after Connect() returns, since Connect() is synchronous. But either way, using Connect() and catching any exception it may raise is the only way to know whether the server port is available or not. That is just the way TCP works, since it is a connection-oriented transport.
Chad Adams
@chadeadams_gitlab
Thanks, i changed to TCPServer instead.
Chad Adams
@chadeadams_gitlab
@rlebeau Im trying to just figure out how to send a simple string and read t he string from client to server. I have the server working and the client connecting but, my writes and reads seem to not work.
Client
Server:
Remy Lebeau
@rlebeau
@chadeadams_gitlab Your check for Connected=True is redunant (especially since you are doing it AFTER writing data), Connect() would raise an exception if it fails to connect. Also, the TidTCPClient.OnConnected event does not take an AContext: TIdContext parameter, it takes a Sender: TObject parameter instead. You should have gotten a compiler error about that mismatch. As for your I/O, your client is writing a 1-char string, which your server reads and then replies to, but your client does not attempt to read that reply before writing its 2nd 1-char string.
Chad Adams
@chadeadams_gitlab
@rlebeau Thanks. I guess i stared at it too long! Thank you. One more question: can you show me an example of how to catch the error on client connect if the server is down?
Remy Lebeau
@rlebeau
@chadeadams_gitlab simply place a normal try..except handler around the call to Connect(), eg:
try
  cc_Client.Connect('localhost', 7000);
except
  // handler error...
end;
Chad Adams
@chadeadams_gitlab
@rlebeau So one final question: i have a TCP Server with multiple clients connected. How can you broadcast to all clients, or individual clients socket connections with Indy? Do I need to keep a var with connection info (socket desc) or some other means? I have a feeling its more simpler than I am thinking.
Remy Lebeau
@rlebeau
@chadeadams_gitlab I've posted TIdTCPServer broadcast examples many many times over the years in various forums, it should not be hard to find with an online search. But the jist of it is that the server already keeps track of the connected clients, so you can simply enumerate the server's Contexts list to access each client as needed. This also means your communication protocol needs to be designed to support unsolicited messages from the server. However, due to the multi-threaded nature of TIdTCPServer, I do not recommend writing to each client directly, as that will cause race conditions. You should keep each client's I/O local to the server's OnConnect/OnExecute/OnDisconnect events. I recommend giving each TIdContext its own thread-safe queue of outgoing data (created in OnConnect and destroyed in OnDisconnect, or better by deriving a new class from TIdServerContext), which any thread can push into as needed, and then have the server's OnExecute event handler transmit the calling TIdContext's queue when it is safe to do so, ie when not actively exchanging other data with the client.
mezen
@mezen
@rlebeau do you know of any existing projects that have implemented load balancing with Indy that are also made publicly available?
Remy Lebeau
@rlebeau
@mezen no, I do not. As besides, load balancing is not something that should typically be handled by the server itself, it should be in front of the server instead.
kabiri
@kabiri
How do I use TIDTCPServer as TIDTCPClient?
I want to connect three TIDTCPServers.
7 replies
arend-c
@arend-c

Hi guys, newbie here so not sure if this is the best place for this.

I've hit an issue using TIdHTTP on iOS using mobile network data. A POST call works fine on WiFi but on mobile I get the following error:

Error resolving Address [URL]: nodename nor servname provided, or not known (8)

Which I've narrowed down to the getaddrinfo() function call in IdStackVCLPosix.pas Ln 987

Has anyone encountered this before? The closest issue I've found to this is https://stackoverflow.com/questions/1238934/getaddrinfo-in-iphone where Apple says battery saving measures limit the types of connections.

Remy Lebeau
@rlebeau
@arend-c Well, it doesn't get more definitive than an official response from Apple, don't you think? Basically, you have to use Apple APIs to trigger the WWAN to activate, then BSD socket APIs (like what Indy uses internally) will work.
arend-c
@arend-c
is there a way to do that through Indy components or should I leave my code as is (since it works on other platforms) and use the mac/ios API to do an initial connection? I haven't really played with ios platform specific code other than to play sounds and vibrate the device so not sure how to do that TBH
arend-c
@arend-c
i actually found an old post of yours @rlebeau : https://stackoverflow.com/questions/69123377/how-do-i-announce-a-bonjour-service which led to the twodesk code snippet using TNSURLRequest. Do you think that would be sufficient? I'm in the process of translating to C++ (I'm using C++ Builder, not Delphi) but haven't been able to get it working yet
Remy Lebeau
@rlebeau
@arend-c There is nothing in Indy to interact with iOS APIs. I don't have any experience with iOS, but I would imagine that making an initial connection with TNSURLRequest should work, since that Apple reply did mention URLRequest would suffice: "The officially supported mechanism to establish a WWAN connection is to use the CFSocketStream API (or dependent API - NSSocket, as well as CFHTTPStream, CFFTPStream, NSURLRequest, and NSURLConnection API's)."
AdrianSRU
@AdrianSRU

Hi,

I am using TIdSMTP to send outbound emails. I have recently upgraded from C++ Builder 10.2 to 10.4, and a user with Exchange Server 2013 is now consistently getting a "Client was not authenticated" error that had never appeared before this update. Nothing about the way I am using TIdSMTP had changed, so I can only presume that it has something to do with the C++ Builder update and/or a newer version of Indy that comes with it.

Were there any changes to the TIdSMTP defaults that might cause this sort of error?

Thank you very much!

Remy Lebeau
@rlebeau
@AdrianSRU I don't recall any changes in recent years that would affect how TIdSMTP handles authentication. You are going to have to debug it to see what is actually failing. Which SMTP command is actually failing? Does TIdSMTP attempt to authenticate but fail, or does it skip authentication completely?
Asbjørn Heid
@aheid_gitlab
could it be some SLL/TLS issues?
i mean, would be the wrong error for that, but not the first time i've seen wrong/illogical errors... and SSL/TLS settings is def something that can change between versions
Remy Lebeau
@rlebeau
@aheid_gitlab I can't answer that without first knowing the details of the failure
Asbjørn Heid
@aheid_gitlab
of course, was just thinking loud :)
Remy Lebeau
@rlebeau
@aheid_gitlab are you capturing the raw SMTP traffic to see the actual commands and responses?
Asbjørn Heid
@aheid_gitlab
i don't have an issue, adrian is, sorry for confusion :)
Remy Lebeau
@rlebeau
@aheid_gitlab sorry, you're right
@AdrianSRU are you capturing the raw SMTP traffic to see the actual commands and responses?
AdrianSRU
@AdrianSRU
I'm not, I am trying to gather more information from the user now. I am using TLS1.2, would it still be possible to observe that raw traffic?
Remy Lebeau
@rlebeau
@AdrianSRU you can capture the raw unencrypted traffic by attaching one of Indy's TIdConnectionIntercept-derived components, such as TIdLogFile, to the TIdSMTP.Intercept property.
AdrianSRU
@AdrianSRU
That actually reminds me, I also use TIdTCPClient along with TIdSSLIOHandlerSocketOpenSSL and I found that in 10.4 I needed to set PassThrough=false on that IO handler. I didn't think about that also possibly being relevant to TIdSMTP but I am using TIdSSLIOHandlerSocketOpenSSL with that as well. Could that be relevant here as well?
Ah, I wasn't aware of those components. I will give that a try. Thank you very much.
Remy Lebeau
@rlebeau
@AdrianSRU TIdSMTP will handle PassThrough automatically for you based on its UseTLS property.
AdrianSRU
@AdrianSRU
OK, I have UseTLS set to utUseExplicitTLS.
Remy Lebeau
@rlebeau
@AdrianSRU then TIdSMTP.Connect() will set PassThrough=True, and then after a STARTTLS command is accepted, TIdSMTP will switch to PassThrough=False
Gregg Wonderly
@greggwon
With TIdSMTP, what do I need to use to see which errors are occuring with TLS or recepient approval?
I am using a delphi 10.3 environment. I see indyprotocols260.bpl as the package
Remy Lebeau
@rlebeau
@greggwon When an OpenSSL TLS handshake fails, you can try checking if the raised Exception (or one of its InnerExceptions) is an EIdOpenSSLAPISSLError, and if so then look at its RetCode and ErrorCode properties. But chances are, you are probably not going to have access to the original EIdOpenSSLAPISSLError exception in many cases. Hard to sayfor sure without knowing more about your particular situation and error messages.