English Amiga Board


Go Back   English Amiga Board > Support > support.WinUAE

 
 
Thread Tools
Old 05 November 2020, 19:07   #1
softwarefailure
Registered User

 
Join Date: Mar 2016
Location: Germany
Posts: 73
Peeking UDP datagrams doesn't work with WinUAE's bsdsocket.library

It seems like WinUAE's bsdsocket.library can't peek UDP datagrams. On real hardware it works fine, though. My TCP/IP stack on real hardware is Genesis. It also works on MorphOS and OS4 so it really looks like a WinUAE bsdsocket.library bug.

To reproduce, run the attached program in two separate shells. In the first shell, run "udptest s" to start the server. In the second shell, run "udptest c" to start the client. The client will try to send "Hello World" to the server while the server will continually peek the queue and report what's in it.

On my WinUAE test system, the server will always print "TAKEN: -1", i.e. nothing in the queue. On real hardware using Genesis, the server will report "TAKEN: 1" as soon as the client program has been run.

Here's the udptest program: https://easyupload.io/5l81j9
Here's the source code: https://easyupload.io/d9zsz8

And here's an unformatted copy & paste of the source code:

Quote:
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include <exec/exec.h>

#include <dos/dos.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/socket.h>

#include <amitcp/socketbasetags.h>

#include <netdb.h>

#include <sys/errno.h>
#include <sys/ioctl.h>

struct addrinfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
char *ai_canonname;
struct sockaddr *ai_addr;
struct addrinfo *ai_next;
};

#define AI_PASSIVE 0x01

struct Library *SocketBase = NULL;

static int inet_aton(const char *cp, struct in_addr *inp)
{
unsigned int a = 0, b = 0, c = 0, d = 0;
int n = 0, r;
unsigned long int addr = 0;

r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n);
if (r == 0 || n == 0) return 0;

cp += n;
if (*cp) return 0;

if (a > 255 || b > 255 || c > 255 || d > 255) return 0;

if (inp) {
addr += a; addr <<= 8;
addr += b; addr <<= 8;
addr += c; addr <<= 8;
addr += d;
inp->s_addr = htonl(addr);
}

return 1;
}

int main(int argc, char *argv[])
{
int isclient = !strcmp(argv[1], "c");
int fd;
LONG nb = 1;
struct addrinfo hints;
struct sockaddr_in local;
int port = (isclient) ? 0 : 12345;

DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 39);

if(!(SocketBase = OpenLibrary("bsdsocket.library", 0))) {
printf("No bsdsocket.library\n");
return 0;
}

fd = socket(AF_INET, SOCK_DGRAM, 0);

// set non-blocking
IoctlSocket(fd, FIONBIO, (char *) &nb);

memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;
hints.ai_family = AF_INET;
hints.ai_flags = AI_PASSIVE;

memset(&local, 0, sizeof(local));

local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(port);
local.sin_family = AF_INET;

bind(fd, &local, sizeof(local));

// set non-blocking
IoctlSocket(fd, FIONBIO, (char *) &nb);

