© BigSpeed Computing Inc. - Mastering algorithms



// *** Delphi example of secure private voice chat server ***





unit uMain;


interface

uses
  ActiveX, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ToolWin, Menus, ActnList, ImgList, StrUtils, Contnrs,
  ExtCtrls, Registry, Variants, ShellAPI, Buttons, IniFiles,
  bsErrors, bsVoiChatSrv_TLB;

type
  TPeer = class
    Handle: Integer;
    Username: WideString;
    ListItem: TListItem;
    UpFileName, DnFileName: String;
    UpFileHandle, UpFileSize, UpFileCount: Integer;
    DnFileHandle, DnFileSize, DnFileCount: Integer;
    UpFileItem, DnFileItem: TListItem;
  end;


  TfMain = class(TForm)
    StatusBar: TStatusBar;
    GroupBox2: TGroupBox;
    btnRemove: TButton;
    lvPeers: TListView;
    GroupBox3: TGroupBox;
    mmLog: TMemo;
    btnClearLog: TButton;
    GroupBox1: TGroupBox;
    btnStart: TButton;
    btnStop: TButton;
    btnSettings: TButton;
    btnUsers: TButton;
    btnMyIP: TButton;
    btnAbout: TButton;
    btnExit: TButton;

    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);

    procedure btnExitClick(Sender: TObject);
    procedure btnAboutClick(Sender: TObject);
    procedure btnMyIPClick(Sender: TObject);
    procedure lvPeersChange(Sender: TObject; Item: TListItem; Change: TItemChange);
    procedure FormShow(Sender: TObject);
    procedure btnRemoveClick(Sender: TObject);
    procedure btnSettingsClick(Sender: TObject);
    procedure btnUsersClick(Sender: TObject);
    procedure btnStartClick(Sender: TObject);
    procedure btnStopClick(Sender: TObject);

  private
    { Private declarations }

    MyPeers: TObjectList;

    procedure LoadForm;
    procedure SaveForm;
    procedure SetSettings;
    procedure LogMsg(aText: String);
    procedure UpdateStatus;
    procedure RemovePeer(aPeer: TPeer);


    //Event handlers
    procedure GoConnectionRequest(Sender: TObject; aHandle: Integer; const aUsername: WideString; var aPassword: WideString; var aAction: Integer);
    procedure GoPeerConnected(Sender: TObject; aHandle: Integer);
    procedure GoPeerRejected(Sender: TObject; aHandle: Integer; aCode: Integer);
    procedure GoPeerDisconnected(Sender: TObject; aHandle: Integer);
  public
    { Public declarations }

    VoiSrv: TBSVoiChatSrvX;
  end;

var
  fMain: TfMain;



implementation

uses uAbout, uSettings, uAdd, uAccess;

{$R *.DFM}



// *** Misc



//Add a trailing slash
function AddSlash(aPath: String): String;
begin
  Result := aPath;
  if RightStr(Result, 1) = '\' then Exit;
  Result := Result + '\';
end;


//Remove the trailing slash
function SlashOff(aPath: String): String;
begin
  Result := aPath;
  if RightStr(Result, 1) <> '\' then Exit;
  Delete(Result, Length(Result), 1);
end;


//Insert a leading slash
function PreSlash(aPath: String): String;
begin
  Result := aPath;
  if LeftStr(Result, 1) = '\' then Exit;
  Result := '\' + Result;
end;


//Check for empty name
function UN(aName: WideString): String;
begin
  Result := aName;
  if Result > '' then Exit;
  Result := 'Guest';
end;



// *** General

procedure TfMain.FormCreate(Sender: TObject);
begin
  LoadForm;
  MyPeers := TObjectList.Create;
  VoiSrv := TBSVoiChatSrvX.Create(Self);

  VoiSrv.OnConnectionRequest := GoConnectionRequest;
  VoiSrv.OnPeerConnected := GoPeerConnected;
  VoiSrv.OnPeerRejected := GoPeerRejected;
  VoiSrv.OnPeerDisconnected := GoPeerDisconnected;
end;







procedure TfMain.FormDestroy(Sender: TObject);
begin
  SaveForm;
  MyPeers.Free;
end;


procedure TfMain.FormShow(Sender: TObject);
begin
  SetSettings;
  btnStart.Click;
end;




//Initializations
procedure TfMain.LoadForm;
var
  Ini: TIniFile;
begin
  try
    Ini := TIniFile.Create(ExtractFilePath(Application.ExeName)+'settings.ini');
  except
    Ini := nil;
  end;
  if Ini = nil then Exit;

  try
    with Ini do
    begin
      Left := ReadInteger('Last', 'Left', Left);
      Top := ReadInteger('Last', 'Top', Top);
    end;
  finally
    Ini.Free;
  end;
end;





procedure TfMain.SaveForm;
var
  Ini: TIniFile;
begin
  try
    Ini := TIniFile.Create(ExtractFilePath(Application.ExeName)+'settings.ini');
  except
    Ini := nil;
  end;
  if Ini = nil then Exit;

  try
    with Ini do
    begin
      WriteInteger('Last', 'Left', Left);
      WriteInteger('Last', 'Top', Top);
    end;
  finally
    Ini.Free;
  end;
end;



//Set the component properties
procedure TfMain.SetSettings;
begin
  VoiSrv.ListeningPort := StrToIntDef(fSettings.edPort.Text, 0);

  VoiSrv.ListeningPort := StrToIntDef(fSettings.edPort.Text, 0);
  VoiSrv.SecurityMode := fSettings.SecurityMode;
  VoiSrv.PublicKey := fSettings.mmPublic.Text;
  VoiSrv.PrivateKey := fSettings.mmPrivate.Text;
  VoiSrv.SecretKey := fSettings.edSecret.Text;
  VoiSrv.Fingerprints := fSettings.lstFingerprints.Items.CommaText;

  VoiSrv.ListeningPort := StrToIntDef(fSettings.edPort.Text, 0);
  VoiSrv.BindAddress := fSettings.edSrvAddr.Text;

  UpdateStatus;
