WSL/test/linux/unit_tests/socket_nonblock.c
Josh Soref abce91d14b
Spelling (#12954)
* link: Collect WSL logs (recommended method)

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Advanced Authoring Tests in C++

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: CMake Documentation and Community

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Collect WSL logs for networking issues

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* link: Collect WSL logs (recommended method)

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: ; otherwise,

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: a

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: access

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: accessible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: across

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: actively

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: adapters

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: address

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: addresses

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: and

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: appropriate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: argument

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: associated

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: attach

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: available

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: beginning

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: between

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: binaries

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: bound

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: buffer

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: buffers

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: cannot

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: canonical

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: capabilities

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: case-insensitive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: case-sensitive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: certified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: command

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: committer

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: communication

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: complains

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: configuration

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: consumed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: continue

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: converted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: currently

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: customers

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: daemon

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: deferred

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: definitions

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: delimiter

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: delivered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: dellink

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: derived

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: descriptor

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destined

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destruct

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destructible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: destructor

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: detach

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: differentiate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: directories

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: disassociate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: disposition

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: distribution

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: distro

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: duping

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: emitted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: empty

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: environment

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: every time

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: exclusive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: expected

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: expire

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: explicitly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: fall back

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: false

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: fastfail

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: filesystem

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: first

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: followed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: for

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: functionality

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: functionally

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: github

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: greater

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: guarantee

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: guaranteed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: handles

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hangup

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hierarchy

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hogwarts

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: hydrated

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: icrnl

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: implementation

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: implementing

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: initialize

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instance

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instantiate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: instantiations

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: intentionally

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: interpret

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: interpreter

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: irreversibly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: iteration

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: iterator

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: its

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: kernel

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: kmsg

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: knowledge

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: maximum

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: mirrored

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: msftconnecttest

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: multi

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: multiple

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: mutable

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: namespace

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: nonexistent

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: notifications

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: occurred

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: occurring

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: otherwise,

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: outstanding

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: overridden

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: partition

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: pass through

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: passthrough

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: performs

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: periodically

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: positional

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: precedence

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: preexisting

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: preferring

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: prepopulate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: previous

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: privileges

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: process

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: processes

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: programmatically

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: protection

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: provided

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: reasonable

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: receive

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: received

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: red hat

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: reentrant

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: registered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: regularly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: relay

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: release

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: representing

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: requests

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: response

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: resurrect

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: retention

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: returned

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: security

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: semaphore

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: separate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: separator

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: service

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: set up

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: setup

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: severely

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: should

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: signal

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: similarly

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: simple

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: simplified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: single

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: specified

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: splitting

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: standard

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: stress

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: succeed

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: success

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: successfully

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: supplementary

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: synced

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: system

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: take

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: than

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: that opening

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: the

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: threadpool

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: to

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: true

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: truncate

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: tunneling

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unexpected

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: uninitialize

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unique

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unprivileged

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: unregistered

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: untrusted

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: upgrade

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: utility

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: validating

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variant

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variation

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: variations

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: verify

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: visible

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: whether

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: winget

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: worker

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: written

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* spelling: wslservice

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>

* format source

---------

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
Co-authored-by: Ben Hillis <benhillis@gmail.com>
Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
2025-07-23 15:19:00 -07:00

650 lines
14 KiB
C

/*++
Copyright (c) Microsoft. All rights reserved.
Module Name:
socket_nonblock.c
Abstract:
This file is a simple test for nonblocking sockets.
--*/
#include "lxtcommon.h"
#include "unittests.h"
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netdb.h>
#include "common.h"
#include <sys/wait.h>
#define LXT_NAME "socket_nonblocking"
int SocketAsyncTest(PLXT_ARGS Args);
#define SOCKET_NAME "PartyInTheUsa"
//
// Global constants
//
static const LXT_VARIATION g_LxtVariations[] = {
{"Socket_Async_Simple", SocketAsyncTest},
};
int SocketNonblockTestEntry(int Argc, char* Argv[])
/*++
--*/
{
LXT_ARGS Args;
int Result;
LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
ErrorExit:
LxtUninitialize();
return !LXT_SUCCESS(Result);
}
#ifndef EPOLLONESHOT
#define EPOLLONESHOT (1 << 30)
#endif
int NonblockEpollCreateClientSocket(int IsNonBlocking)
/*++
--*/
{
int Result;
struct sockaddr_in ServerAddress = {0};
int Socket;
//
// Create a socket.
//
Socket = socket(AF_INET, SOCK_STREAM, 0);
if (Socket < 0)
{
LxtLogError("socket(AF_INET, SOCK_STREAM, 0) - %s", strerror(errno));
Result = -1;
goto cleanup;
}
//
// Connect to the server.
//
ServerAddress.sin_family = AF_INET;
ServerAddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
ServerAddress.sin_port = htons(LXT_SOCKET_DEFAULT_PORT);
Result = connect(Socket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress));
if (Result < 0)
{
LxtLogError("connect(%d) - %s", Socket, strerror(errno));
Result = -1;
goto cleanup;
}
//
// Set the socket as non blocking.
//
if (IsNonBlocking != 0)
{
Result = fcntl(Socket, F_SETFL, O_NONBLOCK);
if (Result < 0)
{
LxtLogError("fcntl(%d) - %d", Socket, errno);
Result = -1;
goto cleanup;
}
}
Result = Socket;
Socket = 0;
cleanup:
if (Socket > 0)
{
if (close(Socket) != 0)
{
LxtLogError("close(%d) - %s", Socket, strerror(errno));
Result = LXT_RESULT_FAILURE;
}
}
return Result;
}
int NonblockEpollCreateClientUnixSocket(int IsNonBlocking)
/*++
--*/
{
int Result;
struct sockaddr_un ServerAddress = {0};
int Socket;
//
// Create a socket.
//
Socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (Socket < 0)
{
LxtLogError("socket(AF_UNIX, SOCK_STREAM, 0) - %s", strerror(errno));
Result = -1;
goto cleanup;
}
//
// Connect to the server.
//
ServerAddress.sun_family = AF_UNIX;
strcpy(ServerAddress.sun_path, SOCKET_NAME);
Result = connect(Socket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress));
if (Result < 0)
{
LxtLogError("connect(%d) - %s", Socket, strerror(errno));
Result = -1;
goto cleanup;
}
//
// Set the socket as non blocking.
//
if (IsNonBlocking != 0)
{
Result = fcntl(Socket, F_SETFL, O_NONBLOCK);
if (Result < 0)
{
LxtLogError("fcntl(%d) - %d", Socket, errno);
Result = -1;
goto cleanup;
}
}
Result = Socket;
Socket = 0;
cleanup:
if (Socket > 0)
{
if (close(Socket) != 0)
{
LxtLogError("close(%d) - %s", Socket, strerror(errno));
Result = LXT_RESULT_FAILURE;
}
}
return Result;
}
int NonblockEpollCreateListenSocket(int IsNonBlocking)
/*++
--*/
{
struct sockaddr_in ServerAddress = {0};
int Result;
int Socket;
//
// Create a socket.
//
Socket = socket(AF_INET, SOCK_STREAM, 0);
if (Socket < 0)
{
LxtLogError("socket - %s", strerror(errno));
Result = -1;
goto cleanup;
}
//
// Bind the socket to an ipv4 socket.
//
ServerAddress.sin_family = AF_INET;
ServerAddress.sin_addr.s_addr = INADDR_ANY;
ServerAddress.sin_port = htons(LXT_SOCKET_DEFAULT_PORT);
Result = bind(Socket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress));
if (Result < 0)
{
LxtLogError("bind(%d) - %s", Socket, strerror(errno));
Result = -1;
goto cleanup;
}
//
// Mark the socket as a listen socket.
//
Result = listen(Socket, LXT_SOCKET_SERVER_MAX_BACKLOG_NUM);
if (Result < 0)
{
LxtLogError("listen(%d) - %s", Socket, strerror(errno));
Result = -1;
goto cleanup;
}
//
// Set the socket as non blocking.
//
if (IsNonBlocking != 0)
{
Result = fcntl(Socket, F_SETFL, O_NONBLOCK);
if (Result < 0)
{
LxtLogError("fcntl(%d) - %d", Socket, errno);
Result = -1;
goto cleanup;
}
}
Result = Socket;
Socket = 0;
cleanup:
if (Socket > 0)
{
if (close(Socket) != 0)
{
LxtLogError("close(%d) - %s", Socket, strerror(errno));
}
}
return Result;
}
int NonblockEpollCreateListenUnixSocket(int IsNonBlocking)
/*++
--*/
{
struct sockaddr_un ServerAddress = {0};
int Result;
int Socket;
//
// Create a socket.
//
Socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (Socket < 0)
{
LxtLogError("socket - %s", strerror(errno));
Result = -1;
goto cleanup;
}
//
// Bind the socket to an ipv4 socket.
//
ServerAddress.sun_family = AF_UNIX;
strcpy(ServerAddress.sun_path, SOCKET_NAME);
Result = bind(Socket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress));
if (Result < 0)
{
LxtLogError("bind(%d) - %s", Socket, strerror(errno));
Result = -1;
goto cleanup;
}
//
// Mark the socket as a listen socket.
//
Result = listen(Socket, LXT_SOCKET_SERVER_MAX_BACKLOG_NUM);
if (Result < 0)
{
LxtLogError("listen(%d) - %s", Socket, strerror(errno));
Result = -1;
goto cleanup;
}
//
// Set the socket as non blocking.
//
if (IsNonBlocking != 0)
{
Result = fcntl(Socket, F_SETFL, O_NONBLOCK);
if (Result < 0)
{
LxtLogError("fcntl(%d) - %d", Socket, errno);
Result = -1;
goto cleanup;
}
}
Result = Socket;
Socket = 0;
cleanup:
if (Socket > 0)
{
if (close(Socket) != 0)
{
LxtLogError("close(%d) - %s", Socket, strerror(errno));
}
}
return Result;
}
int NonblockEpollHandleClientAccept(int Socket)
/*++
--*/
{
struct sockaddr_in ClientAddress = {0};
socklen_t ClientLength;
int Error;
int Result;
int RetryCount;
ClientLength = sizeof(ClientAddress);
Result = -1;
RetryCount = 0;
while (1)
{
Result = accept(Socket, (struct sockaddr*)&ClientAddress, &ClientLength);
if (Result < 0)
{
Error = errno;
LxtLogInfo("[Server] accept(%d) returned %d (error %d)", Socket, Result, Error);
if (Error == EAGAIN)
{
LxtLogInfo("[Server] nonblocking accept said try again, sleeping...");
usleep(1 * 1000 * 1000);
RetryCount += 1;
if (RetryCount > 10)
{
LxtLogInfo("[Server] too many retries, exiting...");
Result = -1;
goto cleanup;
}
continue;
}
}
break;
}
cleanup:
return Result;
}
const char* NonblockDataToWrite[] = {
"<This is the first message> ",
"<This is another message> ",
"<Dumbledore is dead> ",
"<Harry Potter must not go back to Hogwarts> ",
"<There must always be a stark in Winterfell>",
};
const int NonblockWriteItemCount = sizeof(NonblockDataToWrite) / sizeof(NonblockDataToWrite[0]);
int SocketAsyncTest(PLXT_ARGS Args)
/*++
--*/
{
char Buffer[256];
int Result;
int EpollFileDescriptor;
int FileDescriptor1;
int FileDescriptor2;
struct epoll_event EpollControlEvent;
struct epoll_event EpollWaitEvent[2];
int ChildPid;
int Index;
int ChildStatus;
int RetryCount;
//
// Initialize locals.
//
FileDescriptor1 = -1;
FileDescriptor2 = -1;
EpollFileDescriptor = -1;
ChildPid = -1;
//
// Create the server socket.
//
LxtLogInfo("[Setup] About to create server socket...");
FileDescriptor1 = NonblockEpollCreateListenSocket(1);
if (FileDescriptor1 == -1)
{
Result = errno;
LxtLogError("[Setup] Could not create socket! %d", Result);
goto cleanup;
}
//
// Fork to create a server and a client.
//
LxtLogInfo("[Setup] About to fork...");
ChildPid = fork();
if (ChildPid == -1)
{
Result = errno;
LxtLogError("[Setup] Fork failed! %d", Result);
goto cleanup;
}
if (ChildPid == 0)
{
LxtLogInfo("[Client] Waiting 5 seconds to let server block...");
usleep(5 * 1000 * 1000);
LxtLogInfo("[Client] Connecting to server...");
FileDescriptor2 = NonblockEpollCreateClientSocket(1);
if (FileDescriptor2 == -1)
{
Result = errno;
LxtLogError("[Client] Could not connect to server! %d", Result);
goto cleanup;
}
LxtLogInfo("[Client] Connected to server, fd = %d", FileDescriptor2);
//
// Wait for data to be available in a loop.
//
RetryCount = 0;
while (1)
{
LxtLogInfo("[Client] Trying to read data ...");
memset(Buffer, 0, sizeof(Buffer));
Result = read(FileDescriptor2, Buffer, sizeof(Buffer));
if (Result < 0)
{
Result = errno;
if (Result = EAGAIN)
{
LxtLogInfo("[Client] No data available, will try again...");
usleep(1 * 1000 * 1000);
RetryCount += 1;
if (RetryCount > 10)
{
LxtLogInfo("[Client] Too many retries, exiting...");
Result = -1;
goto cleanup;
}
continue;
}
Result = -1;
goto cleanup;
}
LxtLogInfo("[Client] read %d bytes: %s ...", Result, Buffer);
if (Result == 0)
{
LxtLogInfo("[Client] exiting after reading 0 bytes ...");
goto cleanup;
}
//
// Reset the retry count after a successful read.
//
RetryCount = 0;
}
}
//
// Accept an incoming connection.
//
FileDescriptor2 = NonblockEpollHandleClientAccept(FileDescriptor1);
if (FileDescriptor2 == -1)
{
Result = errno;
LxtLogError("[Server] Could not accept! %d", Result);
goto cleanup;
}
LxtLogInfo("[Server] Writing to socket %d times!", NonblockWriteItemCount);
for (Index = 0; Index < NonblockWriteItemCount; Index += 1)
{
Result = write(FileDescriptor2, NonblockDataToWrite[Index], strlen(NonblockDataToWrite[Index]));
if (Result < 0)
{
LxtLogError("[Server] Write %d failed %d", Index, Result);
goto cleanup;
}
LxtLogInfo(
"[Server] Write (%d, %s, %d) -> %d!",
FileDescriptor2,
NonblockDataToWrite[Index],
strlen(NonblockDataToWrite[Index]) + (Index == NonblockWriteItemCount - 1),
Result);
usleep(1 * 1000 * 1000);
}
LxtLogInfo("[Server] Closing client fd = %d", FileDescriptor2);
if (FileDescriptor2 != -1)
{
close(FileDescriptor2);
FileDescriptor2 = -1;
}
LxtLogInfo("[Server] Waiting for child to exit");
ChildStatus = 0;
wait(&ChildStatus);
LxtLogInfo("[Server] Child WIFEXITED=%d WEXITSTATUS=%d", WIFEXITED(ChildStatus), WEXITSTATUS(ChildStatus));
//
// Determine if the test passed or failed.
//
if ((Result < 0) || (WIFEXITED(ChildStatus) == 0) || (WEXITSTATUS(ChildStatus) != 0))
{
LxtLogInfo("[Server] Test failed!");
Result = -1;
}
LxtLogInfo("[Server] Done");
cleanup:
if (FileDescriptor1 != -1)
{
close(FileDescriptor1);
}
if (EpollFileDescriptor != -1)
{
close(EpollFileDescriptor);
}
if (FileDescriptor2 != -1)
{
close(FileDescriptor2);
}
if (ChildPid == 0)
{
LxtLogInfo("[Child] Exit with %d!", Result);
_exit(Result);
}
return Result;
}