Users of AsyncTCP expect callbacks installed on the object to remain
active on close event and do not reinstall them if the just-closed
object is reopened. Fixes failure to react to events after reopening.
Prior to this commit, the mutex that protected the global client socket
list was non-recursive. This forced the release of the mutex before
iterating through sockets on which to call callbacks. However, releasing
the mutex allowed destructors to proceed, therefore possibly
invalidating the object pointers copied to the local list. This in turn
risked calling callbacks on already destroyed objects. Fixed by the use
of a recursive mutex that allows holding the mutex during the callback
invocation.
The discard callback (installed via onDisconnect()) can legitimately
decide to destroy the AsyncTCP client, calling the destructors which in
turn invalidate the write mutex object. Prior to this commit, calling
_clearWriteQueue() (which takes said write mutex) risked accessing
uninitialized memory and causing memory corruption. Fixed.
This prevents a race condicion of the ::add() method modifying the queue
and being preempted by the high-priority asyncTcpSock task that in turn
flushes the same queue to the socket, therefore modifying the queue.