On Thu, Mar 23, 2017 at 9:45 AM, Vincent Torri <[email protected]> wrote:
> if i have read the code correctly, there are problems:
>
> Efl_Net_Socket_Windows_Operation is an analogous of my IRP but you're
> wrong in modifying it, this will not work
elaborate on that please? How is it not working? The relevant change is:
your code used a enum (op), then a single "complete cb" that would use
a "switch" on that op... then switch on errors... I changed that to 2
callbacks, on non-errors, call the success callback, on failure call
the error callback. Your single callback with nested switch is
replaced my multiple callbacks, one for each scope.
please elaborate more on why is it wrong and what could go wrong.
> my error_check is not correctly ported
again, elaborate on that. Taking
_efl_net_server_windows_client_listen() as example:
op = _efl_net_socket_windows_operation_new(pd->next_client,
_efl_net_server_windows_client_listen_success,
_efl_net_server_windows_client_listen_failure,
o);
if (!ConnectNamedPipe(h, ovl))
{
err = GetLastError();
if (err == ERROR_IO_PENDING)
return 0;
else if (err == ERROR_PIPE_CONNECTED)
{
_efl_net_socket_windows_operation_succeeded(op,
(Eina_Rw_Slice){}); // calls CancelThreadpool...
return 0;
}
else
{
_efl_net_socket_windows_operation_failed(op, err); //
calls CancelThreadpool...
return err;
}
}
_efl_net_socket_windows_operation_failed(op, EINVAL); // calls
CancelThreadpool...
Is the same as your _server_listen():
irp = _irp_new(svr, PIPE_CONNECT, NULL);
if (irp)
{
StartThreadpoolIo(svr->io);
_irp_error_check(irp,
ConnectNamedPipe(svr->pipe, (OVERLAPPED *)irp),
svr->io);
return 1;
}
_irp_del(irp);
with your _irp_error_check():
if (!b) // result of ConnectNamedPipe()...
{
DWORD error = GetLastError();
error = GetLastError();
fprintf(stdout, "%s<0x%p> : %lx %lx\n", "CheckError", irp->svr,
STATUS_PENDING, error);
if (error != ERROR_IO_PENDING)
{
CancelThreadpoolIo(io);
_irp_on_complete(irp, error, 0);
}
}
an your _server_on_complete() which is caleld by _irp_on_complete():
...
else if (op == PIPE_CONNECT)
{
switch (error)
{
case ERROR_SUCCESS: /* client just connected */
case ERROR_PIPE_CONNECTED: /* client already connected */
case ERROR_NO_DATA: /* client already connected and
disconnected (really client can send data before disconnect, exist
sense do read) */
if (_server_on_connect(svr))
_server_read(svr);
break;
case ERROR_BROKEN_PIPE: /* server call CloseHandle before
ConnectNamedPipe complete */
case ERROR_PIPE_NOT_CONNECTED: /* server call
DisconnectNamedPipe before ConnectNamedPipe */
case ERROR_OPERATION_ABORTED: /* server call CancelIo[Ex] */
break;
default:
__debugbreak();
}
}
Note: StartThreadpoolIo() is done inside
_efl_net_socket_windows_operation_new().
> the _client|server_on_complete function MUST handle all the I/O
> connections, that is, the connectiion of the client to the server, the
> read I/O and the write I/O. It's not done
As I understand, the OVERLAPPED handle you give to the operation will
be received in the callback, you use that to check "op ==
PIPE_CONNECT", it's extracted from OVERLAPPED extension
(IO_Request_Packet->op). You use:
typedef enum
{
PIPE_CONNECT,
PIPE_READ,
PIPE_WRITE
} Pipe_Operation;
struct _IO_Request_Packet
{
OVERLAPPED ol;
...
Pipe_Operation op;
};
static void
_server_on_complete(...)
{
if (op == PIPE_READ)
{
switch (error)
{
case ERROR_SUCCESS: ...
case ERROR_BROKEN_PIPE: ...
case ERROR_OPERATION_ABORTED: ...
In my code, I use a function pointer for that, my IO_Request_Packet
equivalent is:
struct _Efl_Net_Socket_Windows_Operation
{
OVERLAPPED base;
Efl_Net_Socket_Windows_Operation_Success_Cb success_cb;
Efl_Net_Socket_Windows_Operation_Failure_Cb failure_cb;
const void *data;
...
};
success_cb/failure_cb + data covers what your "op" + checking errors
do inside _server_on_completed():
static void
_efl_net_socket_windows_operation_done(...)
{
if (err)
op->failure_cb((void *)op->data, op->o, err);
else
op->success_cb((void *)op->data, op->o, slice);
}
if you want to be explicit, can use if (err == ERROR_SUCCESS)...
> If you don't do exactly what I have done, and if you modify this code
> based on 2 unrelated msdn doc, this will not work
Those 2 MSDN documentation doesn't use the thread pool, but they
execute the same sequence, they check errors, etc. They are not the
same code as yours, as your code is not the same as the one inside
EFL. Actually, I explained to you how to create your code already
inside Efl using UNIX socket as guideline, you opted to create it
outside, then it's expected it wouldn't fit "as is", which required me
to modify as I did.
--
Gustavo Sverzut Barbieri
--------------------------------------
Mobile: +55 (16) 99354-9890
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel