add iob_write (send io batch through callback, e.g. for SSL)
parent
b48ce77792
commit
86cfc33dab
@ -0,0 +1,89 @@
|
||||
#include <io_internal.h>
|
||||
#include <iob.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define BUFSIZE 16384
|
||||
|
||||
int64 io_mmapwritefile(int64 out,int64 in,uint64 off,uint64 bytes,io_write_callback writecb) {
|
||||
char buf[BUFSIZE];
|
||||
int n,m;
|
||||
uint64 sent=0;
|
||||
io_entry* e=array_get(&io_fds,sizeof(io_entry),out);
|
||||
if (e) {
|
||||
const char* c;
|
||||
long left;
|
||||
do {
|
||||
if (e->mmapped) {
|
||||
/* did we already map the right chunk? */
|
||||
if (off>=e->mapofs && off<e->mapofs+e->maplen)
|
||||
goto mapok; /* ok; mmapped the right chunk*/
|
||||
munmap(e->mmapped,e->maplen);
|
||||
}
|
||||
e->mapofs=off&0xffffffffffff0000ull;
|
||||
if (e->mapofs+0x10000>off+bytes)
|
||||
e->maplen=off+bytes-e->mapofs;
|
||||
else
|
||||
e->maplen=0x10000;
|
||||
if ((e->mmapped=mmap(0,e->maplen,PROT_READ,MAP_SHARED,in,e->mapofs))==MAP_FAILED) {
|
||||
e->mmapped=0;
|
||||
goto readwrite;
|
||||
}
|
||||
mapok:
|
||||
c=(const char*)(e->mmapped)+(off&0xffff);
|
||||
left=e->maplen-(off&0xffff);
|
||||
if (left>bytes) left=bytes;
|
||||
while (left>0) {
|
||||
m=writecb(out,c,left);
|
||||
if (m==-1) {
|
||||
e->canwrite=0;
|
||||
e->next_write=-1;
|
||||
if (errno!=EAGAIN) {
|
||||
munmap(e->mmapped,e->maplen);
|
||||
e->mmapped=0;
|
||||
return -3;
|
||||
}
|
||||
return sent?sent:-1;
|
||||
}
|
||||
if (m==0) return sent;
|
||||
sent+=m;
|
||||
left-=m;
|
||||
bytes-=m;
|
||||
off+=m;
|
||||
c+=m;
|
||||
}
|
||||
} while (bytes);
|
||||
if (e->mmapped) {
|
||||
munmap(e->mmapped,e->maplen);
|
||||
e->mmapped=0;
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
readwrite:
|
||||
if (lseek(in,off,SEEK_SET) != off)
|
||||
return -1;
|
||||
while (bytes>0) {
|
||||
char* tmp=buf;
|
||||
if ((n=read(in,tmp,(bytes<BUFSIZE)?bytes:BUFSIZE))<=0)
|
||||
return (sent?sent:-1);
|
||||
while (n>0) {
|
||||
if ((m=writecb(out,tmp,n))<0) {
|
||||
if (m==-1) {
|
||||
if (e) {
|
||||
e->canwrite=0;
|
||||
e->next_write=-1;
|
||||
}
|
||||
return errno==EAGAIN?(sent?sent:-1):-3;
|
||||
}
|
||||
goto abort;
|
||||
}
|
||||
sent+=m;
|
||||
n-=m;
|
||||
bytes-=m;
|
||||
tmp+=m;
|
||||
}
|
||||
}
|
||||
abort:
|
||||
return sent;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
.TH iob_write 3
|
||||
.SH NAME
|
||||
iob_write \- send I/O batch through callback
|
||||
.SH SYNTAX
|
||||
.B #include <iob.h>
|
||||
|
||||
int64 \fBiob_write\fR(int64 s,io_batch* b,io_write_callback cb);
|
||||
.SH DESCRIPTION
|
||||
iob_write sends the (rest of) \fIb\fR through the callback \fIcb\fR,
|
||||
passing \fIs\fR as first argument. \fIcb\fR is expected to behave like
|
||||
io_trywrite(2).
|
||||
|
||||
This interface is intended to send an I/O batch through a filter, for
|
||||
example to encrypt or compress it. If you just want to send an I/O
|
||||
batch to a socket, use iob_send instead.
|
||||
|
||||
iob_write returns the number of bytes written, 0 if there were no more
|
||||
bytes to be written in the batch, -1 for EAGAIN, or -3 for a permanent
|
||||
error (for example "connection reset by peer").
|
||||
|
||||
The normal usage pattern is using io_wait to know when a descriptor is
|
||||
writable, and then calling iob_write until it returns 0, -1 or -3.
|
||||
|
||||
If it returns 0, terminate the loop (everything was written OK). If it
|
||||
returns -1, call io_wait again. If it returned -3, signal an error.
|
||||
.SH "SEE ALSO"
|
||||
iob_send(3)
|
@ -0,0 +1,36 @@
|
||||
#include <iob_internal.h>
|
||||
|
||||
int64 iob_write(int64 s,io_batch* b,io_write_callback cb) {
|
||||
iob_entry* e,* last;
|
||||
int64 total,sent;
|
||||
long i;
|
||||
int thatsit;
|
||||
|
||||
if (b->bytesleft==0) return 0;
|
||||
last=(iob_entry*)(((char*)array_start(&b->b))+array_bytes(&b->b));
|
||||
total=0;
|
||||
if (!(e=array_get(&b->b,sizeof(iob_entry),b->next)))
|
||||
return -3; /* can't happen error */
|
||||
thatsit=0;
|
||||
for (i=0; e+i<last; ++i) {
|
||||
if (!e[i].n) continue;
|
||||
if (e[i].type==FROMFILE || e[i].type==FROMFILE_CLOSE)
|
||||
sent=io_mmapwritefile(s,e[i].fd,e[i].offset,e[i].n,cb);
|
||||
else
|
||||
sent=cb(s,e[i].buf+e[i].offset,e[i].n);
|
||||
if (sent > e[i].n) sent=e[i].n; /* can't happen */
|
||||
thatsit=(sent != e[i].n);
|
||||
if (sent==-1 && errno!=EAGAIN)
|
||||
sent=-3;
|
||||
if (sent>0) {
|
||||
e[i].offset+=sent;
|
||||
e[i].n-=sent;
|
||||
total+=sent;
|
||||
} else
|
||||
return total?total:sent;
|
||||
if (thatsit) break;
|
||||
}
|
||||
if (total == b->bytesleft)
|
||||
iob_reset(b);
|
||||
return total;
|
||||
}
|
Loading…
Reference in New Issue