!; % ===================================================== % ===================================================== % SOCKETS.SIM: % % Classes to interface with UNIX TCP sockets to give: % % STREAMS AND DATAGRAMS % % ===================================================== % Version 2.1: 1 dec 1997 (J.Vaucher) % - Cleaned up all C-calls with Text parameters % passed by name with Variables (not expressions) % Version 2.0: 21 nov 1997 (J.Vaucher) % Version 1.3: 5 dec 1996 (J.Vaucher) % Version 1.2: 18 june 1992 (J.Vaucher) % ===================================================== % % Outline of declarations % ----------------------- % 19- Class Sockets; % % 93- Class SOCKET; % 179- Integer Procedure PeerPort; % 188- Text Procedure PeerHost; % % 217- Socket Class Dg_Socket; ! datagrams ; % % 240- Text Procedure receive; % 255- Procedure send( Data, Host, Port ); % 268- Procedure Reply( Data ); % % % 293- Socket Class Stream_Server( P ); % 318- Ref(Stream) Procedure accept; % % 336- Socket Class Stream; % 384- Procedure Send( t ); % 390- Procedure outLine( t ); % 394- Procedure outByte( N ); % 407- Text Procedure Receive; % 417- Text Procedure Intext( n ); % 437- Character Procedure InChar; % 441- Integer Procedure InByte; % % 452- Stream Class Stream_Client( SHost, SPort ); % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % ===================================================== Class Sockets; ; ! Name of the "package"; % ===================================================== External Class UNIX; % CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC % //////////////// External C interface ///////////////////// % //////////////// (from inetsock.c) ///////////////////// % ============================================================== % HOST Addresses: % ---------------- Integer PROCEDURE Host_aton( Adr ); Text Adr; % ------------------------------------------------ begin External C PROCEDURE host_aton Is Integer PROCEDURE Hostaton( Adr ); Name Adr; Text Adr;; Text T; T :- Adr & "!0!"; Host_aton := Hostaton( T ); end; Text PROCEDURE Host_ntoa( Adr ); Integer Adr; % ------------------------------------------------ begin % External C PROCEDURE host_ntoa Is % Integer PROCEDURE host2a( Adr );Integer Adr; ; % ! returns String address ; % Host_ntoa :- CtoSText( host2a( Adr ) ); External C PROCEDURE host_ntoa Is Text PROCEDURE host2a( Adr );Integer Adr; ; ! returns String address ; Text T; T :- host2a( Adr ); Host_ntoa :- T; end; Text PROCEDURE Host_ntod( Adr ); Integer Adr; % ------------------------------------------------ begin % External C PROCEDURE host_ntod Is % Integer PROCEDURE host2d( Adr );Integer Adr; ; % Host_ntod :- CtoSText( host2d( Adr ) ); External C PROCEDURE host_ntod Is Text PROCEDURE host2d( Adr );Integer Adr; ; ! returns String address ; Text T; T :- host2d( Adr); Host_ntod :- T; end; % ----------------------------------------- Text PROCEDURE HostName; % ----------------------------------------- BEGIN External C PROCEDURE host_name Is Text PROCEDURE host_name;; % Integer PROCEDURE host_name;; Integer H; % H := host_name; % HostName :- CtoSText( H ); Text T; T :- host_name; HostName :- T; END *** HostName *** ; % -------------------------------------------------- Integer procedure servicePort( Service, Protocol); % -------------------------------------------------- text Service, Protocol; Begin External C PROCEDURE servicePort Is Integer PROCEDURE sp( S,P ); Name S,P ; Text S,P;; Text T1,T2; T1 :- Service & "!0!"; if Protocol == notext then Protocol :- "tcp"; T2 :- Protocol & "!0!"; servicePort := sp(T1, T2 ); End -- servicePort -- ; % ///////////////// End External C interface ///////////////// % ===================================================== Class SOCKET; % ===================================================== BEGIN Integer BUFLEN = 1024; Text Buffer, PeerAdr; ! un "sockaddr_in" ; Integer Sock, ! sock --> numero de socket ; Port; ! Port --> numero de port du socket ; % CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC % //////////////// External C interface ///////////////////// % //////////////// (from inetsock.c) ///////////////////// % ============================================================== % PORT Addresses: % ---------------- External C PROCEDURE socketPort Is Integer PROCEDURE socketPort( Sock ); Integer Sock; ; % Socket Addresses: % ------------------ External C PROCEDURE make_sockadr IS PROCEDURE make_SockAdr( SAdr, Host, Port ); Name SAdr; Text SAdr; Integer Host, Port; ; Text PROCEDURE NewSockAdr( host, port ); Text host; Integer port; BEGIN Text SA; Integer Host_n ; SA :- blanks( sockadr_size ); host_n := host_aton(host); make_sockadr( SA, host_n, port ); NewSockAdr :- SA END; External C PROCEDURE split_SockAdr IS PROCEDURE split_SockAdr( SAdr, Host, Port ); Name Host, Port; Text SAdr; Integer Host, Port; ; % Utility: % -------- External C PROCEDURE chars_avail Is Integer PROCEDURE chars_avail( Socket ); Integer Socket; ; External C PROCEDURE sockadr_size Is Integer PROCEDURE sockAdr_size; ; % ///////////////// End External C interface ///////////////// PROCEDURE close; ! Fermeture d'un socket ; begin External C PROCEDURE close Is Integer PROCEDURE c_close( fd ); Integer fd;; c_close( sock ); sock := 0; end; Boolean PROCEDURE More; More := chars_avail( sock ) > 0; Boolean PROCEDURE Empty; Empty := chars_avail( sock ) = 0; Boolean PROCEDURE isOpen; isOpen := sock > 0; Integer PROCEDURE PeerPort; if PeerAdr =/= notext then begin Integer Host, Port; Split_sockadr(PeerAdr, Host, Port); PeerPort := Port; end; Text PROCEDURE PeerHost; if PeerAdr =/= notext then begin Integer Host, Port; Text T; Split_sockadr(PeerAdr, Host, Port); PeerHost:- host_ntoa(Host); end; Buffer :- blanks(BUFLEN); % while PeerAdr.more do % PeerAdr.putchar(char(0)); END --- Socket --- ; % ===================================================== % ===================================================== % ============== D A T A G R A M S ================ % ===================================================== % ===================================================== ! Classe des sockets de type datagramme sans connexion; ! Avec ce type de sockets, il n y a pas de distinction entre serveur et client; % ===================================================== Socket Class Dg_Socket; BEGIN % ccccccccccccccccccccc interface ccccccccccccccccccccccc % Datagram (udp) connection: % -------------------------- External C PROCEDURE datagram_socket Is Integer PROCEDURE datagram_socket; ; External C PROCEDURE receive_datagram Is Integer PROCEDURE receive_datagram( fd, Buf, Len, Adr ); Name Buf, Adr; Integer fd, Len; Text Buf, Adr; ; External C PROCEDURE send_datagram Is Integer PROCEDURE send_datagram( fd, Buf, Len, Adr ); Name Buf, Adr; Integer fd, Len; Text Buf, Adr; ; % ccccccccccccccccccccccccccccccccccccccccccccccccccccccc % ----------------------------------------- Text PROCEDURE receive; % ----------------------------------------- ! Reception d'un message d'un datagramme socket ; ! Par effet de bord, le nom de l'hote et le port du ; ! socket source sont place dans host et p ; BEGIN Integer res; res := receive_datagram( sock, Buffer, Buffer.length, PeerAdr ); receive :- copy( Buffer.sub( 1, res ) ); END; % ----------------------------------------- PROCEDURE send( Data, Host, Port ); % ----------------------------------------- Text Data, Host; Integer Port; BEGIN Integer H_adr; H_adr := Host_aton(Host); make_SockAdr( PeerAdr, H_adr, Port); send_datagram( sock, Data, Data.length, PeerAdr ); END; % --------------------------------------------- PROCEDURE Reply( Data ); Text Data; % --------------------------------------------- ! Envoi de DATA a PEER ; BEGIN send_datagram( sock, Data, Data.length, PeerAdr ); END; PeerAdr :- blanks( sockAdr_size ); Sock := datagram_socket; Port := socketPort(Sock); END ===== DgSocket ========; % ===================================================== % ===================================================== % ================ S T R E A M S ================== % ===================================================== % ===================================================== % ====================================================== Socket Class Stream_Server(P); integer P; % ====================================================== % Stream servers have no IO procedures associated % They are used to receive Client connection requests. To % do this they have only one operation: % % - "accept" which returns a Stream object on which % one can do IO % ====================================================== BEGIN % ccccccccccccccccccccccccccccccccccccccccccccccccccccccc External C PROCEDURE internet_server Is Integer PROCEDURE internet_server( Port ); Integer Port; ; External C PROCEDURE internet_accept Is Integer PROCEDURE internet_accept( Sock, Peer ); Name Peer; Integer Sock; Text Peer; ; % ccccccccccccccccccccccccccccccccccccccccccccccccccccccc Ref(Stream) PROCEDURE accept; BEGIN Ref(Stream) s; Accept :- s :- New Stream; S.PeerAdr :- blanks( sockAdr_size ); s.sock := internet_accept( Sock, s.PeerAdr ); END; Sock := internet_server( p ); Port := socketPort(Sock); Buffer :- notext; END ******* Stream_Server ********** ; % ===================================================== Socket Class Stream; % ===================================================== % Stream objects are generated by the Stream SERVER for % each connection request. % This class contains the STREAM IO procedures ; % It is also used as a prefix for "stream_client" % ===================================================== BEGIN % cccccccccccccccccccccccccccccccccccccc interface cccccc % Reading & Writing: % cccccccccccccccccccccccccccccccccccccc interface cccccc External C PROCEDURE stream_write Is Integer PROCEDURE stream_write( fd, Buf, Len ); Name Buf; Integer fd, Len; Text Buf; ; External C PROCEDURE stream_read Is Integer PROCEDURE stream_read( fd, Buf, Len ); Name Buf; Integer fd, Len; Text Buf; ; External C PROCEDURE read_string Is Integer PROCEDURE read_string( fd, Buf, Len, Delim ); Name Buf; Integer fd, Len; Text Buf; Character Delim; ; External C PROCEDURE read_char Is Character PROCEDURE read_char (fd); Integer fd; ; External C PROCEDURE read Is Integer PROCEDURE c_read( fd, buf, n ); Name buf; Integer fd, n; Text buf; ; External C PROCEDURE write Is Integer PROCEDURE c_write( fd, buf, n ); Name buf; Integer fd, n; Text buf; ; % ccccccccccccccccccccccccccccccccccccccccccccccccccccccc % OUTPUT % ========== Procedure Send( t ); Text t; ! -------------------------------- Ecriture de la chaine t ; BEGIN Stream_write( sock, t, t.length ); END; PROCEDURE outLine( t ); Text t; ! ------------------------------- Ecriture de T + "\n" ; begin Text TT; TT :- T & "!10!"; send( TT ); end; PROCEDURE outByte(N); integer N; ! --------------------------------; begin external C procedure write_char is integer procedure write_char(s,n); integer s,n;; write_char( sock, n ); end; % INPUT: % ========== Text Procedure Receive; ! Reads what is currently available ; ! ----------------------- ; BEGIN Integer res; res := c_read( sock, Buffer, BUFLEN ); Receive :- copy(Buffer.sub( 1, res )); END; Text PROCEDURE INTEXT( n ); Integer n; ! ----------------------------------------- Lecture de N characteres; BEGIN Text Buffer; Integer Lus; Buffer :- Blanks( n ); Lus := Stream_read( sock, Buffer, n ); intext :- Buffer; END; Text PROCEDURE InLine; ! -----------------------; BEGIN Integer n; n := read_string( sock, Buffer, BUFLEN, '!10!'); InLine :- copy( Buffer.sub(1,n-1)); END; Character PROCEDURE InChar; ! ---------------------------; inchar := read_char( sock ); Integer PROCEDURE InByte; ! ---------------------------; InByte := rank(read_char( sock )); END ========= Stream ============; % ===================================================== Stream Class Stream_Client( SHost, SPort); Text SHost; Integer SPort; % ===================================================== BEGIN % ccccccccccccccccccccccccccccccccccccccccccccccccccccccc External C PROCEDURE internet_connect Is Integer PROCEDURE internet_connect( Host, Port ); Name Host; Text Host; Integer Port; ; % ccccccccccccccccccccccccccccccccccccccccccccccccccccccc sock := internet_connect( SHost, SPort ); Port := socketPort(Sock); PeerAdr :- NewSockAdr( SHost, SPort ); END ***** Stream_Client ***** ;