further Windoze support (test/io5.c works, gatling still doesn't)

This is just to get gatling to work, I may remove it again after
    that.
master
leitner 20 years ago
parent f65398ff2e
commit c1c50c7dbd

@ -4,6 +4,9 @@
allocates space, it also needs to be in the initialized space. allocates space, it also needs to be in the initialized space.
add -D_REENTRANT to CFLAGS so libowfat can be used in multi-threaded add -D_REENTRANT to CFLAGS so libowfat can be used in multi-threaded
programs programs
further Windoze support (test/io5.c works, gatling still doesn't)
This is just to get gatling to work, I may remove it again after
that.
0.24: 0.24:
fix scan_to_sa (Tim Lorenz) fix scan_to_sa (Tim Lorenz)

@ -14,7 +14,9 @@ buffer.a mmap.a taia.a tai.a dns.a case.a mult.a array.a io.a textcode.a
all: t $(LIBS) libowfat.a libsocket all: t $(LIBS) libowfat.a libsocket
CC=gcc CROSS=
#CROSS=i686-mingw-
CC=$(CROSS)gcc
CFLAGS=-pipe -W -Wall -O2 -fomit-frame-pointer CFLAGS=-pipe -W -Wall -O2 -fomit-frame-pointer
#CFLAGS=-pipe -Os -march=pentiumpro -mcpu=pentiumpro -fomit-frame-pointer -fschedule-insns2 -Wall #CFLAGS=-pipe -Os -march=pentiumpro -mcpu=pentiumpro -fomit-frame-pointer -fschedule-insns2 -Wall
@ -126,8 +128,8 @@ $(TAIA_OBJS) $(TAI_OBJS) $(CASE_OBJS) $(ARRAY_OBJS) $(MULT_OBJS) \
$(IO_OBJS) $(IO_OBJS)
libowfat.a: $(ALL_OBJS) libowfat.a: $(ALL_OBJS)
ar cr $@ $(ALL_OBJS) $(CROSS)ar cr $@ $(ALL_OBJS)
-ranlib $@ -$(CROSS)ranlib $@
CFLAGS+=-I. CFLAGS+=-I.
@ -290,3 +292,5 @@ Makefile: GNUmakefile dep libdep
-e 's/^CURNAME=.*/'CURNAME=$(CURNAME)/ \ -e 's/^CURNAME=.*/'CURNAME=$(CURNAME)/ \
-e 's/ Makefile//' < GNUmakefile >> $@ -e 's/ Makefile//' < GNUmakefile >> $@
windoze:
$(MAKE) DIET= CROSS=i686-mingw32-

@ -3,6 +3,10 @@
#include <errno.h> #include <errno.h>
#include "io_internal.h" #include "io_internal.h"
#ifdef __MINGW32__
#include <stdio.h>
#endif
int64 io_canread() { int64 io_canread() {
io_entry* e; io_entry* e;
if (first_readable==-1) if (first_readable==-1)
@ -26,7 +30,18 @@ int64 io_canread() {
first_readable=e->next_read; first_readable=e->next_read;
e->next_read=-1; e->next_read=-1;
debug_printf(("io_canread: dequeue %lld from normal read queue (next is %ld)\n",r,first_readable)); debug_printf(("io_canread: dequeue %lld from normal read queue (next is %ld)\n",r,first_readable));
if (e->wantread && e->canread) {
#ifdef __MINGW32__
// printf("event on %d: wr %d rq %d aq %d\n",(int)r,e->wantread,e->readqueued,e->acceptqueued);
#endif
if (e->wantread &&
#ifdef __MINGW32__
(e->canread || e->acceptqueued==1 || e->readqueued==1)
#else
e->canread
#endif
) {
#ifdef HAVE_SIGIO #ifdef HAVE_SIGIO
e->next_read=alt_firstread; e->next_read=alt_firstread;
alt_firstread=r; alt_firstread=r;

@ -26,7 +26,13 @@ int64 io_canwrite() {
first_writeable=e->next_write; first_writeable=e->next_write;
e->next_write=-1; e->next_write=-1;
debug_printf(("io_canwrite: dequeue %lld from normal write queue (next is %ld)\n",r,first_writeable)); debug_printf(("io_canwrite: dequeue %lld from normal write queue (next is %ld)\n",r,first_writeable));
if (e->wantwrite && e->canwrite) { if (e->wantwrite &&
#ifdef __MINGW32__
(e->canwrite || e->sendfilequeued==1)
#else
e->canwrite
#endif
) {
#ifdef HAVE_SIGIO #ifdef HAVE_SIGIO
e->next_write=alt_firstwrite; e->next_write=alt_firstwrite;
alt_firstwrite=r; alt_firstwrite=r;

@ -50,8 +50,10 @@ int io_fd(int64 d) {
long r; long r;
if ((r=fcntl(d,F_GETFL,0)) == -1) if ((r=fcntl(d,F_GETFL,0)) == -1)
return 0; /* file descriptor not open */ return 0; /* file descriptor not open */
printf("io_fd(%d)\n",(int)d);
#endif #endif
if (!(e=array_allocate(&io_fds,sizeof(io_entry),d))) return 0; if (!(e=array_allocate(&io_fds,sizeof(io_entry),d))) return 0;
if (e->inuse) return 1;
byte_zero(e,sizeof(io_entry)); byte_zero(e,sizeof(io_entry));
e->inuse=1; e->inuse=1;
#ifdef __MINGW32__ #ifdef __MINGW32__
@ -90,8 +92,13 @@ int io_fd(int64 d) {
} }
#endif #endif
#ifdef __MINGW32__ #ifdef __MINGW32__
io_comport=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,1); io_comport=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
if (io_comport) io_waitmode=COMPLETIONPORT; if (io_comport) {
io_waitmode=COMPLETIONPORT;
} else {
errno=EINVAL;
return 0;
}
#endif #endif
} }
#if defined(HAVE_SIGIO) #if defined(HAVE_SIGIO)
@ -103,6 +110,14 @@ int io_fd(int64 d) {
#endif #endif
fcntl(d,F_SETFL,fcntl(d,F_GETFL)|O_NONBLOCK|O_ASYNC); fcntl(d,F_SETFL,fcntl(d,F_GETFL)|O_NONBLOCK|O_ASYNC);
} }
#endif
#ifdef __MINGW32__
if (io_comport) {
if (CreateIoCompletionPort((HANDLE)d,io_comport,(ULONG_PTR)d,0)==0) {
errno=EBADF;
return 0;
}
}
#endif #endif
return 1; return 1;
} }

@ -6,8 +6,8 @@
#include <windows.h> #include <windows.h>
#else #else
#include <sys/mman.h> #include <sys/mman.h>
#include <errno.h>
#endif #endif
#include <errno.h>
#define BUFSIZE 16384 #define BUFSIZE 16384

@ -112,6 +112,38 @@ int64 io_sendfile(int64 s,int64 fd,uint64 off,uint64 n) {
} }
#endif #endif
#elif defined(__MINGW32__)
#include <windows.h>
#include <mswsock.h>
int64 io_sendfile(int64 out,int64 in,uint64 off,uint64 bytes) {
io_entry* e=array_get(&io_fds,sizeof(io_entry),out);
if (!e) { errno=EBADF; return -3; }
if (e->sendfilequeued==1) {
/* we called TransmitFile, and it returned. */
e->sendfilequeued=2;
errno=e->errorcode;
if (e->bytes_written==-1) return -1;
if (e->bytes_written!=bytes) { /* we wrote less than caller wanted to write */
e->sendfilequeued=1; /* so queue next request */
off+=e->bytes_written;
bytes-=e->bytes_written;
e->os.Offset=off;
e->os.OffsetHigh=(off>>32);
TransmitFile(out,(HANDLE)in,bytes>0xffff?0xffff:bytes,0,&e->os,0,TF_USE_KERNEL_APC);
}
return e->bytes_written;
} else {
e->sendfilequeued=1;
e->os.Offset=off;
e->os.OffsetHigh=(off>>32);
/* we always write at most 64k, so timeout handling is possible */
if (!TransmitFile(out,(HANDLE)in,bytes>0xffff?0xffff:bytes,0,&e->os,0,TF_USE_KERNEL_APC))
return -3;
}
}
#else #else
#include <iob.h> #include <iob.h>

@ -1,8 +1,74 @@
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#ifdef __MINGW32__
#include <windows.h>
#include <stdio.h>
#else
#include <poll.h> #include <poll.h>
#endif
#include <errno.h> #include <errno.h>
#include "io_internal.h" #include "io_internal.h"
#include "byte.h"
#ifdef __MINGW32__
/* In Windows, I/O works differently. */
/* Instead of calling read until it says EAGAIN, you call read in
* overlapping mode, and then wait for it to finish.
* We map this to our API by having the first call to io_tryread always
* return EAGAIN, wait for the I/O completion port to tell us the read
* is finished, and then return the data we actually read the next time
* we are called. */
int64 io_tryread(int64 d,char* buf,int64 len) {
io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
if (!e) { errno=EBADF; return -3; }
if (len<0) { errno=EINVAL; return -3; }
if (e->readqueued==2) {
int x=e->bytes_read;
if (e->errorcode) {
errno=e->errorcode;
e->canread=0;
return -3;
}
if (x>len) x=len;
if (x) {
byte_copy(buf,x,e->inbuf);
byte_copy(e->inbuf,e->bytes_read-x,e->inbuf+x);
e->bytes_read-=x;
}
if (!e->bytes_read) {
e->canread=0;
if (len>x) {
/* queue next read */
if (len>sizeof(e->inbuf)) len=sizeof(e->inbuf);
if (ReadFile((HANDLE)d,e->inbuf,len,0,&e->or)) {
e->canread=1;
e->readqueued=2;
e->next_write=first_writeable;
first_writeable=d;
} else if ((e->errorcode=GetLastError())==ERROR_IO_PENDING) {
e->readqueued=1;
e->errorcode=0;
} else {
e->canread=1;
e->readqueued=2;
e->next_write=first_writeable;
first_writeable=d;
}
}
}
return x;
}
if (!e->readqueued) {
if (len>sizeof(e->inbuf)) len=sizeof(e->inbuf);
if (ReadFile((HANDLE)d,e->inbuf,len,0,&e->or))
e->readqueued=1;
}
errno=EAGAIN;
return -1;
}
#else
int64 io_tryread(int64 d,char* buf,int64 len) { int64 io_tryread(int64 d,char* buf,int64 len) {
long r; long r;
@ -48,3 +114,5 @@ int64 io_tryread(int64 d,char* buf,int64 len) {
} }
return r; return r;
} }
#endif

@ -1,9 +1,63 @@
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#ifdef __MINGW32__
#include <windows.h>
#else
#include <poll.h> #include <poll.h>
#endif
#include <errno.h> #include <errno.h>
#include "io_internal.h" #include "io_internal.h"
#ifdef __MINGW32__
/* All the Unix trickery is unsupported on Windows. Instead, one is
* supposed to do the whole write in overlapping mode and then get
* notified via an I/O completion port when it's done. */
/* So we assume io_trywrite is not used so much and do the overlapping
* stuff on I/O batches. */
int64 io_trywrite(int64 d,const char* buf,int64 len) {
io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
int r;
if (!e) { errno=EBADF; return -3; }
if (!e->nonblock) {
DWORD written;
if (WriteFile((HANDLE)d,buf,len,&written,0))
return written;
else
return winsock2errno(-3);
} else {
if (e->writequeued) {
errno=EAGAIN;
return -1;
}
if (e->canwrite) {
e->canwrite=0;
e->next_write=-1;
if (e->errorcode) {
errno=winsock2errno(e->errorcode);
return -3;
}
return e->bytes_written;
} else {
if (WriteFile((HANDLE)d,buf,len,&e->errorcode,&e->ow))
return e->errorcode; /* should not happen */
else if (GetLastError()==ERROR_IO_PENDING) {
e->writequeued=1;
errno=EAGAIN;
e->errorcode=0;
return -1;
} else {
winsock2errno(-1);
e->errorcode=errno;
return -3;
}
}
}
}
#else
int64 io_trywrite(int64 d,const char* buf,int64 len) { int64 io_trywrite(int64 d,const char* buf,int64 len) {
long r; long r;
struct itimerval old,new; struct itimerval old,new;
@ -49,3 +103,5 @@ int64 io_trywrite(int64 d,const char* buf,int64 len) {
} }
return r; return r;
} }
#endif

@ -1,8 +1,34 @@
#include <unistd.h> #include <unistd.h>
#ifdef __MINGW32__
#include <windows.h>
#else
#include <poll.h> #include <poll.h>
#endif
#include <errno.h> #include <errno.h>
#include "io_internal.h" #include "io_internal.h"
#ifdef __MINGW32__
int64 io_waitread(int64 d,char* buf,int64 len) {
long r;
io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
if (!e) { errno=EBADF; return -3; }
if (e->nonblock) {
unsigned long i=0;
ioctlsocket(d, FIONBIO, &i);
}
r=read(d,buf,len);
if (e->nonblock) {
unsigned long i=1;
ioctlsocket(d, FIONBIO, &i);
}
if (r==-1)
r=-3;
return r;
}
#else
int64 io_waitread(int64 d,char* buf,int64 len) { int64 io_waitread(int64 d,char* buf,int64 len) {
long r; long r;
struct pollfd p; struct pollfd p;
@ -25,3 +51,5 @@ again:
} }
return r; return r;
} }
#endif