end;



procedure TfMain.LogMsg(aText: String);
begin
  mmLog.Lines.Add(TimeToStr(Now) + ': ' + aText);
end;



//Update the status text
procedure TfMain.UpdateStatus;
begin
  if VoiSrv.Running then
  begin
    StatusBar.Panels[0].Text := ' Started';
    btnStart.Enabled := False;
    btnStop.Enabled := True;
  end
  else
  begin
    StatusBar.Panels[0].Text := ' Stopped';
    btnStart.Enabled := True;
    btnStop.Enabled := False;
  end;

  if lvPeers.Items.Count = 0 then
    StatusBar.Panels[1].Text := ' No active connection'
  else
    StatusBar.Panels[1].Text := ' ' + IntToStr(lvPeers.Items.Count) + ' connection(s)';
end;




procedure TfMain.RemovePeer(aPeer: TPeer);
begin
  if aPeer = nil then Exit;
  lvPeers.Items.Delete(aPeer.ListItem.Index);
  MyPeers.Remove(aPeer);
end;








//*** Hide log box caret



//************  User Events



//Start the server
procedure TfMain.btnStartClick(Sender: TObject);
begin
  if VoiSrv.Start then
    LogMsg('server is started')
  else
    ShowMessage('Cannot start the server!');
  UpdateStatus;
end;


//Stop the server
procedure TfMain.btnStopClick(Sender: TObject);
var
  Pr: TPeer;
  i: Integer;
begin
  VoiSrv.Stop;

  for i := lvPeers.Items.Count-1 downto 0 do
  begin
    Pr := TPeer(lvPeers.Items[i].Data);
    VoiSrv.DisconnectPeer(Pr.Handle);
//    RemovePeer(Pr);
  end;

  UpdateStatus;
  LogMsg('server is stopped');
end;


//Modify the settings
procedure TfMain.btnSettingsClick(Sender: TObject);
begin
  if fSettings.ShowModal <> mrOk then Exit;
  SetSettings;
end;


procedure TfMain.btnUsersClick(Sender: TObject);
begin
  fAccess.Ask;
end;


procedure TfMain.btnMyIPClick(Sender: TObject);
begin
  ShowMessage(VoiSrv.LocalIPList);
end;


procedure TfMain.btnAboutClick(Sender: TObject);
begin
  fAbout.ShowModal;
end;


procedure TfMain.btnExitClick(Sender: TObject);
begin
  Application.Terminate;
end;



procedure TfMain.lvPeersChange(Sender: TObject; Item: TListItem; Change: TItemChange);
begin
  if Change <> ctState then Exit;
  btnRemove.Enabled := lvPeers.SelCount = 1;
  UpdateStatus;
end;




//Remove a peer connection
procedure TfMain.btnRemoveClick(Sender: TObject);
var
  Pr: TPeer;
begin
  if lvPeers.Selected = nil then Exit;
  Pr := TPeer(lvPeers.Selected.Data);
  VoiSrv.DisconnectPeer(Pr.Handle);
//  RemovePeer(Pr);
end;







// *** Peer events



//A request for a session
procedure TfMain.GoConnectionRequest(Sender: TObject; aHandle: Integer; const aUsername: WideString; var aPassword: WideString; var aAction: Integer);
begin
  aAction := 1;
  aPassword := fAccess.GetPassword(aUsername);
end;




//A new peer is just connected
procedure TfMain.GoPeerConnected(Sender: TObject; aHandle: Integer);
var
  LI: TListItem;
  Pr: TPeer;
begin
  Pr := TPeer.Create;
  MyPeers.Add(Pr);
  Pr.Handle := aHandle;

  LI := lvPeers.Items.Add;
  LI.Data := Pointer(Pr);
  Pr.ListItem := LI;

  LI.Caption := UN(VoiSrv.GetPeerName(aHandle));
  LI.Subitems.Add(VoiSrv.GetPeerAddress(aHandle));
  LI.Subitems.Add(IntToStr(VoiSrv.GetPeerPort(aHandle)));
  LI.Subitems.Add(TimeToStr(Now));
  LI.Subitems.Add('Connected');
  VoiSrv.SetMoniker(aHandle, Integer(Pr));
  UpdateStatus;
  LogMsg('New peer at ' + LI.SubItems[0] + ':' + LI.SubItems[1]);
end;


//A connection is rejected
procedure TfMain.GoPeerRejected(Sender: TObject; aHandle: Integer; aCode: Integer);
begin
  LogMsg('Rejected peer from ' + VoiSrv.GetPeerAddress(aHandle) + ':' + IntToStr(VoiSrv.GetPeerPort(aHandle)) + '   Error: ' + bsErrorDescription(aCode));
end;



//A connection is broken
procedure TfMain.GoPeerDisconnected(Sender: TObject; aHandle: Integer);
var
  Pr: TPeer;
begin
  Pr := TPeer(VoiSrv.GetMoniker(aHandle));
  if Pr = nil then Exit;
  LogMsg('Disconnected peer ' + Pr.Username + ' ' + VoiSrv.GetPeerAddress(aHandle) + ':' + IntToStr(VoiSrv.GetPeerPort(aHandle)));
  RemovePeer(Pr);
end;




end.
© BigSpeed Computing Inc. - Mastering algorithms