On 12/08/2009 13:54, Jon TURNEY wrote:
Hmmm... but if it's really the size of the sockname argument which is
causing the accept() to fail, this would be a bug in cygwin's accept()
implementation, as it's supposed to truncate the data written to the
sockname, rather than fail if it won't fit [1]. If that actually is the
case, since we don't actually use the peer address here, the code as
stands is correct (if a little odd).

I suppose I need to write a small test case to look at this...

[1] http://www.opengroup.org/onlinepubs/009695399/functions/accept.html

A couple of small programs which hopefully demonstrate this problem.

(As is, the connection fails, but uncommenting the alternate definition of cliaddr in listener.c allows it to work)

I'd hazard a guess that perhaps this is because the underlying winsock accept() doesn't have this truncate behaviour and considers a too-small address_len an error.
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <netinet/in.h>

//
// gcc connector.c -o connector
//

int
main(int argc, char **argv)
{
  int sockfd;
  struct sockaddr_in6 servaddr;

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin6_family = AF_INET6;
  servaddr.sin6_addr = in6addr_loopback;
  servaddr.sin6_port = htons(13); /* daytime server */

  if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
     {
       printf("socket error\n");
       exit(1);
     }

  if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
     {
       printf("connect error\n");
       exit(1);
     }
}
#include <stdio.h>
#include <strings.h>
#include <netinet/in.h>

//
// gcc listener.c -o listener
//

int
main(int argc, char **argv)
{
  int listenfd, connfd;
  socklen_t len;
  struct sockaddr_in6 servaddr;
  struct sockaddr_in cliaddr;
//  struct sockaddr_in6 cliaddr;

  listenfd = socket(AF_INET6, SOCK_STREAM, 0);

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin6_family = AF_INET6;
  servaddr.sin6_addr = in6addr_any;
  servaddr.sin6_port = htons(13); /* daytime server */

  bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
  listen(listenfd, 5);

  for (;;)
    {
      len = sizeof(cliaddr);
      connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &len);
      if (connfd > 0)
        {
          printf("accept() succeeded\n");
        }
      else
        {
          printf("accept() failed\n");
        }
    }
}

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to