I have been thinking about the correct way to implement AcceptEx, and I was looking for comments about the approach. Note I know all of these cases will require tests, I'm just listing them for problems someone might see.
Wineserver changes: - add an async* to the socket structure to track this socket's request on the listening socket's queue. (set = null on accept) - Can anything do anything wrong while trying to remove the async when the accepting socket is closed before the accept event is received? (removing another socket's async request) - When/how should we handle setting this (create a new request type (that queues & sets), create a new request type (that just sets) or somehow splice into sock_queue_async? - my vote for first, as much as I hate it) - change accept_socket to use two sockets instead of returning the accepted socket - Problem: we have to destroy the fd of the old socket. Can anything queue async reads/writes before the overlapped acceptex returns? Do we care that the fd of a socket object gets switched (you lose internal state, but I don't think you can have a lot of state on an unbound socket) - Deferred sockets are a pain: 2 clients attempt to connect->accept->defer->acceptex=which socket does it return? Also if this order happens, and we have to destroy the fd as above, would the application possibly care? - need to implement SO_UPDATE_ACCEPT_CONTEXT and have accept() call it right after getting an accept. - if we close the listener socket, what happens to sockets waiting for clients on the accepting socket? Can we reuse these sockets?
ws2 changes: - exactly the same as the previous attempt, just using the above requests - more strict checks are needed on the second acceptex socket (need to check family, bound state) - accept: a = create_socket(), accept_socket(listener, a), ioctl)SO_UPDATE_ACCEPT_CONTEXT, a, &listener);
I just started looking at wineserver, so don't be surprised if something above doesn't make sense.
Mike.