@ -8,7 +8,11 @@
#endif #endif
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#ifdef __MINGW32__
#include <windows.h>
#else
#include <poll.h> #include <poll.h>
#endif
#include <errno.h> #include <errno.h>
#ifdef HAVE_KQUEUE #ifdef HAVE_KQUEUE
#include <sys/event.h> #include <sys/event.h>
@ -28,7 +32,9 @@
#endif #endif
int64 io_waituntil2(int64 milliseconds) { int64 io_waituntil2(int64 milliseconds) {
#ifndef __MINGW32__
struct pollfd* p; struct pollfd* p;
#endif
long i,j,r; long i,j,r;
if (!io_wanted_fds) return 0; if (!io_wanted_fds) return 0;
#ifdef HAVE_EPOLL #ifdef HAVE_EPOLL
@ -195,6 +201,78 @@ int64 io_waituntil2(int64 milliseconds) {
} }
dopoll: dopoll:
#endif #endif
#ifdef __MINGW32__
DWORD numberofbytes;
ULONG_PTR x;
LPOVERLAPPED o;
if (first_readable!=-1 || first_writeable!=-1) return;
if (GetQueuedCompletionStatus(io_comport,&numberofbytes,&x,&o,milliseconds==-1?milliseconds:INFINITE)) {
io_entry* e=array_get(&io_fds,sizeof(io_entry),x);
if (!e) return 0;
e->errorcode=0;
if (o==&e->or && e->readqueued==1) {
e->readqueued=2;
e->canread=1;
e->bytes_read=numberofbytes;
e->next_read=first_readable;
first_readable=x;
// printf("read %lu bytes on fd %lu: %p\n",numberofbytes,x,e);
} else if (o==&e->ow && e->writequeued==1) {
e->writequeued=2;
e->canwrite=1;
e->bytes_written=numberofbytes;
e->next_write=first_writeable;
first_writeable=x;
} else if (o==&e->or && e->acceptqueued==1) {
e->acceptqueued=2;
e->canread=1;
e->next_read=first_readable;
first_readable=x;
} else if (o==&e->ow && e->connectqueued==1) {
e->connectqueued=2;
e->canwrite=1;
e->next_write=first_writeable;
first_writeable=x;
} else if (o==&e->os && e->sendfilequeued==1) {
e->sendfilequeued=2;
e->canwrite=1;
e->bytes_written=numberofbytes;
e->next_write=first_writeable;
first_writeable=x;
}
return 1;
} else {
/* either the overlapped I/O request failed or we timed out */
DWORD err;
io_entry* e;
if (!o) return 0; /* timeout */
/* we got a completion packet for a failed I/O operation */
err=GetLastError();
if (err==WAIT_TIMEOUT) return 0; /* or maybe not */
e=array_get(&io_fds,sizeof(io_entry),x);
if (!e) return 0; /* WTF?! */
e->errorcode=err;
if (o==&e->or && (e->readqueued || e->acceptqueued)) {
if (e->readqueued) e->readqueued=2; else
if (e->acceptqueued) e->acceptqueued=2;
e->canread=1;
e->bytes_read=-1;
e->next_read=first_readable;
first_readable=x;
} else if ((o==&e->ow || o==&e->os) &&
(e->writequeued || e->connectqueued || e->sendfilequeued)) {
if (o==&e->ow) {
if (e->writequeued) e->writequeued=2; else
if (e->connectqueued) e->connectqueued=2;
} else if (o==&e->os) e->sendfilequeued=2;
e->canwrite=1;
e->bytes_written=-1;
e->next_write=first_writeable;
first_writeable=x;
}
return 1;
}
#else
for (i=r=0; i<array_length(&io_fds,sizeof(io_entry)); ++i) { for (i=r=0; i<array_length(&io_fds,sizeof(io_entry)); ++i) {
io_entry* e=array_get(&io_fds,sizeof(io_entry),i); io_entry* e=array_get(&io_fds,sizeof(io_entry),i);
if (!e) return -1; if (!e) return -1;
@ -231,4 +309,5 @@ dopoll:
p++; p++;
} }
return i; return i;
#endif
} }

