2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #define TRACE_TAG TRACE_SYSDEPS
25 extern void fatal(const char *fmt, ...);
27 #define assert(cond) do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0)
29 /**************************************************************************/
30 /**************************************************************************/
32 /***** replaces libs/cutils/load_file.c *****/
34 /**************************************************************************/
35 /**************************************************************************/
37 void *load_file(const char *fn, unsigned *_sz)
43 file = CreateFile( fn,
51 if (file == INVALID_HANDLE_VALUE)
54 file_size = GetFileSize( file, NULL );
58 data = (char*) malloc( file_size + 1 );
60 D("load_file: could not allocate %ld bytes\n", file_size );
65 if ( !ReadFile( file, data, file_size, &out_bytes, NULL ) ||
66 out_bytes != file_size )
68 D("load_file: could not read %ld bytes from '%s'\n", file_size, fn);
77 *_sz = (unsigned) file_size;
81 /**************************************************************************/
82 /**************************************************************************/
84 /***** common file descriptor handling *****/
86 /**************************************************************************/
87 /**************************************************************************/
89 typedef const struct FHClassRec_* FHClass;
91 typedef struct FHRec_* FH;
93 typedef struct EventHookRec_* EventHook;
95 typedef struct FHClassRec_
97 void (*_fh_init) ( FH f );
98 int (*_fh_close)( FH f );
99 int (*_fh_lseek)( FH f, int pos, int origin );
100 int (*_fh_read) ( FH f, void* buf, int len );
101 int (*_fh_write)( FH f, const void* buf, int len );
102 void (*_fh_hook) ( FH f, int events, EventHook hook );
106 /* used to emulate unix-domain socket pairs */
107 typedef struct SocketPairRec_* SocketPair;
109 typedef struct FHRec_
127 #define fh_handle u.handle
128 #define fh_socket u.socket
129 #define fh_pair u.pair
131 #define WIN32_FH_BASE 100
133 #define WIN32_MAX_FHS 128
135 static sdb_mutex_t _win32_lock;
136 static FHRec _win32_fhs[ WIN32_MAX_FHS ];
137 static int _win32_fh_count;
140 _fh_from_int( int fd )
146 if (fd < 0 || fd >= _win32_fh_count) {
147 D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
155 D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
167 if (f && f->used && f >= _win32_fhs && f < _win32_fhs + WIN32_MAX_FHS)
168 return (int)(f - _win32_fhs) + WIN32_FH_BASE;
174 _fh_alloc( FHClass clazz )
179 sdb_mutex_lock( &_win32_lock );
181 if (_win32_fh_count < WIN32_MAX_FHS) {
182 f = &_win32_fhs[ _win32_fh_count++ ];
186 for (nn = 0; nn < WIN32_MAX_FHS; nn++) {
187 if ( _win32_fhs[nn].clazz == NULL) {
192 D( "_fh_alloc: no more free file descriptors\n" );
200 sdb_mutex_unlock( &_win32_lock );
209 f->clazz->_fh_close( f );
217 /* forward definitions */
218 static const FHClassRec _fh_file_class;
219 static const FHClassRec _fh_socket_class;
221 /**************************************************************************/
222 /**************************************************************************/
224 /***** file-based descriptor handling *****/
226 /**************************************************************************/
227 /**************************************************************************/
230 _fh_file_init( FH f )
232 f->fh_handle = INVALID_HANDLE_VALUE;
236 _fh_file_close( FH f )
238 CloseHandle( f->fh_handle );
239 f->fh_handle = INVALID_HANDLE_VALUE;
244 _fh_file_read( FH f, void* buf, int len )
248 if ( !ReadFile( f->fh_handle, buf, (DWORD)len, &read_bytes, NULL ) ) {
249 D( "sdb_read: could not read %d bytes from %s\n", len, f->name );
252 } else if (read_bytes < (DWORD)len) {
255 return (int)read_bytes;
259 _fh_file_write( FH f, const void* buf, int len )
263 if ( !WriteFile( f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL ) ) {
264 D( "sdb_file_write: could not write %d bytes from %s\n", len, f->name );
267 } else if (wrote_bytes < (DWORD)len) {
270 return (int)wrote_bytes;
274 _fh_file_lseek( FH f, int pos, int origin )
281 case SEEK_SET: method = FILE_BEGIN; break;
282 case SEEK_CUR: method = FILE_CURRENT; break;
283 case SEEK_END: method = FILE_END; break;
289 result = SetFilePointer( f->fh_handle, pos, NULL, method );
290 if (result == INVALID_SET_FILE_POINTER) {
299 static void _fh_file_hook( FH f, int event, EventHook eventhook ); /* forward */
301 static const FHClassRec _fh_file_class =
311 /**************************************************************************/
312 /**************************************************************************/
314 /***** file-based descriptor handling *****/
316 /**************************************************************************/
317 /**************************************************************************/
319 int sdb_open(const char* path, int options)
323 DWORD desiredAccess = 0;
324 DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
328 desiredAccess = GENERIC_READ;
331 desiredAccess = GENERIC_WRITE;
334 desiredAccess = GENERIC_READ | GENERIC_WRITE;
337 D("sdb_open: invalid options (0x%0x)\n", options);
342 f = _fh_alloc( &_fh_file_class );
348 f->fh_handle = CreateFile( path, desiredAccess, shareMode, NULL, OPEN_EXISTING,
351 if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
353 D( "sdb_open: could not open '%s':", path );
354 switch (GetLastError()) {
355 case ERROR_FILE_NOT_FOUND:
356 D( "file not found\n" );
360 case ERROR_PATH_NOT_FOUND:
361 D( "path not found\n" );
366 D( "unknown error\n" );
372 snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
373 D( "sdb_open: '%s' => fd %d\n", path, _fh_to_int(f) );
374 return _fh_to_int(f);
377 /* ignore mode on Win32 */
378 int sdb_creat(const char* path, int mode)
382 f = _fh_alloc( &_fh_file_class );
388 f->fh_handle = CreateFile( path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
389 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
392 if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
394 D( "sdb_creat: could not open '%s':", path );
395 switch (GetLastError()) {
396 case ERROR_FILE_NOT_FOUND:
397 D( "file not found\n" );
401 case ERROR_PATH_NOT_FOUND:
402 D( "path not found\n" );
407 D( "unknown error\n" );
412 snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
413 D( "sdb_creat: '%s' => fd %d\n", path, _fh_to_int(f) );
414 return _fh_to_int(f);
418 int sdb_read(int fd, void* buf, int len)
420 FH f = _fh_from_int(fd);
426 return f->clazz->_fh_read( f, buf, len );
430 int sdb_write(int fd, const void* buf, int len)
432 FH f = _fh_from_int(fd);
438 return f->clazz->_fh_write(f, buf, len);
442 int sdb_lseek(int fd, int pos, int where)
444 FH f = _fh_from_int(fd);
450 return f->clazz->_fh_lseek(f, pos, where);
454 int sdb_shutdown(int fd)
456 FH f = _fh_from_int(fd);
462 D( "sdb_shutdown: %s\n", f->name);
463 shutdown( f->fh_socket, SD_BOTH );
468 int sdb_close(int fd)
470 FH f = _fh_from_int(fd);
476 D( "sdb_close: %s\n", f->name);
481 /**************************************************************************/
482 /**************************************************************************/
484 /***** socket-based file descriptors *****/
486 /**************************************************************************/
487 /**************************************************************************/
490 _socket_set_errno( void )
492 switch (WSAGetLastError()) {
493 case 0: errno = 0; break;
494 case WSAEWOULDBLOCK: errno = EAGAIN; break;
495 case WSAEINTR: errno = EINTR; break;
497 D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() );
503 _fh_socket_init( FH f )
505 f->fh_socket = INVALID_SOCKET;
506 f->event = WSACreateEvent();
511 _fh_socket_close( FH f )
513 /* gently tell any peer that we're closing the socket */
514 shutdown( f->fh_socket, SD_BOTH );
515 closesocket( f->fh_socket );
516 f->fh_socket = INVALID_SOCKET;
517 CloseHandle( f->event );
523 _fh_socket_lseek( FH f, int pos, int origin )
530 _fh_socket_read( FH f, void* buf, int len )
532 int result = recv( f->fh_socket, buf, len, 0 );
533 if (result == SOCKET_ERROR) {
541 _fh_socket_write( FH f, const void* buf, int len )
543 int result = send( f->fh_socket, buf, len, 0 );
544 if (result == SOCKET_ERROR) {
551 static void _fh_socket_hook( FH f, int event, EventHook hook ); /* forward */
553 static const FHClassRec _fh_socket_class =
563 /**************************************************************************/
564 /**************************************************************************/
566 /***** replacement for libs/cutils/socket_xxxx.c *****/
568 /**************************************************************************/
569 /**************************************************************************/
571 #include <winsock2.h>
573 static int _winsock_init;
576 _cleanup_winsock( void )
582 _init_winsock( void )
584 if (!_winsock_init) {
586 int rc = WSAStartup( MAKEWORD(2,2), &wsaData);
588 fatal( "sdb: could not initialize Winsock\n" );
590 atexit( _cleanup_winsock );
595 int socket_loopback_client(int port, int type)
597 FH f = _fh_alloc( &_fh_socket_class );
598 struct sockaddr_in addr;
607 memset(&addr, 0, sizeof(addr));
608 addr.sin_family = AF_INET;
609 addr.sin_port = htons(port);
610 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
612 s = socket(AF_INET, type, 0);
613 if(s == INVALID_SOCKET) {
614 D("socket_loopback_client: could not create socket\n" );
620 if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
621 D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port );
625 snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
626 D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
627 return _fh_to_int(f);
630 #define LISTEN_BACKLOG 4
632 int socket_loopback_server(int port, int type)
634 FH f = _fh_alloc( &_fh_socket_class );
635 struct sockaddr_in addr;
646 memset(&addr, 0, sizeof(addr));
647 addr.sin_family = AF_INET;
648 addr.sin_port = htons(port);
649 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
651 s = socket(AF_INET, type, 0);
652 if(s == INVALID_SOCKET) return -1;
657 setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
659 if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
663 if (type == SOCK_STREAM) {
666 ret = listen(s, LISTEN_BACKLOG);
672 snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
673 D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
674 return _fh_to_int(f);
678 int socket_network_client(const char *host, int port, int type)
680 FH f = _fh_alloc( &_fh_socket_class );
682 struct sockaddr_in addr;
691 hp = gethostbyname(host);
697 memset(&addr, 0, sizeof(addr));
698 addr.sin_family = hp->h_addrtype;
699 addr.sin_port = htons(port);
700 memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
702 s = socket(hp->h_addrtype, type, 0);
703 if(s == INVALID_SOCKET) {
709 if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
714 snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
715 D( "socket_network_client: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
716 return _fh_to_int(f);
720 int socket_inaddr_any_server(int port, int type)
722 FH f = _fh_alloc( &_fh_socket_class );
723 struct sockaddr_in addr;
733 memset(&addr, 0, sizeof(addr));
734 addr.sin_family = AF_INET;
735 addr.sin_port = htons(port);
736 addr.sin_addr.s_addr = htonl(INADDR_ANY);
738 s = socket(AF_INET, type, 0);
739 if(s == INVALID_SOCKET) {
746 setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
748 if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
753 if (type == SOCK_STREAM) {
756 ret = listen(s, LISTEN_BACKLOG);
762 snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
763 D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
764 return _fh_to_int(f);
768 int sdb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
770 FH serverfh = _fh_from_int(serverfd);
773 if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
774 D( "sdb_socket_accept: invalid fd %d\n", serverfd );
778 fh = _fh_alloc( &_fh_socket_class );
780 D( "sdb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
784 fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
785 if (fh->fh_socket == INVALID_SOCKET) {
787 D( "sdb_socket_accept: accept on fd %d return error %ld\n", serverfd, GetLastError() );
791 snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
792 D( "sdb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
793 return _fh_to_int(fh);
797 void disable_tcp_nagle(int fd)
799 FH fh = _fh_from_int(fd);
802 if ( !fh || fh->clazz != &_fh_socket_class )
805 setsockopt( fh->fh_socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on) );
808 /**************************************************************************/
809 /**************************************************************************/
811 /***** emulated socketpairs *****/
813 /**************************************************************************/
814 /**************************************************************************/
816 /* we implement socketpairs directly in use space for the following reasons:
817 * - it avoids copying data from/to the Nt kernel
818 * - it allows us to implement fdevent hooks easily and cheaply, something
819 * that is not possible with standard Win32 pipes !!
821 * basically, we use two circular buffers, each one corresponding to a given
824 * each buffer is implemented as two regions:
826 * region A which is (a_start,a_end)
827 * region B which is (0, b_end) with b_end <= a_start
829 * an empty buffer has: a_start = a_end = b_end = 0
831 * a_start is the pointer where we start reading data
832 * a_end is the pointer where we start writing data, unless it is BUFFER_SIZE,
833 * then you start writing at b_end
835 * the buffer is full when b_end == a_start && a_end == BUFFER_SIZE
837 * there is room when b_end < a_start || a_end < BUFER_SIZE
839 * when reading, a_start is incremented, it a_start meets a_end, then
840 * we do: a_start = 0, a_end = b_end, b_end = 0, and keep going on..
843 #define BIP_BUFFER_SIZE 4096
848 # define BIPDUMP bip_dump_hex
850 static void bip_dump_hex( const unsigned char* ptr, size_t len )
854 if (len2 > 8) len2 = 8;
856 for (nn = 0; nn < len2; nn++)
857 printf("%02x", ptr[nn]);
860 for (nn = 0; nn < len2; nn++) {
862 if (c < 32 || c > 127)
871 # define BIPD(x) do {} while (0)
872 # define BIPDUMP(p,l) BIPD(p)
875 typedef struct BipBufferRec_
883 int can_write; /* boolean */
884 HANDLE evt_write; /* event signaled when one can write to a buffer */
885 int can_read; /* boolean */
886 HANDLE evt_read; /* event signaled when one can read from a buffer */
887 CRITICAL_SECTION lock;
888 unsigned char buff[ BIP_BUFFER_SIZE ];
890 } BipBufferRec, *BipBuffer;
893 bip_buffer_init( BipBuffer buffer )
895 D( "bit_buffer_init %p\n", buffer );
899 buffer->can_write = 1;
900 buffer->can_read = 0;
904 buffer->evt_write = CreateEvent( NULL, TRUE, TRUE, NULL );
905 buffer->evt_read = CreateEvent( NULL, TRUE, FALSE, NULL );
906 InitializeCriticalSection( &buffer->lock );
910 bip_buffer_close( BipBuffer bip )
914 if (!bip->can_read) {
915 SetEvent( bip->evt_read );
917 if (!bip->can_write) {
918 SetEvent( bip->evt_write );
923 bip_buffer_done( BipBuffer bip )
925 BIPD(( "bip_buffer_done: %d->%d\n", bip->fdin, bip->fdout ));
926 CloseHandle( bip->evt_read );
927 CloseHandle( bip->evt_write );
928 DeleteCriticalSection( &bip->lock );
932 bip_buffer_write( BipBuffer bip, const void* src, int len )
934 int avail, count = 0;
939 BIPD(( "bip_buffer_write: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
942 EnterCriticalSection( &bip->lock );
944 while (!bip->can_write) {
946 LeaveCriticalSection( &bip->lock );
952 /* spinlocking here is probably unfair, but let's live with it */
953 ret = WaitForSingleObject( bip->evt_write, INFINITE );
954 if (ret != WAIT_OBJECT_0) { /* buffer probably closed */
955 D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError() );
962 EnterCriticalSection( &bip->lock );
965 BIPD(( "bip_buffer_write: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
967 avail = BIP_BUFFER_SIZE - bip->a_end;
970 /* we can append to region A */
974 memcpy( bip->buff + bip->a_end, src, avail );
980 if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) {
982 ResetEvent( bip->evt_write );
990 avail = bip->a_start - bip->b_end;
991 assert( avail > 0 ); /* since can_write is TRUE */
996 memcpy( bip->buff + bip->b_end, src, avail );
1000 if (bip->b_end == bip->a_start) {
1002 ResetEvent( bip->evt_write );
1006 assert( count > 0 );
1008 if ( !bip->can_read ) {
1010 SetEvent( bip->evt_read );
1013 BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
1014 bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
1015 LeaveCriticalSection( &bip->lock );
1021 bip_buffer_read( BipBuffer bip, void* dst, int len )
1023 int avail, count = 0;
1028 BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
1030 EnterCriticalSection( &bip->lock );
1031 while ( !bip->can_read )
1034 LeaveCriticalSection( &bip->lock );
1039 LeaveCriticalSection( &bip->lock );
1046 ret = WaitForSingleObject( bip->evt_read, INFINITE );
1047 if (ret != WAIT_OBJECT_0) { /* probably closed buffer */
1048 D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError());
1055 EnterCriticalSection( &bip->lock );
1059 BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
1061 avail = bip->a_end - bip->a_start;
1062 assert( avail > 0 ); /* since can_read is TRUE */
1067 memcpy( dst, bip->buff + bip->a_start, avail );
1072 bip->a_start += avail;
1073 if (bip->a_start < bip->a_end)
1077 bip->a_end = bip->b_end;
1084 memcpy( dst, bip->buff, avail );
1086 bip->a_start += avail;
1088 if ( bip->a_start < bip->a_end )
1091 bip->a_start = bip->a_end = 0;
1095 ResetEvent( bip->evt_read );
1098 assert( count > 0 );
1100 if (!bip->can_write ) {
1102 SetEvent( bip->evt_write );
1105 BIPDUMP( (const unsigned char*)dst - count, count );
1106 BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
1107 bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
1108 LeaveCriticalSection( &bip->lock );
1113 typedef struct SocketPairRec_
1115 BipBufferRec a2b_bip;
1116 BipBufferRec b2a_bip;
1122 void _fh_socketpair_init( FH f )
1128 _fh_socketpair_close( FH f )
1131 SocketPair pair = f->fh_pair;
1133 if ( f == pair->a_fd ) {
1137 bip_buffer_close( &pair->b2a_bip );
1138 bip_buffer_close( &pair->a2b_bip );
1140 if ( --pair->used == 0 ) {
1141 bip_buffer_done( &pair->b2a_bip );
1142 bip_buffer_done( &pair->a2b_bip );
1151 _fh_socketpair_lseek( FH f, int pos, int origin )
1158 _fh_socketpair_read( FH f, void* buf, int len )
1160 SocketPair pair = f->fh_pair;
1166 if ( f == pair->a_fd )
1167 bip = &pair->b2a_bip;
1169 bip = &pair->a2b_bip;
1171 return bip_buffer_read( bip, buf, len );
1175 _fh_socketpair_write( FH f, const void* buf, int len )
1177 SocketPair pair = f->fh_pair;
1183 if ( f == pair->a_fd )
1184 bip = &pair->a2b_bip;
1186 bip = &pair->b2a_bip;
1188 return bip_buffer_write( bip, buf, len );
1192 static void _fh_socketpair_hook( FH f, int event, EventHook hook ); /* forward */
1194 static const FHClassRec _fh_socketpair_class =
1196 _fh_socketpair_init,
1197 _fh_socketpair_close,
1198 _fh_socketpair_lseek,
1199 _fh_socketpair_read,
1200 _fh_socketpair_write,
1205 int sdb_socketpair( int sv[2] )
1210 fa = _fh_alloc( &_fh_socketpair_class );
1211 fb = _fh_alloc( &_fh_socketpair_class );
1216 pair = malloc( sizeof(*pair) );
1218 D("sdb_socketpair: not enough memory to allocate pipes\n" );
1222 bip_buffer_init( &pair->a2b_bip );
1223 bip_buffer_init( &pair->b2a_bip );
1230 sv[0] = _fh_to_int(fa);
1231 sv[1] = _fh_to_int(fb);
1233 pair->a2b_bip.fdin = sv[0];
1234 pair->a2b_bip.fdout = sv[1];
1235 pair->b2a_bip.fdin = sv[1];
1236 pair->b2a_bip.fdout = sv[0];
1238 snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
1239 snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
1240 D( "sdb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
1249 /**************************************************************************/
1250 /**************************************************************************/
1252 /***** fdevents emulation *****/
1254 /***** this is a very simple implementation, we rely on the fact *****/
1255 /***** that SDB doesn't use FDE_ERROR. *****/
1257 /**************************************************************************/
1258 /**************************************************************************/
1260 #define FATAL(x...) fatal(__FUNCTION__, x)
1263 static void dump_fde(fdevent *fde, const char *info)
1265 fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
1266 fde->state & FDE_READ ? 'R' : ' ',
1267 fde->state & FDE_WRITE ? 'W' : ' ',
1268 fde->state & FDE_ERROR ? 'E' : ' ',
1272 #define dump_fde(fde, info) do { } while(0)
1275 #define FDE_EVENTMASK 0x00ff
1276 #define FDE_STATEMASK 0xff00
1278 #define FDE_ACTIVE 0x0100
1279 #define FDE_PENDING 0x0200
1280 #define FDE_CREATED 0x0400
1282 static void fdevent_plist_enqueue(fdevent *node);
1283 static void fdevent_plist_remove(fdevent *node);
1284 static fdevent *fdevent_plist_dequeue(void);
1286 static fdevent list_pending = {
1287 .next = &list_pending,
1288 .prev = &list_pending,
1291 static fdevent **fd_table = 0;
1292 static int fd_table_max = 0;
1294 typedef struct EventLooperRec_* EventLooper;
1296 typedef struct EventHookRec_
1301 int wanted; /* wanted event flags */
1302 int ready; /* ready event flags */
1304 void (*prepare)( EventHook hook );
1305 int (*start) ( EventHook hook );
1306 void (*stop) ( EventHook hook );
1307 int (*check) ( EventHook hook );
1308 int (*peek) ( EventHook hook );
1311 static EventHook _free_hooks;
1314 event_hook_alloc( FH fh )
1316 EventHook hook = _free_hooks;
1318 _free_hooks = hook->next;
1320 hook = malloc( sizeof(*hook) );
1322 fatal( "could not allocate event hook\n" );
1328 hook->h = INVALID_HANDLE_VALUE;
1331 hook->prepare = NULL;
1341 event_hook_free( EventHook hook )
1346 hook->next = _free_hooks;
1352 event_hook_signal( EventHook hook )
1355 int fd = _fh_to_int(f);
1356 fdevent* fde = fd_table[ fd - WIN32_FH_BASE ];
1358 if (fde != NULL && fde->fd == fd) {
1359 if ((fde->state & FDE_PENDING) == 0) {
1360 fde->state |= FDE_PENDING;
1361 fdevent_plist_enqueue( fde );
1363 fde->events |= hook->wanted;
1368 #define MAX_LOOPER_HANDLES WIN32_MAX_FHS
1370 typedef struct EventLooperRec_
1373 HANDLE htab[ MAX_LOOPER_HANDLES ];
1379 event_looper_find_p( EventLooper looper, FH fh )
1381 EventHook *pnode = &looper->hooks;
1382 EventHook node = *pnode;
1384 if ( node == NULL || node->fh == fh )
1386 pnode = &node->next;
1393 event_looper_hook( EventLooper looper, int fd, int events )
1395 FH f = _fh_from_int(fd);
1399 if (f == NULL) /* invalid arg */ {
1400 D("event_looper_hook: invalid fd=%d\n", fd);
1404 pnode = event_looper_find_p( looper, f );
1406 if ( node == NULL ) {
1407 node = event_hook_alloc( f );
1408 node->next = *pnode;
1412 if ( (node->wanted & events) != events ) {
1413 /* this should update start/stop/check/peek */
1414 D("event_looper_hook: call hook for %d (new=%x, old=%x)\n",
1415 fd, node->wanted, events);
1416 f->clazz->_fh_hook( f, events & ~node->wanted, node );
1417 node->wanted |= events;
1419 D("event_looper_hook: ignoring events %x for %d wanted=%x)\n",
1420 events, fd, node->wanted);
1425 event_looper_unhook( EventLooper looper, int fd, int events )
1427 FH fh = _fh_from_int(fd);
1428 EventHook *pnode = event_looper_find_p( looper, fh );
1429 EventHook node = *pnode;
1432 int events2 = events & node->wanted;
1433 if ( events2 == 0 ) {
1434 D( "event_looper_unhook: events %x not registered for fd %d\n", events, fd );
1437 node->wanted &= ~events2;
1438 if (!node->wanted) {
1439 *pnode = node->next;
1440 event_hook_free( node );
1445 static EventLooperRec win32_looper;
1447 static void fdevent_init(void)
1449 win32_looper.htab_count = 0;
1450 win32_looper.hooks = NULL;
1453 static void fdevent_connect(fdevent *fde)
1455 EventLooper looper = &win32_looper;
1456 int events = fde->state & FDE_EVENTMASK;
1459 event_looper_hook( looper, fde->fd, events );
1462 static void fdevent_disconnect(fdevent *fde)
1464 EventLooper looper = &win32_looper;
1465 int events = fde->state & FDE_EVENTMASK;
1468 event_looper_unhook( looper, fde->fd, events );
1471 static void fdevent_update(fdevent *fde, unsigned events)
1473 EventLooper looper = &win32_looper;
1474 unsigned events0 = fde->state & FDE_EVENTMASK;
1476 if (events != events0) {
1477 int removes = events0 & ~events;
1478 int adds = events & ~events0;
1480 D("fdevent_update: remove %x from %d\n", removes, fde->fd);
1481 event_looper_unhook( looper, fde->fd, removes );
1484 D("fdevent_update: add %x to %d\n", adds, fde->fd);
1485 event_looper_hook ( looper, fde->fd, adds );
1490 static void fdevent_process()
1492 EventLooper looper = &win32_looper;
1496 /* if we have at least one ready hook, execute it/them */
1497 for (hook = looper->hooks; hook; hook = hook->next) {
1499 if (hook->prepare) {
1500 hook->prepare(hook);
1501 if (hook->ready != 0) {
1502 event_hook_signal( hook );
1508 /* nothing's ready yet, so wait for something to happen */
1511 looper->htab_count = 0;
1513 for (hook = looper->hooks; hook; hook = hook->next)
1515 if (hook->start && !hook->start(hook)) {
1516 D( "fdevent_process: error when starting a hook\n" );
1519 if (hook->h != INVALID_HANDLE_VALUE) {
1522 for (nn = 0; nn < looper->htab_count; nn++)
1524 if ( looper->htab[nn] == hook->h )
1527 looper->htab[ looper->htab_count++ ] = hook->h;
1533 if (looper->htab_count == 0) {
1534 D( "fdevent_process: nothing to wait for !!\n" );
1542 D( "sdb_win32: waiting for %d events\n", looper->htab_count );
1543 if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) {
1544 D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS, aborting!\n", looper->htab_count);
1547 wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE );
1548 if (wait_ret == (int)WAIT_FAILED) {
1549 D( "sdb_win32: wait failed, error %ld\n", GetLastError() );
1551 D( "sdb_win32: got one (index %d)\n", wait_ret );
1553 /* according to Cygwin, some objects like consoles wake up on "inappropriate" events
1554 * like mouse movements. we need to filter these with the "check" function
1556 if ((unsigned)wait_ret < (unsigned)looper->htab_count)
1558 for (hook = looper->hooks; hook; hook = hook->next)
1560 if ( looper->htab[wait_ret] == hook->h &&
1561 (!hook->check || hook->check(hook)) )
1563 D( "sdb_win32: signaling %s for %x\n", hook->fh->name, hook->ready );
1564 event_hook_signal( hook );
1574 for (hook = looper->hooks; hook; hook = hook->next) {
1580 for (hook = looper->hooks; hook; hook = hook->next) {
1581 if (hook->peek && hook->peek(hook))
1582 event_hook_signal( hook );
1587 static void fdevent_register(fdevent *fde)
1589 int fd = fde->fd - WIN32_FH_BASE;
1592 FATAL("bogus negative fd (%d)\n", fde->fd);
1595 if(fd >= fd_table_max) {
1596 int oldmax = fd_table_max;
1597 if(fde->fd > 32000) {
1598 FATAL("bogus huuuuge fd (%d)\n", fde->fd);
1600 if(fd_table_max == 0) {
1604 while(fd_table_max <= fd) {
1607 fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
1609 FATAL("could not expand fd_table to %d entries\n", fd_table_max);
1611 memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
1617 static void fdevent_unregister(fdevent *fde)
1619 int fd = fde->fd - WIN32_FH_BASE;
1621 if((fd < 0) || (fd >= fd_table_max)) {
1622 FATAL("fd out of range (%d)\n", fde->fd);
1625 if(fd_table[fd] != fde) {
1626 FATAL("fd_table out of sync");
1631 if(!(fde->state & FDE_DONT_CLOSE)) {
1632 dump_fde(fde, "close");
1637 static void fdevent_plist_enqueue(fdevent *node)
1639 fdevent *list = &list_pending;
1642 node->prev = list->prev;
1643 node->prev->next = node;
1647 static void fdevent_plist_remove(fdevent *node)
1649 node->prev->next = node->next;
1650 node->next->prev = node->prev;
1655 static fdevent *fdevent_plist_dequeue(void)
1657 fdevent *list = &list_pending;
1658 fdevent *node = list->next;
1660 if(node == list) return 0;
1662 list->next = node->next;
1663 list->next->prev = list;
1670 fdevent *fdevent_create(int fd, fd_func func, void *arg)
1672 fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
1673 if(fde == 0) return 0;
1674 fdevent_install(fde, fd, func, arg);
1675 fde->state |= FDE_CREATED;
1679 void fdevent_destroy(fdevent *fde)
1681 if(fde == 0) return;
1682 if(!(fde->state & FDE_CREATED)) {
1683 FATAL("fde %p not created by fdevent_create()\n", fde);
1685 fdevent_remove(fde);
1688 void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
1690 memset(fde, 0, sizeof(fdevent));
1691 fde->state = FDE_ACTIVE;
1696 fdevent_register(fde);
1697 dump_fde(fde, "connect");
1698 fdevent_connect(fde);
1699 fde->state |= FDE_ACTIVE;
1702 void fdevent_remove(fdevent *fde)
1704 if(fde->state & FDE_PENDING) {
1705 fdevent_plist_remove(fde);
1708 if(fde->state & FDE_ACTIVE) {
1709 fdevent_disconnect(fde);
1710 dump_fde(fde, "disconnect");
1711 fdevent_unregister(fde);
1719 void fdevent_set(fdevent *fde, unsigned events)
1721 events &= FDE_EVENTMASK;
1723 if((fde->state & FDE_EVENTMASK) == (int)events) return;
1725 if(fde->state & FDE_ACTIVE) {
1726 fdevent_update(fde, events);
1727 dump_fde(fde, "update");
1730 fde->state = (fde->state & FDE_STATEMASK) | events;
1732 if(fde->state & FDE_PENDING) {
1733 /* if we're pending, make sure
1734 ** we don't signal an event that
1735 ** is no longer wanted.
1737 fde->events &= (~events);
1738 if(fde->events == 0) {
1739 fdevent_plist_remove(fde);
1740 fde->state &= (~FDE_PENDING);
1745 void fdevent_add(fdevent *fde, unsigned events)
1748 fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
1751 void fdevent_del(fdevent *fde, unsigned events)
1754 fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
1763 fprintf(stderr,"--- ---- waiting for events\n");
1767 while((fde = fdevent_plist_dequeue())) {
1768 unsigned events = fde->events;
1770 fde->state &= (~FDE_PENDING);
1771 dump_fde(fde, "callback");
1772 fde->func(fde->fd, events, fde->arg);
1777 /** FILE EVENT HOOKS
1780 static void _event_file_prepare( EventHook hook )
1782 if (hook->wanted & (FDE_READ|FDE_WRITE)) {
1783 /* we can always read/write */
1784 hook->ready |= hook->wanted & (FDE_READ|FDE_WRITE);
1788 static int _event_file_peek( EventHook hook )
1790 return (hook->wanted & (FDE_READ|FDE_WRITE));
1793 static void _fh_file_hook( FH f, int events, EventHook hook )
1795 hook->h = f->fh_handle;
1796 hook->prepare = _event_file_prepare;
1797 hook->peek = _event_file_peek;
1800 /** SOCKET EVENT HOOKS
1803 static void _event_socket_verify( EventHook hook, WSANETWORKEVENTS* evts )
1805 if ( evts->lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE) ) {
1806 if (hook->wanted & FDE_READ)
1807 hook->ready |= FDE_READ;
1808 if ((evts->iErrorCode[FD_READ] != 0) && hook->wanted & FDE_ERROR)
1809 hook->ready |= FDE_ERROR;
1811 if ( evts->lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE) ) {
1812 if (hook->wanted & FDE_WRITE)
1813 hook->ready |= FDE_WRITE;
1814 if ((evts->iErrorCode[FD_WRITE] != 0) && hook->wanted & FDE_ERROR)
1815 hook->ready |= FDE_ERROR;
1817 if ( evts->lNetworkEvents & FD_OOB ) {
1818 if (hook->wanted & FDE_ERROR)
1819 hook->ready |= FDE_ERROR;
1823 static void _event_socket_prepare( EventHook hook )
1825 WSANETWORKEVENTS evts;
1827 /* look if some of the events we want already happened ? */
1828 if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts ))
1829 _event_socket_verify( hook, &evts );
1832 static int _socket_wanted_to_flags( int wanted )
1835 if (wanted & FDE_READ)
1836 flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
1838 if (wanted & FDE_WRITE)
1839 flags |= FD_WRITE | FD_CONNECT | FD_CLOSE;
1841 if (wanted & FDE_ERROR)
1847 static int _event_socket_start( EventHook hook )
1849 /* create an event which we're going to wait for */
1851 long flags = _socket_wanted_to_flags( hook->wanted );
1853 hook->h = fh->event;
1854 if (hook->h == INVALID_HANDLE_VALUE) {
1855 D( "_event_socket_start: no event for %s\n", fh->name );
1859 if ( flags != fh->mask ) {
1860 D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags );
1861 if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) {
1862 D( "_event_socket_start: WSAEventSelect() for %s failed, error %d\n", hook->fh->name, WSAGetLastError() );
1863 CloseHandle( hook->h );
1864 hook->h = INVALID_HANDLE_VALUE;
1873 static void _event_socket_stop( EventHook hook )
1875 hook->h = INVALID_HANDLE_VALUE;
1878 static int _event_socket_check( EventHook hook )
1882 WSANETWORKEVENTS evts;
1884 if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) {
1885 _event_socket_verify( hook, &evts );
1886 result = (hook->ready != 0);
1888 ResetEvent( hook->h );
1891 D( "_event_socket_check %s returns %d\n", fh->name, result );
1895 static int _event_socket_peek( EventHook hook )
1897 WSANETWORKEVENTS evts;
1900 /* look if some of the events we want already happened ? */
1901 if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) {
1902 _event_socket_verify( hook, &evts );
1904 ResetEvent( hook->h );
1907 return hook->ready != 0;
1912 static void _fh_socket_hook( FH f, int events, EventHook hook )
1914 hook->prepare = _event_socket_prepare;
1915 hook->start = _event_socket_start;
1916 hook->stop = _event_socket_stop;
1917 hook->check = _event_socket_check;
1918 hook->peek = _event_socket_peek;
1920 _event_socket_start( hook );
1923 /** SOCKETPAIR EVENT HOOKS
1926 static void _event_socketpair_prepare( EventHook hook )
1929 SocketPair pair = fh->fh_pair;
1930 BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
1931 BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
1933 if (hook->wanted & FDE_READ && rbip->can_read)
1934 hook->ready |= FDE_READ;
1936 if (hook->wanted & FDE_WRITE && wbip->can_write)
1937 hook->ready |= FDE_WRITE;
1940 static int _event_socketpair_start( EventHook hook )
1943 SocketPair pair = fh->fh_pair;
1944 BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
1945 BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
1947 if (hook->wanted == FDE_READ)
1948 hook->h = rbip->evt_read;
1950 else if (hook->wanted == FDE_WRITE)
1951 hook->h = wbip->evt_write;
1954 D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" );
1957 D( "_event_socketpair_start: hook %s for %x wanted=%x\n",
1958 hook->fh->name, _fh_to_int(fh), hook->wanted);
1962 static int _event_socketpair_peek( EventHook hook )
1964 _event_socketpair_prepare( hook );
1965 return hook->ready != 0;
1968 static void _fh_socketpair_hook( FH fh, int events, EventHook hook )
1970 hook->prepare = _event_socketpair_prepare;
1971 hook->start = _event_socketpair_start;
1972 hook->peek = _event_socketpair_peek;
1977 sdb_sysdeps_init( void )
1979 #define SDB_MUTEX(x) InitializeCriticalSection( & x );
1980 #include "mutex_list.h"
1981 InitializeCriticalSection( &_win32_lock );