comp.lang.ada
 help / color / mirror / Atom feed
From: xorquewasp@googlemail.com
Subject: GNAT.Sockets writing data to nowhere...
Date: Sat, 28 Feb 2009 17:32:07 -0800 (PST)
Date: 2009-02-28T17:32:07-08:00	[thread overview]
Message-ID: <4e84cb08-9a96-4691-9baf-265eb76b7e12@w9g2000yqa.googlegroups.com> (raw)

I've been trying, for a couple of frustrating hours now, to write a
very
simple Ada TCP/IP client that connects to an SMTP server and
delivers a message.

Apparently, data I'm writing to the socket is disappearing into a
void.

I can connect to localhost:25 and conduct an SMTP session using
netcat, so the problem isn't one of configuration.

Here's what I have right now:

-- smtp.ads

package SMTP is

  procedure Send_Mail
    (Server_Address : in String;
     Server_Port    : in Natural;
     Server_User    : in String;
     Server_Pass    : in String;
     Sender         : in String;
     Recipient      : in String;
     Data           : in String);

end SMTP;

-- smtp.adb

with GNAT.Sockets;
with Ada.Streams;
with Ada.Unchecked_Conversion;
with Ada.Strings.Unbounded;
with Ada.Text_IO;

package body SMTP is
  package Sockets renames GNAT.Sockets;
  package UB_Strings renames Ada.Strings.Unbounded;
  package Streams renames Ada.Streams;
  package Text_IO renames Ada.Text_IO;

  use type Streams.Stream_Element_Offset;

  --
  -- Write Data to Socket.
  --

  procedure Socket_Write
    (Socket  : Sockets.Socket_Type;
     Data    : in String)
  is
    subtype Source is String (Data'First .. Data'Last);
    subtype Target is Streams.Stream_Element_Array
      (Streams.Stream_Element_Offset (Data'First) ..
       Streams.Stream_Element_Offset (Data'Last));
    function Convert is new Ada.Unchecked_Conversion (Source, Target);

    Buffer : constant Streams.Stream_Element_Array := Convert (Data);
    Wrote  : Streams.Stream_Element_Offset;
  begin
    Sockets.Send_Socket
     (Socket => Socket,
      Item   => Buffer,
      Last   => Wrote);
    pragma Assert (Wrote = Buffer'Last);
  end Socket_Write;

  --
  -- Read data from Socket, return in Data
  --

  procedure Socket_Read
    (Socket : Sockets.Socket_Type;
     Data   : out UB_Strings.Unbounded_String)
  is
    Temp_Buffer : Streams.Stream_Element_Array (1 .. 256);
    Temp_Last   : Streams.Stream_Element_Offset;
  begin
    loop
      Sockets.Receive_Socket (Socket, Temp_Buffer, Temp_Last);
      declare
        subtype Source is Streams.Stream_Element_Array
          (Streams.Stream_Element_Offset (Temp_Buffer'First) ..
Temp_Last);
        subtype Target is String
          (Natural (Temp_Buffer'First) .. Natural (Temp_Last));
        function Convert is new Ada.Unchecked_Conversion (Source,
Target);
      begin
        UB_Strings.Append (Data,
          Convert (Temp_Buffer (Temp_Buffer'First .. Temp_Last)));
      end;
      exit when Temp_Last < Temp_Buffer'Last;
    end loop;
  end Socket_Read;

  --
  -- Connect to server at Server_Address:Server_Port, return
connection in Socket.
  --

  procedure Connect_To_Server
    (Server_Address : in String;
     Server_Port    : in Natural;
     Socket         : out Sockets.Socket_Type)
  is
    Address : Sockets.Sock_Addr_Type;
  begin
    Address.Port := Sockets.Port_Type (Server_Port);
    Address.Addr := Sockets.Addresses
      (Sockets.Get_Host_By_Name (Server_Address), 1);

    Sockets.Create_Socket (Socket);
    Sockets.Connect_Socket (Socket, Address);
  end Connect_To_Server;

  --
  -- Send mail Data to Recipient, from Sender, via
Server_Address:Server_Port,
  -- authenticating as Server_User with Server_Pass.
  --

  procedure Send_Mail
    (Server_Address : in String;
     Server_Port    : in Natural;
     Server_User    : in String;
     Server_Pass    : in String;
     Sender         : in String;
     Recipient      : in String;
     Data           : in String)
  is
    Socket       : Sockets.Socket_Type;
    Input_Buffer : UB_Strings.Unbounded_String;
  begin
    pragma Assert (Server_User /= "");
    pragma Assert (Server_Pass /= "");
    pragma Assert (Sender      /= "");
    pragma Assert (Recipient   /= "");
    pragma Assert (Data        /= "");

    Connect_To_Server (Server_Address, Server_Port, Socket);

    Socket_Read  (Socket, Input_Buffer);
    Text_IO.Put_Line ("-- read " & UB_Strings.To_String
(Input_Buffer));

    Socket_Write (Socket, "HELO " & Sockets.Host_Name);
    Text_IO.Put_Line ("-- wrote");

    Socket_Read  (Socket, Input_Buffer);
    Text_IO.Put_Line ("-- read " & UB_Strings.To_String
(Input_Buffer));
  end Send_Mail;

end SMTP;

-- smtp_client.adb

with SMTP;

procedure smtp_client is
begin
  SMTP.Send_Mail
    (Server_Address => "127.0.0.1",
     Server_Port    => 25,
     Server_User    => "me",
     Server_Pass    => "mypass",
     Sender         => "me@localhost",
     Recipient      => "me@localhost",
     Data           => "hello");
end smtp_client;

Here's a trace of the system calls:

 22630 smtp_client CALL  socket(0x2,0x1,0)
 22630 smtp_client RET   socket 3
 22630 smtp_client CALL  setsockopt(0x3,0xffff,0x800,0xbfbfe7d0,0x4)
 22630 smtp_client RET   setsockopt 0
 22630 smtp_client CALL  connect(0x3,0xbfbfe800,0x10)
 22630 smtp_client RET   connect 0
 22630 smtp_client CALL  recvfrom(0x3,0xbfbfe710,0x100,0,0,0)
 22630 smtp_client GIO   fd 3 read 34 bytes
       "220 pxrma.lambda78.c7.info ESMTP\r
       "
 22630 smtp_client RET   recvfrom 34/0x22
 22630 smtp_client CALL  write(0x1,0xbfbfe790,0x2b)
 22630 smtp_client GIO   fd 1 wrote 43 bytes
       "-- read 220 pxrma.lambda78.c7.info ESMTP\r

       "
 22630 smtp_client RET   write 43/0x2b
 22630 smtp_client CALL  __sysctl
(0xbfbfe7b8,0x2,0xbfbfe7e4,0xbfbfe7d4,0,0)
 22630 smtp_client RET   __sysctl 0
 22630 smtp_client CALL  sendto(0x3,0xbfbfe7b0,0x1b,0,0,0)
 22630 smtp_client GIO   fd 3 wrote 27 bytes
       "HELO pxrma.lambda78.c7.info"
 22630 smtp_client RET   sendto 27/0x1b
 22630 smtp_client CALL  write(0x1,0xbfbfe7b0,0x9)
 22630 smtp_client GIO   fd 1 wrote 9 bytes
       "-- wrote
       "
 22630 smtp_client RET   write 9
 22630 smtp_client CALL  recvfrom(0x3,0xbfbfe710,0x100,0,0,0)
 22630 smtp_client RET   recvfrom -1 errno 4 Interrupted system call
 22630 smtp_client PSIG  SIGINT SIG_DFL

Note that Ada believes it has written data (the sendto() call returns
27 bytes written). The server (Postfix, configured to dump the entire
conversation to the log) never sees the HELO message.
The response never comes (obviously) and I interrupt the recvfrom()
call with ^C.

Platform is FreeBSD 6.4, x86. GNAT FSF 4.3.2.

Any ideas what I'm doing wrong?



             reply	other threads:[~2009-03-01  1:32 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-01  1:32 xorquewasp [this message]
2009-03-01  3:36 ` GNAT.Sockets writing data to nowhere xorquewasp
2009-03-01  9:09   ` Pascal Obry
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox