procedure TDC_SPA.FSocketClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
Index: Integer;
AClient: TClient;
DCFrame: String;
begin
if FClients.FindSocket(Socket, Index) then begin
AClient := FClients.Client[Index];
AClient.Buffer := AClient.Buffer + Socket.ReceiveText;
AClient.Buffer := StringReplace(AClient.Buffer, #$d#$a, LineFeed, [rfReplaceAll]);
if AClient.Buffer > '' then begin
while (Pos(EOCommand, AClient.Buffer) > 0) do begin
Index := Pos(EOCommand, AClient.Buffer);
DCFrame := Copy(AClient.Buffer, 1, Index + 4); // +4 ersetzten durch Length(EOCommand)
AClient.Buffer := Copy(AClient.Buffer, Index + 5, Length(AClient.Buffer)); // +5 ersetzen
Parse_DCFrame(AClient, DCFrame);
if not Assigned(AClient) then
Exit; [b]// break würde reichen...[/b]
if AClient.Buffer = '' then
Exit; [b]// break würde reichen...[/b]
if AClient.SID = 0 then
Exit; [b]// break würde reichen...[/b]
end;
end;
end;
end;
procedure TDC_SPA.Parse_DCFrame(AClient: TClient; AFrame: String);
var
Framelist: TFramelist;
Command: Integer;
AUser: TUser;
Index: Integer;
begin
if Assigned(FOnRawData) then
FOnRawData(Self, rsIn, AClient.SID, AFrame);
[...]
case Command of // Kommandoframe auswerten
CMD_AUTH: HandleLogin(AClient, Framelist); // Anmelden
CMD_PONG: HandlePong(AClient, Framelist); // Pong
CMD_SEND_USER: HandleUserMessage(AClient, FrameList); // Nachricht an einen Benutzer
// Alle Commands > 100 werden extern gehandled;
else begin
// Sicherstellen das das Command über 100 liegt
if Command < 100 then
Exit; [b]// was ist mit der Framelist? Speicherleck?[/b]
// Nur wenn der Socket einem Benutzer zugeordnet werden kann fortfahren
if Users.FindSocket(AClient.Socket, Index) then
AUser := Users.User[Index]
else Exit; [b]// was ist mit der Framelist? Speicherleck?[/b]
// Übergabe an Extern
if Assigned(FOnCommand) then
FOnCommand(Self, AUser, Command, Framelist);
end;
end;
Framelist.Free;
end;
procedure TDC_SPA.HandleLogin(AClient: TClient; FrameList: TFrameList);
var
Index: Integer;
AUser: TUser;
AuthVal: Boolean;
begin
if Framelist.Count <> 6 then // Anzahl der Frames MUSS 6 sein
begin
SendMessage(AClient.Socket, CMD_LOGIN_FAIL, 'Login Error. Not enough parameters'); // Fehlermeldung falls ungültig
AClient.Socket.Close; // Socket freigeben
Exit;
end;
if Not Users.FindUser( FrameList.Frames[1].Frame, Index ) then begin
AUser := FUsers.AddConnection(AClient.Socket);
AUser.SID := AClient.SID;
AUser.LoginTime := Now;
AUser.LPStamp := TimeStamp;
AUser.Address := FrameList.Frames[3].Frame;
AUser.User := FrameList.Frames[1].Frame;
AUser.Name := FrameList.Frames[2].Frame;
AUser.Pass := Framelist.Frames[4].Frame;
if Assigned(FAuthData) then
FAuthData(Self, AUser, AuthVal)
else AuthVal := True;
AUser.Authed := AuthVal;
if AuthVal then begin
SendMessage(AUser.Socket, CMD_LOGIN_OK, 'Logged on');
SendUserlist(AUser, ucsLogin);
if Assigned(FConnectionsStatus) then
FConnectionsStatus(Self, FClients.Count, FUsers.Count);
end
else begin
SendMessage(AUser.Socket, CMD_LOGIN_FAIL, 'Login Disabled');
AUser.Socket.Close; // Verbindung trennen
end;
end
else begin
SendMessage(AClient.Socket, CMD_USER_IN_USE, 'User [b]already[/b] connected'); // Benutzer bereits verbunden
AClient.Socket.Close; // Verbindung trennen
end;
end;
procedure TDC_SPA.FSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var
Index: Integer;
TmpUser: TUser;
SID: Integer;
begin
if FUsers.FindSocket(Socket, Index) then begin
TmpUser := FUsers.User[Index];
SID := TmpUser.SID;
TmpUser.Free;
end;
if FClients.FindSocket(Socket, Index) then begin
FClients.Client[Index].SID := 0; // Nutze ich nun zur Prüfung ob der Client noch vorhanden ist, damit gehts ohne Fehler
FClients.Client[Index].Free; // <-- Hier wird das Item in dem Fall der Inhalt aus AClient freigegeben
[/b]// Client ist TCollectionItem? Übernimmt die Collection die Einträge und gibt sie somit frei?
// Grundsätzlich solltest du hier aber nil dem ehemaligen Eintrag zuweisen nach dem Free. Damit müsstest
// du aber auch entsprechend darauf achten, dass du beim Zugriff auf die Collection NIL Einträge bekommen
// kannst.
end;
if Assigned(FConnectionsStatus) then
FConnectionsStatus(Self, FClients.Count, FUsers.Count);
// Clients über die veränderung benachrichtigen
end;