blob: c2a9a985f58043c2aa23c1f2b6151630b4c10ce9 [file] [log] [blame]
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001#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