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