efl/src/lib/ecore_con/efl_net_dialer_windows.c

159 lines
5.0 KiB
C

#define EFL_NET_SOCKET_WINDOWS_PROTECTED 1
#define EFL_IO_READER_PROTECTED 1
#define EFL_IO_WRITER_PROTECTED 1
#define EFL_IO_CLOSER_PROTECTED 1
#define EFL_NET_DIALER_PROTECTED 1
#define EFL_NET_SOCKET_PROTECTED 1
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <evil_private.h> /* evil_format_message evil_last_error_get */
#include "Ecore.h"
#include "Ecore_Con.h"
#include "ecore_con_private.h"
#define MY_CLASS EFL_NET_DIALER_WINDOWS_CLASS
typedef struct _Efl_Net_Dialer_Windows_Data
{
Eina_Stringshare *address_dial;
double timeout_dial;
Eina_Bool connected;
} Efl_Net_Dialer_Windows_Data;
EOLIAN static void
_efl_net_dialer_windows_efl_object_destructor(Eo *o, Efl_Net_Dialer_Windows_Data *pd)
{
efl_destructor(efl_super(o, MY_CLASS));
eina_stringshare_replace(&pd->address_dial, NULL);
}
EOLIAN static Eina_Error
_efl_net_dialer_windows_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Windows_Data *pd, const char *address)
{
Eina_Error err;
HANDLE h;
char cstr[256], sstr[256];
ULONG cpid, spid;
EINA_SAFETY_ON_NULL_RETURN_VAL(address, EINVAL);
EINA_SAFETY_ON_TRUE_RETURN_VAL(strchr(address, '/') != NULL, EINVAL);
EINA_SAFETY_ON_TRUE_RETURN_VAL(strchr(address, '\\') != NULL, EINVAL);
EINA_SAFETY_ON_TRUE_RETURN_VAL(strlen(PIPE_NS) + strlen(address) >= 256, EINVAL);
EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_net_dialer_connected_get(o), EISCONN);
efl_net_dialer_address_dial_set(o, address);
h = CreateFile(pd->address_dial,
FILE_READ_ATTRIBUTES | FILE_READ_DATA |
FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
if (h == INVALID_HANDLE_VALUE)
{
DWORD win32err = GetLastError();
switch (win32err)
{
case ERROR_ACCESS_DENIED: return EACCES;
case ERROR_INVALID_PARAMETER: return EINVAL;
case ERROR_SHARING_VIOLATION: return EINVAL;
case ERROR_FILE_EXISTS: return EEXIST;
case ERROR_FILE_NOT_FOUND: return ENOENT;
case ERROR_PIPE_BUSY: return EBUSY;
case ERROR_INVALID_NAME: return EADDRNOTAVAIL;
default:
{
ERR("CreateFile(%s): Unexpected win32err=%lu (%s)",
pd->address_dial, win32err, evil_format_message(win32err));
return EINVAL;
}
}
}
err = _efl_net_socket_windows_init(o, h);
if (err)
{
CloseHandle(h);
return err;
}
if (GetNamedPipeClientProcessId(_efl_net_socket_windows_handle_get(o), &cpid))
snprintf(cstr, sizeof(cstr), "%s:%lu", address, cpid);
else
{
WRN("server=%p (%s) could not GetNamedPipeClientProcessId(o): %s",
o, address, evil_last_error_get());
eina_strlcpy(cstr, address, sizeof(cstr));
}
if (GetNamedPipeServerProcessId(_efl_net_socket_windows_handle_get(o), &spid))
snprintf(sstr, sizeof(sstr), "%s:%lu", address, spid);
else
{
WRN("server=%p (%s) could not GetNamedPipeServerProcessId(o): %s",
o, address, evil_last_error_get());
eina_strlcpy(sstr, address, sizeof(sstr));
}
efl_net_socket_address_remote_set(o, sstr);
efl_net_socket_address_local_set(o, cstr);
efl_event_callback_call(o, EFL_NET_DIALER_EVENT_DIALER_RESOLVED, NULL);
efl_net_dialer_connected_set(o, EINA_TRUE);
return _efl_net_socket_windows_io_start(o);
}
EOLIAN static void
_efl_net_dialer_windows_efl_net_dialer_address_dial_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Windows_Data *pd, const char *address)
{
const char *tmp = eina_stringshare_printf(PIPE_NS "%s", address);
eina_stringshare_del(pd->address_dial);
pd->address_dial = tmp;
}
EOLIAN static const char *
_efl_net_dialer_windows_efl_net_dialer_address_dial_get(const Eo *o EINA_UNUSED, Efl_Net_Dialer_Windows_Data *pd)
{
return pd->address_dial + strlen(PIPE_NS);
}
EOLIAN static void
_efl_net_dialer_windows_efl_net_dialer_connected_set(Eo *o, Efl_Net_Dialer_Windows_Data *pd, Eina_Bool connected)
{
if (pd->connected == connected) return;
pd->connected = connected;
if (connected) efl_event_callback_call(o, EFL_NET_DIALER_EVENT_DIALER_CONNECTED, NULL);
}
EOLIAN static Eina_Bool
_efl_net_dialer_windows_efl_net_dialer_connected_get(const Eo *o EINA_UNUSED, Efl_Net_Dialer_Windows_Data *pd)
{
return pd->connected;
}
EOLIAN static void
_efl_net_dialer_windows_efl_net_dialer_timeout_dial_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Windows_Data *pd, double seconds)
{
pd->timeout_dial = seconds;
}
EOLIAN static double
_efl_net_dialer_windows_efl_net_dialer_timeout_dial_get(const Eo *o EINA_UNUSED, Efl_Net_Dialer_Windows_Data *pd)
{
return pd->timeout_dial;
}
EOLIAN static Eina_Error
_efl_net_dialer_windows_efl_io_closer_close(Eo *o, Efl_Net_Dialer_Windows_Data *pd EINA_UNUSED)
{
efl_net_dialer_connected_set(o, EINA_FALSE);
return efl_io_closer_close(efl_super(o, MY_CLASS));
}
#include "efl_net_dialer_windows.eo.c"