if(isclient) {

memset(&local, 0, sizeof(local));

inet_aton("127.0.0.1", &local.sin_addr);

local.sin_family = AF_INET;
local.sin_port = htons(12345);

for(; {

long put = (long) sendto(fd, "Hello World", 11, 0, &local, sizeof(local));

if(put >= 0) {
printf("PUT: %d\n", put);
break;
}
}

} else {

for(; {

int dummy;
long taken;

taken = (long) recvfrom(fd, (char *) &dummy, 1, MSG_PEEK, NULL, NULL);
printf("TAKEN: %d\n", taken);

Delay(10);
}
}

CloseSocket(fd);
CloseLibrary(SocketBase);
CloseLibrary((struct Library *) DOSBase);

return 0;
}
softwarefailure is offline  
Old 05 November 2020, 19:21   #2
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 45
Posts: 24,647
This test won't really tell anything else than that UDP data is not received. For some reason (Windows firewall?)

Do you mean you get data if you don't use MSG_PEEK?
Toni Wilen is offline  
Old 05 November 2020, 19:44   #3
softwarefailure
Registered User

 
Join Date: Mar 2016
Location: Germany
Posts: 73
Right, so I don't get data without MSG_PEEK either. But disabling the Windows firewall doesn't help. It just doesn't work.

So is this a problem on my system only? Can you reproduce it?
softwarefailure is offline  
Old 05 November 2020, 20:14   #4
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 45
Posts: 24,647
Same happens here. WinUAE forwards correct data to winsock sendto() and recvfrom() parameters are also correct so this must be some Windows feature.

recvfrom() also returns EWOULDBLOCK so there really is no data available.

Perhaps the reason is that reader uses Windows current IP but writer uses 127.0.0.1?
Toni Wilen is offline  
Old 05 November 2020, 20:31   #5
softwarefailure
Registered User

 
Join Date: Mar 2016
Location: Germany
Posts: 73
IIRC I think there are a few incompatibilities between Winsock and Unix sockets. So this might be one of them?!

FWIW I just tried the program on Ubuntu and it works fine there as well so it really looks like a Windows issue but of course WinUAE should try to work around that then so that bsdsocket.library's behaviour is identical between WinUAE and real Amiga hardware...
softwarefailure is offline  
Old 05 November 2020, 20:41   #6
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 45
Posts: 24,647
First someone needs to find whats the difference and why.. UAE bsdsocket.library emulation is basically a pipe between Amiga bsdsocket and host bsdsocket, there is not much it can fake.
Toni Wilen is offline  
Old 06 November 2020, 17:51   #7
softwarefailure
Registered User

 
Join Date: Mar 2016
Location: Germany
Posts: 73
Quote:
Originally Posted by Toni Wilen View Post
First someone needs to find whats the difference and why
Ok, so I've compiled the program for Windows and analyzed what's going on. There is indeed a difference in behaviour when it comes to MSG_PEEK. On Windows, recvfrom() with MSG_PEEK will return -1 and set WSAEMSGSIZE if the provided buffer isn't large enough for what's in the socket. This doesn't happen with Unix/Amiga sockets. On Unix/Amiga recvfrom() with MSG_PEEK won't fail if the buffer is smaller than the data in the socket. So this is what should be fixed in WinUAE.

Here is the Windows test program: https://easyupload.io/zxlx75
And the source code: https://easyupload.io/wa1eht

If you do some googling, you'll also notice that some other projects which map the Unix socket API directly to Winsock had to deal with this issue as well, see here for example: https://cygwin.cygwin.narkive.com/sB...sg-peek-broken
softwarefailure is offline  
Old 06 November 2020, 18:14   #8
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 45
Posts: 24,647
Right, seems simple enough to work around.

Does this affect both UDP and TCP sockets? (I wasn't sure after few net searchs..)

EDIT: and what should happen if buffer size is zero?

EDIT2: also does it only affect MSG_PEEK? Non-MSG_PEEK reads work "correctly" already?

Last edited by Toni Wilen; 06 November 2020 at 18:25.
Toni Wilen is offline  
Old 06 November 2020, 20:50   #9
softwarefailure
Registered User

 
Join Date: Mar 2016
Location: Germany
Posts: 73
From my tests only UDP sockets are affected. The Cygwin guys in the thread linked above also seem to have had the problem with UDP sockets only.

When the buffer size is 0, recvfrom() returns 0 and errno is set to 0 as well on real hardware. So this is the behaviour WinUAE should replicate.

Actually, it doesn't seem to be limited to MSG_PEEK. Without MSG_PEEK the behaviour is the same, i.e. -1 is returned and WSAEMSGSIZE is set. This is also consistent with MSDN's documentation of recvfrom() which says: "If no error occurs, recvfrom returns the number of bytes received." and "If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recvfrom generates the error WSAEMSGSIZE". In other words: whenever WSAEMSGSIZE is set, -1 will be returned. This is different from the Unix recvfrom() which doesn't generate an error if the buffer is too small.
softwarefailure is offline  
Old 06 November 2020, 21:21   #10
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 45
Posts: 24,647
https://download.abime.net/winuae/files/b/winuae.7z should fix it.

If recv() or recvfrom() returns -1 and error is WSAEMSGSIZE and UDP socket: clear error and return buffer length value instead of -1.
Toni Wilen is offline  
Old 06 November 2020, 21:48   #11
softwarefailure
Registered User

 
Join Date: Mar 2016
Location: Germany
Posts: 73
Works, thanks for the quick fix!
softwarefailure is offline  
Old 07 November 2020, 18:30   #12
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 45
Posts: 24,647
I'll (almost) always fix problems quickly if there is nice test case(s) and problem is well known.
Toni Wilen is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
bsdsocket.library - how does it work? Sim085 support.WinUAE 17 30 June 2019 20:17
Bsdsocket.Library Emufr3ak Coders. Asm / Hardware 5 25 December 2016 12:20
winuae bsdsocket.library clauddio support.WinUAE 5 21 July 2015 22:47
Can't connect with bsdsocket.library error (WinUAE 2.5.0) arti support.WinUAE 12 13 December 2012 22:29
WinUAE doesn't work under Vista bobgeldof support.WinUAE 22 23 October 2009 20:42

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 06:01.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, vBulletin Solutions Inc.
Page generated in 0.07988 seconds with 12 queries