Others (clean up this...) - JulTob/Ada GitHub Wiki

Sockets

Send (sentto and sendmsg) are supersets of write. When you use write on a socket, it's actually implemented using the send family.

Write will not work on UDP because it's connectionless. Use send to specify an address everytime.

Protocol Families PF_INET Internet (IPv4) PF_INET6 Internet (IPv6) PF_IPX Novell PF_NETLINK Kernel user interface device PF_X25 ITU-T X.25 / ISO-8208 PF_AX25 Amateur radio AX.25 PF_ATMPVC Access to raw ATM PVCs PF_APPLETALK Appletalk PF_PACKET Low-level packet interface

Socket Types SOCK_STREAM Two-way reliable connection, with possible out-of-band transmission (eg. TCP/IP) SOCK_DGRAM (Datagram) Connectionless, unreliable messages (eg. UDP/IP) SOCK_SEQPACKET Sequenced, reliable datagram connection. SOCK_RAQ Raw network protocol access. SOCK_RDM Reliable, unordered datagrams.

function socket( domain, soctype, protocol : integer ) return integer; pragma import( C, socket ); Creates a network socket for protocol family domain, connection type soctype, and a protocol (0 uses the default protocol). Returns -1 on an error, or else a kernel file descriptor for the socket. Example: mySocket := socket( PF_INET, SOCK_STREAM, 0 ); -- open a standard Internet socket