@ -1,8 +1,34 @@
#include <unistd.h> #include <unistd.h>
#ifdef __MINGW32__
#include <windows.h>
#else
#include <poll.h> #include <poll.h>
#endif
#include <errno.h> #include <errno.h>
#include "io_internal.h" #include "io_internal.h"
#ifdef __MINGW32__
int64 io_waitwrite(int64 d,const char* buf,int64 len) {
long r;
io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
if (!e) { errno=EBADF; return -3; }
if (e->nonblock) {
unsigned long i=0;
ioctlsocket(d, FIONBIO, &i);
}
r=write(d,buf,len);
if (e->nonblock) {
unsigned long i=1;
ioctlsocket(d, FIONBIO, &i);
}
if (r==-1)
r=-3;
return r;
}
#else
int64 io_waitwrite(int64 d,const char* buf,int64 len) { int64 io_waitwrite(int64 d,const char* buf,int64 len) {
long r; long r;
struct pollfd p; struct pollfd p;
@ -26,3 +52,5 @@ again:
} }
return r; return r;
} }
#endif

@ -19,6 +19,9 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/devpoll.h> #include <sys/devpoll.h>
#endif #endif
#ifdef __MINGW32__
#include <mswsock.h>
#endif
void io_wantread(int64 d) { void io_wantread(int64 d) {
int newfd; int newfd;
@ -69,6 +72,34 @@ void io_wantread(int64 d) {
first_readable=d; first_readable=d;
} }
} }
#endif
#ifdef __MINGW32__
if (e->listened) {
if (e->next_accept==0) e->next_accept=socket(AF_INET,SOCK_STREAM,0);
if (e->next_accept!=-1) {
AcceptEx(d,e->next_accept,e->inbuf,0,200,200,&e->errorcode,&e->or);
e->acceptqueued=1;
}
} else if (!e->wantread) {
if (ReadFile((HANDLE)d,e->inbuf,sizeof(e->inbuf),&e->errorcode,&e->or)) {
queueread:
/* had something to read immediately. Damn! */
e->readqueued=0;
e->canread=1;
e->bytes_read=e->errorcode;
e->errorcode=0;
e->next_read=first_readable;
first_readable=d;
return;
} else if (GetLastError()==ERROR_IO_PENDING)
e->readqueued=1;
else
goto queueread;
#if 0
e->next_read=first_readable;
first_readable=d;
#endif
}
#endif #endif
e->wantread=1; e->wantread=1;
} }

