From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,ffd2f11f12371bc7,start X-Google-Attributes: gid103376,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!postnews.google.com!w9g2000yqa.googlegroups.com!not-for-mail From: xorquewasp@googlemail.com Newsgroups: comp.lang.ada Subject: GNAT.Sockets writing data to nowhere... Date: Sat, 28 Feb 2009 17:32:07 -0800 (PST) Organization: http://groups.google.com Message-ID: <4e84cb08-9a96-4691-9baf-265eb76b7e12@w9g2000yqa.googlegroups.com> NNTP-Posting-Host: 81.86.41.187 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: posting.google.com 1235871128 11993 127.0.0.1 (1 Mar 2009 01:32:08 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Sun, 1 Mar 2009 01:32:08 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: w9g2000yqa.googlegroups.com; posting-host=81.86.41.187; posting-account=D9GNUgoAAAAmg7CCIh9FhKHNAJmHypsp User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.6) Gecko/2009020409 Iceweasel/3.0.6 (Debian-3.0.6-1),gzip(gfe),gzip(gfe) Xref: g2news2.google.com comp.lang.ada:4831 Date: 2009-02-28T17:32:07-08:00 List-Id: 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?