176 lines
5.2 KiB
Plaintext
176 lines
5.2 KiB
Plaintext
{$X+,V-,B-}
|
|
program M_PEP; { Master / Sender }
|
|
|
|
{ Testprogram for the nwPEP unit / NwTP 0.6 API. (c) 1993,1995, R.Spronk }
|
|
|
|
{ Sents a single packet, waits for acknowledgement }
|
|
|
|
uses crt,nwMisc,nwBindry,nwConn,nwIPX,nwPEP;
|
|
|
|
CONST IOSocket=$5678; { socket to transmit/receive on }
|
|
|
|
Var ListenECB :Tecb; { ECB and header, to listen for acknowledgement }
|
|
ListenPepHdr :TpepHeader;
|
|
|
|
SendECB :Tecb; { ECB and header, used to send the data }
|
|
SendPepHdr :TpepHeader;
|
|
|
|
socket :word;
|
|
|
|
buf :array[1..546] of byte; { buffer for data to be sent }
|
|
|
|
AckReceived :boolean; { set to true within the ListenForAckESR }
|
|
|
|
SendTransId :LongInt; { transactionID. This uniquely identifies
|
|
the packet. The slave/receiver has to
|
|
reply with the same transactionID in the
|
|
header of the acknowledgement. Only if
|
|
this number is the same as the transactioID
|
|
of the sent packet, the pavket is considered
|
|
successfully delivered. }
|
|
|
|
NewStack:array[1..1024] of word; { !! used by ESR }
|
|
StackBottom:word; { !! used by ESR }
|
|
|
|
|
|
{$F+}
|
|
Procedure ListenForAckHandler(Var p:TPecb);
|
|
{ Interrupts are turned off -and should remain turned off- }
|
|
begin
|
|
IF (ListenECB.CompletionCode<>0) { packet must be suucessfully received.. }
|
|
or (ListenPepHdr.IPXhdr.packetType<>PEP_PACKET_TYPE) { of type PEP.. }
|
|
or (ListenPepHdr.ClientType<>$EA) { of client type $EA }
|
|
or (ListenPepHdr.TransactionID<>SendTransId) { with a correct clientID (of the packet the master sent) }
|
|
then IPXListenForPacket(ListenECB) { Invalid packet => listen again }
|
|
else AckReceived:=true; { valid packet => ACK received ! }
|
|
end;
|
|
{$F-}
|
|
|
|
{$F+}
|
|
Procedure ListenForAckESR; assembler;
|
|
asm { ES:SI are the only valid registers when entering this procedure ! }
|
|
{ interrupts are turned off -and should remain turned off- }
|
|
mov dx, seg stackbottom
|
|
mov ds, dx
|
|
|
|
mov dx,ss { setup of a new local stack }
|
|
mov bx,sp { ss:sp copied to dx:bx}
|
|
mov ax,ds
|
|
mov ss,ax
|
|
mov sp,offset stackbottom
|
|
push dx { push old ss:sp on new stack }
|
|
push bx
|
|
|
|
push es { push es:si on stack as local vars }
|
|
push si
|
|
mov di,sp
|
|
|
|
push ss { push address of local ptr on stack }
|
|
push di
|
|
CALL ListenForAckHandler
|
|
|
|
add sp,4 { skip stack ptr-copy }
|
|
pop bx { restore ss:sp from new stack }
|
|
pop dx
|
|
mov sp,bx
|
|
mov ss,dx
|
|
end;
|
|
{$F-}
|
|
|
|
|
|
Var dest:TinternetworkAddress;
|
|
ticks,ticks2:word;
|
|
retries :word;
|
|
|
|
Uname:string;
|
|
NbrOfConn:byte;
|
|
connList:TconnectionList;
|
|
|
|
begin
|
|
If paramcount<>1
|
|
then begin
|
|
writeln('Usage: M_PEP <username>');
|
|
writeln('-a test pep packet will be sent to the workstation of this user.');
|
|
writeln('-run S_PEP on that workstation to receive the packet.');
|
|
halt(1);
|
|
end;
|
|
Uname:=ParamStr(1);
|
|
UpString(Uname);
|
|
NbrOfConn:=0;
|
|
IF (NOT GetObjectConnectionNumbers(Uname,OT_USER,NbrOfConn,connList))
|
|
or (NbrOfConn=0)
|
|
then begin
|
|
writeln('Error: can''t locate user ',Uname);
|
|
halt(1);
|
|
end;
|
|
IF NbrOfConn>1
|
|
then begin
|
|
writeln('The specified user has multiple connections.');
|
|
writeln('This demonstation program doesn''t support multiple connections.');
|
|
halt(1);
|
|
end;
|
|
IF NOT GetInternetAddress(connList[1],dest)
|
|
then begin
|
|
writeln('Error: can''t find the address of user ',Uname);
|
|
halt(1);
|
|
end;
|
|
|
|
|
|
IF NOT IpxInitialize
|
|
then begin
|
|
writeln('Ipx needs to be installed.');
|
|
halt(1);
|
|
end;
|
|
socket:=IOSocket;
|
|
IF NOT IPXopenSocket(Socket,SHORT_LIVED_SOCKET)
|
|
then begin
|
|
writeln('IPXopenSocket returned error# ',nwIPX.result);
|
|
halt(1);
|
|
end;
|
|
|
|
|
|
{ setup listening for ack }
|
|
AckReceived:=False;
|
|
FillChar(buf,546,#0);
|
|
{ Setup ECB and IPX header }
|
|
PEPsetupListenECB(Addr(ListenForAckESR),IOsocket,@buf,546,
|
|
ListenPepHdr,ListenECB);
|
|
IPXListenForPacket(ListenECB);
|
|
|
|
{ send packet }
|
|
|
|
dest.socket:=IOsocket;
|
|
buf[1]:=ord('s');buf[2]:=ord('m');
|
|
PEPsetupSendECB(NIL,IOsocket,dest,@buf[1],2,
|
|
SendPepHdr,SendECB);
|
|
SendTransID:=1;
|
|
SendPepHdr.TransactionId:=SendTransId;
|
|
SendPepHdr.ClientType:=$EA;
|
|
IPXsendPacket(SendECB);
|
|
writeln('Packet was sent.');
|
|
while sendECB.InuseFlag<>0 do IPXrelinquishControl;
|
|
IPXGetIntervalMarker(ticks);
|
|
|
|
{ wait for acknowledgement or timeout }
|
|
retries:=0;
|
|
|
|
REPEAT
|
|
IPXrelinquishcontrol;
|
|
IPXGetIntervalMarker(ticks2);
|
|
if (ticks2-ticks)>4
|
|
then begin
|
|
inc(retries);
|
|
writeln('Timeout: resending');
|
|
IPXsendPacket(SendECB);
|
|
while sendECB.InuseFlag<>0 do IPXrelinquishControl;
|
|
IPXGetIntervalMarker(ticks);
|
|
end;
|
|
UNTIL AckReceived or Keypressed or (retries>50);
|
|
|
|
if AckReceived
|
|
then writeln('Ack was received.');
|
|
|
|
IF NOT IPXcloseSocket(IOsocket)
|
|
then writeln('IPXcloseSocket returned error# ',nwIPX.result);
|
|
|
|
end. |