sysdeps_win32.c revision 4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53
1#include "sysdeps.h"
2#include <windows.h>
3#include <winsock2.h>
4#include <stdio.h>
5#include <errno.h>
6#define  TRACE_TAG  TRACE_SYSDEPS
7#include "adb.h"
8
9extern void fatal(const char *fmt, ...);
10
11#define assert(cond)  do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0)
12
13/**************************************************************************/
14/**************************************************************************/
15/*****                                                                *****/
16/*****      replaces libs/cutils/load_file.c                          *****/
17/*****                                                                *****/
18/**************************************************************************/
19/**************************************************************************/
20
21void *load_file(const char *fn, unsigned *_sz)
22{
23    HANDLE    file;
24    char     *data;
25    DWORD     file_size;
26
27    file = CreateFile( fn,
28                       GENERIC_READ,
29                       FILE_SHARE_READ,
30                       NULL,
31                       OPEN_EXISTING,
32                       0,
33                       NULL );
34
35    if (file == INVALID_HANDLE_VALUE)
36        return NULL;
37
38    file_size = GetFileSize( file, NULL );
39    data      = NULL;
40
41    if (file_size > 0) {
42        data = (char*) malloc( file_size + 1 );
43        if (data == NULL) {
44            D("load_file: could not allocate %ld bytes\n", file_size );
45            file_size = 0;
46        } else {
47            DWORD  out_bytes;
48
49            if ( !ReadFile( file, data, file_size, &out_bytes, NULL ) ||
50                 out_bytes != file_size )
51            {
52                D("load_file: could not read %ld bytes from '%s'\n", file_size, fn);
53                free(data);
54                data      = NULL;
55                file_size = 0;
56            }
57        }
58    }
59    CloseHandle( file );
60
61    *_sz = (unsigned) file_size;
62    return  data;
63}
64
65/**************************************************************************/
66/**************************************************************************/
67/*****                                                                *****/
68/*****    common file descriptor handling                             *****/
69/*****                                                                *****/
70/**************************************************************************/
71/**************************************************************************/
72
73typedef const struct FHClassRec_*   FHClass;
74
75typedef struct FHRec_*          FH;
76
77typedef struct EventHookRec_*  EventHook;
78
79typedef struct FHClassRec_
80{
81    void (*_fh_init) ( FH  f );
82    int  (*_fh_close)( FH  f );
83    int  (*_fh_lseek)( FH  f, int  pos, int  origin );
84    int  (*_fh_read) ( FH  f, void*  buf, int  len );
85    int  (*_fh_write)( FH  f, const void*  buf, int  len );
86    void (*_fh_hook) ( FH  f, int  events, EventHook  hook );
87
88} FHClassRec;
89
90/* used to emulate unix-domain socket pairs */
91typedef struct SocketPairRec_*  SocketPair;
92
93typedef struct FHRec_
94{
95    FHClass    clazz;
96    int        used;
97    int        eof;
98    union {
99        HANDLE      handle;
100        SOCKET      socket;
101        SocketPair  pair;
102    } u;
103
104    HANDLE    event;
105    int       mask;
106
107    char  name[32];
108
109} FHRec;
110
111#define  fh_handle  u.handle
112#define  fh_socket  u.socket
113#define  fh_pair    u.pair
114
115#define  WIN32_FH_BASE    100
116
117#define  WIN32_MAX_FHS    128
118
119static adb_mutex_t   _win32_lock;
120static  FHRec        _win32_fhs[ WIN32_MAX_FHS ];
121static  int          _win32_fh_count;
122
123static FH
124_fh_from_int( int   fd )
125{
126    FH  f;
127
128    fd -= WIN32_FH_BASE;
129
130    if (fd < 0 || fd >= _win32_fh_count) {
131        D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
132        errno = EBADF;
133        return NULL;
134    }
135
136    f = &_win32_fhs[fd];
137
138    if (f->used == 0) {
139        D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
140        errno = EBADF;
141        return NULL;
142    }
143
144    return f;
145}
146
147
148static int
149_fh_to_int( FH  f )
150{
151    if (f && f->used && f >= _win32_fhs && f < _win32_fhs + WIN32_MAX_FHS)
152        return (int)(f - _win32_fhs) + WIN32_FH_BASE;
153
154    return -1;
155}
156
157static FH
158_fh_alloc( FHClass  clazz )
159{
160    int  nn;
161    FH   f = NULL;
162
163    adb_mutex_lock( &_win32_lock );
164
165    if (_win32_fh_count < WIN32_MAX_FHS) {
166        f = &_win32_fhs[ _win32_fh_count++ ];
167        goto Exit;
168    }
169
170    for (nn = 0; nn < WIN32_MAX_FHS; nn++) {
171        if ( _win32_fhs[nn].clazz == NULL) {
172            f = &_win32_fhs[nn];
173            goto Exit;
174        }
175    }
176    D( "_fh_alloc: no more free file descriptors\n" );
177Exit:
178    if (f) {
179        f->clazz = clazz;
180        f->used  = 1;
181        f->eof   = 0;
182        clazz->_fh_init(f);
183    }
184    adb_mutex_unlock( &_win32_lock );
185    return f;
186}
187
188
189static int
190_fh_close( FH   f )
191{
192    if ( f->used ) {
193        f->clazz->_fh_close( f );
194        f->used = 0;
195        f->eof  = 0;
196        f->clazz = NULL;
197    }
198    return 0;
199}
200
201/* forward definitions */
202static const FHClassRec   _fh_file_class;
203static const FHClassRec   _fh_socket_class;
204
205/**************************************************************************/
206/**************************************************************************/
207/*****                                                                *****/
208/*****    file-based descriptor handling                              *****/
209/*****                                                                *****/
210/**************************************************************************/
211/**************************************************************************/
212
213static void
214_fh_file_init( FH  f )
215{
216    f->fh_handle = INVALID_HANDLE_VALUE;
217}
218
219static int
220_fh_file_close( FH  f )
221{
222    CloseHandle( f->fh_handle );
223    f->fh_handle = INVALID_HANDLE_VALUE;
224    return 0;
225}
226
227static int
228_fh_file_read( FH  f,  void*  buf, int   len )
229{
230    DWORD  read_bytes;
231
232    if ( !ReadFile( f->fh_handle, buf, (DWORD)len, &read_bytes, NULL ) ) {
233        D( "adb_read: could not read %d bytes from %s\n", len, f->name );
234        errno = EIO;
235        return -1;
236    } else if (read_bytes < (DWORD)len) {
237        f->eof = 1;
238    }
239    return (int)read_bytes;
240}
241
242static int
243_fh_file_write( FH  f,  const void*  buf, int   len )
244{
245    DWORD  wrote_bytes;
246
247    if ( !WriteFile( f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL ) ) {
248        D( "adb_file_write: could not write %d bytes from %s\n", len, f->name );
249        errno = EIO;
250        return -1;
251    } else if (wrote_bytes < (DWORD)len) {
252        f->eof = 1;
253    }
254    return  (int)wrote_bytes;
255}
256
257static int
258_fh_file_lseek( FH  f, int  pos, int  origin )
259{
260    DWORD  method;
261    DWORD  result;
262
263    switch (origin)
264    {
265        case SEEK_SET:  method = FILE_BEGIN; break;
266        case SEEK_CUR:  method = FILE_CURRENT; break;
267        case SEEK_END:  method = FILE_END; break;
268        default:
269            errno = EINVAL;
270            return -1;
271    }
272
273    result = SetFilePointer( f->fh_handle, pos, NULL, method );
274    if (result == INVALID_SET_FILE_POINTER) {
275        errno = EIO;
276        return -1;
277    } else {
278        f->eof = 0;
279    }
280    return (int)result;
281}
282
283static void  _fh_file_hook( FH  f, int  event, EventHook  eventhook );  /* forward */
284
285static const FHClassRec  _fh_file_class =
286{
287    _fh_file_init,
288    _fh_file_close,
289    _fh_file_lseek,
290    _fh_file_read,
291    _fh_file_write,
292    _fh_file_hook
293};
294
295/**************************************************************************/
296/**************************************************************************/
297/*****                                                                *****/
298/*****    file-based descriptor handling                              *****/
299/*****                                                                *****/
300/**************************************************************************/
301/**************************************************************************/
302
303int  adb_open(const char*  path, int  options)
304{
305    FH  f;
306
307    DWORD  desiredAccess       = 0;
308    DWORD  shareMode           = FILE_SHARE_READ | FILE_SHARE_WRITE;
309
310    switch (options) {
311        case O_RDONLY:
312            desiredAccess = GENERIC_READ;
313            break;
314        case O_WRONLY:
315            desiredAccess = GENERIC_WRITE;
316            break;
317        case O_RDWR:
318            desiredAccess = GENERIC_READ | GENERIC_WRITE;
319            break;
320        default:
321            D("adb_open: invalid options (0x%0x)\n", options);
322            errno = EINVAL;
323            return -1;
324    }
325
326    f = _fh_alloc( &_fh_file_class );
327    if ( !f ) {
328        errno = ENOMEM;
329        return -1;
330    }
331
332    f->fh_handle = CreateFile( path, desiredAccess, shareMode, NULL, OPEN_EXISTING,
333                               0, NULL );
334
335    if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
336        _fh_close(f);
337        D( "adb_open: could not open '%s':", path );
338        switch (GetLastError()) {
339            case ERROR_FILE_NOT_FOUND:
340                D( "file not found\n" );
341                errno = ENOENT;
342                return -1;
343
344            case ERROR_PATH_NOT_FOUND:
345                D( "path not found\n" );
346                errno = ENOTDIR;
347                return -1;
348
349            default:
350                D( "unknown error\n" );
351                errno = ENOENT;
352                return -1;
353        }
354    }
355
356    snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
357    D( "adb_open: '%s' => fd %d\n", path, _fh_to_int(f) );
358    return _fh_to_int(f);
359}
360
361/* ignore mode on Win32 */
362int  adb_creat(const char*  path, int  mode)
363{
364    FH  f;
365
366    f = _fh_alloc( &_fh_file_class );
367    if ( !f ) {
368        errno = ENOMEM;
369        return -1;
370    }
371
372    f->fh_handle = CreateFile( path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
373                               NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
374                               NULL );
375
376    if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
377        _fh_close(f);
378        D( "adb_creat: could not open '%s':", path );
379        switch (GetLastError()) {
380            case ERROR_FILE_NOT_FOUND:
381                D( "file not found\n" );
382                errno = ENOENT;
383                return -1;
384
385            case ERROR_PATH_NOT_FOUND:
386                D( "path not found\n" );
387                errno = ENOTDIR;
388                return -1;
389
390            default:
391                D( "unknown error\n" );
392                errno = ENOENT;
393                return -1;
394        }
395    }
396    snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
397    D( "adb_creat: '%s' => fd %d\n", path, _fh_to_int(f) );
398    return _fh_to_int(f);
399}
400
401
402int  adb_read(int  fd, void* buf, int len)
403{
404    FH     f = _fh_from_int(fd);
405
406    if (f == NULL) {
407        return -1;
408    }
409
410    return f->clazz->_fh_read( f, buf, len );
411}
412
413
414int  adb_write(int  fd, const void*  buf, int  len)
415{
416    FH     f = _fh_from_int(fd);
417
418    if (f == NULL) {
419        return -1;
420    }
421
422    return f->clazz->_fh_write(f, buf, len);
423}
424
425
426int  adb_lseek(int  fd, int  pos, int  where)
427{
428    FH     f = _fh_from_int(fd);
429
430    if (!f) {
431        return -1;
432    }
433
434    return f->clazz->_fh_lseek(f, pos, where);
435}
436
437
438int  adb_close(int  fd)
439{
440    FH   f = _fh_from_int(fd);
441
442    if (!f) {
443        return -1;
444    }
445
446    D( "adb_close: %s\n", f->name);
447    _fh_close(f);
448    return 0;
449}
450
451/**************************************************************************/
452/**************************************************************************/
453/*****                                                                *****/
454/*****    socket-based file descriptors                               *****/
455/*****                                                                *****/
456/**************************************************************************/
457/**************************************************************************/
458
459static void
460_socket_set_errno( void )
461{
462    switch (WSAGetLastError()) {
463    case 0:              errno = 0; break;
464    case WSAEWOULDBLOCK: errno = EAGAIN; break;
465    case WSAEINTR:       errno = EINTR; break;
466    default:
467        D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() );
468        errno = EINVAL;
469    }
470}
471
472static void
473_fh_socket_init( FH  f )
474{
475    f->fh_socket = INVALID_SOCKET;
476    f->event     = WSACreateEvent();
477    f->mask      = 0;
478}
479
480static int
481_fh_socket_close( FH  f )
482{
483    /* gently tell any peer that we're closing the socket */
484    shutdown( f->fh_socket, SD_BOTH );
485    closesocket( f->fh_socket );
486    f->fh_socket = INVALID_SOCKET;
487    CloseHandle( f->event );
488    f->mask = 0;
489    return 0;
490}
491
492static int
493_fh_socket_lseek( FH  f, int pos, int origin )
494{
495    errno = EPIPE;
496    return -1;
497}
498
499static int
500_fh_socket_read( FH  f, void*  buf, int  len )
501{
502    int  result = recv( f->fh_socket, buf, len, 0 );
503    if (result == SOCKET_ERROR) {
504        _socket_set_errno();
505        result = -1;
506    }
507    return  result;
508}
509
510static int
511_fh_socket_write( FH  f, const void*  buf, int  len )
512{
513    int  result = send( f->fh_socket, buf, len, 0 );
514    if (result == SOCKET_ERROR) {
515        _socket_set_errno();
516        result = -1;
517    }
518    return result;
519}
520
521static void  _fh_socket_hook( FH  f, int  event, EventHook  hook );  /* forward */
522
523static const FHClassRec  _fh_socket_class =
524{
525    _fh_socket_init,
526    _fh_socket_close,
527    _fh_socket_lseek,
528    _fh_socket_read,
529    _fh_socket_write,
530    _fh_socket_hook
531};
532
533/**************************************************************************/
534/**************************************************************************/
535/*****                                                                *****/
536/*****    replacement for libs/cutils/socket_xxxx.c                   *****/
537/*****                                                                *****/
538/**************************************************************************/
539/**************************************************************************/
540
541#include <winsock2.h>
542
543static int  _winsock_init;
544
545static void
546_cleanup_winsock( void )
547{
548    WSACleanup();
549}
550
551static void
552_init_winsock( void )
553{
554    if (!_winsock_init) {
555        WSADATA  wsaData;
556        int      rc = WSAStartup( MAKEWORD(2,2), &wsaData);
557        if (rc != 0) {
558            fatal( "adb: could not initialize Winsock\n" );
559        }
560        atexit( _cleanup_winsock );
561        _winsock_init = 1;
562    }
563}
564
565int socket_loopback_client(int port, int type)
566{
567    FH  f = _fh_alloc( &_fh_socket_class );
568    struct sockaddr_in addr;
569    SOCKET  s;
570
571    if (!f)
572        return -1;
573
574    if (!_winsock_init)
575        _init_winsock();
576
577    memset(&addr, 0, sizeof(addr));
578    addr.sin_family = AF_INET;
579    addr.sin_port = htons(port);
580    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
581
582    s = socket(AF_INET, type, 0);
583    if(s == INVALID_SOCKET) {
584        D("socket_loopback_client: could not create socket\n" );
585        _fh_close(f);
586        return -1;
587    }
588
589    f->fh_socket = s;
590    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
591        D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port );
592        _fh_close(f);
593        return -1;
594    }
595    snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
596    D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
597    return _fh_to_int(f);
598}
599
600#define LISTEN_BACKLOG 4
601
602int socket_loopback_server(int port, int type)
603{
604    FH   f = _fh_alloc( &_fh_socket_class );
605    struct sockaddr_in addr;
606    SOCKET  s;
607    int  n;
608
609    if (!f) {
610        return -1;
611    }
612
613    if (!_winsock_init)
614        _init_winsock();
615
616    memset(&addr, 0, sizeof(addr));
617    addr.sin_family = AF_INET;
618    addr.sin_port = htons(port);
619    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
620
621    s = socket(AF_INET, type, 0);
622    if(s == INVALID_SOCKET) return -1;
623
624    f->fh_socket = s;
625
626    n = 1;
627    setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
628
629    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
630        _fh_close(f);
631        return -1;
632    }
633    if (type == SOCK_STREAM) {
634        int ret;
635
636        ret = listen(s, LISTEN_BACKLOG);
637        if (ret < 0) {
638            _fh_close(f);
639            return -1;
640        }
641    }
642    snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
643    D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
644    return _fh_to_int(f);
645}
646
647
648int socket_network_client(const char *host, int port, int type)
649{
650    FH  f = _fh_alloc( &_fh_socket_class );
651    struct hostent *hp;
652    struct sockaddr_in addr;
653    SOCKET s;
654
655    if (!f)
656        return -1;
657
658    if (!_winsock_init)
659        _init_winsock();
660
661    hp = gethostbyname(host);
662    if(hp == 0) {
663        _fh_close(f);
664        return -1;
665    }
666
667    memset(&addr, 0, sizeof(addr));
668    addr.sin_family = hp->h_addrtype;
669    addr.sin_port = htons(port);
670    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
671
672    s = socket(hp->h_addrtype, type, 0);
673    if(s == INVALID_SOCKET) {
674        _fh_close(f);
675        return -1;
676    }
677    f->fh_socket = s;
678
679    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
680        _fh_close(f);
681        return -1;
682    }
683
684    snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
685    D( "socket_network_client: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
686    return _fh_to_int(f);
687}
688
689
690int socket_inaddr_any_server(int port, int type)
691{
692    FH  f = _fh_alloc( &_fh_socket_class );
693    struct sockaddr_in addr;
694    SOCKET  s;
695    int n;
696
697    if (!f)
698        return -1;
699
700    if (!_winsock_init)
701        _init_winsock();
702
703    memset(&addr, 0, sizeof(addr));
704    addr.sin_family = AF_INET;
705    addr.sin_port = htons(port);
706    addr.sin_addr.s_addr = htonl(INADDR_ANY);
707
708    s = socket(AF_INET, type, 0);
709    if(s == INVALID_SOCKET) {
710        _fh_close(f);
711        return -1;
712    }
713
714    f->fh_socket = s;
715    n = 1;
716    setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
717
718    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
719        _fh_close(f);
720        return -1;
721    }
722
723    if (type == SOCK_STREAM) {
724        int ret;
725
726        ret = listen(s, LISTEN_BACKLOG);
727        if (ret < 0) {
728            _fh_close(f);
729            return -1;
730        }
731    }
732    snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
733    D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
734    return _fh_to_int(f);
735}
736
737#undef accept
738int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen)
739{
740    FH   serverfh = _fh_from_int(serverfd);
741    FH   fh;
742
743    if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
744        D( "adb_socket_accept: invalid fd %d\n", serverfd );
745        return -1;
746    }
747
748    fh = _fh_alloc( &_fh_socket_class );
749    if (!fh) {
750        D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
751        return -1;
752    }
753
754    fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
755    if (fh->fh_socket == INVALID_SOCKET) {
756        _fh_close( fh );
757        D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, GetLastError() );
758        return -1;
759    }
760
761    snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
762    D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
763    return  _fh_to_int(fh);
764}
765
766
767void  disable_tcp_nagle(int fd)
768{
769    FH   fh = _fh_from_int(fd);
770    int  on;
771
772    if ( !fh || fh->clazz != &_fh_socket_class )
773        return;
774
775    setsockopt( fh->fh_socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on) );
776}
777
778/**************************************************************************/
779/**************************************************************************/
780/*****                                                                *****/
781/*****    emulated socketpairs                                       *****/
782/*****                                                                *****/
783/**************************************************************************/
784/**************************************************************************/
785
786/* we implement socketpairs directly in use space for the following reasons:
787 *   - it avoids copying data from/to the Nt kernel
788 *   - it allows us to implement fdevent hooks easily and cheaply, something
789 *     that is not possible with standard Win32 pipes !!
790 *
791 * basically, we use two circular buffers, each one corresponding to a given
792 * direction.
793 *
794 * each buffer is implemented as two regions:
795 *
796 *   region A which is (a_start,a_end)
797 *   region B which is (0, b_end)  with b_end <= a_start
798 *
799 * an empty buffer has:  a_start = a_end = b_end = 0
800 *
801 * a_start is the pointer where we start reading data
802 * a_end is the pointer where we start writing data, unless it is BUFFER_SIZE,
803 * then you start writing at b_end
804 *
805 * the buffer is full when  b_end == a_start && a_end == BUFFER_SIZE
806 *
807 * there is room when b_end < a_start || a_end < BUFER_SIZE
808 *
809 * when reading, a_start is incremented, it a_start meets a_end, then
810 * we do:  a_start = 0, a_end = b_end, b_end = 0, and keep going on..
811 */
812
813#define  BIP_BUFFER_SIZE   4096
814
815#if 0
816#include <stdio.h>
817#  define  BIPD(x)      D x
818#  define  BIPDUMP   bip_dump_hex
819
820static void  bip_dump_hex( const unsigned char*  ptr, size_t  len )
821{
822    int  nn, len2 = len;
823
824    if (len2 > 8) len2 = 8;
825
826    for (nn = 0; nn < len2; nn++)
827        printf("%02x", ptr[nn]);
828    printf("  ");
829
830    for (nn = 0; nn < len2; nn++) {
831        int  c = ptr[nn];
832        if (c < 32 || c > 127)
833            c = '.';
834        printf("%c", c);
835    }
836    printf("\n");
837    fflush(stdout);
838}
839
840#else
841#  define  BIPD(x)        do {} while (0)
842#  define  BIPDUMP(p,l)   BIPD(p)
843#endif
844
845typedef struct BipBufferRec_
846{
847    int                a_start;
848    int                a_end;
849    int                b_end;
850    int                fdin;
851    int                fdout;
852    int                closed;
853    int                can_write;  /* boolean */
854    HANDLE             evt_write;  /* event signaled when one can write to a buffer  */
855    int                can_read;   /* boolean */
856    HANDLE             evt_read;   /* event signaled when one can read from a buffer */
857    CRITICAL_SECTION  lock;
858    unsigned char      buff[ BIP_BUFFER_SIZE ];
859
860} BipBufferRec, *BipBuffer;
861
862static void
863bip_buffer_init( BipBuffer  buffer )
864{
865    D( "bit_buffer_init %p\n", buffer );
866    buffer->a_start   = 0;
867    buffer->a_end     = 0;
868    buffer->b_end     = 0;
869    buffer->can_write = 1;
870    buffer->can_read  = 0;
871    buffer->fdin      = 0;
872    buffer->fdout     = 0;
873    buffer->closed    = 0;
874    buffer->evt_write = CreateEvent( NULL, TRUE, TRUE, NULL );
875    buffer->evt_read  = CreateEvent( NULL, TRUE, FALSE, NULL );
876    InitializeCriticalSection( &buffer->lock );
877}
878
879static void
880bip_buffer_close( BipBuffer  bip )
881{
882    bip->closed = 1;
883
884    if (!bip->can_read) {
885        SetEvent( bip->evt_read );
886    }
887    if (!bip->can_write) {
888        SetEvent( bip->evt_write );
889    }
890}
891
892static void
893bip_buffer_done( BipBuffer  bip )
894{
895    BIPD(( "bip_buffer_done: %d->%d\n", bip->fdin, bip->fdout ));
896    CloseHandle( bip->evt_read );
897    CloseHandle( bip->evt_write );
898    DeleteCriticalSection( &bip->lock );
899}
900
901static int
902bip_buffer_write( BipBuffer  bip, const void* src, int  len )
903{
904    int  avail, count = 0;
905
906    if (len <= 0)
907        return 0;
908
909    BIPD(( "bip_buffer_write: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
910    BIPDUMP( src, len );
911
912    EnterCriticalSection( &bip->lock );
913
914    while (!bip->can_write) {
915        int  ret;
916        LeaveCriticalSection( &bip->lock );
917
918        if (bip->closed) {
919            errno = EPIPE;
920            return -1;
921        }
922        /* spinlocking here is probably unfair, but let's live with it */
923        ret = WaitForSingleObject( bip->evt_write, INFINITE );
924        if (ret != WAIT_OBJECT_0) {  /* buffer probably closed */
925            D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError() );
926            return 0;
927        }
928        if (bip->closed) {
929            errno = EPIPE;
930            return -1;
931        }
932        EnterCriticalSection( &bip->lock );
933    }
934
935    BIPD(( "bip_buffer_write: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
936
937    avail = BIP_BUFFER_SIZE - bip->a_end;
938    if (avail > 0)
939    {
940        /* we can append to region A */
941        if (avail > len)
942            avail = len;
943
944        memcpy( bip->buff + bip->a_end, src, avail );
945        src   += avail;
946        count += avail;
947        len   -= avail;
948
949        bip->a_end += avail;
950        if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) {
951            bip->can_write = 0;
952            ResetEvent( bip->evt_write );
953            goto Exit;
954        }
955    }
956
957    if (len == 0)
958        goto Exit;
959
960    avail = bip->a_start - bip->b_end;
961    assert( avail > 0 );  /* since can_write is TRUE */
962
963    if (avail > len)
964        avail = len;
965
966    memcpy( bip->buff + bip->b_end, src, avail );
967    count += avail;
968    bip->b_end += avail;
969
970    if (bip->b_end == bip->a_start) {
971        bip->can_write = 0;
972        ResetEvent( bip->evt_write );
973    }
974
975Exit:
976    assert( count > 0 );
977
978    if ( !bip->can_read ) {
979        bip->can_read = 1;
980        SetEvent( bip->evt_read );
981    }
982
983    BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
984            bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
985    LeaveCriticalSection( &bip->lock );
986
987    return count;
988 }
989
990static int
991bip_buffer_read( BipBuffer  bip, void*  dst, int  len )
992{
993    int  avail, count = 0;
994
995    if (len <= 0)
996        return 0;
997
998    BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
999
1000    EnterCriticalSection( &bip->lock );
1001    while ( !bip->can_read )
1002    {
1003#if 0
1004        LeaveCriticalSection( &bip->lock );
1005        errno = EAGAIN;
1006        return -1;
1007#else
1008        int  ret;
1009        LeaveCriticalSection( &bip->lock );
1010
1011        if (bip->closed) {
1012            errno = EPIPE;
1013            return -1;
1014        }
1015
1016        ret = WaitForSingleObject( bip->evt_read, INFINITE );
1017        if (ret != WAIT_OBJECT_0) { /* probably closed buffer */
1018            D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError());
1019            return 0;
1020        }
1021        if (bip->closed) {
1022            errno = EPIPE;
1023            return -1;
1024        }
1025        EnterCriticalSection( &bip->lock );
1026#endif
1027    }
1028
1029    BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
1030
1031    avail = bip->a_end - bip->a_start;
1032    assert( avail > 0 );  /* since can_read is TRUE */
1033
1034    if (avail > len)
1035        avail = len;
1036
1037    memcpy( dst, bip->buff + bip->a_start, avail );
1038    dst   += avail;
1039    count += avail;
1040    len   -= avail;
1041
1042    bip->a_start += avail;
1043    if (bip->a_start < bip->a_end)
1044        goto Exit;
1045
1046    bip->a_start = 0;
1047    bip->a_end   = bip->b_end;
1048    bip->b_end   = 0;
1049
1050    avail = bip->a_end;
1051    if (avail > 0) {
1052        if (avail > len)
1053            avail = len;
1054        memcpy( dst, bip->buff, avail );
1055        count += avail;
1056        bip->a_start += avail;
1057
1058        if ( bip->a_start < bip->a_end )
1059            goto Exit;
1060
1061        bip->a_start = bip->a_end = 0;
1062    }
1063
1064    bip->can_read = 0;
1065    ResetEvent( bip->evt_read );
1066
1067Exit:
1068    assert( count > 0 );
1069
1070    if (!bip->can_write ) {
1071        bip->can_write = 1;
1072        SetEvent( bip->evt_write );
1073    }
1074
1075    BIPDUMP( (const unsigned char*)dst - count, count );
1076    BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
1077            bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
1078    LeaveCriticalSection( &bip->lock );
1079
1080    return count;
1081}
1082
1083typedef struct SocketPairRec_
1084{
1085    BipBufferRec  a2b_bip;
1086    BipBufferRec  b2a_bip;
1087    FH            a_fd;
1088    int           used;
1089
1090} SocketPairRec;
1091
1092void _fh_socketpair_init( FH  f )
1093{
1094    f->fh_pair = NULL;
1095}
1096
1097static int
1098_fh_socketpair_close( FH  f )
1099{
1100    if ( f->fh_pair ) {
1101        SocketPair  pair = f->fh_pair;
1102
1103        if ( f == pair->a_fd ) {
1104            pair->a_fd = NULL;
1105        }
1106
1107        bip_buffer_close( &pair->b2a_bip );
1108        bip_buffer_close( &pair->a2b_bip );
1109
1110        if ( --pair->used == 0 ) {
1111            bip_buffer_done( &pair->b2a_bip );
1112            bip_buffer_done( &pair->a2b_bip );
1113            free( pair );
1114        }
1115        f->fh_pair = NULL;
1116    }
1117    return 0;
1118}
1119
1120static int
1121_fh_socketpair_lseek( FH  f, int pos, int  origin )
1122{
1123    errno = ESPIPE;
1124    return -1;
1125}
1126
1127static int
1128_fh_socketpair_read( FH  f, void* buf, int  len )
1129{
1130    SocketPair  pair = f->fh_pair;
1131    BipBuffer   bip;
1132
1133    if (!pair)
1134        return -1;
1135
1136    if ( f == pair->a_fd )
1137        bip = &pair->b2a_bip;
1138    else
1139        bip = &pair->a2b_bip;
1140
1141    return bip_buffer_read( bip, buf, len );
1142}
1143
1144static int
1145_fh_socketpair_write( FH  f, const void*  buf, int  len )
1146{
1147    SocketPair  pair = f->fh_pair;
1148    BipBuffer   bip;
1149
1150    if (!pair)
1151        return -1;
1152
1153    if ( f == pair->a_fd )
1154        bip = &pair->a2b_bip;
1155    else
1156        bip = &pair->b2a_bip;
1157
1158    return bip_buffer_write( bip, buf, len );
1159}
1160
1161
1162static void  _fh_socketpair_hook( FH  f, int  event, EventHook  hook );  /* forward */
1163
1164static const FHClassRec  _fh_socketpair_class =
1165{
1166    _fh_socketpair_init,
1167    _fh_socketpair_close,
1168    _fh_socketpair_lseek,
1169    _fh_socketpair_read,
1170    _fh_socketpair_write,
1171    _fh_socketpair_hook
1172};
1173
1174
1175int  adb_socketpair( int  sv[2] )
1176{
1177    FH          fa, fb;
1178    SocketPair  pair;
1179
1180    fa = _fh_alloc( &_fh_socketpair_class );
1181    fb = _fh_alloc( &_fh_socketpair_class );
1182
1183    if (!fa || !fb)
1184        goto Fail;
1185
1186    pair = malloc( sizeof(*pair) );
1187    if (pair == NULL) {
1188        D("adb_socketpair: not enough memory to allocate pipes\n" );
1189        goto Fail;
1190    }
1191
1192    bip_buffer_init( &pair->a2b_bip );
1193    bip_buffer_init( &pair->b2a_bip );
1194
1195    fa->fh_pair = pair;
1196    fb->fh_pair = pair;
1197    pair->used  = 2;
1198    pair->a_fd  = fa;
1199
1200    sv[0] = _fh_to_int(fa);
1201    sv[1] = _fh_to_int(fb);
1202
1203    pair->a2b_bip.fdin  = sv[0];
1204    pair->a2b_bip.fdout = sv[1];
1205    pair->b2a_bip.fdin  = sv[1];
1206    pair->b2a_bip.fdout = sv[0];
1207
1208    snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
1209    snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
1210    D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
1211    return 0;
1212
1213Fail:
1214    _fh_close(fb);
1215    _fh_close(fa);
1216    return -1;
1217}
1218
1219/**************************************************************************/
1220/**************************************************************************/
1221/*****                                                                *****/
1222/*****    fdevents emulation                                          *****/
1223/*****                                                                *****/
1224/*****   this is a very simple implementation, we rely on the fact    *****/
1225/*****   that ADB doesn't use FDE_ERROR.                              *****/
1226/*****                                                                *****/
1227/**************************************************************************/
1228/**************************************************************************/
1229
1230#define FATAL(x...) fatal(__FUNCTION__, x)
1231
1232#if DEBUG
1233static void dump_fde(fdevent *fde, const char *info)
1234{
1235    fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
1236            fde->state & FDE_READ ? 'R' : ' ',
1237            fde->state & FDE_WRITE ? 'W' : ' ',
1238            fde->state & FDE_ERROR ? 'E' : ' ',
1239            info);
1240}
1241#else
1242#define dump_fde(fde, info) do { } while(0)
1243#endif
1244
1245#define FDE_EVENTMASK  0x00ff
1246#define FDE_STATEMASK  0xff00
1247
1248#define FDE_ACTIVE     0x0100
1249#define FDE_PENDING    0x0200
1250#define FDE_CREATED    0x0400
1251
1252static void fdevent_plist_enqueue(fdevent *node);
1253static void fdevent_plist_remove(fdevent *node);
1254static fdevent *fdevent_plist_dequeue(void);
1255
1256static fdevent list_pending = {
1257    .next = &list_pending,
1258    .prev = &list_pending,
1259};
1260
1261static fdevent **fd_table = 0;
1262static int       fd_table_max = 0;
1263
1264typedef struct EventLooperRec_*  EventLooper;
1265
1266typedef struct EventHookRec_
1267{
1268    EventHook    next;
1269    FH           fh;
1270    HANDLE       h;
1271    int          wanted;   /* wanted event flags */
1272    int          ready;    /* ready event flags  */
1273    void*        aux;
1274    void        (*prepare)( EventHook  hook );
1275    int         (*start)  ( EventHook  hook );
1276    void        (*stop)   ( EventHook  hook );
1277    int         (*check)  ( EventHook  hook );
1278    int         (*peek)   ( EventHook  hook );
1279} EventHookRec;
1280
1281static EventHook  _free_hooks;
1282
1283static EventHook
1284event_hook_alloc( FH  fh )
1285{
1286    EventHook  hook = _free_hooks;
1287    if (hook != NULL)
1288        _free_hooks = hook->next;
1289    else {
1290        hook = malloc( sizeof(*hook) );
1291        if (hook == NULL)
1292            fatal( "could not allocate event hook\n" );
1293    }
1294    hook->next   = NULL;
1295    hook->fh     = fh;
1296    hook->wanted = 0;
1297    hook->ready  = 0;
1298    hook->h      = INVALID_HANDLE_VALUE;
1299    hook->aux    = NULL;
1300
1301    hook->prepare = NULL;
1302    hook->start   = NULL;
1303    hook->stop    = NULL;
1304    hook->check   = NULL;
1305    hook->peek    = NULL;
1306
1307    return hook;
1308}
1309
1310static void
1311event_hook_free( EventHook  hook )
1312{
1313    hook->fh     = NULL;
1314    hook->wanted = 0;
1315    hook->ready  = 0;
1316    hook->next   = _free_hooks;
1317    _free_hooks  = hook;
1318}
1319
1320
1321static void
1322event_hook_signal( EventHook  hook )
1323{
1324    FH        f   = hook->fh;
1325    int       fd  = _fh_to_int(f);
1326    fdevent*  fde = fd_table[ fd - WIN32_FH_BASE ];
1327
1328    if (fde != NULL && fde->fd == fd) {
1329        if ((fde->state & FDE_PENDING) == 0) {
1330            fde->state |= FDE_PENDING;
1331            fdevent_plist_enqueue( fde );
1332        }
1333        fde->events |= hook->wanted;
1334    }
1335}
1336
1337
1338#define  MAX_LOOPER_HANDLES  WIN32_MAX_FHS
1339
1340typedef struct EventLooperRec_
1341{
1342    EventHook    hooks;
1343    HANDLE       htab[ MAX_LOOPER_HANDLES ];
1344    int          htab_count;
1345
1346} EventLooperRec;
1347
1348static EventHook*
1349event_looper_find_p( EventLooper  looper, FH  fh )
1350{
1351    EventHook  *pnode = &looper->hooks;
1352    EventHook   node  = *pnode;
1353    for (;;) {
1354        if ( node == NULL || node->fh == fh )
1355            break;
1356        pnode = &node->next;
1357        node  = *pnode;
1358    }
1359    return  pnode;
1360}
1361
1362static void
1363event_looper_hook( EventLooper  looper, int  fd, int  events )
1364{
1365    FH          f = _fh_from_int(fd);
1366    EventHook  *pnode;
1367    EventHook   node;
1368
1369    if (f == NULL)  /* invalid arg */ {
1370        D("event_looper_hook: invalid fd=%d\n", fd);
1371        return;
1372    }
1373
1374    pnode = event_looper_find_p( looper, f );
1375    node  = *pnode;
1376    if ( node == NULL ) {
1377        node       = event_hook_alloc( f );
1378        node->next = *pnode;
1379        *pnode     = node;
1380    }
1381
1382    if ( (node->wanted & events) != events ) {
1383        /* this should update start/stop/check/peek */
1384        D("event_looper_hook: call hook for %d (new=%x, old=%x)\n",
1385           fd, node->wanted, events);
1386        f->clazz->_fh_hook( f, events & ~node->wanted, node );
1387        node->wanted |= events;
1388    } else {
1389        D("event_looper_hook: ignoring events %x for %d wanted=%x)\n",
1390           events, fd, node->wanted);
1391    }
1392}
1393
1394static void
1395event_looper_unhook( EventLooper  looper, int  fd, int  events )
1396{
1397    FH          fh    = _fh_from_int(fd);
1398    EventHook  *pnode = event_looper_find_p( looper, fh );
1399    EventHook   node  = *pnode;
1400
1401    if (node != NULL) {
1402        int  events2 = events & node->wanted;
1403        if ( events2 == 0 ) {
1404            D( "event_looper_unhook: events %x not registered for fd %d\n", events, fd );
1405            return;
1406        }
1407        node->wanted &= ~events2;
1408        if (!node->wanted) {
1409            *pnode = node->next;
1410            event_hook_free( node );
1411        }
1412    }
1413}
1414
1415static EventLooperRec  win32_looper;
1416
1417static void fdevent_init(void)
1418{
1419    win32_looper.htab_count = 0;
1420    win32_looper.hooks      = NULL;
1421}
1422
1423static void fdevent_connect(fdevent *fde)
1424{
1425    EventLooper  looper = &win32_looper;
1426    int          events = fde->state & FDE_EVENTMASK;
1427
1428    if (events != 0)
1429        event_looper_hook( looper, fde->fd, events );
1430}
1431
1432static void fdevent_disconnect(fdevent *fde)
1433{
1434    EventLooper  looper = &win32_looper;
1435    int          events = fde->state & FDE_EVENTMASK;
1436
1437    if (events != 0)
1438        event_looper_unhook( looper, fde->fd, events );
1439}
1440
1441static void fdevent_update(fdevent *fde, unsigned events)
1442{
1443    EventLooper  looper  = &win32_looper;
1444    unsigned     events0 = fde->state & FDE_EVENTMASK;
1445
1446    if (events != events0) {
1447        int  removes = events0 & ~events;
1448        int  adds    = events  & ~events0;
1449        if (removes) {
1450            D("fdevent_update: remove %x from %d\n", removes, fde->fd);
1451            event_looper_unhook( looper, fde->fd, removes );
1452        }
1453        if (adds) {
1454            D("fdevent_update: add %x to %d\n", adds, fde->fd);
1455            event_looper_hook  ( looper, fde->fd, adds );
1456        }
1457    }
1458}
1459
1460static void fdevent_process()
1461{
1462    EventLooper  looper = &win32_looper;
1463    EventHook    hook;
1464    int          gotone = 0;
1465
1466    /* if we have at least one ready hook, execute it/them */
1467    for (hook = looper->hooks; hook; hook = hook->next) {
1468        hook->ready = 0;
1469        if (hook->prepare) {
1470            hook->prepare(hook);
1471            if (hook->ready != 0) {
1472                event_hook_signal( hook );
1473                gotone = 1;
1474            }
1475        }
1476    }
1477
1478    /* nothing's ready yet, so wait for something to happen */
1479    if (!gotone)
1480    {
1481        looper->htab_count = 0;
1482
1483        for (hook = looper->hooks; hook; hook = hook->next)
1484        {
1485            if (hook->start && !hook->start(hook)) {
1486                D( "fdevent_process: error when starting a hook\n" );
1487                return;
1488            }
1489            if (hook->h != INVALID_HANDLE_VALUE) {
1490                int  nn;
1491
1492                for (nn = 0; nn < looper->htab_count; nn++)
1493                {
1494                    if ( looper->htab[nn] == hook->h )
1495                        goto DontAdd;
1496                }
1497                looper->htab[ looper->htab_count++ ] = hook->h;
1498            DontAdd:
1499                ;
1500            }
1501        }
1502
1503        if (looper->htab_count == 0) {
1504            D( "fdevent_process: nothing to wait for !!\n" );
1505            return;
1506        }
1507
1508        do
1509        {
1510            int   wait_ret;
1511
1512            D( "adb_win32: waiting for %d events\n", looper->htab_count );
1513            if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) {
1514                D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS, aborting!\n", looper->htab_count);
1515                abort();
1516            }
1517            wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE );
1518            if (wait_ret == (int)WAIT_FAILED) {
1519                D( "adb_win32: wait failed, error %ld\n", GetLastError() );
1520            } else {
1521                D( "adb_win32: got one (index %d)\n", wait_ret );
1522
1523                /* according to Cygwin, some objects like consoles wake up on "inappropriate" events
1524                 * like mouse movements. we need to filter these with the "check" function
1525                 */
1526                if ((unsigned)wait_ret < (unsigned)looper->htab_count)
1527                {
1528                    for (hook = looper->hooks; hook; hook = hook->next)
1529                    {
1530                        if ( looper->htab[wait_ret] == hook->h       &&
1531                         (!hook->check || hook->check(hook)) )
1532                        {
1533                            D( "adb_win32: signaling %s for %x\n", hook->fh->name, hook->ready );
1534                            event_hook_signal( hook );
1535                            gotone = 1;
1536                            break;
1537                        }
1538                    }
1539                }
1540            }
1541        }
1542        while (!gotone);
1543
1544        for (hook = looper->hooks; hook; hook = hook->next) {
1545            if (hook->stop)
1546                hook->stop( hook );
1547        }
1548    }
1549
1550    for (hook = looper->hooks; hook; hook = hook->next) {
1551        if (hook->peek && hook->peek(hook))
1552                event_hook_signal( hook );
1553    }
1554}
1555
1556
1557static void fdevent_register(fdevent *fde)
1558{
1559    int  fd = fde->fd - WIN32_FH_BASE;
1560
1561    if(fd < 0) {
1562        FATAL("bogus negative fd (%d)\n", fde->fd);
1563    }
1564
1565    if(fd >= fd_table_max) {
1566        int oldmax = fd_table_max;
1567        if(fde->fd > 32000) {
1568            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
1569        }
1570        if(fd_table_max == 0) {
1571            fdevent_init();
1572            fd_table_max = 256;
1573        }
1574        while(fd_table_max <= fd) {
1575            fd_table_max *= 2;
1576        }
1577        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
1578        if(fd_table == 0) {
1579            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
1580        }
1581        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
1582    }
1583
1584    fd_table[fd] = fde;
1585}
1586
1587static void fdevent_unregister(fdevent *fde)
1588{
1589    int  fd = fde->fd - WIN32_FH_BASE;
1590
1591    if((fd < 0) || (fd >= fd_table_max)) {
1592        FATAL("fd out of range (%d)\n", fde->fd);
1593    }
1594
1595    if(fd_table[fd] != fde) {
1596        FATAL("fd_table out of sync");
1597    }
1598
1599    fd_table[fd] = 0;
1600
1601    if(!(fde->state & FDE_DONT_CLOSE)) {
1602        dump_fde(fde, "close");
1603        adb_close(fde->fd);
1604    }
1605}
1606
1607static void fdevent_plist_enqueue(fdevent *node)
1608{
1609    fdevent *list = &list_pending;
1610
1611    node->next = list;
1612    node->prev = list->prev;
1613    node->prev->next = node;
1614    list->prev = node;
1615}
1616
1617static void fdevent_plist_remove(fdevent *node)
1618{
1619    node->prev->next = node->next;
1620    node->next->prev = node->prev;
1621    node->next = 0;
1622    node->prev = 0;
1623}
1624
1625static fdevent *fdevent_plist_dequeue(void)
1626{
1627    fdevent *list = &list_pending;
1628    fdevent *node = list->next;
1629
1630    if(node == list) return 0;
1631
1632    list->next = node->next;
1633    list->next->prev = list;
1634    node->next = 0;
1635    node->prev = 0;
1636
1637    return node;
1638}
1639
1640fdevent *fdevent_create(int fd, fd_func func, void *arg)
1641{
1642    fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
1643    if(fde == 0) return 0;
1644    fdevent_install(fde, fd, func, arg);
1645    fde->state |= FDE_CREATED;
1646    return fde;
1647}
1648
1649void fdevent_destroy(fdevent *fde)
1650{
1651    if(fde == 0) return;
1652    if(!(fde->state & FDE_CREATED)) {
1653        FATAL("fde %p not created by fdevent_create()\n", fde);
1654    }
1655    fdevent_remove(fde);
1656}
1657
1658void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
1659{
1660    memset(fde, 0, sizeof(fdevent));
1661    fde->state = FDE_ACTIVE;
1662    fde->fd = fd;
1663    fde->func = func;
1664    fde->arg = arg;
1665
1666    fdevent_register(fde);
1667    dump_fde(fde, "connect");
1668    fdevent_connect(fde);
1669    fde->state |= FDE_ACTIVE;
1670}
1671
1672void fdevent_remove(fdevent *fde)
1673{
1674    if(fde->state & FDE_PENDING) {
1675        fdevent_plist_remove(fde);
1676    }
1677
1678    if(fde->state & FDE_ACTIVE) {
1679        fdevent_disconnect(fde);
1680        dump_fde(fde, "disconnect");
1681        fdevent_unregister(fde);
1682    }
1683
1684    fde->state = 0;
1685    fde->events = 0;
1686}
1687
1688
1689void fdevent_set(fdevent *fde, unsigned events)
1690{
1691    events &= FDE_EVENTMASK;
1692
1693    if((fde->state & FDE_EVENTMASK) == (int)events) return;
1694
1695    if(fde->state & FDE_ACTIVE) {
1696        fdevent_update(fde, events);
1697        dump_fde(fde, "update");
1698    }
1699
1700    fde->state = (fde->state & FDE_STATEMASK) | events;
1701
1702    if(fde->state & FDE_PENDING) {
1703            /* if we're pending, make sure
1704            ** we don't signal an event that
1705            ** is no longer wanted.
1706            */
1707        fde->events &= (~events);
1708        if(fde->events == 0) {
1709            fdevent_plist_remove(fde);
1710            fde->state &= (~FDE_PENDING);
1711        }
1712    }
1713}
1714
1715void fdevent_add(fdevent *fde, unsigned events)
1716{
1717    fdevent_set(
1718        fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
1719}
1720
1721void fdevent_del(fdevent *fde, unsigned events)
1722{
1723    fdevent_set(
1724        fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
1725}
1726
1727void fdevent_loop()
1728{
1729    fdevent *fde;
1730
1731    for(;;) {
1732#if DEBUG
1733        fprintf(stderr,"--- ---- waiting for events\n");
1734#endif
1735        fdevent_process();
1736
1737        while((fde = fdevent_plist_dequeue())) {
1738            unsigned events = fde->events;
1739            fde->events = 0;
1740            fde->state &= (~FDE_PENDING);
1741            dump_fde(fde, "callback");
1742            fde->func(fde->fd, events, fde->arg);
1743        }
1744    }
1745}
1746
1747/**  FILE EVENT HOOKS
1748 **/
1749
1750static void  _event_file_prepare( EventHook  hook )
1751{
1752    if (hook->wanted & (FDE_READ|FDE_WRITE)) {
1753        /* we can always read/write */
1754        hook->ready |= hook->wanted & (FDE_READ|FDE_WRITE);
1755    }
1756}
1757
1758static int  _event_file_peek( EventHook  hook )
1759{
1760    return (hook->wanted & (FDE_READ|FDE_WRITE));
1761}
1762
1763static void  _fh_file_hook( FH  f, int  events, EventHook  hook )
1764{
1765    hook->h       = f->fh_handle;
1766    hook->prepare = _event_file_prepare;
1767    hook->peek    = _event_file_peek;
1768}
1769
1770/** SOCKET EVENT HOOKS
1771 **/
1772
1773static void  _event_socket_verify( EventHook  hook, WSANETWORKEVENTS*  evts )
1774{
1775    if ( evts->lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE) ) {
1776        if (hook->wanted & FDE_READ)
1777            hook->ready |= FDE_READ;
1778        if ((evts->iErrorCode[FD_READ] != 0) && hook->wanted & FDE_ERROR)
1779            hook->ready |= FDE_ERROR;
1780    }
1781    if ( evts->lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE) ) {
1782        if (hook->wanted & FDE_WRITE)
1783            hook->ready |= FDE_WRITE;
1784        if ((evts->iErrorCode[FD_WRITE] != 0) && hook->wanted & FDE_ERROR)
1785            hook->ready |= FDE_ERROR;
1786    }
1787    if ( evts->lNetworkEvents & FD_OOB ) {
1788        if (hook->wanted & FDE_ERROR)
1789            hook->ready |= FDE_ERROR;
1790    }
1791}
1792
1793static void  _event_socket_prepare( EventHook  hook )
1794{
1795    WSANETWORKEVENTS  evts;
1796
1797    /* look if some of the events we want already happened ? */
1798    if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts ))
1799        _event_socket_verify( hook, &evts );
1800}
1801
1802static int  _socket_wanted_to_flags( int  wanted )
1803{
1804    int  flags = 0;
1805    if (wanted & FDE_READ)
1806        flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
1807
1808    if (wanted & FDE_WRITE)
1809        flags |= FD_WRITE | FD_CONNECT | FD_CLOSE;
1810
1811    if (wanted & FDE_ERROR)
1812        flags |= FD_OOB;
1813
1814    return flags;
1815}
1816
1817static int _event_socket_start( EventHook  hook )
1818{
1819    /* create an event which we're going to wait for */
1820    FH    fh    = hook->fh;
1821    long  flags = _socket_wanted_to_flags( hook->wanted );
1822
1823    hook->h = fh->event;
1824    if (hook->h == INVALID_HANDLE_VALUE) {
1825        D( "_event_socket_start: no event for %s\n", fh->name );
1826        return 0;
1827    }
1828
1829    if ( flags != fh->mask ) {
1830        D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags );
1831        if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) {
1832            D( "_event_socket_start: WSAEventSelect() for %s failed, error %d\n", hook->fh->name, WSAGetLastError() );
1833            CloseHandle( hook->h );
1834            hook->h = INVALID_HANDLE_VALUE;
1835            exit(1);
1836            return 0;
1837        }
1838        fh->mask = flags;
1839    }
1840    return 1;
1841}
1842
1843static void _event_socket_stop( EventHook  hook )
1844{
1845    hook->h = INVALID_HANDLE_VALUE;
1846}
1847
1848static int  _event_socket_check( EventHook  hook )
1849{
1850    int               result = 0;
1851    FH                fh = hook->fh;
1852    WSANETWORKEVENTS  evts;
1853
1854    if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) {
1855        _event_socket_verify( hook, &evts );
1856        result = (hook->ready != 0);
1857        if (result) {
1858            ResetEvent( hook->h );
1859        }
1860    }
1861    D( "_event_socket_check %s returns %d\n", fh->name, result );
1862    return  result;
1863}
1864
1865static int  _event_socket_peek( EventHook  hook )
1866{
1867    WSANETWORKEVENTS  evts;
1868    FH                fh = hook->fh;
1869
1870    /* look if some of the events we want already happened ? */
1871    if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) {
1872        _event_socket_verify( hook, &evts );
1873        if (hook->ready)
1874            ResetEvent( hook->h );
1875    }
1876
1877    return hook->ready != 0;
1878}
1879
1880
1881
1882static void  _fh_socket_hook( FH  f, int  events, EventHook  hook )
1883{
1884    hook->prepare = _event_socket_prepare;
1885    hook->start   = _event_socket_start;
1886    hook->stop    = _event_socket_stop;
1887    hook->check   = _event_socket_check;
1888    hook->peek    = _event_socket_peek;
1889
1890    _event_socket_start( hook );
1891}
1892
1893/** SOCKETPAIR EVENT HOOKS
1894 **/
1895
1896static void  _event_socketpair_prepare( EventHook  hook )
1897{
1898    FH          fh   = hook->fh;
1899    SocketPair  pair = fh->fh_pair;
1900    BipBuffer   rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
1901    BipBuffer   wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
1902
1903    if (hook->wanted & FDE_READ && rbip->can_read)
1904        hook->ready |= FDE_READ;
1905
1906    if (hook->wanted & FDE_WRITE && wbip->can_write)
1907        hook->ready |= FDE_WRITE;
1908 }
1909
1910 static int  _event_socketpair_start( EventHook  hook )
1911 {
1912    FH          fh   = hook->fh;
1913    SocketPair  pair = fh->fh_pair;
1914    BipBuffer   rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
1915    BipBuffer   wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
1916
1917    if (hook->wanted == FDE_READ)
1918        hook->h = rbip->evt_read;
1919
1920    else if (hook->wanted == FDE_WRITE)
1921        hook->h = wbip->evt_write;
1922
1923    else {
1924        D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" );
1925        return 0;
1926    }
1927    D( "_event_socketpair_start: hook %s for %x wanted=%x\n",
1928       hook->fh->name, _fh_to_int(fh), hook->wanted);
1929    return 1;
1930}
1931
1932static int  _event_socketpair_peek( EventHook  hook )
1933{
1934    _event_socketpair_prepare( hook );
1935    return hook->ready != 0;
1936}
1937
1938static void  _fh_socketpair_hook( FH  fh, int  events, EventHook  hook )
1939{
1940    hook->prepare = _event_socketpair_prepare;
1941    hook->start   = _event_socketpair_start;
1942    hook->peek    = _event_socketpair_peek;
1943}
1944
1945
1946void
1947adb_sysdeps_init( void )
1948{
1949#define  ADB_MUTEX(x)  InitializeCriticalSection( & x );
1950#include "mutex_list.h"
1951    InitializeCriticalSection( &_win32_lock );
1952}
1953
1954