@ -69,6 +69,12 @@ void io_wantwrite(int64 d) {
first_writeable=d; first_writeable=d;
} }
} }
#endif
#ifdef __MINGW32__
if (!e->wantwrite) {
e->next_write=first_writeable;
first_writeable=d;
}
#endif #endif
e->wantwrite=1; e->wantwrite=1;
} }

@ -1,4 +1,15 @@
#include "iob_internal.h" #include "iob_internal.h"
#ifdef __MINGW32__
/* not supported */
void iob_internal(io_batch* b,uint64 bytes) {
(void)b;
(void)bytes;
}
#else
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h> #include <sys/mman.h>
@ -40,3 +51,5 @@ void iob_prefetch(io_batch* b,uint64 bytes) {
} }
(void)x; (void)x;
} }
#endif

@ -1,3 +1,82 @@
#ifdef __MINGW32__
#include <windows.h>
#include <mswsock.h>
#include <errno.h>
#include "io_internal.h"
#include "iob_internal.h"
int64 iob_send(int64 s,io_batch* b) {
/* Windows has a sendfile called TransmitFile, which can send one
* header and one trailer buffer. */
iob_entry* x,* last;
io_entry* e;
int64 sent;
int i;
if (b->bytesleft==0) return 0;
sent=-1;
e=array_get(&io_fds,sizeof(io_entry),s);
if (!e) { errno=EBADF; return -3; }
if (!(x=array_get(&b->b,sizeof(iob_entry),b->next)))
return -3; /* can't happen error */
last=(iob_entry*)(((char*)array_start(&b->b))+array_bytes(&b->b));
if (e->canwrite || e->sendfilequeued==1) {
/* An overlapping write finished. Reap the result. */
if (e->bytes_written==-1) return -3;
if (e->bytes_written<x->n) {
sent=e->bytes_written;
if (x->n < e->bytes_written) {
e->bytes_written-=x->n;
x->n=0;
++x;
}
x->n -= e->bytes_written;
x->offset += e->bytes_written;
b->bytesleft -= e->bytes_written;
}
e->canwrite=0; e->sendfilequeued=0;
}
for (i=0; x+i<last; ++i)
if (x[i].n) break;
if (x[i].type==FROMBUF || x[i].type==FROMBUF_FREE) {
if (x+i+1 < last &&
(x[i+1].type==FROMFILE || x[i+1].type==FROMFILE_CLOSE)) {
TRANSMIT_FILE_BUFFERS tfb;
e->sendfilequeued=1;
memset(&tfb,0,sizeof(tfb));
memset(&e[i].os,0,sizeof(e[i].os));
e[i].os.Offset=x[i].offset;
e[i].os.OffsetHigh=(x[i].offset>>32);
if (!TransmitFile(s,(HANDLE)x[i].fd,
x[i].n+tfb.HeadLength>0xffff?0xffff:x[i].n,
0,&e[i].os,&tfb,TF_USE_KERNEL_APC))
return -3;
return sent;
} else {
e->writequeued=1;
if (!WriteFile(s,x[i].buf+x[i].offset,x[i].n,0,&e->ow))
return -3;
return sent;
}
} else {
e->sendfilequeued=1;
memset(&e[i].os,0,sizeof(e[i].os));
e[i].os.Offset=x[i].offset;
e[i].os.OffsetHigh=(x[i].offset>>32);
if (!TransmitFile(s,(HANDLE)x[i].fd,
x[i].n>0xffff?0xffff:x[i].n,
0,&e[i].os,0,TF_USE_KERNEL_APC))
return -3;
return sent;
}
}
#else
#include "havebsdsf.h" #include "havebsdsf.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -132,3 +211,5 @@ eagain:
abort: abort:
return total; return total;
} }
#endif

