* * *

Author Topic: [SOLVED] Invalid argument with fpsetsockopt & SO_RCVTIMEO  (Read 1105 times)

russdirks

  • New member
  • *
  • Posts: 35
[SOLVED] Invalid argument with fpsetsockopt & SO_RCVTIMEO
« on: August 01, 2017, 07:31:53 am »
I'm using the code below to open a socket for UDP communication, and set a receive timeout.  The call to fpsetsockopt to set the timeout works fine for Windows and MacOS, but under Ubuntu, it reports error 22, which I believe is invalid argument.  Anybody have an idea what the problem could be?

Code: Pascal  [Select]
  1.  
  2.    // open the socket
  3.    m_socket := fpSocket(AF_INET, SOCK_DGRAM, 0);
  4.    m_addrIn.sa_family := AF_INET;
  5.    m_addrIn.sin_port := htons(m_portIn);
  6.    m_addrIn.sin_addr.s_addr := INADDR_ANY;
  7.    res := fpbind(m_socket, @m_addrIn, sizeof(m_addrIn));
  8.  
  9.    ...
  10.  
  11.    // set the timeout
  12.    {$IFDEF Windows}
  13.    tv.tv_sec := 100;                            // milliseconds
  14.    tv.tv_usec := 0;                             // unused
  15.    {$ELSE}
  16.    tv.tv_sec := 0;                              // seconds
  17.    tv.tv_usec := 100 * 1000;            // microseconds
  18.    {$ENDIF}
  19.  
  20.    res := fpsetsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO,  @tv, sizeof(tv));
  21.  
  22.  
« Last Edit: August 12, 2017, 11:33:15 pm by russdirks »

russdirks

  • New member
  • *
  • Posts: 35
Re: Invalid argument with fpsetsockopt & SO_RCVTIMEO
« Reply #1 on: August 12, 2017, 07:38:03 am »
Still stuck on this one.  I was looking at the source code for the rtl-extra package, and code for fpsetsockopt looks like this:

Code: Pascal  [Select]
  1. function  fpsetsockopt  (s:cint; level:cint; optname:cint; optval:pointer; optlen : tsocklen):cint;
  2. begin
  3.   fpSetSockOpt:=do_syscall(syscall_nr_SetSockOpt,S,level,optname,TSysParam(optval),optlen);
  4.   internal_socketerror:=fpgeterrno;
  5. end;
  6.  

The do_syscall is just a call  to some external code somewhere. 

According to this man page the argument for SO_RCVTIMEO is a struct timeval.  My tv variable is declared like so:

Code: Pascal  [Select]
  1. TTimeVal = record
  2.    tv_sec : uint32;
  3.    tv_usec : uint32;
  4. end;

Anybody have any ideas what the problem might be?

Thaddy

  • Hero Member
  • *****
  • Posts: 4789
Re: Invalid argument with fpsetsockopt & SO_RCVTIMEO
« Reply #2 on: August 12, 2017, 08:08:38 am »
Code: Pascal  [Select]
  1. TTimeVal = packed record
  2.    tv_sec : longint;//time_t
  3.    tv_usec : longint;//suseconds_t
  4. end;

Note the members are signed members and you need a packed record.
From the man pages https://linux.die.net/man/2/gettimeofday
MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/ms740560(v=vs.85).aspx
« Last Edit: August 12, 2017, 08:18:15 am by Thaddy »
"Logically, no number of positive outcomes at the level of experimental testing can confirm a scientific theory, but a single counterexample is logically decisive."

russdirks

  • New member
  • *
  • Posts: 35
Re: Invalid argument with fpsetsockopt & SO_RCVTIMEO
« Reply #3 on: August 12, 2017, 05:57:46 pm »
Thanks for responding.  I made those changes, but the error still persists.

engkin

  • Hero Member
  • *****
  • Posts: 1759
Re: Invalid argument with fpsetsockopt & SO_RCVTIMEO
« Reply #4 on: August 12, 2017, 07:09:05 pm »
I am a Windows person, so I don't know what's wrong with your code under Linux. But, package fcl-net has DNS query in unit netdb.pp using fpSelect instead of fpsetsockopt. DNS query, you know, should not wait forever:

Code: Pascal  [Select]
  1. ...
  2. fpsendto(sock,@qry,qrylen+12,0,@SA,SizeOf(SA));
  3.   // Wait for answer.
  4.   RTO:=TimeOutS*1000+TimeOutMS;
  5.   fpFD_ZERO(ReadFDS);
  6.   fpFD_Set(sock,readfds);
  7.   if fpSelect(Sock+1,@readfds,Nil,Nil,RTO)<=0 then
  8.     begin
  9.     fpclose(Sock);
  10.     exit;
  11.     end;
  12.   AL:=SizeOf(SA);
  13.   L:=fprecvfrom(Sock,@ans,SizeOf(Ans),0,@SA,@AL);
  14.   fpclose(Sock);
  15. ...

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 5875
Re: Invalid argument with fpsetsockopt & SO_RCVTIMEO
« Reply #5 on: August 12, 2017, 07:17:12 pm »
Maybe linux migrated to a 64-bit timeval ? Do you generate 32-bit or 64-bit applications?

Thaddy

  • Hero Member
  • *****
  • Posts: 4789
Re: Invalid argument with fpsetsockopt & SO_RCVTIMEO
« Reply #6 on: August 12, 2017, 08:17:54 pm »
Maybe linux migrated to a 64-bit timeval ? Do you generate 32-bit or 64-bit applications?
I thought I checked sys/time.h but I will check it again.
« Last Edit: August 12, 2017, 08:20:58 pm by Thaddy »
"Logically, no number of positive outcomes at the level of experimental testing can confirm a scientific theory, but a single counterexample is logically decisive."

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 5875
Re: Invalid argument with fpsetsockopt & SO_RCVTIMEO
« Reply #7 on: August 12, 2017, 08:22:12 pm »
The best is to compile a small C program that prints sizeof.

Though on Linux that is still open to interpretation, since sometimes kernel and userland use different structures there.

russdirks

  • New member
  • *
  • Posts: 35
Re: Invalid argument with fpsetsockopt & SO_RCVTIMEO
« Reply #8 on: August 12, 2017, 09:54:02 pm »
@marcov I think you were right.  I got it working!  I changed the type values to PtrInt and now it works.  I'll have to go back to Mac OS X and Windows to see how it works there.  May have to do some $IFDEFs.

@engkin  Thanks for the sample code.  Based on that and some things I read in the comments section of this Stack Overflow question, it seems the fpSelect method with a non-blocking sockets is the better way to go.

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus