366 lines
9.6 KiB
ObjectPascal
366 lines
9.6 KiB
ObjectPascal
{******************************************************************************}
|
|
{ UNIFIED INTERBASE (UIB) }
|
|
{ }
|
|
{ Project JEDI Code Library (JCL) }
|
|
{ }
|
|
{ The contents of this file are subject to the Mozilla Public License Version }
|
|
{ 1.0 (the "License"); you may not use this file except in compliance with the }
|
|
{ License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ }
|
|
{ }
|
|
{ Software distributed under the License is distributed on an "AS IS" basis, }
|
|
{ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for }
|
|
{ the specific language governing rights and limitations under the License. }
|
|
{ }
|
|
{ The Original Code is JvUIBLib.pas. }
|
|
{ }
|
|
{ The Initial Developer of the Original Code is documented in the accompanying }
|
|
{ help file JCL.chm. Portions created by these individuals are Copyright (C) }
|
|
{ 2000 of these individuals. }
|
|
{ }
|
|
{ ORB Server }
|
|
{ }
|
|
{ Unit owner: Henri Gourvest }
|
|
{ Last modified: Mar 16, 2003 }
|
|
{ }
|
|
{******************************************************************************}
|
|
|
|
unit JvUIBSrv;
|
|
|
|
{$I jvcl.inc}
|
|
{$I jvuib.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF USEJVCL}
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
{$ENDIF USEJVCL}
|
|
Classes, IdTCPServer, SysUtils,
|
|
JvUIBObj, JvUIBConst;
|
|
|
|
type
|
|
|
|
TJvUIBPeerThread = class;
|
|
TJvUIBObjectFactory = class;
|
|
|
|
TJvUIBServer = class(TObject)
|
|
private
|
|
FTCPServer: TidTCPServer;
|
|
FFactoryList: TJvUIBObjectFactory;
|
|
FLock: TMultiReadExclusiveWriteSynchronizer;
|
|
function GetActive: Boolean;
|
|
procedure SetActive(const Value: Boolean);
|
|
function GetDefaultPort: Integer;
|
|
procedure SetDefaultPort(const Value: Integer);
|
|
procedure AddObjectFactory(Factory: TJvUIBObjectFactory);
|
|
procedure RemoveObjectFactory(Factory: TJvUIBObjectFactory);
|
|
procedure FreeFactories;
|
|
function GetFactoryFromClassID(const ClassID: TGUID): TJvUIBObjectFactory;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Start;
|
|
procedure Stop;
|
|
published
|
|
property Active: Boolean read GetActive write SetActive default False;
|
|
property DefaultPort: Integer read GetDefaultPort write SetDefaultPort;
|
|
end;
|
|
|
|
TJvUIBObjectFactory = class(TObject)
|
|
private
|
|
FNext: TJvUIBObjectFactory;
|
|
FClassID: TGUID;
|
|
FNetClass: TJvUIBStubClass;
|
|
public
|
|
constructor Create(Server: TJvUIBServer; NetClass: TJvUIBStubClass;
|
|
const ClassID: TGUID);
|
|
function CreateInstance(Connection: TIdTCPServerConnection): TJvUIBStub;
|
|
destructor Destroy; override;
|
|
property ClassID: TGUID read FClassID;
|
|
property JvUIBClass: TJvUIBStubClass read FNetClass;
|
|
end;
|
|
|
|
TJvUIBPeerThread = class(TIdPeerThread)
|
|
protected
|
|
procedure Run; override;
|
|
procedure CleanUp; override;
|
|
procedure GetClassObject;
|
|
procedure InvokeMethod;
|
|
end;
|
|
|
|
var
|
|
JvUIBServer: TJvUIBServer = nil;
|
|
|
|
{$IFDEF USEJVCL}
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvUIBSrv.pas $';
|
|
Revision: '$Revision: 10612 $';
|
|
Date: '$Date: 2006-05-19 21:04:09 +0200 (ven., 19 mai 2006) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
{$ENDIF USEJVCL}
|
|
|
|
implementation
|
|
|
|
uses
|
|
IdThread, IdException, IdStackConsts, IdTCPConnection;
|
|
|
|
//=== { TJvUIBServer } =======================================================
|
|
|
|
constructor TJvUIBServer.Create;
|
|
begin
|
|
inherited Create;
|
|
FLock := TMultiReadExclusiveWriteSynchronizer.Create;
|
|
FTCPServer := TidTCPServer.Create(nil);
|
|
FTCPServer.ThreadClass := TJvUIBPeerThread;
|
|
end;
|
|
|
|
destructor TJvUIBServer.Destroy;
|
|
begin
|
|
FTCPServer.Free;
|
|
FreeFactories;
|
|
FLock.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJvUIBServer.GetActive: Boolean;
|
|
begin
|
|
Result := FTCPServer.Active;
|
|
end;
|
|
|
|
function TJvUIBServer.GetDefaultPort: Integer;
|
|
begin
|
|
Result := FTCPServer.DefaultPort;
|
|
end;
|
|
|
|
procedure TJvUIBServer.SetActive(const Value: Boolean);
|
|
begin
|
|
FTCPServer.Active := Value;
|
|
end;
|
|
|
|
procedure TJvUIBServer.SetDefaultPort(const Value: Integer);
|
|
begin
|
|
FTCPServer.DefaultPort := Value;
|
|
end;
|
|
|
|
procedure TJvUIBServer.Start;
|
|
begin
|
|
Active := True;
|
|
end;
|
|
|
|
procedure TJvUIBServer.Stop;
|
|
begin
|
|
Active := False;
|
|
end;
|
|
|
|
procedure TJvUIBServer.AddObjectFactory(Factory: TJvUIBObjectFactory);
|
|
begin
|
|
FLock.BeginWrite;
|
|
try
|
|
Factory.FNext := FFactoryList;
|
|
FFactoryList := Factory;
|
|
finally
|
|
FLock.EndWrite;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvUIBServer.FreeFactories;
|
|
var
|
|
Factory, Next: TJvUIBObjectFactory;
|
|
begin
|
|
FLock.BeginWrite;
|
|
try
|
|
Factory := FFactoryList;
|
|
while Factory <> nil do
|
|
begin
|
|
Next := Factory.FNext;
|
|
Factory.Free;
|
|
Factory := Next;
|
|
end;
|
|
finally
|
|
FLock.EndWrite;
|
|
end;
|
|
end;
|
|
|
|
function TJvUIBServer.GetFactoryFromClassID(const ClassID: TGUID): TJvUIBObjectFactory;
|
|
begin
|
|
FLock.BeginRead;
|
|
try
|
|
Result := FFactoryList;
|
|
while Result <> nil do
|
|
begin
|
|
{$IFDEF DELPHI6_UP}
|
|
if IsEqualGUID(Result.ClassID, ClassID) then
|
|
{$ELSE}
|
|
if CompareMem(@Result.ClassID, @ClassID, SizeOf(TGUID)) then
|
|
{$ENDIF DELPHI6_UP}
|
|
Exit;
|
|
Result := Result.FNext;
|
|
end;
|
|
finally
|
|
FLock.EndRead;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvUIBServer.RemoveObjectFactory(Factory: TJvUIBObjectFactory);
|
|
var
|
|
F, P: TJvUIBObjectFactory;
|
|
begin
|
|
FLock.BeginWrite;
|
|
try
|
|
P := nil;
|
|
F := FFactoryList;
|
|
while F <> nil do
|
|
begin
|
|
if F = Factory then
|
|
begin
|
|
if P <> nil then
|
|
P.FNext := F.FNext
|
|
else
|
|
FFactoryList := F.FNext;
|
|
Exit;
|
|
end;
|
|
P := F;
|
|
F := F.FNext;
|
|
end;
|
|
finally
|
|
FLock.EndWrite;
|
|
end;
|
|
end;
|
|
|
|
//=== { TJvUIBObjectFactory } ================================================
|
|
|
|
constructor TJvUIBObjectFactory.Create(Server: TJvUIBServer;
|
|
NetClass: TJvUIBStubClass; const ClassID: TGUID);
|
|
begin
|
|
Assert(Assigned(Server));
|
|
FNetClass := NetClass;
|
|
FClassID := ClassID;
|
|
JvUIBServer.AddObjectFactory(Self);
|
|
end;
|
|
|
|
function TJvUIBObjectFactory.CreateInstance(Connection: TIdTCPServerConnection): TJvUIBStub;
|
|
begin
|
|
Result := FNetClass.Create(Connection);
|
|
IUnknown(Result)._AddRef;
|
|
end;
|
|
|
|
destructor TJvUIBObjectFactory.Destroy;
|
|
begin
|
|
JvUIBServer.RemoveObjectFactory(Self);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
//=== { TJvUIBPeerThread } ===================================================
|
|
|
|
procedure TJvUIBPeerThread.CleanUp;
|
|
begin
|
|
if FData <> nil then
|
|
begin
|
|
IUnknown(TJvUIBStub(FData))._Release;
|
|
FData := nil;
|
|
end;
|
|
inherited CleanUp;
|
|
end;
|
|
|
|
procedure TJvUIBPeerThread.GetClassObject;
|
|
var
|
|
GUID: TGUID;
|
|
Factory: TJvUIBObjectFactory;
|
|
Reslt: HRESULT;
|
|
begin
|
|
Reslt := S_OK;
|
|
with FConnection do
|
|
begin
|
|
ReadBuffer(GUID, SizeOf(TGUID));
|
|
Factory := JvUIBServer.GetFactoryFromClassID(GUID);
|
|
if Factory <> nil then
|
|
begin
|
|
if FData <> nil then
|
|
begin
|
|
IUnknown(TJvUIBStub(FData))._Release;
|
|
FData := nil;
|
|
end;
|
|
FData := Factory.CreateInstance(FConnection);
|
|
OpenWriteBuffer;
|
|
Connection.WriteBuffer(Reslt, SizeOf(HRESULT));
|
|
CloseWriteBuffer;
|
|
end
|
|
else
|
|
begin
|
|
Reslt := S_FALSE;
|
|
OpenWriteBuffer;
|
|
Connection.WriteBuffer(Reslt, SizeOf(HRESULT));
|
|
CloseWriteBuffer;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TJvUIBPeerThread.InvokeMethod;
|
|
var
|
|
MethodID: Integer;
|
|
begin
|
|
if FData <> nil then
|
|
begin
|
|
FConnection.ReadBuffer(MethodID, SizeOf(Integer));
|
|
TJvUIBStub(FData).Invoke(MethodID);
|
|
end
|
|
else
|
|
begin
|
|
// TODO Disconnect !!!
|
|
end;
|
|
end;
|
|
|
|
procedure TJvUIBPeerThread.Run;
|
|
var
|
|
Command: TServerCommand;
|
|
begin
|
|
try
|
|
while Connection.Connected do
|
|
begin
|
|
FConnection.ReadBuffer(Command, SizeOf(TServerCommand));
|
|
case Command of
|
|
scGetClassObject:
|
|
GetClassObject;
|
|
scInvokeMethod:
|
|
InvokeMethod;
|
|
else
|
|
// TODO Disconnect
|
|
end;
|
|
end;
|
|
except
|
|
on E: EIdSocketError do begin
|
|
case E.LastError of
|
|
Id_WSAECONNABORTED, Id_WSAECONNRESET:
|
|
Connection.Disconnect;
|
|
end;
|
|
end;
|
|
end;
|
|
if not Connection.Connected then
|
|
Stop;
|
|
end;
|
|
|
|
initialization
|
|
{$IFDEF USEJVCL}
|
|
{$IFDEF UNITVERSIONING}
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
{$ENDIF UNITVERSIONING}
|
|
{$ENDIF USEJVCL}
|
|
JvUIBServer := TJvUIBServer.Create;
|
|
|
|
finalization
|
|
JvUIBServer.Free;
|
|
JvUIBServer := nil;
|
|
{$IFDEF USEJVCL}
|
|
{$IFDEF UNITVERSIONING}
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
{$ENDIF USEJVCL}
|
|
|
|
end.
|