Win32 Port

Ralf Habacker ralf.habacker at freenet.de
Sat Apr 29 11:35:21 PDT 2006


Kosina, Martin schrieb:
> Ralf Habacker wrote:
>
>   
>> to become a little familar with the stuff I tried to hack the sources
>>     
> to 
>   
>> see how complicate a port would be. Tcp connections are mostly working
>>     
>
>   
>> and some data could already be exchanged, but test_names does not
>>     
> finish 
>   
>> it's call. probably as Martin Kosina already stated.
>>     
>
>   
>> - initialisation of winsock library in dbus-sysdeps-utils-win32.c
>>     
>
> I'd like to ask for suggestions on this, as well - it's a perenial
> question for ported libraries that wrap Winsock. Any natural place this
> could happen in the dbus stack? For now, I added something similar -
> _dbus_win32_init() - but is there another place we could stick it that
> would hide this [silly] step? It just needs to execute once (that could
> be handled by a static flag) before any Winsock calls are made.
>
>   
I have used two places :
_dbus_connect_tcp_socket() -> used by client
_dbus_listen_tcp_socket()  -> used by server

in each case before the socket() call.

The related init function looks like this

void _dbus_tcp_init()
{
    static BOOL isCalled = FALSE;
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    DBusError  error;

    if (isCalled)
        return;

    wVersionRequested = MAKEWORD( 2, 2 );

    err = WSAStartup( wVersionRequested, &wsaData );
    isCalled = TRUE;
    if (err)
      fprintf(stderr,"socket initialisation failed with errorcode=%d",err);
    else
      fprintf(stderr,"Winsocket initialisation done");
      //dbus_set_error (&error,"socket initialisation failed with
errorcode=%d",err);
}

>> - fixed socket/file incompatible write/read functions -> 
>> dbus-sysdeps-win32.c has now a isSocket(), which are used in 
>> _dbus_read/_dbus_write
>>     
>
> Just curious - is your isSocket() something like _get_osfhandle()<0 ? Or
> did you find a better WinAPI that answers the handle type precisely ?
>
>   
I used the return code of getsockopt(), which is zero for socket file
types  and  -1  for non socket type. In the second case
WSAGetLastError() returns WSAENOTSOCK

int isSocket(int fd)
{
  char buf[10];
  int len = 10;
  int ret = getsockopt(fd,SOL_SOCKET,SO_TYPE,buf,&len) == 0 ? TRUE : FALSE;
  _dbus_verbose("isSocket called for fd %d => %d
(%d)\n",fd,ret,WSAGetLastError());
  return ret;
}

>> native _dbus_directory_open() , _dbus_directory_get_next_file () 
>> implementations (not tested complete)
>>     
>
> Got those working, as well, the usual FindNextFile() stuff with handles,
> etc.
>
>   
okay, then it is obsolate from my path. Do you have ported the
gettimeofday()  function in dbus-sysdeps-unix.c:_dbus_get_current_time()

>> - Because there are several places changed and some new files are
>>     
> added 
>   
>> i've created a tarball at
>>     
> http://webdev.cegit.de/snapshots/kde-windows/dbus-win
>
> Thanks for sharing that - few other run-time things I had to add to mine
> that turned out to be crucial:
>
> - Sockets must be set non-blocking (this is pretty important or things
> won't work right):
>
> In _dbus_set_fd_nonblocking (), I used:
>
> 	u_long NonBlock;
> 	if (ioctlsocket(fd, FIONBIO, &NonBlock) == SOCKET_ERROR)
> 	{
> 		....
> 	}
>
Ths may fix of one of the problems i had
> - In dbus-transport-unix():do_reading(), I had to check
> WSAGetLastError() == WSAEWOULDBLOCK (errno == EAGAIN won't give the
> right answer with Winsock). Same with writing, when the descriptor is a
> socket.
>   
this could completly managed in dbus_read() and
dbus_write() function by setting errno.

> - vnsnprintf() is used to check required buffer size - the POSIX variant
> returns the number of bytes that are required, on Windows the function
> simply fails. _dbus_string_append_printf_valist() relies on the former
> behavior.
>   
I had patched this too.

dbus_bool_t
_dbus_string_append_printf_valist  (DBusString        *str,
                                    const char        *format,
                                    va_list            args)
{
#ifdef _WIN32
    /* see http://msdn2.microsoft.com/en-us/library/1kt27hek(VS.80).aspx */
    char c[1024];
#else
  char c;
#endif

> Looks like we had couple different philosophies - I #ifdef'ed and
> re-implemented individual calls or small blocks in the original
> dbus-sysdeps* files, ala Tor's diff. The amount of platform-specific
> linecount is ultimately pretty low, so duplicating lot of otherwise
> independent logic seemed somehow undesirable. But the dual-file approach
> has its merits, as well, so its ultimately up to the maintainers - which
> approach is preferable? 
>  


I have used the Qt approach (which is used also by KDE) means to have
- a public header -> for example dbus-transport.h
- optional a private headers -> I found dbus-transport_protected.h
- a platform independent base file,               -> dbus-transport.c
- and platform depending files,                     ->
dbus-tranport-unix.c, dbus-tranport-win32.c

In the above mentioned schema according to this scheme
- unix domain sockets are platform depending and would be located in
dbus-transport-unix.c
- tcp domain sockets are platform independing which little differences,
that means mostly functions would be located in dbus-transport.c maybe
with small platform related catches, some as for example the unix
implementations of dbus_read(), dbus_write()  are located in
dbus-transport-unix.c  and  the win32 counterparts  in
dbus-transport-win32.c. In dbus-transport-win32.c named pipe support
will be also located. This would be the same for other platform related 
code areas.


After relooking into the source there may be also another approach by 
using to use transport related files like
dbus-transport-win32-pipe.c -> containing win32 named pipe
dbus-transport-unix-domain.c -> containing unix domain socket related code
dbus-transport-tcp.c ->  containing tcp related code

to provide a function pointer table similar the following

    int (*init)(..);
    int (*listen)(..);
    int (*connect)(..);
    int (*read)(..);
    int (*write)(..)
    int (*close)(..)
        (*read_credentials)(..)
        (*write_credentials)(..)
    int (*getopt)(..);
    int (*setopt)(..);

either in DBusTransferVTable or DBusServerVTable depending on where it 
fits better and to refactor the relating code.

In my opinion such a concept would makes sense because it will make it 
very easy to add additional procotols as stated in 
http://www.freedesktop.org/wiki/Software_2fDBusRemote.

Ralf




More information about the dbus mailing list