SuperTCP Chat Demo Question

I m checking the SuperTCP chat Demo:

I’ve not following code not so clear .

The below marked not clear block, it should for the current login user to get those already login user. Am I correct?

If yes, why the client did not receive this event sink?

but the remain logined client can receive the new login user.

Please advise.

procedure TLoginService.Login(const Nickname: Unicodestring);
var
  ev: IChatEvents_Writer;
  i: Integer;
  s: Unicodestring;
begin
  UserClientIDListCs.Acquire;
  try
    if UserClientIDList.IndexOfName(Nickname) <> -1 then raise Exception.Create('Nickname already in use');
    s := VarToWideStr(Session['nick']);
    if s <> '' then
      UserClientIDList.Delete(UserClientIDList.IndexOfName(s));

    CreateSession;
    RegisterEventClient((GuidToString(Session.SessionID)), EID_ChatEvents);

<<< Not Clear Start
    ev := (EventRepository as IChatEvents_Writer);
    ev.ExcludeSender := False;
    ev.SessionList.Add(GuidToString(Session.SessionID));

    for i := 0 to UserClientIDList.Count - 1 do begin
      ev.UserLogin(Session.SessionID, UserClientIDList.Names[i]);
    end; 

<<< Not Clear End


    UserClientIDList.Add(Nickname + '=' + GUIDToString(Session.SessionID));

    ev := (EventRepository as IChatEvents_Writer);
    ev.ExcludeSender := False;
    for i := 0 to UserClientIDList.Count - 1 do
      ev.SessionList.Add(Copy(UserClientIDList[i], pos('=', UserClientIDList[i])+1, MaxInt));
    ev.UserLogin(Session.SessionID, Nickname);
  finally
    UserClientIDListCs.Release;
  end;
  Session['nick'] := Nickname;
end;

Hi,

that code notifies all other logged users that new user is logged

ev := (EventRepository as IChatEvents_Writer);
ev.ExcludeSender := False;
ev.SessionList.Add(GuidToString(Session.SessionID));

for i := 0 to UserClientIDList.Count - 1 do begin
  ev.UserLogin(Session.SessionID, UserClientIDList.Names[i]);
end; 

I mean this part . notifies all other logged users that new user is logged ?

yes. check the client code:

procedure TSuperTCPChannelChat_ClientMainForm.UserLogin(const Nickname: Unicodestring);
var
  Data: TStringArray;
begin
  SetLength(Data, 1);
  Data[0] := Nickname;
  SendMessage(Handle, WM_USER, Longint(stUserLogin), Longint(Data));
end;

as you can see, it passes stUserLogin with new user name to SyncCall:

    procedure SyncCall(var Msg: TMessage); message WM_USER;
...
procedure TSuperTCPChannelChat_ClientMainForm.SyncCall(var Msg: TMessage);
...
    stUserLogin:
      SuperTCPChannelChat_ClientMainForm.edUsers.Items.Add(lData[0]);

as a result, it just adds that username into list of users into the pane at the right

I make my question clear , see if I miss or misunderstanding the case:

ev := (EventRepository as IChatEvents_Writer);
ev.ExcludeSender := False;
for i := 0 to UserClientIDList.Count - 1 do
  ev.SessionList.Add(Copy(UserClientIDList[i], pos('=', UserClientIDList[i])+1, MaxInt));
ev.UserLogin(Session.SessionID, Nickname);

This part is what you mean notice all other user , the new user login.

ev := (EventRepository as IChatEvents_Writer);
ev.ExcludeSender := False;
ev.SessionList.Add(GuidToString(Session.SessionID));

for i := 0 to UserClientIDList.Count - 1 do begin
  ev.UserLogin(Session.SessionID, UserClientIDList.Names[i]);
end; 

This part is to notice current login user the logined user . am i correct?
As Now this part not trigger the client Userlogin code.

See if i get the correct meaning.

I’m sorry, I misread code.

for i := 0 to UserClientIDList.Count - 1 do begin
  ev.UserLogin(Session.SessionID, UserClientIDList.Names[i]);
end; 

this one should notify current user about others logged users


this one:

ev.UserLogin(Session.SessionID, Nickname);

notify other users about current one.

for i := 0 to UserClientIDList.Count - 1 do begin
ev.UserLogin(Session.SessionID, UserClientIDList.Names[i]);
end;

this code is not working, current user cant get the “already logined user”.

Delphi 10.3.3 / DA 10.0.0.1463

Please advise

Hi,

pls update LoginService_Impl.pas as

  TLoginService = class(TRORemoteDataModule, ILoginService)
..
  protected
..    procedure DoOnDeactivate(aClientID: TGUID); override;

procedure TLoginService.DoOnDeactivate(aClientID: TGUID);
var
  ev: IChatEvents_Writer;
  i: Integer;
begin
  inherited;
  if SessionManager.IsSessionPresent(aClientID) then begin
    ev := (EventRepository as IChatEvents_Writer);
    ev.ExcludeSender := False;
    ev.SessionList.Add(GuidToString(Session.SessionID));
    for i := 0 to UserClientIDList.Count - 1 do begin
      ev.UserLogin(Session.SessionID, UserClientIDList.Names[i]);
    end;
  end;
end;

Why it doesn’t work in this sample: we have closed security hole in code and now session is added to session manager after the login call is completed and DestroySession wasn’t called in the Login method.

I’ll update the SuperTCP chat sample.

Thanks, logged as bugs://84107

bugs://84107 got closed with status fixed.