sysdeps_win32.c revision 74d7ff8cfd490852d3df1c4b9d8a21beed619caa
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_shutdown(int  fd)
439{
440    FH   f = _fh_from_int(fd);
441
442    if (!f) {
443        return -1;
444    }
445
446    D( "adb_shutdown: %s\n", f->name);
447    shutdown( f->fh_socket, SD_BOTH );
448    return 0;
449}
450
451
452int  adb_close(int  fd)
453{
454    FH   f = _fh_from_int(fd);
455
456    if (!f) {
457        return -1;
458    }
459
460    D( "adb_close: %s\n", f->name);
461    _fh_close(f);
462    return 0;
463}
464
465/**************************************************************************/
466/**************************************************************************/
467/*****                                                                *****/
468/*****    socket-based file descriptors                               *****/
469/*****                                                                *****/
470/**************************************************************************/
471/**************************************************************************/
472
473static void
474_socket_set_errno( void )
475{
476    switch (WSAGetLastError()) {
477    case 0:              errno = 0; break;
478    case WSAEWOULDBLOCK: errno = EAGAIN; break;
479    case WSAEINTR:       errno = EINTR; break;
480    default:
481        D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() );
482        errno = EINVAL;
483    }
484}
485
486static void
487_fh_socket_init( FH  f )
488{
489    f->fh_socket = INVALID_SOCKET;
490    f->event     = WSACreateEvent();
491    f->mask      = 0;
492}
493
494static int
495_fh_socket_close( FH  f )
496{
497    /* gently tell any peer that we're closing the socket */
498    shutdown( f->fh_socket, SD_BOTH );
499    closesocket( f->fh_socket );
500    f->fh_socket = INVALID_SOCKET;
501    CloseHandle( f->event );
502    f->mask = 0;
503    return 0;
504}
505
506static int
507_fh_socket_lseek( FH  f, int pos, int origin )
508{
509    errno = EPIPE;
510    return -1;
511}
512
513static int
514_fh_socket_read( FH  f, void*  buf, int  len )
515{
516    int  result = recv( f->fh_socket, buf, len, 0 );
517    if (result == SOCKET_ERROR) {
518        _socket_set_errno();
519        result = -1;
520    }
521    return  result;
522}
523
524static int
525_fh_socket_write( FH  f, const void*  buf, int  len )
526{
527    int  result = send( f->fh_socket, buf, len, 0 );
528    if (result == SOCKET_ERROR) {
529        _socket_set_errno();
530        result = -1;
531    }
532    return result;
533}
534
535static void  _fh_socket_hook( FH  f, int  event, EventHook  hook );  /* forward */
536
537static const FHClassRec  _fh_socket_class =
538{
539    _fh_socket_init,
540    _fh_socket_close,
541    _fh_socket_lseek,
542    _fh_socket_read,
543    _fh_socket_write,
544    _fh_socket_hook
545};
546
547/**************************************************************************/
548/**************************************************************************/
549/*****                                                                *****/
550/*****    replacement for libs/cutils/socket_xxxx.c                   *****/
551/*****                                                                *****/
552/**************************************************************************/
553/**************************************************************************/
554
555#include <winsock2.h>
556
557static int  _winsock_init;
558
559static void
560_cleanup_winsock( void )
561{
562    WSACleanup();
563}
564
565static void
566_init_winsock( void )
567{
568    if (!_winsock_init) {
569        WSADATA  wsaData;
570        int      rc = WSAStartup( MAKEWORD(2,2), &wsaData);
571        if (rc != 0) {
572            fatal( "adb: could not initialize Winsock\n" );
573        }
574        atexit( _cleanup_winsock );
575        _winsock_init = 1;
576    }
577}
578
579int socket_loopback_client(int port, int type)
580{
581    FH  f = _fh_alloc( &_fh_socket_class );
582    struct sockaddr_in addr;
583    SOCKET  s;
584
585    if (!f)
586        return -1;
587
588    if (!_winsock_init)
589        _init_winsock();
590
591    memset(&addr, 0, sizeof(addr));
592    addr.sin_family = AF_INET;
593    addr.sin_port = htons(port);
594    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
595
596    s = socket(AF_INET, type, 0);
597    if(s == INVALID_SOCKET) {
598        D("socket_loopback_client: could not create socket\n" );
599        _fh_close(f);
600        return -1;
601    }
602
603    f->fh_socket = s;
604    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
605        D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port );
606        _fh_close(f);
607        return -1;
608    }
609    snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
610    D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
611    return _fh_to_int(f);
612}
613
614#define LISTEN_BACKLOG 4
615
616int socket_loopback_server(int port, int type)
617{
618    FH   f = _fh_alloc( &_fh_socket_class );
619    struct sockaddr_in addr;
620    SOCKET  s;
621    int  n;
622
623    if (!f) {
624        return -1;
625    }
626
627    if (!_winsock_init)
628        _init_winsock();
629
630    memset(&addr, 0, sizeof(addr));
631    addr.sin_family = AF_INET;
632    addr.sin_port = htons(port);
633    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
634
635    s = socket(AF_INET, type, 0);
636    if(s == INVALID_SOCKET) return -1;
637
638    f->fh_socket = s;
639
640    n = 1;
641    setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
642
643    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
644        _fh_close(f);
645        return -1;
646    }
647    if (type == SOCK_STREAM) {
648        int ret;
649
650        ret = listen(s, LISTEN_BACKLOG);
651        if (ret < 0) {
652            _fh_close(f);
653            return -1;
654        }
655    }
656    snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
657    D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
658    return _fh_to_int(f);
659}
660
661
662int socket_network_client(const char *host, int port, int type)
663{
664    FH  f = _fh_alloc( &_fh_socket_class );
665    struct hostent *hp;
666    struct sockaddr_in addr;
667    SOCKET s;
668
669    if (!f)
670        return -1;
671
672    if (!_winsock_init)
673        _init_winsock();
674
675    hp = gethostbyname(host);
676    if(hp == 0) {
677        _fh_close(f);
678        return -1;
679    }
680
681    memset(&addr, 0, sizeof(addr));
682    addr.sin_family = hp->h_addrtype;
683    addr.sin_port = htons(port);
684    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
685
686    s = socket(hp->h_addrtype, type, 0);
687    if(s == INVALID_SOCKET) {
688        _fh_close(f);
689        return -1;
690    }
691    f->fh_socket = s;
692
693    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
694        _fh_close(f);
695        return -1;
696    }
697
698    snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
699    D( "socket_network_client: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
700    return _fh_to_int(f);
701}
702
703
704int socket_inaddr_any_server(int port, int type)
705{
706    FH  f = _fh_alloc( &_fh_socket_class );
707    struct sockaddr_in addr;
708    SOCKET  s;
709    int n;
710
711    if (!f)
712        return -1;
713
714    if (!_winsock_init)
715        _init_winsock();
716
717    memset(&addr, 0, sizeof(addr));
718    addr.sin_family = AF_INET;
719    addr.sin_port = htons(port);
720    addr.sin_addr.s_addr = htonl(INADDR_ANY);
721
722    s = socket(AF_INET, type, 0);
723    if(s == INVALID_SOCKET) {
724        _fh_close(f);
725        return -1;
726    }
727
728    f->fh_socket = s;
729    n = 1;
730    setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
731
732    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
733        _fh_close(f);
734        return -1;
735    }
736
737    if (type == SOCK_STREAM) {
738        int ret;
739
740        ret = listen(s, LISTEN_BACKLOG);
741        if (ret < 0) {
742            _fh_close(f);
743            return -1;
744        }
745    }
746    snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
747    D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
748    return _fh_to_int(f);
749}
750
751#undef accept
752int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen)
753{
754    FH   serverfh = _fh_from_int(serverfd);
755    FH   fh;
756
757    if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
758        D( "adb_socket_accept: invalid fd %d\n", serverfd );
759        return -1;
760    }
761
762    fh = _fh_alloc( &_fh_socket_class );
763    if (!fh) {
764        D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
765        return -1;
766    }
767
768    fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
769    if (fh->fh_socket == INVALID_SOCKET) {
770        _fh_close( fh );
771        D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, GetLastError() );
772        return -1;
773    }
774
775    snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
776    D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
777    return  _fh_to_int(fh);
778}
779
780
781void  disable_tcp_nagle(int fd)
782{
783    FH   fh = _fh_from_int(fd);
784    int  on;
785
786    if ( !fh || fh->clazz != &_fh_socket_class )
787        return;
788
789    setsockopt( fh->fh_socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on) );
790}
791
792/**************************************************************************/
793/**************************************************************************/
794/*****                                                                *****/
795/*****    emulated socketpairs                                       *****/
796/*****                                                                *****/
797/**************************************************************************/
798/**************************************************************************/
799
800/* we implement socketpairs directly in use space for the following reasons:
801 *   - it avoids copying data from/to the Nt kernel
802 *   - it allows us to implement fdevent hooks easily and cheaply, something
803 *     that is not possible with standard Win32 pipes !!
804 *
805 * basically, we use two circular buffers, each one corresponding to a given
806 * direction.
807 *
808 * each buffer is implemented as two regions:
809 *
810 *   region A which is (a_start,a_end)
811 *   region B which is (0, b_end)  with b_end <= a_start
812 *
813 * an empty buffer has:  a_start = a_end = b_end = 0
814 *
815 * a_start is the pointer where we start reading data
816 * a_end is the pointer where we start writing data, unless it is BUFFER_SIZE,
817 * then you start writing at b_end
818 *
819 * the buffer is full when  b_end == a_start && a_end == BUFFER_SIZE
820 *
821 * there is room when b_end < a_start || a_end < BUFER_SIZE
822 *
823 * when reading, a_start is incremented, it a_start meets a_end, then
824 * we do:  a_start = 0, a_end = b_end, b_end = 0, and keep going on..
825 */
826
827#define  BIP_BUFFER_SIZE   4096
828
829#if 0
830#include <stdio.h>
831#  define  BIPD(x)      D x
832#  define  BIPDUMP   bip_dump_hex
833
834static void  bip_dump_hex( const unsigned char*  ptr, size_t  len )
835{
836    int  nn, len2 = len;
837
838    if (len2 > 8) len2 = 8;
839
840    for (nn = 0; nn < len2; nn++)
841        printf("%02x", ptr[nn]);
842    printf("  ");
843
844    for (nn = 0; nn < len2; nn++) {
845        int  c = ptr[nn];
846        if (c < 32 || c > 127)
847            c = '.';
848        printf("%c", c);
849    }
850    printf("\n");
851    fflush(stdout);
852}
853
854#else
855#  define  BIPD(x)        do {} while (0)
856#  define  BIPDUMP(p,l)   BIPD(p)
857#endif
858
859typedef struct BipBufferRec_
860{
861    int                a_start;
862    int                a_end;
863    int                b_end;
864    int                fdin;
865    int                fdout;
866    int                closed;
867    int                can_write;  /* boolean */
868    HANDLE             evt_write;  /* event signaled when one can write to a buffer  */
869    int                can_read;   /* boolean */
870    HANDLE             evt_read;   /* event signaled when one can read from a buffer */
871    CRITICAL_SECTION  lock;
872    unsigned char      buff[ BIP_BUFFER_SIZE ];
873
874} BipBufferRec, *BipBuffer;
875
876static void
877bip_buffer_init( BipBuffer  buffer )
878{
879    D( "bit_buffer_init %p\n", buffer );
880    buffer->a_start   = 0;
881    buffer->a_end     = 0;
882    buffer->b_end     = 0;
883    buffer->can_write = 1;
884    buffer->can_read  = 0;
885    buffer->fdin      = 0;
886    buffer->fdout     = 0;
887    buffer->closed    = 0;
888    buffer->evt_write = CreateEvent( NULL, TRUE, TRUE, NULL );
889    buffer->evt_read  = CreateEvent( NULL, TRUE, FALSE, NULL );
890    InitializeCriticalSection( &buffer->lock );
891}
892
893static void
894bip_buffer_close( BipBuffer  bip )
895{
896    bip->closed = 1;
897
898    if (!bip->can_read) {
899        SetEvent( bip->evt_read );
900    }
901    if (!bip->can_write) {
902        SetEvent( bip->evt_write );
903    }
904}
905
906static void
907bip_buffer_done( BipBuffer  bip )
908{
909    BIPD(( "bip_buffer_done: %d->%d\n", bip->fdin, bip->fdout ));
910    CloseHandle( bip->evt_read );
911    CloseHandle( bip->evt_write );
912    DeleteCriticalSection( &bip->lock );
913}
914
915static int
916bip_buffer_write( BipBuffer  bip, const void* src, int  len )
917{
918    int  avail, count = 0;
919
920    if (len <= 0)
921        return 0;
922
923    BIPD(( "bip_buffer_write: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
924    BIPDUMP( src, len );
925
926    EnterCriticalSection( &bip->lock );
927
928    while (!bip->can_write) {
929        int  ret;
930        LeaveCriticalSection( &bip->lock );
931
932        if (bip->closed) {
933            errno = EPIPE;
934            return -1;
935        }
936        /* spinlocking here is probably unfair, but let's live with it */
937        ret = WaitForSingleObject( bip->evt_write, INFINITE );
938        if (ret != WAIT_OBJECT_0) {  /* buffer probably closed */
939            D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError() );
940            return 0;
941        }
942        if (bip->closed) {
943            errno = EPIPE;
944            return -1;
945        }
946        EnterCriticalSection( &bip->lock );
947    }
948
949    BIPD(( "bip_buffer_write: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
950
951    avail = BIP_BUFFER_SIZE - bip->a_end;
952    if (avail > 0)
953    {
954        /* we can append to region A */
955        if (avail > len)
956            avail = len;
957
958        memcpy( bip->buff + bip->a_end, src, avail );
959        src   += avail;
960        count += avail;
961        len   -= avail;
962
963        bip->a_end += avail;
964        if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) {
965            bip->can_write = 0;
966            ResetEvent( bip->evt_write );
967            goto Exit;
968        }
969    }
970
971    if (len == 0)
972        goto Exit;
973
974    avail = bip->a_start - bip->b_end;
975    assert( avail > 0 );  /* since can_write is TRUE */
976
977    if (avail > len)
978        avail = len;
979
980    memcpy( bip->buff + bip->b_end, src, avail );
981    count += avail;
982    bip->b_end += avail;
983
984    if (bip->b_end == bip->a_start) {
985        bip->can_write = 0;
986        ResetEvent( bip->evt_write );
987    }
988
989Exit:
990    assert( count > 0 );
991
992    if ( !bip->can_read ) {
993        bip->can_read = 1;
994        SetEvent( bip->evt_read );
995    }
996
997    BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
998            bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
999    LeaveCriticalSection( &bip->lock );
1000
1001    return count;
1002 }
1003
1004static int
1005bip_buffer_read( BipBuffer  bip, void*  dst, int  len )
1006{
1007    int  avail, count = 0;
1008
1009    if (len <= 0)
1010        return 0;
1011
1012    BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
1013
1014    EnterCriticalSection( &bip->lock );
1015    while ( !bip->can_read )
1016    {
1017#if 0
1018        LeaveCriticalSection( &bip->lock );
1019        errno = EAGAIN;
1020        return -1;
1021#else
1022        int  ret;
1023        LeaveCriticalSection( &bip->lock );
1024
1025        if (bip->closed) {
1026            errno = EPIPE;
1027            return -1;
1028        }
1029
1030        ret = WaitForSingleObject( bip->evt_read, INFINITE );
1031        if (ret != WAIT_OBJECT_0) { /* probably closed buffer */
1032            D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError());
1033            return 0;
1034        }
1035        if (bip->closed) {
1036            errno = EPIPE;
1037            return -1;
1038        }
1039        EnterCriticalSection( &bip->lock );
1040#endif
1041    }
1042
1043    BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
1044
1045    avail = bip->a_end - bip->a_start;
1046    assert( avail > 0 );  /* since can_read is TRUE */
1047
1048    if (avail > len)
1049        avail = len;
1050
1051    memcpy( dst, bip->buff + bip->a_start, avail );
1052    dst   += avail;
1053    count += avail;
1054    len   -= avail;
1055
1056    bip->a_start += avail;
1057    if (bip->a_start < bip->a_end)
1058        goto Exit;
1059
1060    bip->a_start = 0;
1061    bip->a_end   = bip->b_end;
1062    bip->b_end   = 0;
1063
1064    avail = bip->a_end;
1065    if (avail > 0) {
1066        if (avail > len)
1067            avail = len;
1068        memcpy( dst, bip->buff, avail );
1069        count += avail;
1070        bip->a_start += avail;
1071
1072        if ( bip->a_start < bip->a_end )
1073            goto Exit;
1074
1075        bip->a_start = bip->a_end = 0;
1076    }
1077
1078    bip->can_read = 0;
1079    ResetEvent( bip->evt_read );
1080
1081Exit:
1082    assert( count > 0 );
1083
1084    if (!bip->can_write ) {
1085        bip->can_write = 1;
1086        SetEvent( bip->evt_write );
1087    }
1088
1089    BIPDUMP( (const unsigned char*)dst - count, count );
1090    BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
1091            bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
1092    LeaveCriticalSection( &bip->lock );
1093
1094    return count;
1095}
1096
1097typedef struct SocketPairRec_
1098{
1099    BipBufferRec  a2b_bip;
1100    BipBufferRec  b2a_bip;
1101    FH            a_fd;
1102    int           used;
1103
1104} SocketPairRec;
1105
1106void _fh_socketpair_init( FH  f )
1107{
1108    f->fh_pair = NULL;
1109}
1110
1111static int
1112_fh_socketpair_close( FH  f )
1113{
1114    if ( f->fh_pair ) {
1115        SocketPair  pair = f->fh_pair;
1116
1117        if ( f == pair->a_fd ) {
1118            pair->a_fd = NULL;
1119        }
1120
1121        bip_buffer_close( &pair->b2a_bip );
1122        bip_buffer_close( &pair->a2b_bip );
1123
1124        if ( --pair->used == 0 ) {
1125            bip_buffer_done( &pair->b2a_bip );
1126            bip_buffer_done( &pair->a2b_bip );
1127            free( pair );
1128        }
1129        f->fh_pair = NULL;
1130    }
1131    return 0;
1132}
1133
1134static int
1135_fh_socketpair_lseek( FH  f, int pos, int  origin )
1136{
1137    errno = ESPIPE;
1138    return -1;
1139}
1140
1141static int
1142_fh_socketpair_read( FH  f, void* buf, int  len )
1143{
1144    SocketPair  pair = f->fh_pair;
1145    BipBuffer   bip;
1146
1147    if (!pair)
1148        return -1;
1149
1150    if ( f == pair->a_fd )
1151        bip = &pair->b2a_bip;
1152    else
1153        bip = &pair->a2b_bip;
1154
1155    return bip_buffer_read( bip, buf, len );
1156}
1157
1158static int
1159_fh_socketpair_write( FH  f, const void*  buf, int  len )
1160{
1161    SocketPair  pair = f->fh_pair;
1162    BipBuffer   bip;
1163
1164    if (!pair)
1165        return -1;
1166
1167    if ( f == pair->a_fd )
1168        bip = &pair->a2b_bip;
1169    else
1170        bip = &pair->b2a_bip;
1171
1172    return bip_buffer_write( bip, buf, len );
1173}
1174
1175
1176static void  _fh_socketpair_hook( FH  f, int  event, EventHook  hook );  /* forward */
1177
1178static const FHClassRec  _fh_socketpair_class =
1179{
1180    _fh_socketpair_init,
1181    _fh_socketpair_close,
1182    _fh_socketpair_lseek,
1183    _fh_socketpair_read,
1184    _fh_socketpair_write,
1185    _fh_socketpair_hook
1186};
1187
1188
1189int  adb_socketpair( int  sv[2] )
1190{
1191    FH          fa, fb;
1192    SocketPair  pair;
1193
1194    fa = _fh_alloc( &_fh_socketpair_class );
1195    fb = _fh_alloc( &_fh_socketpair_class );
1196
1197    if (!fa || !fb)
1198        goto Fail;
1199
1200    pair = malloc( sizeof(*pair) );
1201    if (pair == NULL) {
1202        D("adb_socketpair: not enough memory to allocate pipes\n" );
1203        goto Fail;
1204    }
1205
1206    bip_buffer_init( &pair->a2b_bip );
1207    bip_buffer_init( &pair->b2a_bip );
1208
1209    fa->fh_pair = pair;
1210    fb->fh_pair = pair;
1211    pair->used  = 2;
1212    pair->a_fd  = fa;
1213
1214    sv[0] = _fh_to_int(fa);
1215    sv[1] = _fh_to_int(fb);
1216
1217    pair->a2b_bip.fdin  = sv[0];
1218    pair->a2b_bip.fdout = sv[1];
1219    pair->b2a_bip.fdin  = sv[1];
1220    pair->b2a_bip.fdout = sv[0];
1221
1222    snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
1223    snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
1224    D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
1225    return 0;
1226
1227Fail:
1228    _fh_close(fb);
1229    _fh_close(fa);
1230    return -1;
1231}
1232
1233/**************************************************************************/
1234/**************************************************************************/
1235/*****                                                                *****/
1236/*****    fdevents emulation                                          *****/
1237/*****                                                                *****/
1238/*****   this is a very simple implementation, we rely on the fact    *****/
1239/*****   that ADB doesn't use FDE_ERROR.                              *****/
1240/*****                                                                *****/
1241/**************************************************************************/
1242/**************************************************************************/
1243
1244#define FATAL(x...) fatal(__FUNCTION__, x)
1245
1246#if DEBUG
1247static void dump_fde(fdevent *fde, const char *info)
1248{
1249    fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
1250            fde->state & FDE_READ ? 'R' : ' ',
1251            fde->state & FDE_WRITE ? 'W' : ' ',
1252            fde->state & FDE_ERROR ? 'E' : ' ',
1253            info);
1254}
1255#else
1256#define dump_fde(fde, info) do { } while(0)
1257#endif
1258
1259#define FDE_EVENTMASK  0x00ff
1260#define FDE_STATEMASK  0xff00
1261
1262#define FDE_ACTIVE     0x0100
1263#define FDE_PENDING    0x0200
1264#define FDE_CREATED    0x0400
1265
1266static void fdevent_plist_enqueue(fdevent *node);
1267static void fdevent_plist_remove(fdevent *node);
1268static fdevent *fdevent_plist_dequeue(void);
1269
1270static fdevent list_pending = {
1271    .next = &list_pending,
1272    .prev = &list_pending,
1273};
1274
1275static fdevent **fd_table = 0;
1276static int       fd_table_max = 0;
1277
1278typedef struct EventLooperRec_*  EventLooper;
1279
1280typedef struct EventHookRec_
1281{
1282    EventHook    next;
1283    FH           fh;
1284    HANDLE       h;
1285    int          wanted;   /* wanted event flags */
1286    int          ready;    /* ready event flags  */
1287    void*        aux;
1288    void        (*prepare)( EventHook  hook );
1289    int         (*start)  ( EventHook  hook );
1290    void        (*stop)   ( EventHook  hook );
1291    int         (*check)  ( EventHook  hook );
1292    int         (*peek)   ( EventHook  hook );
1293} EventHookRec;
1294
1295static EventHook  _free_hooks;
1296
1297static EventHook
1298event_hook_alloc( FH  fh )
1299{
1300    EventHook  hook = _free_hooks;
1301    if (hook != NULL)
1302        _free_hooks = hook->next;
1303    else {
1304        hook = malloc( sizeof(*hook) );
1305        if (hook == NULL)
1306            fatal( "could not allocate event hook\n" );
1307    }
1308    hook->next   = NULL;
1309    hook->fh     = fh;
1310    hook->wanted = 0;
1311    hook->ready  = 0;
1312    hook->h      = INVALID_HANDLE_VALUE;
1313    hook->aux    = NULL;
1314
1315    hook->prepare = NULL;
1316    hook->start   = NULL;
1317    hook->stop    = NULL;
1318    hook->check   = NULL;
1319    hook->peek    = NULL;
1320
1321    return hook;
1322}
1323
1324static void
1325event_hook_free( EventHook  hook )
1326{
1327    hook->fh     = NULL;
1328    hook->wanted = 0;
1329    hook->ready  = 0;
1330    hook->next   = _free_hooks;
1331    _free_hooks  = hook;
1332}
1333
1334
1335static void
1336event_hook_signal( EventHook  hook )
1337{
1338    FH        f   = hook->fh;
1339    int       fd  = _fh_to_int(f);
1340    fdevent*  fde = fd_table[ fd - WIN32_FH_BASE ];
1341
1342    if (fde != NULL && fde->fd == fd) {
1343        if ((fde->state & FDE_PENDING) == 0) {
1344            fde->state |= FDE_PENDING;
1345            fdevent_plist_enqueue( fde );
1346        }
1347        fde->events |= hook->wanted;
1348    }
1349}
1350
1351
1352#define  MAX_LOOPER_HANDLES  WIN32_MAX_FHS
1353
1354typedef struct EventLooperRec_
1355{
1356    EventHook    hooks;
1357    HANDLE       htab[ MAX_LOOPER_HANDLES ];
1358    int          htab_count;
1359
1360} EventLooperRec;
1361
1362static EventHook*
1363event_looper_find_p( EventLooper  looper, FH  fh )
1364{
1365    EventHook  *pnode = &looper->hooks;
1366    EventHook   node  = *pnode;
1367    for (;;) {
1368        if ( node == NULL || node->fh == fh )
1369            break;
1370        pnode = &node->next;
1371        node  = *pnode;
1372    }
1373    return  pnode;
1374}
1375
1376static void
1377event_looper_hook( EventLooper  looper, int  fd, int  events )
1378{
1379    FH          f = _fh_from_int(fd);
1380    EventHook  *pnode;
1381    EventHook   node;
1382
1383    if (f == NULL)  /* invalid arg */ {
1384        D("event_looper_hook: invalid fd=%d\n", fd);
1385        return;
1386    }
1387
1388    pnode = event_looper_find_p( looper, f );
1389    node  = *pnode;
1390    if ( node == NULL ) {
1391        node       = event_hook_alloc( f );
1392        node->next = *pnode;
1393        *pnode     = node;
1394    }
1395
1396    if ( (node->wanted & events) != events ) {
1397        /* this should update start/stop/check/peek */
1398        D("event_looper_hook: call hook for %d (new=%x, old=%x)\n",
1399           fd, node->wanted, events);
1400        f->clazz->_fh_hook( f, events & ~node->wanted, node );
1401        node->wanted |= events;
1402    } else {
1403        D("event_looper_hook: ignoring events %x for %d wanted=%x)\n",
1404           events, fd, node->wanted);
1405    }
1406}
1407
1408static void
1409event_looper_unhook( EventLooper  looper, int  fd, int  events )
1410{
1411    FH          fh    = _fh_from_int(fd);
1412    EventHook  *pnode = event_looper_find_p( looper, fh );
1413    EventHook   node  = *pnode;
1414
1415    if (node != NULL) {
1416        int  events2 = events & node->wanted;
1417        if ( events2 == 0 ) {
1418            D( "event_looper_unhook: events %x not registered for fd %d\n", events, fd );
1419            return;
1420        }
1421        node->wanted &= ~events2;
1422        if (!node->wanted) {
1423            *pnode = node->next;
1424            event_hook_free( node );
1425        }
1426    }
1427}
1428
1429static EventLooperRec  win32_looper;
1430
1431static void fdevent_init(void)
1432{
1433    win32_looper.htab_count = 0;
1434    win32_looper.hooks      = NULL;
1435}
1436
1437static void fdevent_connect(fdevent *fde)
1438{
1439    EventLooper  looper = &win32_looper;
1440    int          events = fde->state & FDE_EVENTMASK;
1441
1442    if (events != 0)
1443        event_looper_hook( looper, fde->fd, events );
1444}
1445
1446static void fdevent_disconnect(fdevent *fde)
1447{
1448    EventLooper  looper = &win32_looper;
1449    int          events = fde->state & FDE_EVENTMASK;
1450
1451    if (events != 0)
1452        event_looper_unhook( looper, fde->fd, events );
1453}
1454
1455static void fdevent_update(fdevent *fde, unsigned events)
1456{
1457    EventLooper  looper  = &win32_looper;
1458    unsigned     events0 = fde->state & FDE_EVENTMASK;
1459
1460    if (events != events0) {
1461        int  removes = events0 & ~events;
1462        int  adds    = events  & ~events0;
1463        if (removes) {
1464            D("fdevent_update: remove %x from %d\n", removes, fde->fd);
1465            event_looper_unhook( looper, fde->fd, removes );
1466        }
1467        if (adds) {
1468            D("fdevent_update: add %x to %d\n", adds, fde->fd);
1469            event_looper_hook  ( looper, fde->fd, adds );
1470        }
1471    }
1472}
1473
1474static void fdevent_process()
1475{
1476    EventLooper  looper = &win32_looper;
1477    EventHook    hook;
1478    int          gotone = 0;
1479
1480    /* if we have at least one ready hook, execute it/them */
1481    for (hook = looper->hooks; hook; hook = hook->next) {
1482        hook->ready = 0;
1483        if (hook->prepare) {
1484            hook->prepare(hook);
1485            if (hook->ready != 0) {
1486                event_hook_signal( hook );
1487                gotone = 1;
1488            }
1489        }
1490    }
1491
1492    /* nothing's ready yet, so wait for something to happen */
1493    if (!gotone)
1494    {
1495        looper->htab_count = 0;
1496
1497        for (hook = looper->hooks; hook; hook = hook->next)
1498        {
1499            if (hook->start && !hook->start(hook)) {
1500                D( "fdevent_process: error when starting a hook\n" );
1501                return;
1502            }
1503            if (hook->h != INVALID_HANDLE_VALUE) {
1504                int  nn;
1505
1506                for (nn = 0; nn < looper->htab_count; nn++)
1507                {
1508                    if ( looper->htab[nn] == hook->h )
1509                        goto DontAdd;
1510                }
1511                looper->htab[ looper->htab_count++ ] = hook->h;
1512            DontAdd:
1513                ;
1514            }
1515        }
1516
1517        if (looper->htab_count == 0) {
1518            D( "fdevent_process: nothing to wait for !!\n" );
1519            return;
1520        }
1521
1522        do
1523        {
1524            int   wait_ret;
1525
1526            D( "adb_win32: waiting for %d events\n", looper->htab_count );
1527            if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) {
1528                D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS, aborting!\n", looper->htab_count);
1529                abort();
1530            }
1531            wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE );
1532            if (wait_ret == (int)WAIT_FAILED) {
1533                D( "adb_win32: wait failed, error %ld\n", GetLastError() );
1534            } else {
1535                D( "adb_win32: got one (index %d)\n", wait_ret );
1536
1537                /* according to Cygwin, some objects like consoles wake up on "inappropriate" events
1538                 * like mouse movements. we need to filter these with the "check" function
1539                 */
1540                if ((unsigned)wait_ret < (unsigned)looper->htab_count)
1541                {
1542                    for (hook = looper->hooks; hook; hook = hook->next)
1543                    {
1544                        if ( looper->htab[wait_ret] == hook->h       &&
1545                         (!hook->check || hook->check(hook)) )
1546                        {
1547                            D( "adb_win32: signaling %s for %x\n", hook->fh->name, hook->ready );
1548                            event_hook_signal( hook );
1549                            gotone = 1;
1550                            break;
1551                        }
1552                    }
1553                }
1554            }
1555        }
1556        while (!gotone);
1557
1558        for (hook = looper->hooks; hook; hook = hook->next) {
1559            if (hook->stop)
1560                hook->stop( hook );
1561        }
1562    }
1563
1564    for (hook = looper->hooks; hook; hook = hook->next) {
1565        if (hook->peek && hook->peek(hook))
1566                event_hook_signal( hook );
1567    }
1568}
1569
1570
1571static void fdevent_register(fdevent *fde)
1572{
1573    int  fd = fde->fd - WIN32_FH_BASE;
1574
1575    if(fd < 0) {
1576        FATAL("bogus negative fd (%d)\n", fde->fd);
1577    }
1578
1579    if(fd >= fd_table_max) {
1580        int oldmax = fd_table_max;
1581        if(fde->fd > 32000) {
1582            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
1583        }
1584        if(fd_table_max == 0) {
1585            fdevent_init();
1586            fd_table_max = 256;
1587        }
1588        while(fd_table_max <= fd) {
1589            fd_table_max *= 2;
1590        }
1591        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
1592        if(fd_table == 0) {
1593            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
1594        }
1595        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
1596    }
1597
1598    fd_table[fd] = fde;
1599}
1600
1601static void fdevent_unregister(fdevent *fde)
1602{
1603    int  fd = fde->fd - WIN32_FH_BASE;
1604
1605    if((fd < 0) || (fd >= fd_table_max)) {
1606        FATAL("fd out of range (%d)\n", fde->fd);
1607    }
1608
1609    if(fd_table[fd] != fde) {
1610        FATAL("fd_table out of sync");
1611    }
1612
1613    fd_table[fd] = 0;
1614
1615    if(!(fde->state & FDE_DONT_CLOSE)) {
1616        dump_fde(fde, "close");
1617        adb_close(fde->fd);
1618    }
1619}
1620
1621static void fdevent_plist_enqueue(fdevent *node)
1622{
1623    fdevent *list = &list_pending;
1624
1625    node->next = list;
1626    node->prev = list->prev;
1627    node->prev->next = node;
1628    list->prev = node;
1629}
1630
1631static void fdevent_plist_remove(fdevent *node)
1632{
1633    node->prev->next = node->next;
1634    node->next->prev = node->prev;
1635    node->next = 0;
1636    node->prev = 0;
1637}
1638
1639static fdevent *fdevent_plist_dequeue(void)
1640{
1641    fdevent *list = &list_pending;
1642    fdevent *node = list->next;
1643
1644    if(node == list) return 0;
1645
1646    list->next = node->next;
1647    list->next->prev = list;
1648    node->next = 0;
1649    node->prev = 0;
1650
1651    return node;
1652}
1653
1654fdevent *fdevent_create(int fd, fd_func func, void *arg)
1655{
1656    fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
1657    if(fde == 0) return 0;
1658    fdevent_install(fde, fd, func, arg);
1659    fde->state |= FDE_CREATED;
1660    return fde;
1661}
1662
1663void fdevent_destroy(fdevent *fde)
1664{
1665    if(fde == 0) return;
1666    if(!(fde->state & FDE_CREATED)) {
1667        FATAL("fde %p not created by fdevent_create()\n", fde);
1668    }
1669    fdevent_remove(fde);
1670}
1671
1672void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
1673{
1674    memset(fde, 0, sizeof(fdevent));
1675    fde->state = FDE_ACTIVE;
1676    fde->fd = fd;
1677    fde->func = func;
1678    fde->arg = arg;
1679
1680    fdevent_register(fde);
1681    dump_fde(fde, "connect");
1682    fdevent_connect(fde);
1683    fde->state |= FDE_ACTIVE;
1684}
1685
1686void fdevent_remove(fdevent *fde)
1687{
1688    if(fde->state & FDE_PENDING) {
1689        fdevent_plist_remove(fde);
1690    }
1691
1692    if(fde->state & FDE_ACTIVE) {
1693        fdevent_disconnect(fde);
1694        dump_fde(fde, "disconnect");
1695        fdevent_unregister(fde);
1696    }
1697
1698    fde->state = 0;
1699    fde->events = 0;
1700}
1701
1702
1703void fdevent_set(fdevent *fde, unsigned events)
1704{
1705    events &= FDE_EVENTMASK;
1706
1707    if((fde->state & FDE_EVENTMASK) == (int)events) return;
1708
1709    if(fde->state & FDE_ACTIVE) {
1710        fdevent_update(fde, events);
1711        dump_fde(fde, "update");
1712    }
1713
1714    fde->state = (fde->state & FDE_STATEMASK) | events;
1715
1716    if(fde->state & FDE_PENDING) {
1717            /* if we're pending, make sure
1718            ** we don't signal an event that
1719            ** is no longer wanted.
1720            */
1721        fde->events &= (~events);
1722        if(fde->events == 0) {
1723            fdevent_plist_remove(fde);
1724            fde->state &= (~FDE_PENDING);
1725        }
1726    }
1727}
1728
1729void fdevent_add(fdevent *fde, unsigned events)
1730{
1731    fdevent_set(
1732        fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
1733}
1734
1735void fdevent_del(fdevent *fde, unsigned events)
1736{
1737    fdevent_set(
1738        fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
1739}
1740
1741void fdevent_loop()
1742{
1743    fdevent *fde;
1744
1745    for(;;) {
1746#if DEBUG
1747        fprintf(stderr,"--- ---- waiting for events\n");
1748#endif
1749        fdevent_process();
1750
1751        while((fde = fdevent_plist_dequeue())) {
1752            unsigned events = fde->events;
1753            fde->events = 0;
1754            fde->state &= (~FDE_PENDING);
1755            dump_fde(fde, "callback");
1756            fde->func(fde->fd, events, fde->arg);
1757        }
1758    }
1759}
1760
1761/**  FILE EVENT HOOKS
1762 **/
1763
1764static void  _event_file_prepare( EventHook  hook )
1765{
1766    if (hook->wanted & (FDE_READ|FDE_WRITE)) {
1767        /* we can always read/write */
1768        hook->ready |= hook->wanted & (FDE_READ|FDE_WRITE);
1769    }
1770}
1771
1772static int  _event_file_peek( EventHook  hook )
1773{
1774    return (hook->wanted & (FDE_READ|FDE_WRITE));
1775}
1776
1777static void  _fh_file_hook( FH  f, int  events, EventHook  hook )
1778{
1779    hook->h       = f->fh_handle;
1780    hook->prepare = _event_file_prepare;
1781    hook->peek    = _event_file_peek;
1782}
1783
1784/** SOCKET EVENT HOOKS
1785 **/
1786
1787static void  _event_socket_verify( EventHook  hook, WSANETWORKEVENTS*  evts )
1788{
1789    if ( evts->lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE) ) {
1790        if (hook->wanted & FDE_READ)
1791            hook->ready |= FDE_READ;
1792        if ((evts->iErrorCode[FD_READ] != 0) && hook->wanted & FDE_ERROR)
1793            hook->ready |= FDE_ERROR;
1794    }
1795    if ( evts->lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE) ) {
1796        if (hook->wanted & FDE_WRITE)
1797            hook->ready |= FDE_WRITE;
1798        if ((evts->iErrorCode[FD_WRITE] != 0) && hook->wanted & FDE_ERROR)
1799            hook->ready |= FDE_ERROR;
1800    }
1801    if ( evts->lNetworkEvents & FD_OOB ) {
1802        if (hook->wanted & FDE_ERROR)
1803            hook->ready |= FDE_ERROR;
1804    }
1805}
1806
1807static void  _event_socket_prepare( EventHook  hook )
1808{
1809    WSANETWORKEVENTS  evts;
1810
1811    /* look if some of the events we want already happened ? */
1812    if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts ))
1813        _event_socket_verify( hook, &evts );
1814}
1815
1816static int  _socket_wanted_to_flags( int  wanted )
1817{
1818    int  flags = 0;
1819    if (wanted & FDE_READ)
1820        flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
1821
1822    if (wanted & FDE_WRITE)
1823        flags |= FD_WRITE | FD_CONNECT | FD_CLOSE;
1824
1825    if (wanted & FDE_ERROR)
1826        flags |= FD_OOB;
1827
1828    return flags;
1829}
1830
1831static int _event_socket_start( EventHook  hook )
1832{
1833    /* create an event which we're going to wait for */
1834    FH    fh    = hook->fh;
1835    long  flags = _socket_wanted_to_flags( hook->wanted );
1836
1837    hook->h = fh->event;
1838    if (hook->h == INVALID_HANDLE_VALUE) {
1839        D( "_event_socket_start: no event for %s\n", fh->name );
1840        return 0;
1841    }
1842
1843    if ( flags != fh->mask ) {
1844        D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags );
1845        if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) {
1846            D( "_event_socket_start: WSAEventSelect() for %s failed, error %d\n", hook->fh->name, WSAGetLastError() );
1847            CloseHandle( hook->h );
1848            hook->h = INVALID_HANDLE_VALUE;
1849            exit(1);
1850            return 0;
1851        }
1852        fh->mask = flags;
1853    }
1854    return 1;
1855}
1856
1857static void _event_socket_stop( EventHook  hook )
1858{
1859    hook->h = INVALID_HANDLE_VALUE;
1860}
1861
1862static int  _event_socket_check( EventHook  hook )
1863{
1864    int               result = 0;
1865    FH                fh = hook->fh;
1866    WSANETWORKEVENTS  evts;
1867
1868    if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) {
1869        _event_socket_verify( hook, &evts );
1870        result = (hook->ready != 0);
1871        if (result) {
1872            ResetEvent( hook->h );
1873        }
1874    }
1875    D( "_event_socket_check %s returns %d\n", fh->name, result );
1876    return  result;
1877}
1878
1879static int  _event_socket_peek( EventHook  hook )
1880{
1881    WSANETWORKEVENTS  evts;
1882    FH                fh = hook->fh;
1883
1884    /* look if some of the events we want already happened ? */
1885    if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) {
1886        _event_socket_verify( hook, &evts );
1887        if (hook->ready)
1888            ResetEvent( hook->h );
1889    }
1890
1891    return hook->ready != 0;
1892}
1893
1894
1895
1896static void  _fh_socket_hook( FH  f, int  events, EventHook  hook )
1897{
1898    hook->prepare = _event_socket_prepare;
1899    hook->start   = _event_socket_start;
1900    hook->stop    = _event_socket_stop;
1901    hook->check   = _event_socket_check;
1902    hook->peek    = _event_socket_peek;
1903
1904    _event_socket_start( hook );
1905}
1906
1907/** SOCKETPAIR EVENT HOOKS
1908 **/
1909
1910static void  _event_socketpair_prepare( 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 && rbip->can_read)
1918        hook->ready |= FDE_READ;
1919
1920    if (hook->wanted & FDE_WRITE && wbip->can_write)
1921        hook->ready |= FDE_WRITE;
1922 }
1923
1924 static int  _event_socketpair_start( EventHook  hook )
1925 {
1926    FH          fh   = hook->fh;
1927    SocketPair  pair = fh->fh_pair;
1928    BipBuffer   rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
1929    BipBuffer   wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
1930
1931    if (hook->wanted == FDE_READ)
1932        hook->h = rbip->evt_read;
1933
1934    else if (hook->wanted == FDE_WRITE)
1935        hook->h = wbip->evt_write;
1936
1937    else {
1938        D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" );
1939        return 0;
1940    }
1941    D( "_event_socketpair_start: hook %s for %x wanted=%x\n",
1942       hook->fh->name, _fh_to_int(fh), hook->wanted);
1943    return 1;
1944}
1945
1946static int  _event_socketpair_peek( EventHook  hook )
1947{
1948    _event_socketpair_prepare( hook );
1949    return hook->ready != 0;
1950}
1951
1952static void  _fh_socketpair_hook( FH  fh, int  events, EventHook  hook )
1953{
1954    hook->prepare = _event_socketpair_prepare;
1955    hook->start   = _event_socketpair_start;
1956    hook->peek    = _event_socketpair_peek;
1957}
1958
1959
1960void
1961adb_sysdeps_init( void )
1962{
1963#define  ADB_MUTEX(x)  InitializeCriticalSection( & x );
1964#include "mutex_list.h"
1965    InitializeCriticalSection( &_win32_lock );
1966}
1967
1968