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?
next 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