@ -1,5 +1,9 @@
#include "io.h" #include "io.h"
#include "array.h" #include "array.h"
#ifdef __MINGW32__
#include "socket.h"
extern HANDLE io_comport;
#else
#include "haveepoll.h" #include "haveepoll.h"
#include "havekqueue.h" #include "havekqueue.h"
#include "havedevpoll.h" #include "havedevpoll.h"
@ -8,10 +12,6 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <signal.h> #include <signal.h>
#endif #endif
#ifdef __MINGW32__
#include "socket.h"
extern HANDLE io_comport;
#endif #endif
typedef struct { typedef struct {
@ -22,6 +22,14 @@ typedef struct {
unsigned int canwrite:1; unsigned int canwrite:1;
unsigned int nonblock:1; unsigned int nonblock:1;
unsigned int inuse:1; unsigned int inuse:1;
#ifdef __MINGW32__
unsigned int readqueued:2;
unsigned int writequeued:2;
unsigned int acceptqueued:2;
unsigned int connectqueued:2;
unsigned int sendfilequeued:2;
unsigned int listened:1;
#endif
long next_read; long next_read;
long next_write; long next_write;
void* cookie; void* cookie;
@ -29,8 +37,12 @@ typedef struct {
long maplen; long maplen;
uint64 mapofs; uint64 mapofs;
#ifdef __MINGW32__ #ifdef __MINGW32__
OVERLAPPED o; OVERLAPPED or,ow,os; /* overlapped for read+accept, write+connect, sendfile */
HANDLE /* fd, */ mh; HANDLE /* fd, */ mh;
char inbuf[8192];
int bytes_read,bytes_written;
DWORD errorcode;
SOCKET next_accept;
#endif #endif
} io_entry; } io_entry;

@ -7,12 +7,75 @@
#include "socket.h" #include "socket.h"
#include "havesl.h" #include "havesl.h"
#ifdef __MINGW32__
#include <windows.h>
#include <mswsock.h>
#include <errno.h>
#include <stdio.h>
#include "io_internal.h"
#endif
int socket_accept4(int s,char *ip,uint16 *port) { int socket_accept4(int s,char *ip,uint16 *port) {
struct sockaddr_in si; struct sockaddr_in si;
socklen_t len = sizeof si; socklen_t len = sizeof si;
int fd; int fd;
#ifdef __MINGW32__
io_entry* e=array_get(&io_fds,sizeof(io_entry),s);
if (e && e->inuse) {
int sa2len;
fd=-1;
if (e->acceptqueued==1) {
errno=EAGAIN;
return -1;
}
if (e->acceptqueued==2) {
incoming:
/* incoming! */
{
struct sockaddr* x,* y;
GetAcceptExSockaddrs(e->inbuf,0,200,200,&x,&sa2len,&y,&len);
if (len>sizeof(si)) len=sizeof(si);
memcpy(&si,y,len);
}
fd=e->next_accept;
e->next_accept=0;
if (e->nonblock) {
if (io_fd(fd)) {
io_entry* f=array_get(&io_fds,sizeof(io_entry),fd);
if (f) {
f->nonblock=1;
// printf("setting fd %lu to non-blocking\n",(int)fd);
}
}
}
}
/* no accept queued, queue one now. */
if (e->next_accept==0) {
e->next_accept=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (e==-1)
return winsock2errno(-1);
}
if (AcceptEx(s,e->next_accept,e->inbuf,0,200,200,&e->errorcode,&e->or))
goto incoming;
if (WSAGetLastError() != ERROR_IO_PENDING)
return winsock2errno(-1);
e->acceptqueued=1;
if (fd==-1) {
errno=EAGAIN;
return fd;
}
} else {
#endif
if ((fd=accept(s,(void*) &si,&len))==-1) if ((fd=accept(s,(void*) &si,&len))==-1)
return winsock2errno(-1); return winsock2errno(-1);
#ifdef __MINGW32__
}
#endif
if (ip) *(uint32*)ip = *(uint32*)&si.sin_addr; if (ip) *(uint32*)ip = *(uint32*)&si.sin_addr;
if (port) uint16_unpack_big((char *) &si.sin_port,port); if (port) uint16_unpack_big((char *) &si.sin_port,port);
return fd; return fd;

@ -12,6 +12,14 @@
#include "havesl.h" #include "havesl.h"
#include "havescope.h" #include "havescope.h"
#ifdef __MINGW32__
#include <windows.h>
#include <mswsock.h>
#include <errno.h>
#include <stdio.h>
#include "io_internal.h"
#endif
int socket_accept6(int s,char* ip,uint16* port,uint32* scope_id) int socket_accept6(int s,char* ip,uint16* port,uint32* scope_id)
{ {
#ifdef LIBC_HAS_IP6 #ifdef LIBC_HAS_IP6
@ -22,9 +30,61 @@ int socket_accept6(int s,char* ip,uint16* port,uint32* scope_id)
socklen_t dummy = sizeof sa; socklen_t dummy = sizeof sa;
int fd; int fd;
#ifdef __MINGW32__
io_entry* e=array_get(&io_fds,sizeof(io_entry),s);
if (e && e->inuse) {
int sa2len;
fd=-1;
if (e->acceptqueued==1) {
errno=EAGAIN;
return -1;
}
if (e->acceptqueued==2) {
incoming:
/* incoming! */
{
struct sockaddr* x,* y;
GetAcceptExSockaddrs(e->inbuf,0,200,200,&x,&sa2len,&y,&dummy);
if (dummy>sizeof(sa)) dummy=sizeof(sa);
memcpy(&sa,y,dummy);
}
fd=e->next_accept;
e->next_accept=0;
if (e->nonblock) {
if (io_fd(fd)) {
io_entry* f=array_get(&io_fds,sizeof(io_entry),fd);
if (f) {
f->nonblock=1;
// printf("setting fd %lu to non-blocking\n",(int)fd);
}
}
}
}
/* no accept queued, queue one now. */
if (e->next_accept==0) {
e->next_accept=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (e==-1)
return winsock2errno(-1);
}
if (AcceptEx(s,e->next_accept,e->inbuf,0,200,200,&e->errorcode,&e->or))
goto incoming;
if (WSAGetLastError() != ERROR_IO_PENDING)
return winsock2errno(-1);
e->acceptqueued=1;
if (fd==-1) {
errno=EAGAIN;
return fd;
}
} else {
#endif
fd = accept(s,(struct sockaddr *) &sa,&dummy); fd = accept(s,(struct sockaddr *) &sa,&dummy);
if (fd == -1) if (fd == -1)
return winsock2errno(-1); return winsock2errno(-1);
#ifdef __MINGW32__
}
#endif
#ifdef LIBC_HAS_IP6 #ifdef LIBC_HAS_IP6
if (sa.sin6_family==AF_INET) { if (sa.sin6_family==AF_INET) {

@ -1,10 +1,33 @@
#include <sys/types.h> #include <sys/types.h>
#ifndef __MINGW32__ #ifdef __MINGW32__
#include "io_internal.h"
#include <mswsock.h>
#else
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#include "socket.h" #include "socket.h"
#include "windoze.h" #include "windoze.h"
int socket_listen(int s,unsigned int backlog) { int socket_listen(int s,unsigned int backlog) {
return winsock2errno(listen(s, backlog)); #ifdef __MINGW32__
io_entry* e;
int r = listen(s, backlog);
if (r==-1) return winsock2errno(-1);
e=array_get(&io_fds,sizeof(io_entry),s);
if (e && e->inuse) {
e->listened=1;
if (e->wantread) {
/* queue a non-blocking accept */
DWORD received;
e->next_accept=socket(AF_INET,SOCK_STREAM,0);
if (e->next_accept!=-1) {
AcceptEx(s,e->next_accept,e->inbuf,0,200,200,&received,&e->or);
e->acceptqueued=1;
}
}
}
return r;
#else
return listen(s, backlog);
#endif
} }

@ -15,19 +15,19 @@ int main() {
buffer_putnlflush(buffer_2); buffer_putnlflush(buffer_2);
return 111; return 111;
} }
if (socket_listen(s,16)==-1) { if (!io_fd(s)) {
buffer_puts(buffer_2,"socket_listen: "); buffer_puts(buffer_2,"io_fd: ");
buffer_puterror(buffer_2); buffer_puterror(buffer_2);
buffer_putnlflush(buffer_2); buffer_putnlflush(buffer_2);
return 111; return 111;
} }
io_nonblock(s); if (socket_listen(s,16)==-1) {
if (!io_fd(s)) { buffer_puts(buffer_2,"socket_listen: ");
buffer_puts(buffer_2,"io_fd: ");
buffer_puterror(buffer_2); buffer_puterror(buffer_2);
buffer_putnlflush(buffer_2); buffer_putnlflush(buffer_2);
return 111; return 111;
} }
io_nonblock(s);
io_wantread(s); io_wantread(s);
buffer_puts(buffer_2,"listening on port 1234 (fd #"); buffer_puts(buffer_2,"listening on port 1234 (fd #");
buffer_putulong(buffer_2,s); buffer_putulong(buffer_2,s);
@ -35,7 +35,6 @@ int main() {
for (;;) { for (;;) {
int64 i; int64 i;
io_wait(); io_wait();
buffer_putsflush(buffer_2,"io_wait() returned!\n");
while ((i=io_canread())!=-1) { while ((i=io_canread())!=-1) {
if (i==s) { if (i==s) {
int n; int n;
@ -64,6 +63,7 @@ int main() {
} }
} else { } else {
char buf[1024]; char buf[1024];
int l=io_tryread(i,buf,sizeof buf); int l=io_tryread(i,buf,sizeof buf);
if (l==-1) { if (l==-1) {
buffer_puts(buffer_2,"io_tryread("); buffer_puts(buffer_2,"io_tryread(");

Loading…
Cancel
Save