procedure connect( result : out integer; socket : integer; addr : in out socketaddr; addrlen : integer ); pragma import( C, connect ); pragma import_valued_procedure( connect ); Connects to a server on the network. socket is the socket to use; addr is the machine and service to connect to; addrlen is the length of the addr record. Returns -1 on an error, 0 for success. Example: connect( result, webserver, webserver'size/8 ); -- connect to the web server described by the webserver record function shutdown( socket, how : integer ) return integer; pragma import( C, shutdown ); Shuts down one or both directions of a socket. This is used, for example, by web browsers to let the server know there are no more HTTP requests being sent. Returns 0 on sucess, -1 on failure. Example: result := shutdown( mysocket, 1 );

procedure bind( result : out integer; myaddr : in out sockaddr, addrlen : integer ); pragma import( C, bind ); pragma import_valued_procedure( bind ); Registers your server on a particular port number with the Linux kernel. addrlen is the length of myaddr. Returns 0 on success, -1 on failure. Example: bind( result, myservice, myservice'size/8 );

function listen( socket : integer; backlog : integer ) return integer; pragma import( C, listen ); pragma import_valued_procedure( listen ); Prepares a socket for your server to listen for incoming connections. Backlog is the maximum number of established connections that can be queued. Returns 0 on success, -1 on failure. Example: result := listen( mysocket, 10 );

procedure accept( result : out integer; socket : integer; clientaddr : in out sockaddr; addrlen : in out addrlen ); pragma import( C, accept ); pragma import_valued_procuedre( accept ); Returns the next connection to your server. If there are no connections, it waits for a new connection (unless you disabled blocking on the socket.) myaddr is the address of the incoming connection, and addrlen is the size of the address is bytes. addrlen should be initialized to the size of your sockaddr record. You must use listen before accept. Returns -1 on failure, or a new socket with the connection on success. You have to close the new socket when you are finished handling the connection. Example: len := clientaddr'size/8; accept( newsocket, listensocket, clientaddr, len );

This section ends with a demonstration of how to get a web page off the Internet.

with Ada.Text_IO, Interfaces.C, System.Address_To_Access_Conversions; use Ada.Text_IO, Interfaces.C;

procedure websocket is

-- A program to fetch a web page from a server

-- Socket related definitions

-- These are the kernel calls and types we need to create -- and use a basic Internet socket.

type aSocketFD is new int;

-- a socket file descriptor is an integer -- man socket -- make this a new integer for strong typing purposes

type aProtocolFamily is new unsigned_short; AF_INET : constant aProtocolFamily := 2;

-- Internet protocol PF_Net defined as 2 in -- /usr/src/linux/include/linux/socket.h -- Make this a new integer for strong typing purposes

type aSocketType is new int; SOCK_STREAM : constant aSocketType := 1;

-- this is for a steady connection. Defined as 1 in -- /usr/src/linux/include/linux/socket.h -- Make this a new integer for strong typing purposes

type aNetProtocol is new int; IPPROTO_TCP : constant aNetProtocol := 6;

-- The number of the TCP/IP protocol -- TCP protocol defined as 6 in /etc/protocols -- See man 5 protocols -- Make this a new integer for strong typing purposes

type aNetDomain is new integer; PF_INET : constant aNetDomain := 2;

-- The number of the Internet domain -- Make this a new integer for strong typing purposes

type aInAddr is record addr : unsigned := 0; end record; for aInAddr'size use 96; -- A sockaddr_in record is defined as 16 bytes long (or 96 bits) -- Request Ada to use 16 bytes to represent this record

type aSocketAddr is record family : aProtocolFamily := AF_INET; -- protocol (AF_INET for TCP/IP) port : unsigned_short := 0; -- the port number (eg 80 for web) ip : aInAddr; -- IP number end record; -- an Internet socket address -- defined in /usr/src/linux/include/linux/socket.h -- and /usr/src/linux/include/linux/in.h

function socket( domain : aNetDomain; stype : aSocketType; protocol : aNetProtocol ) return aSocketFD; pragma import( C, socket ); -- initialize a communication socket. -1 if error

procedure bind( result : out int; sockfd : aSocketFD; sa : in out aSocketAddr; addrlen : int ); pragma import( C, bind ); pragma import_valued_procedure( bind ); -- give socket a name. 0 if successful

procedure Connect( result : out int; socket : aSocketFD; sa : in out aSocketAddr; addrlen : int ); pragma import( C, connect ); pragma import_valued_procedure( connect ); -- connect to a (Internet) server. 0 if successful

procedure Close( fd : aSocketFD ); pragma import( C, close ); -- close the socket, discard the integer result

procedure Read( result : out integer; from : aSocketFD; buffer : in out string; buffersize : integer ); pragma import( C, read ); pragma import_valued_procedure( read ); -- read from a socket

procedure Write( result : out integer; from : aSocketFD; buffer : system.address; buffersize : integer ); pragma import( C, write ); pragma import_valued_procedure( write ); -- write to a socket

package addrListPtrs is new System.Address_To_Access_Conversions( System.Address ); -- We need to use C pointers with the address list because this is -- a pointer to a pointer in C. This will allow us to dereference -- the C pointers in Ada.

subtype addrListPtr is System.Address; -- easier to read than System.Address

type aHostEnt is record h_name : System.Address; -- pointer to offical name of host h_aliases : System.Address; -- pointer to alias list h_addrtype : int := 0; -- host address type (PF_INET) h_length : int := 0; -- length of address h_addr_list : addrListPtr; -- pointer to list IP addresses -- we only want first one end record; -- defined in man gethostbyname

package HEptrs is new System.Address_To_Access_Conversions( aHostEnt ); -- Again, we need to work with C pointers here subtype aHEptr is System.Address; -- and this is easier to read use HEptrs; -- use makes = (equals) visible

function getHostByName( cname : string ) return aHEptr; pragma import( C, getHostByName ); -- look up a host by it's name, returning the IP number

function htons( s : unsigned_short ) return unsigned_short; pragma import( C, htons ); -- acronym: host to network short -- on Intel x86 platforms, -- switches the byte order on a short integer to the network -- Most Significant Byte first standard of the Internet

procedure memcpy( dest, src : System.Address; numbytes : int ); pragma import( C, memcpy); -- Copies bytes from one C pointer to another. We could probably -- use unchecked_conversion, but the C examples use this.

errno : int; pragma import( C, errno ); -- last error number

procedure perror( s : string ); pragma import( C, perror ); -- print the last kernel error and a leading C string

procedure PutIPNum( ia : aInAddr ) is -- divide an IP number into bytes and display it IP : unsigned := ia.addr; Byte1, Byte2, Byte3, Byte4 : unsigned; begin Byte4 := IP mod 256; IP := IP / 256; Byte3 := IP mod 256; IP := IP / 256; Byte2 := IP mod 256; Byte1 := IP / 256; Put( Byte4'img ); Put( "." ); Put( Byte3'img ); Put( "." ); Put( Byte2'img ); Put( "." ); Put( Byte1'img ); end PutIPNum;

procedure SendHTTPCommand( soc : aSocketFD; cmd : string ) is -- Write a HTTP command string to the socket amountWritten : integer := 0; totalWritten : integer := 0; position : integer := cmd'first; begin loop Write( amountWritten, soc, cmd( position )'address, cmd'length - integer( totalWritten ) ); if amountWritten < 0 then Put_Line( Standard_Error, "Write to socket failed" ); return; end if; Put_Line( "Sent" & amountWritten'img & " bytes" ); totalWritten := totalWritten + amountWritten; position := position + amountWritten; exit when totalWritten = cmd'length; end loop; end SendHTTPCommand;

procedure ShowWebPage( soc : aSocketFD ) is -- Read the web server's response and display it to the screen amountRead : integer := 1; buffer : string( 1..80 ); begin -- continue reading until an error or no more data read -- up to 80 bytes at a time while amountRead > 0 loop Read( amountRead, soc, buffer, buffer'length ); if amountRead > 0 then Put( buffer( 1..amountRead ) ); end if; end loop; end ShowWebPage;

