{
// Version:5.6.3 Build:1091 Date:1/31/00 //
////////////////////////////////////////////////////////////////////////////
// //
// Copyright ?1997-1999, NetMasters, L.L.C - All rights reserved worldwide. //
// Portions may be Copyright ?Borland International, Inc. //
// //
// Unit Name: NMUDP //
// //
// DESCRIPTION:Internet UDP Component //
// + Aug-9-98 Version 4.1 -- KNA //
// //
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY //
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE //
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR //
// PURPOSE. //
// //
////////////////////////////////////////////////////////////////////////////
}
// Revision History
// 01 04 00 - KNA - Non ASYNC messages passed on
// 07 12 99 - KNA - Resolve Host converted to Wait
// 07 02 98 - KNA - Port of sender available
// 01 27 98 - KNA - Final release Ver 4.00 VCLS
//
{*******************************************************************************************
Destroy Power Socket
********************************************************************************************}
destructor TNMUDP.Destroy;
begin
{cancel;
}
freemem(RemoteHostS, MAXGETHOSTSTRUCT);
{Free memory for fetching Host Entity}
DeAllocateHWnd(FSocketWindow);
{Release window handle for Winsock messages}
CloseHandle(EventHandle);
WSACleanUp;
{Clean up Winsock}
inherited destroy;
{Do inherited destroy method}
end;
{_ destructor TNMUDP.Destroy;
_}
procedure TNMUDP.SetLocalPort(NewLocalPort: integer);
begin
if ThisSocket <> 0 then
closesocket(ThisSocket);
WSAcleanup;
if WSAStartUp($0101, MyWSADATA) = 0 then
try
ThisSocket := Socket(AF_INET, SOCK_DGRAM, 0);
{Get a new socket}
if ThisSocket = TSocket(INVALID_SOCKET) then
ErrorManager(WSAEWOULDBLOCK);
{If error handle error}
except
WSACleanup;
{If error Cleanup}
raise;
{Pass exception to calling function}
end {_ try _}
else
{_ NOT if WSAStartUp($0101, MyWSADATA) = 0 then
_}
ErrorManager(WSAEWOULDBLOCK);
{Handle Statrtup error}
FLocalPort := NewLocalPort;
Loaded;
end;
procedure TNMUDP.Loaded;
var
buf: array[0..17] of char;
begin
if not (csDesigning in ComponentState) then
begin
RemoteAddress2.sin_addr.S_addr := Inet_Addr(strpcopy(buf, '0.0.0.0'));
RemoteAddress2.sin_family := AF_INET;
{Family = Internet address}
RemoteAddress2.sin_port := htons(FLocalPort);
{Set port to given port}
wait_flag := FALSE;
{Set flag to wait}
{Bind Socket to given address}
WinSock.bind(ThisSocket, RemoteAddress2, SizeOf(RemoteAddress2));
{Direct reply message to WM_WAITFORRESPONSE handler}
WSAAsyncselect(ThisSocket, FSocketWindow, WM_ASYNCHRONOUSPROCESS, FD_READ);
end;
{_ if not (csDesigning in ComponentState) then
_}
end;
{_ procedure TNMUDP.Loaded;
_}
{*******************************************************************************************
Resolve IP Address of Remote Host
********************************************************************************************}
procedure TNMUDP.ResolveRemoteHost;
var
BUF: array[0..127] of char;
CTry: integer;
Handled: boolean;
begin
remoteaddress.sin_addr.S_addr := Inet_Addr(strpcopy(buf, FRemoteHost));
if remoteaddress.sin_addr.S_addr = SOCKET_ERROR then
{If given name not an IP address already}
begin
CTry := 0;
repeat
Wait_Flag := FALSE;
{Reset flag indicating wait over}
{Resolve IP address}
wsaasyncgethostbyname(FSocketWindow, WM_ASYNCHRONOUSPROCESS, Buf, PChar(remotehostS), MAXGETHOSTSTRUCT);
repeat
Wait;
until Wait_Flag or Canceled;
{Till host name resolved, Timed out or cancelled}
{Handle errors}
if Canceled then
raise UDPSockError.create(Cons_Msg_Lkp);
if Succeed = FALSE then
begin
if CTry < 1 then
begin
CTry := CTry + 1;
Handled := FALSE;
if assigned(FOnInvalidHost) then
FOnInvalidHost(Handled);
if not handled then
UDPSockError.create(Cons_Msg_Lkp);
end {_ if CTry < 1 then
_}
else
{_ NOT if CTry < 1 then
_} raise UDPSockError.create(Cons_Msg_Lkp);
end {_ if Succeed = FALSE then
_}
else
{_ NOT if Succeed = FALSE then
_}
{Fill up remote host information with retreived results}
with RemoteAddress.sin_addr.S_un_bdo
{_ with RemoteAddress.sin_addr.S_un_bdo
_}
until Succeed = true;
end;
{_ if remoteaddress.sin_addr.S_addr = SOCKET_ERROR then
_}
end;
{_ procedure TNMUDP.ResolveRemoteHost;
_}
procedure TNMUDP.SendStream(DataStream: TStream);
var Ctry, i: integer;
BUf: array[0..DataPackSize] of char;
//////lsyx
Handled: boolean;
begin
CTry := 0;
while DataStream.size = 0do
if CTry > 0 then
raise Exception.create(Cons_Msg_InvStrm)
else
{_ NOT if CTry > 0 then
raise Exception.create(Cons_Msg_InvStrm) _}
if not assigned(FOnStreamInvalid) then
raise Exception.create(Cons_Msg_InvStrm)
else
{_ NOT if not assigned(FOnStreamInvalid) then
raise Exception.create(Cons_Msg_InvStrm) _}
begin
Handled := FALSE;
FOnStreamInvalid(Handled, DataStream);
if not Handled then
raise Exception.create(Cons_Msg_InvStrm)
else
{_ NOT if not Handled then
raise Exception.create(Cons_Msg_InvStrm) _} CTry := CTry + 1;
end;
{_ NOT if not assigned(FOnStreamInvalid) then
raise Exception.create(Cons_Msg_InvStrm) _}
Canceled := FALSE;
{Turn Canceled off}
ResolveRemoteHost;
{Resolve the IP address of remote host}
if RemoteAddress.sin_addr.S_addr = 0 then
raise UDPSockError.create(Cons_Err_Addr);
{If Resolving failed raise exception}
StatusMessage(Status_Basic, Cons_Msg_Data);
{Inform status}
RemoteAddress.sin_family := AF_INET;
{Make connected true}
{$R-}
RemoteAddress.sin_port := htons(FRemotePort);
{If no proxy get port from Port property}
{$R+}
i := SizeOf(RemoteAddress);
{i := size of remoteaddress structure}
{Connect to remote host}
DataStream.position := 0;
DataStream.ReadBuffer(Buf, DataStream.size);
WinSock.SendTo(ThisSocket, Buf, DataStream.size, 0, RemoteAddress, i);
if assigned(FOnDataSend) then
FOnDataSend(self);
end;
procedure TNMUDP.SendBuffer(Buff: array of char;
length: integer);
var Ctry, i: integer;
Handled: boolean;
begin
CTry := 0;
while length = 0do
if CTry > 0 then
raise Exception.create(Cons_Err_Buffer)
else
{_ NOT if CTry > 0 then
raise Exception.create(Cons_Err_Buffer) _}
if not assigned(FOnBufferInvalid) then
raise Exception.create(Cons_Err_Buffer)
else
{_ NOT if not assigned(FOnBufferInvalid) then
raise Exception.create(Cons_Err_Buffer) _}
begin
Handled := FALSE;
FOnBufferInvalid(Handled, Buff, length);
if not Handled then
raise Exception.create(Cons_Err_Buffer)
else
{_ NOT if not Handled then
raise Exception.create(Cons_Err_Buffer) _} CTry := CTry + 1;
end;
{_ NOT if not assigned(FOnBufferInvalid) then
raise Exception.create(Cons_Err_Buffer) _}
Canceled := FALSE;
{Turn Canceled off}
ResolveRemoteHost;
{Resolve the IP address of remote host}
if RemoteAddress.sin_addr.S_addr = 0 then
raise UDPSockError.create(Cons_Err_Addr);
{If Resolving failed raise exception}
StatusMessage(Status_Basic, Cons_Msg_Data);
{Inform status}
RemoteAddress.sin_family := AF_INET;
{Make connected true}
{$R-}
RemoteAddress.sin_port := htons(FRemotePort);
{If no proxy get port from Port property}
{$R+}
i := SizeOf(RemoteAddress);
{i := size of remoteaddress structure}
WinSock.SendTo(ThisSocket, Buff, length, 0, RemoteAddress, i);
if assigned(FOnDataSend) then
FOnDataSend(self);
end;
{_ procedure TNMUDP.SendBuffer(Buff: array of char;
length: integer);
_}
{*******************************************************************************************
Handle Power socket error
********************************************************************************************}
function TNMUDP.ErrorManager(ignore: word): string;
var
slasterror: string;
begin
StatusMessage(STATUS_TRACE, Cons_Msg_Echk);
{Report Status}
FLastErrorno := wsagetlasterror;
{Set last error}
if (FLastErrorno and ignore) <> ignore then
{If the error is not the error to be ignored}
begin
slasterror := SocketErrorStr(FLastErrorno);
{Get the description string for error}
if assigned(fonerrorevent) then
{_ if (FLastErrorno and ignore) <> ignore then
_}
result := slasterror;
{return error string}
end;
{_ function TNMUDP.ErrorManager(ignore: word): string;
_}
{*******************************************************************************************
Return Error Message Corresponding To Error number
********************************************************************************************}
function TNMUDP.SocketErrorStr(ErrNo: word): string;
begin
if ErrNo <> 0 then
{If error exits}
begin
(*for x := 0 to 50do
{Get error string}
if winsockmessage[x].errorcode = errno then
Result := inttostr( winsockmessage[x].errorcode ) + ':' + winsockmessage[x].text;
*)
if Result = '' then
{If not found say unknown error}
Result := Cons_Msg_Eno + IntToStr(ErrNo);
end;
{_ if ErrNo <> 0 then
_}
StatusMessage(Status_DEBUG, Cons_Msg_ELkp + result);
{Status message}
end;
{_ function TNMUDP.SocketErrorStr(ErrNo: word): string;
_}
{*******************************************************************************************
Output a Status message: depends on current Reporting Level
********************************************************************************************}
procedure TNMUDP.StatusMessage(Level: byte;
value: string);
begin
if level <= FReportLevel then
{If level of error less than present report level}
begin
_status := value;
{Set status to vale of error}
if assigned(FOnStatus) then
FOnStatus(self, _status);
{If Status handler present excecute it}
end;