Home > Back-end >  Why am I getting Invalid argument error on my connect calls?
Why am I getting Invalid argument error on my connect calls?

Time:01-14

I am trying to modify the wrk codebase so that it will connect to multiple servers instead of just the one. I have found and am modifying the connect_socket function to this end but am getting the following output when it runs:

143.204.186.52
connect: Invalid argument
64.190.62.111
connect: Invalid argument
45.33.18.44
connect: Invalid argument
64.190.62.111
connect: Invalid argument
52.128.23.153
connect: Invalid argument
173.255.194.134
connect: Invalid argument
^C  Thread Stats   Avg      Stdev     Max    /- Stdev
    Latency     0.00us    0.00us   0.00us    -nan%
    Req/Sec     0.00      0.00     0.00      -nan%
  0 requests in 1.66s, 0.00B read
  Socket errors: connect 100000, read 0, write 0, timeout 0
Requests/sec:      0.00
Transfer/sec:       0.00B

Here is the modified function that I am calling:

static int connect_socket(thread *thread, connection *c) {
    struct addrinfo *addr = thread->addr;
    struct aeEventLoop *loop = thread->loop;
    int fd, flags;
    char ip[128];
    struct sockaddr_in myaddr;
    
    if (fscanf(fp, "8s", ip) == 1) {
        printf("%s\n", ip);
    }
    
    memset(&myaddr, '0', sizeof(myaddr));
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(80);

    if(inet_pton(AF_INET, ip, &myaddr.sin_addr)<=0)
    {
        printf("\n inet_pton error occured\n");
    }

    fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);

    flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);

    if (connect(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
        if (errno != EINPROGRESS) goto error;
    }

    flags = 1;
    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof(flags));

    flags = AE_READABLE | AE_WRITABLE;
    if (aeCreateFileEvent(loop, fd, flags, socket_connected, c) == AE_OK) {
        c->parser.data = c;
        c->fd = fd;
        return fd;
    }

  error:
    perror("connect");
    thread->errors.connect  ;
    close(fd);
    return -1;
}

I guess it must be a problem with my arguments to connect. Any ideas what I am doing wrong?

CodePudding user response:

There is a mistake in the following line:

fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);

It should be:

fd = socket(AF_INET, addr->ai_socktype, addr->ai_protocol);

CodePudding user response:

This code is a logic mess.

The use of the addrinfo struct implies the getaddrinfo() function is being used elsewhere before the thread is started.

Your thread is being passed in an addrinfo, and is then creating the socket based on the IP address type specified by that addrinfo, but is ignoring the actual IP address stored in the addrinfo (which could be either an IPv4 or IPv6 address). It is instead obtaining an IP address as a string from elsewhere, parsing it only as an IPv4 address, and then passing it to connect() in a sockaddr_in struct. connect() can fail with an "invalid argument" error in that case if the socket is not an IPv4 (AF_INET) socket, ie if it is an IPv6 (AF_INET6) socket instead, which requires a sockaddr_in6 struct.

To fix this, you need to either:

  • get rid of the sockaddr_in and use the IP address in the sockaddr as-is:

    connect(fd, addr->ai_addr, addr->ai_addrlen)

  • get rid of the sockaddr and hard-code the socket type as AF_INET to match the use of sockaddr_in:

    socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)

  •  Tags:  
  • Related