ServerName: string := "www.adapower.com";

mySocket : aSocketFD; -- the socket myAddress : aSocketAddr; -- where it goes myServer : aHEptr; -- IP number of server myServerPtr : HEptrs.Object_Pointer; addrList : addrListPtrs.Object_Pointer; Result : int;

begin

Put_Line( "Socket Demonstration" ); New_Line; Put_Line( "This program opens a socket to a web server" ); Put_Line( "and retrieves the server's home page" ); New_Line;

-- initialize a new TCP/IP socket -- 0 for the third param lets the kernel decide

Put_Line( "Initializing a TCP/IP socket" ); Put_Line( "Socket( " & PF_INET'img & ',' & SOCK_STREAM'img & ", 0 );" );

mySocket := Socket( PF_INET, SOCK_STREAM, 0 ); if mySocket = -1 then perror( "Error making socket" & ASCII.NUL ); return; end if; New_Line;

-- Lookup the IP number for the server

Put_Line( "Looking for information on " & ServerName ); Put_Line( "GetHostByName( " & ServerName & ");" );

myServer := GetHostByName( ServerName & ASCII.NUL ); myServerPtr := HEptrs.To_Pointer( myServer ); if myServerPtr = null then Put_Line( Standard_Error, "Error looking up server" ); return; end if;

Put_Line( "IP number is" & myServerPtr.h_length'img & " bytes long" ); addrList := addrlistPtrs.To_Pointer( myServerPtr.h_addr_list ); New_Line;

-- Create the IP, port and protocol information

Put_Line( "Preparing connection destination information" ); myAddress.family := AF_INET; myAddress.port := htons( 80 ); memcpy( myAddress.ip'address, addrlist.all, myServerPtr.h_length ); New_Line;

-- Open a connection to the server

Put_Line( "Connect( Result, Socket, Family/Address rec, F/A rec size )" );

Connect( Result, mySocket, myAddress, myAddress'size/8 );

Put( "Connect( " & Result'img & "," ); Put( myAddress.family'img & "/" ); PutIPNum( myAddress.ip ); Put( "," & integer'image( myAddress'size / 8 ) & ")" ); if Result /= 0 then perror( "Error connecting to server" & ASCII.NUL ); return; end if; New_Line;

-- Write the request

-- "GET" returns a web page from a web server -- Also send minimal HTTP header using User-Agent -- Followed with a blank line to indicate end of command

Put_Line( "Transmitting HTTP command..." ); SendHTTPCommand( mySocket, "GET /index.html HTTP/1.0" & ASCII.CR & ASCII.LF & "User-Agent: WebSocket/1.0 (BigBookLinuxAda Example)" & ASCII.CR & ASCII.LF & ASCII.CR & ASCII.LF ); New_Line;

-- read web page back

Put_Line( "---Web Page / Server Results-------------------------" ); ShowWebPage( mySocket ); Put_Line( "-----------------------------------------------------" );

-- close the connection

Put_Line( "Closing the connection" ); close( mySocket );

Put_Line( "Demonstration finished - have a nice day" );

end websocket;

Socket Demonstration

This program opens a socket to a web server and retrieves the server's home page

Initializing a TCP/IP socket Socket( 2, 1, 0 );

Looking for information on www.adapower.com GetHostByName( www.adapower.com); IP number is 4 bytes long

Preparing connection destination information

Connect( Result, Socket, Family/Address rec, F/A rec size ) Connect( 0, 2/ 216. 92. 66. 46, 16) Transmitting HTTP command... Sent 81 bytes

---Web Page / Server Results------------------------- HTTP/1.0 200 OK Date: Wed, 29 Mar 2000 02:32:56 GMT Server: Apache/1.3.3 Last-Modified: Thu, 11 Nov 1999 02:03:14 GMT Etag: "1f31-406-382a23e2" Accept-Ranges: Bytes Content-Length: 1030 Content-Type: text/html Age: 39 Via: HTTP/1.0 csmc2 (Traffic-Server/3.0.3 [uScHs f p eN:t cCHi p s ])

> <TITLE>AdaPower.com</TITLE> <NOFRAMES> Click here </NOFRAMES>
⚠️ **GitHub.com Fallback** ⚠️