{Greg Miller, C490 Networks Seminar. Final Project. 7:30p - 8:45p Mon, Wed. Spring 1993.} {This program looks for a node running RECEIVE.PAS on the same network, and tranfers a file, specified from the command line, to the node running RECEIVE.PAS.} {This program has a bug. After the first packet is sent both programs SEND and RECEIVE usually lock up. Sometimes they don't, but this is still a good example of how to use asynchronous IPXsend and IPXreceive.} program send; uses IPX; const receive_socket = $7777; {These two sockets can be any numbers not reserved by Novell.} send_socket = $6666; max_time = 99999999; {Timeout set to infinity for debugging} packet_size = 1; {The packet size may be set to any size which doesn't exceed the frame size on the physical network in question} null = ptr(0,0); var user_network_number:networkNumber; user_node:NetworkNode; done:boolean; last_packet:boolean; ready_to_finish:boolean; timer:word; send_file:file of char; receive_ecb:ecb; receive_header:IPXHeader; receive_message:string; send_ecb:ecb; send_header:IPXHeader; send_message:string; packet_count:integer; hr,mn,start,s100:word; {Simplifies the asm STI instruction call} procedure sti; begin asm sti end; end; {Halts the program if an error occurs} procedure abort(error:string); begin writeln; writeln(error); halt(0); end; {opens sockets for sending and receiving packets} procedure open_user_sockets_and_file; begin IPXCloseSocket(receive_socket); IPXCloseSocket(send_socket); if IPXOpenSocket(receive_socket) <> 0 then abort('Error opening socket') else if IPXOpenSocket(send_socket) <> 0 then abort('Error opening socket') else begin assign(send_file,paramSTR(1)); reset(send_file); end; end; {Finds the physical address of the node running RECEIVE} procedure establish_connection_to_remote_user; var connection:integer; procedure add255(var num:NetworkNumber;var node:networkNode); var x:integer; begin for x:=0 to 3 do num[x]:=0; {Net Number 0000 = Current network} for x:=0 to 5 do node[x] := 255; {Addrs FFFFFF = All nodes} end; procedure fix_address(var num:networkNumber; var node:networkNode; address:IPXHeader); var x:integer; begin for x:=0 to 3 do num[x] := address.Source_network_number[x]; for x:=0 to 5 do node[x] := address.Source_network_node[x]; end; begin receive_message := ''; IPXReceive(receive_ecb,receive_header,receive_socket,@receive_message, sizeof(receive_message),null); while receive_message <> 'Looking for Greg Millers host' do begin write(Receive_Message); end; fix_address(User_network_number,User_node,receive_header); send_message := 'Greg Millers host hears you'; for connection := 1 to 10 do IPXSend(User_network_number, User_node, receive_socket, @send_message, length(send_message)+1,send_ecb,send_header,send_socket,null); {Debugging code. user_network_number[0]:=9; user_network_number[1]:=90; user_network_number[2]:=0; user_network_number[3]:=3; User_node[0]:=0; User_node[1]:=1; User_node[2]:=200; User_node[3]:=80; User_node[4]:=56; User_node[5]:=159; { connection := Get1stConnectionNumber(ParamSTR(1)); if Connection = 0 then abort('User not found') else If getInternetAddress(connection, user_network_number, user_node) <> 0 then abort('Network error');} end; {Ensures that both nodes begin the file transfer at the same time} procedure get_ready_to_begin_file_send; const null = ptr(0,0); var receive_ecb:ecb; receive_header:IPXHeader; receive_Message:string; segin_file_send; const null = ptr(0,0); var receive_ecb:ecb; receive_header:IPXHeader; receive_Message:string; send_ecb:ecb; send_header:IPXHeader; send_message:string; begin receive_message := ''; IPXReceive(receive_ecb,receive_header,receive_socket,@receive_message, sizeof(receive_message),null); send_message := 'GO!'; repeat begin IPXSend(User_network_number, User_node, receive_socket, @send_message, length(send_message)+1,send_ecb,send_header,send_socket,null); end; until (receive_ecb.Completion_code <> 0) or (receive_ecb.in_use <> 0) or (receive_message <> 'GO!') end; {Not used} {$F+} procedure send_service_routine;{$F-} interrupt; begin asm pop bp pop es pop ds pop di pop si {This code must bypass the normal IRET Pascal would generate pop dx here. If the function isn't decalred as INTERRUPT, a run-time pop cx error occurs. This code appears throughout other procedures also} pop bx pop ax retf end; end; {reads information from file and surrounds it in an IPX packet} procedure compose_packet; var input:char; bytes:integer; begin if eof(send_file) then last_packet:=true else begin send_message:=''; bytes := 0; while (not eof(send_file)) and (bytes < packet_size) do begin read(send_file,input); send_message := send_message + input; inc(bytes); end; end; end; {actually sends the packet and sets SEND_SERVICE_ROUTINE to be called when the packet is actually sent} procedure send_packet; begin inc(packet_count); IPXSend(user_network_number,User_node,Receive_socket,@send_message, length(send_message)+1,send_ecb,send_header,send_socket, @send_service_routine); end; {Processes acknowledgments. Any packet on RECEIVE_SOCKET is said to be an ACK, regardless of which node it really came from, and regardless of its content} {$F+} procedure receive_service_routine;{$F-} {A receive indicates an acknowledgement} interrupt; begin sti; compose_packet; send_packet; if last_packet then done := true else begin if last_packet then ready_to_finish := true; IPXReceive(receive_ecb,receive_header,receive_socket, @receive_message,sizeof(receive_message), @receive_service_routine); {getTime(hr,mn,start,s100);} start := 0; end; asm pop bp pop es pop ds pop di pop si pop dx pop cx pop bx pop ax retf end; end; procedure go_send_file; begin IPXReceive(receive_ecb,receive_header,receive_socket, @receive_message,sizeof(receive_message), @receive_service_routine); done:=false; last_packet:=false; ready_to_finish:=false; compose_packet; send_packet; write(send_message); while not done do begin {gotoXY(1,1); write('Packet count:',packet_count);} {getTime(hr,mn,timer,s100);} inc(start); write(send_message); if start > max_time then begin writeln('Time out'); send_packet; start := 0; end; end; end; begin if not IPXInstalled then writeln('IPX not installed'); writeln('Opening files'); open_user_sockets_and_file; writeln('Connecting to remote user'); establish_connection_to_remote_user; writeln('Getting ready to send'); Get_ready_to_begin_file_send; Writeln('Sending file'); go_send_file; writeln('Done'); close(send_file) end. tting ready to send'); Get_ready_to_begin_file_send; Writeln('Sending file'); go_send_file; writeln('Done'); close(send_file) end.