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.
This commit is contained in:
parent
f65398ff2e
commit
c1c50c7dbd
3
CHANGES
3
CHANGES
@ -4,6 +4,9 @@
|
||||
allocates space, it also needs to be in the initialized space.
|
||||
add -D_REENTRANT to CFLAGS so libowfat can be used in multi-threaded
|
||||
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:
|
||||
fix scan_to_sa (Tim Lorenz)
|
||||
|
10
GNUmakefile
10
GNUmakefile
@ -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
|
||||
|
||||
CC=gcc
|
||||
CROSS=
|
||||
#CROSS=i686-mingw-
|
||||
CC=$(CROSS)gcc
|
||||
CFLAGS=-pipe -W -Wall -O2 -fomit-frame-pointer
|
||||
#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)
|
||||
|
||||
libowfat.a: $(ALL_OBJS)
|
||||
ar cr $@ $(ALL_OBJS)
|
||||
-ranlib $@
|
||||
$(CROSS)ar cr $@ $(ALL_OBJS)
|
||||
-$(CROSS)ranlib $@
|
||||
|
||||
CFLAGS+=-I.
|
||||
|
||||
@ -290,3 +292,5 @@ Makefile: GNUmakefile dep libdep
|
||||
-e 's/^CURNAME=.*/'CURNAME=$(CURNAME)/ \
|
||||
-e 's/ Makefile//' < GNUmakefile >> $@
|
||||
|
||||
windoze:
|
||||
$(MAKE) DIET= CROSS=i686-mingw32-
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include <errno.h>
|
||||
#include "io_internal.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
int64 io_canread() {
|
||||
io_entry* e;
|
||||
if (first_readable==-1)
|
||||
@ -26,7 +30,18 @@ int64 io_canread() {
|
||||
first_readable=e->next_read;
|
||||
e->next_read=-1;
|
||||
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
|
||||
e->next_read=alt_firstread;
|
||||
alt_firstread=r;
|
||||
|
@ -26,7 +26,13 @@ int64 io_canwrite() {
|
||||
first_writeable=e->next_write;
|
||||
e->next_write=-1;
|
||||
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
|
||||
e->next_write=alt_firstwrite;
|
||||
alt_firstwrite=r;
|
||||
|
19
io/io_fd.c
19
io/io_fd.c
@ -50,8 +50,10 @@ int io_fd(int64 d) {
|
||||
long r;
|
||||
if ((r=fcntl(d,F_GETFL,0)) == -1)
|
||||
return 0; /* file descriptor not open */
|
||||
printf("io_fd(%d)\n",(int)d);
|
||||
#endif
|
||||
if (!(e=array_allocate(&io_fds,sizeof(io_entry),d))) return 0;
|
||||
if (e->inuse) return 1;
|
||||
byte_zero(e,sizeof(io_entry));
|
||||
e->inuse=1;
|
||||
#ifdef __MINGW32__
|
||||
@ -90,8 +92,13 @@ int io_fd(int64 d) {
|
||||
}
|
||||
#endif
|
||||
#ifdef __MINGW32__
|
||||
io_comport=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,1);
|
||||
if (io_comport) io_waitmode=COMPLETIONPORT;
|
||||
io_comport=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
|
||||
if (io_comport) {
|
||||
io_waitmode=COMPLETIONPORT;
|
||||
} else {
|
||||
errno=EINVAL;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(HAVE_SIGIO)
|
||||
@ -103,6 +110,14 @@ int io_fd(int64 d) {
|
||||
#endif
|
||||
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
|
||||
return 1;
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#define BUFSIZE 16384
|
||||
|
||||
|
@ -112,6 +112,38 @@ int64 io_sendfile(int64 s,int64 fd,uint64 off,uint64 n) {
|
||||
}
|
||||
#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
|
||||
|
||||
#include <iob.h>
|
||||
|
@ -1,8 +1,74 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <errno.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) {
|
||||
long r;
|
||||
@ -48,3 +114,5 @@ int64 io_tryread(int64 d,char* buf,int64 len) {
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,9 +1,63 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <errno.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) {
|
||||
long r;
|
||||
struct itimerval old,new;
|
||||
@ -49,3 +103,5 @@ int64 io_trywrite(int64 d,const char* buf,int64 len) {
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,8 +1,34 @@
|
||||
#include <unistd.h>
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <errno.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) {
|
||||
long r;
|
||||
struct pollfd p;
|
||||
@ -25,3 +51,5 @@ again:
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,11 @@
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_KQUEUE
|
||||
#include <sys/event.h>
|
||||
@ -28,7 +32,9 @@
|
||||
#endif
|
||||
|
||||
int64 io_waituntil2(int64 milliseconds) {
|
||||
#ifndef __MINGW32__
|
||||
struct pollfd* p;
|
||||
#endif
|
||||
long i,j,r;
|
||||
if (!io_wanted_fds) return 0;
|
||||
#ifdef HAVE_EPOLL
|
||||
@ -195,6 +201,78 @@ int64 io_waituntil2(int64 milliseconds) {
|
||||
}
|
||||
dopoll:
|
||||
#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) {
|
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),i);
|
||||
if (!e) return -1;
|
||||
@ -231,4 +309,5 @@ dopoll:
|
||||
p++;
|
||||
}
|
||||
return i;
|
||||
#endif
|
||||
}
|
||||
|
@ -1,8 +1,34 @@
|
||||
#include <unistd.h>
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#include <errno.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) {
|
||||
long r;
|
||||
struct pollfd p;
|
||||
@ -26,3 +52,5 @@ again:
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/devpoll.h>
|
||||
#endif
|
||||
#ifdef __MINGW32__
|
||||
#include <mswsock.h>
|
||||
#endif
|
||||
|
||||
void io_wantread(int64 d) {
|
||||
int newfd;
|
||||
@ -69,6 +72,34 @@ void io_wantread(int64 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
|
||||
e->wantread=1;
|
||||
}
|
||||
|
@ -69,6 +69,12 @@ void io_wantwrite(int64 d) {
|
||||
first_writeable=d;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef __MINGW32__
|
||||
if (!e->wantwrite) {
|
||||
e->next_write=first_writeable;
|
||||
first_writeable=d;
|
||||
}
|
||||
#endif
|
||||
e->wantwrite=1;
|
||||
}
|
||||
|
@ -1,4 +1,15 @@
|
||||
#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 <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
@ -40,3 +51,5 @@ void iob_prefetch(io_batch* b,uint64 bytes) {
|
||||
}
|
||||
(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 <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@ -132,3 +211,5 @@ eagain:
|
||||
abort:
|
||||
return total;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,9 @@
|
||||
#include "io.h"
|
||||
#include "array.h"
|
||||
#ifdef __MINGW32__
|
||||
#include "socket.h"
|
||||
extern HANDLE io_comport;
|
||||
#else
|
||||
#include "haveepoll.h"
|
||||
#include "havekqueue.h"
|
||||
#include "havedevpoll.h"
|
||||
@ -8,10 +12,6 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include "socket.h"
|
||||
extern HANDLE io_comport;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
@ -22,6 +22,14 @@ typedef struct {
|
||||
unsigned int canwrite:1;
|
||||
unsigned int nonblock: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_write;
|
||||
void* cookie;
|
||||
@ -29,8 +37,12 @@ typedef struct {
|
||||
long maplen;
|
||||
uint64 mapofs;
|
||||
#ifdef __MINGW32__
|
||||
OVERLAPPED o;
|
||||
OVERLAPPED or,ow,os; /* overlapped for read+accept, write+connect, sendfile */
|
||||
HANDLE /* fd, */ mh;
|
||||
char inbuf[8192];
|
||||
int bytes_read,bytes_written;
|
||||
DWORD errorcode;
|
||||
SOCKET next_accept;
|
||||
#endif
|
||||
} io_entry;
|
||||
|
||||
|
@ -7,12 +7,75 @@
|
||||
#include "socket.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) {
|
||||
struct sockaddr_in si;
|
||||
socklen_t len = sizeof si;
|
||||
int fd;
|
||||
if ((fd=accept(s,(void*) &si,&len))==-1)
|
||||
return winsock2errno(-1);
|
||||
|
||||
#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)
|
||||
return winsock2errno(-1);
|
||||
|
||||
#ifdef __MINGW32__
|
||||
}
|
||||
#endif
|
||||
if (ip) *(uint32*)ip = *(uint32*)&si.sin_addr;
|
||||
if (port) uint16_unpack_big((char *) &si.sin_port,port);
|
||||
return fd;
|
||||
|
@ -12,6 +12,14 @@
|
||||
#include "havesl.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)
|
||||
{
|
||||
#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;
|
||||
int fd;
|
||||
|
||||
fd = accept(s,(struct sockaddr *) &sa,&dummy);
|
||||
if (fd == -1)
|
||||
return winsock2errno(-1);
|
||||
#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);
|
||||
if (fd == -1)
|
||||
return winsock2errno(-1);
|
||||
#ifdef __MINGW32__
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LIBC_HAS_IP6
|
||||
if (sa.sin6_family==AF_INET) {
|
||||
|
@ -1,10 +1,33 @@
|
||||
#include <sys/types.h>
|
||||
#ifndef __MINGW32__
|
||||
#ifdef __MINGW32__
|
||||
#include "io_internal.h"
|
||||
#include <mswsock.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include "socket.h"
|
||||
#include "windoze.h"
|
||||
|
||||
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
|
||||
}
|
||||
|
14
test/io5.c
14
test/io5.c
@ -15,6 +15,12 @@ int main() {
|
||||
buffer_putnlflush(buffer_2);
|
||||
return 111;
|
||||
}
|
||||
if (!io_fd(s)) {
|
||||
buffer_puts(buffer_2,"io_fd: ");
|
||||
buffer_puterror(buffer_2);
|
||||
buffer_putnlflush(buffer_2);
|
||||
return 111;
|
||||
}
|
||||
if (socket_listen(s,16)==-1) {
|
||||
buffer_puts(buffer_2,"socket_listen: ");
|
||||
buffer_puterror(buffer_2);
|
||||
@ -22,12 +28,6 @@ int main() {
|
||||
return 111;
|
||||
}
|
||||
io_nonblock(s);
|
||||
if (!io_fd(s)) {
|
||||
buffer_puts(buffer_2,"io_fd: ");
|
||||
buffer_puterror(buffer_2);
|
||||
buffer_putnlflush(buffer_2);
|
||||
return 111;
|
||||
}
|
||||
io_wantread(s);
|
||||
buffer_puts(buffer_2,"listening on port 1234 (fd #");
|
||||
buffer_putulong(buffer_2,s);
|
||||
@ -35,7 +35,6 @@ int main() {
|
||||
for (;;) {
|
||||
int64 i;
|
||||
io_wait();
|
||||
buffer_putsflush(buffer_2,"io_wait() returned!\n");
|
||||
while ((i=io_canread())!=-1) {
|
||||
if (i==s) {
|
||||
int n;
|
||||
@ -64,6 +63,7 @@ int main() {
|
||||
}
|
||||
} else {
|
||||
char buf[1024];
|
||||
|
||||
int l=io_tryread(i,buf,sizeof buf);
|
||||
if (l==-1) {
|
||||
buffer_puts(buffer_2,"io_tryread(");
|
||||
|
Loading…
x
Reference in New Issue
Block a user