From c2011088f312028d2c6f242a437e14c12127a8ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Wed, 25 Mar 1998 23:39:40 +0100 Subject: [PATCH] Added support for out-of-band data. Rev: src/acconfig.h:1.18 Rev: src/backend.c:1.24 Rev: src/backend.h:1.5 Rev: src/configure.in:1.169 Rev: src/fdlib.c:1.15 Rev: src/fdlib.h:1.12 Rev: src/modules/files/file.c:1.81 Rev: src/modules/files/file.h:1.8 --- src/acconfig.h | 3 + src/backend.c | 191 +++++++++++++++- src/backend.h | 12 + src/configure.in | 3 +- src/fdlib.c | 1 + src/fdlib.h | 2 + src/modules/files/file.c | 462 ++++++++++++++++++++++++++++++++++++++- src/modules/files/file.h | 4 + 8 files changed, 665 insertions(+), 13 deletions(-) diff --git a/src/acconfig.h b/src/acconfig.h index 7c45fb2226..26eb98f333 100644 --- a/src/acconfig.h +++ b/src/acconfig.h @@ -183,6 +183,9 @@ /* Use poll() instead of select() ? */ #undef HAVE_AND_USE_POLL +/* Enable code to handle Out-Of-Band data */ +#undef WITH_OOB + @BOTTOM@ /* NT stuff */ diff --git a/src/backend.c b/src/backend.c index 8f7e7fc96d..ac85d38c71 100644 --- a/src/backend.c +++ b/src/backend.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: backend.c,v 1.23 1998/03/10 03:16:34 per Exp $"); +RCSID("$Id: backend.c,v 1.24 1998/03/25 22:39:38 grubba Exp $"); #include "fdlib.h" #include "backend.h" #include <errno.h> @@ -37,6 +37,12 @@ file_callback read_callback[MAX_OPEN_FILEDESCRIPTORS]; void *read_callback_data[MAX_OPEN_FILEDESCRIPTORS]; file_callback write_callback[MAX_OPEN_FILEDESCRIPTORS]; void *write_callback_data[MAX_OPEN_FILEDESCRIPTORS]; +#ifdef WITH_OOB +file_callback read_oob_callback[MAX_OPEN_FILEDESCRIPTORS]; +void *read_oob_callback_data[MAX_OPEN_FILEDESCRIPTORS]; +file_callback write_oob_callback[MAX_OPEN_FILEDESCRIPTORS]; +void *write_oob_callback_data[MAX_OPEN_FILEDESCRIPTORS]; +#endif /* WITH_OOB */ #ifndef HAVE_AND_USE_POLL #undef HAVE_POLL @@ -55,7 +61,11 @@ static struct selectors selectors; #include <poll.h> struct pollfd *poll_fds, *active_poll_fds; int num_in_poll=0; +int active_num_in_poll=0; +/* + * This code probably uses realloc a bit too much... + */ void POLL_FD_SET(int fd, short add) { int i; @@ -81,17 +91,30 @@ void POLL_FD_CLR(int fd, short sub) poll_fds[i].events &= ~sub; if(!poll_fds[i].events) { - if(i!=num_in_poll-1) - MEMCPY(poll_fds+i, poll_fds+i+1, - (num_in_poll-1-i)*sizeof(struct pollfd)); + /* Note that num_in_poll is decreased here. + * This is to avoid a lot of -1's below. + * /grubba + */ num_in_poll--; + if(i != num_in_poll) { +#if 0 + /* Not very efficient... + * /grubba + */ + MEMCPY(poll_fds+i, poll_fds+i+1, + (num_in_poll-i)*sizeof(struct pollfd)); +#else /* !0 */ + /* This should speed things up a bit... + */ + *(poll_fds+i) = *(poll_fds+num_in_poll); +#endif /* 0 */ + } } break; } return; } -int active_num_in_poll; void switch_poll_set() { struct pollfd *tmp = active_poll_fds; @@ -242,6 +265,94 @@ void set_write_callback(int fd,file_callback cb,void *data) } } +#ifdef WITH_OOB +void set_read_oob_callback(int fd,file_callback cb,void *data) +{ +#ifdef HAVE_POLL + int was_set = (read_oob_callback[fd]!=0); +#endif +#ifdef DEBUG + if(fd<0 || fd>=MAX_OPEN_FILEDESCRIPTORS) + fatal("File descriptor out of range.\n %d",fd); +#endif + read_oob_callback[fd]=cb; + read_oob_callback_data[fd]=data; + + if(cb) + { +#ifdef HAVE_POLL + POLL_FD_SET(fd,POLLRDBAND); +#else + my_FD_SET(fd, &selectors.read); /* FIXME:? */ +#endif + if(max_fd < fd) max_fd = fd; + wake_up_backend(); + }else{ +#ifndef HAVE_POLL + /* FIXME:? */ + if(fd <= max_fd) + { + my_FD_CLR(fd, &selectors.read); + + if(fd == max_fd) + { + while(max_fd >=0 && + !my_FD_ISSET(max_fd, &selectors.read) && + !my_FD_ISSET(max_fd, &selectors.write)) + max_fd--; + } + } +#else + if(was_set) + POLL_FD_CLR(fd,POLLRDBAND); +#endif + } +} + +void set_write_oob_callback(int fd,file_callback cb,void *data) +{ +#ifdef HAVE_POLL + int was_set = (write_oob_callback[fd]!=0); +#endif +#ifdef DEBUG + if(fd<0 || fd>=MAX_OPEN_FILEDESCRIPTORS) + fatal("File descriptor out of range.\n %d",fd); +#endif + + write_oob_callback[fd]=cb; + write_oob_callback_data[fd]=data; + + if(cb) + { +#ifdef HAVE_POLL + POLL_FD_SET(fd,POLLWRBAND); +#else + my_FD_SET(fd, &selectors.write); /* FIXME:? */ +#endif + if(max_fd < fd) max_fd = fd; + wake_up_backend(); + }else{ +#ifndef HAVE_POLL + /* FIXME:? */ + if(fd <= max_fd) + { + my_FD_CLR(fd, &selectors.write); + if(fd == max_fd) + { + while(max_fd >=0 && + !my_FD_ISSET(max_fd, &selectors.read) && + !my_FD_ISSET(max_fd, &selectors.write)) + max_fd--; + } + } +#else + if(was_set) + POLL_FD_CLR(fd,POLLWRBAND); +#endif + } +} +#endif /* WITH_OOB */ + file_callback query_read_callback(int fd) { #ifdef DEBUG @@ -262,6 +373,28 @@ file_callback query_write_callback(int fd) return write_callback[fd]; } +#ifdef WITH_OOB +file_callback query_read_oob_callback(int fd) +{ +#ifdef DEBUG + if(fd<0 || fd>=MAX_OPEN_FILEDESCRIPTORS) + fatal("File descriptor out of range.\n %d",fd); +#endif + + return read_oob_callback[fd]; +} + +file_callback query_write_oob_callback(int fd) +{ +#ifdef DEBUG + if(fd<0 || fd>=MAX_OPEN_FILEDESCRIPTORS) + fatal("File descriptor out of range.\n %d",fd); +#endif + + return write_oob_callback[fd]; +} +#endif /* WITH_OOB */ + void *query_read_callback_data(int fd) { #ifdef DEBUG @@ -282,6 +415,28 @@ void *query_write_callback_data(int fd) return write_callback_data[fd]; } +#ifdef WITH_OOB +void *query_read_oob_callback_data(int fd) +{ +#ifdef DEBUG + if(fd<0 || fd>=MAX_OPEN_FILEDESCRIPTORS) + fatal("File descriptor out of range.\n %d",fd); +#endif + + return read_oob_callback_data[fd]; +} + +void *query_write_oob_callback_data(int fd) +{ +#ifdef DEBUG + if(fd<0 || fd>=MAX_OPEN_FILEDESCRIPTORS) + fatal("File descriptor out of range.\n %d",fd); +#endif + + return write_oob_callback_data[fd]; +} +#endif /* WITH_OOB */ + #ifdef DEBUG struct callback_list do_debug_callbacks; @@ -306,6 +461,7 @@ void do_debug(void) call_callback(& do_debug_callbacks, 0); + /* FIXME: OOB? */ #ifndef HAVE_POLL for(e=0;e<=max_fd;e++) { @@ -384,6 +540,7 @@ void backend(void) check_threads_etc(); #ifndef HAVE_POLL + /* FIXME: OOB? */ fd_copy_my_fd_set_to_fd_set(&rset, &selectors.read, max_fd+1); fd_copy_my_fd_set_to_fd_set(&wset, &selectors.write, max_fd+1); #endif @@ -412,6 +569,7 @@ void backend(void) i=poll(active_poll_fds, active_num_in_poll, msec); } #else + /* FIXME: OOB? */ i=fd_select(max_fd+1, &rset, &wset, 0, &next_timeout); #endif GETTIMEOFDAY(¤t_time); @@ -421,6 +579,7 @@ void backend(void) if(i>=0) { #ifndef HAVE_POLL + /* FIXME: OOB? */ for(i=0; i<max_fd+1; i++) { if(fd_FD_ISSET(i, &rset) && read_callback[i]) @@ -440,15 +599,32 @@ void backend(void) if(poll_fds[j].fd == fd) /* It's still there... */ fatal("Bad filedescriptor %d to select().\n", fd); } + +#ifdef WITH_OOB + if ((active_poll_fds[i].revents & POLLRDBAND) && + read_oob_callback[fd]) { + (*(read_oob_callback[fd]))(fd, read_oob_callback_data[fd]); + } +#endif /* WITH_OOB */ + if((active_poll_fds[i].revents & POLLHUP) || (active_poll_fds[i].revents & POLLERR)) active_poll_fds[i].revents |= POLLRDNORM; - if((active_poll_fds[i].revents & POLLRDNORM)&& read_callback[fd]) + if((active_poll_fds[i].revents & POLLRDNORM)&& read_callback[fd]) { (*(read_callback[fd]))(fd,read_callback_data[fd]); + } - if((active_poll_fds[i].revents & POLLOUT)&& write_callback[fd]) +#ifdef WITH_OOB + if ((active_poll_fds[i].revents & POLLWRBAND) && + write_oob_callback[fd]) { + (*(write_oob_callback[fd]))(fd, write_oob_callback_data[fd]); + } +#endif /* WITH_OOB */ + + if((active_poll_fds[i].revents & POLLOUT)&& write_callback[fd]) { (*(write_callback[fd]))(fd,write_callback_data[fd]); + } } #endif }else{ @@ -479,6 +655,7 @@ void backend(void) case EBADF: /* TODO: Fix poll version! */ #ifndef HAVE_POLL + /* FIXME: OOB? */ fd_copy_my_fd_set_to_fd_set(&rset, &selectors.read, max_fd+1); fd_copy_my_fd_set_to_fd_set(&wset, &selectors.write, max_fd+1); next_timeout.tv_usec=0; diff --git a/src/backend.h b/src/backend.h index e58a610727..002d5cfc09 100644 --- a/src/backend.h +++ b/src/backend.h @@ -24,10 +24,22 @@ void wake_up_backend(void); void init_backend(void); void set_read_callback(int fd,file_callback cb,void *data); void set_write_callback(int fd,file_callback cb,void *data); +#ifdef WITH_OOB +void set_read_oob_callback(int fd,file_callback cb,void *data); +void set_write_oob_callback(int fd,file_callback cb,void *data); +#endif /* WITH_OOB */ file_callback query_read_callback(int fd); file_callback query_write_callback(int fd); +#ifdef WITH_OOB +file_callback query_read_oob_callback(int fd); +file_callback query_write_oob_callback(int fd); +#endif /* WITH_OOB */ void *query_read_callback_data(int fd); void *query_write_callback_data(int fd); +#ifdef WITH_OOB +void *query_read_oob_callback_data(int fd); +void *query_write_oob_callback_data(int fd); +#endif /* WITH_OOB */ void do_debug(void); void backend(void); int write_to_stderr(char *a, INT32 len); diff --git a/src/configure.in b/src/configure.in index 18d80a481c..29fb29d40e 100644 --- a/src/configure.in +++ b/src/configure.in @@ -1,4 +1,4 @@ -AC_REVISION("$Id: configure.in,v 1.168 1998/03/22 03:20:31 hubbe Exp $") +AC_REVISION("$Id: configure.in,v 1.169 1998/03/25 22:39:39 grubba Exp $") AC_INIT(interpret.c) AC_CONFIG_HEADER(machine.h) @@ -103,6 +103,7 @@ AC_ARG_WITH(dmalloc, [ --with-dmalloc enable memory-leak tests],[AC AC_ARG_WITH(profiling, [ --with-profiling add code used to profile pike code ],[AC_DEFINE(PROFILING)],[]) AC_ARG_WITH(poll, [ --with-poll use poll instead of select],[AC_DEFINE(HAVE_AND_USE_POLL)],[]) AC_ARG_WITH(max-fd, [ --with-max-fd=X set how many filedescriptors can be used at once],[pike_cv_max_open_fd=$withval],[]) +AC_ARG_WITH(oob, [ --with-oob enable out-of-band data handling],[AC_DEFINE(WITH_OOB)],[]) # # Allow --with(out)-debug to toggle both cdebug and rtldebug, but diff --git a/src/fdlib.c b/src/fdlib.c index ae68f31eed..e6d0c60e70 100644 --- a/src/fdlib.c +++ b/src/fdlib.c @@ -335,6 +335,7 @@ SOCKFUN2(getsockname,struct sockaddr *,int *) SOCKFUN2(getpeername,struct sockaddr *,int *) SOCKFUN3(recv,void *,int,int) SOCKFUN5(recvfrom,void *,int,int,struct sockaddr *,int*) +SOCKFUN3(send,void *,int,int) SOCKFUN5(sendto,void *,int,int,struct sockaddr *,int*) SOCKFUN1(shutdown, int) SOCKFUN1(listen, int) diff --git a/src/fdlib.h b/src/fdlib.h index 5c6c40405e..adac723483 100644 --- a/src/fdlib.h +++ b/src/fdlib.h @@ -73,6 +73,7 @@ SOCKFUN2(getsockname,struct sockaddr *,int *) SOCKFUN2(getpeername,struct sockaddr *,int *) SOCKFUN3(recv,void *,int,int) SOCKFUN5(recvfrom,void *,int,int,struct sockaddr *,int*) +SOCKFUN3(send,void *,int,int) SOCKFUN5(sendto,void *,int,int,struct sockaddr *,int*) SOCKFUN1(shutdown, int) SOCKFUN1(listen, int) @@ -235,6 +236,7 @@ typedef int FD; #define fd_getsockname getsockname #define fd_getpeername getpeername #define fd_recv recv +#define fd_send send #define fd_sendto sendto #define fd_recvfrom recvfrom #define fd_shutdown shutdown diff --git a/src/modules/files/file.c b/src/modules/files/file.c index 038fc948c2..92470bebf2 100644 --- a/src/modules/files/file.c +++ b/src/modules/files/file.c @@ -8,7 +8,7 @@ #define READ_BUFFER 8192 #include "global.h" -RCSID("$Id: file.c,v 1.80 1998/03/22 04:37:19 per Exp $"); +RCSID("$Id: file.c,v 1.81 1998/03/25 22:39:40 grubba Exp $"); #include "fdlib.h" #include "interpret.h" #include "svalue.h" @@ -119,6 +119,12 @@ static void init_fd(int fd, int open_mode) files[fd].read_callback.u.integer=0; files[fd].write_callback.type=T_INT; files[fd].write_callback.u.integer=0; +#ifdef WITH_OOB + files[fd].read_oob_callback.type=T_INT; + files[fd].read_oob_callback.u.integer=0; + files[fd].write_oob_callback.type=T_INT; + files[fd].write_oob_callback.u.integer=0; +#endif /* WITH_OOB */ files[fd].close_callback.type=T_INT; files[fd].close_callback.u.integer=0; } @@ -138,14 +144,26 @@ static int close_fd(int fd) { set_read_callback(fd,0,0); set_write_callback(fd,0,0); +#ifdef WITH_OOB + set_read_oob_callback(fd,0,0); + set_write_oob_callback(fd,0,0); +#endif /* WITH_OOB */ free_svalue(& files[fd].id); free_svalue(& files[fd].read_callback); free_svalue(& files[fd].write_callback); +#ifdef WITH_OOB + free_svalue(& files[fd].read_oob_callback); + free_svalue(& files[fd].write_oob_callback); +#endif /* WITH_OOB */ free_svalue(& files[fd].close_callback); files[fd].id.type=T_INT; files[fd].read_callback.type=T_INT; files[fd].write_callback.type=T_INT; +#ifdef WITH_OOB + files[fd].read_oob_callback.type=T_INT; + files[fd].write_oob_callback.type=T_INT; +#endif /* WITH_OOB */ files[fd].close_callback.type=T_INT; files[fd].open_mode = 0; @@ -261,7 +279,6 @@ static int parse(char *a) case 'X': ret|=FILE_EXCLUSIVE; break; - } } } @@ -408,6 +425,129 @@ static struct pike_string *do_read(int fd, } } +#ifdef WITH_OOB +static struct pike_string *do_read_oob(int fd, + INT32 r, + int all, + short *err) +{ + ONERROR ebuf; + INT32 bytes_read,i; + bytes_read=0; + *err=0; + + if(r <= 65536) + { + struct pike_string *str; + + str=begin_shared_string(r); + + SET_ONERROR(ebuf, call_free, str); + + do{ + int fd=FD; + THREADS_ALLOW(); + i=fd_recv(fd, str->str+bytes_read, r, MSG_OOB); + THREADS_DISALLOW(); + + check_signals(0,0,0); + + if(i>0) + { + r-=i; + bytes_read+=i; + if(!all) break; + } + else if(i==0) + { + break; + } + else if(errno != EINTR) + { + *err=errno; + if(!bytes_read) + { + free((char *)str); + UNSET_ONERROR(ebuf); + return 0; + } + break; + } + }while(r); + + UNSET_ONERROR(ebuf); + + if(bytes_read == str->len) + { + return end_shared_string(str); + }else{ + struct pike_string *foo; /* Per */ + foo = make_shared_binary_string(str->str,bytes_read); + free((char *)str); + return foo; + } + + }else{ +#define CHUNK 65536 + INT32 try_read; + dynamic_buffer b; + + b.s.str=0; + initialize_buf(&b); + SET_ONERROR(ebuf, free_dynamic_buffer, &b); + do{ + char *buf; + try_read=MINIMUM(CHUNK,r); + + buf = low_make_buf_space(try_read, &b); + + THREADS_ALLOW(); + i=fd_recv(fd, buf, try_read, MSG_OOB); + THREADS_DISALLOW(); + + check_signals(0,0,0); + + if(i==try_read) + { + r-=i; + bytes_read+=i; + if(!all) break; + } + else if(i>0) + { + bytes_read+=i; + r-=i; + low_make_buf_space(i - try_read, &b); + if(!all) break; + } + else if(i==0) + { + low_make_buf_space(-try_read, &b); + break; + } + else + { + low_make_buf_space(-try_read, &b); + if(errno != EINTR) + { + *err=errno; + if(!bytes_read) + { + free(b.s.str); + UNSET_ONERROR(ebuf); + return 0; + } + break; + } + } + }while(r); + + UNSET_ONERROR(ebuf); + return low_free_buf(&b); + } +} +#endif /* WITH_OOB */ + static void file_read(INT32 args) { struct pike_string *tmp; @@ -426,7 +566,7 @@ static void file_read(INT32 args) error("Bad argument 1 to file->read().\n"); len=sp[-args].u.integer; if(len<0) - error("Cannot read negative number of args.\n"); + error("Cannot read negative number of characters.\n"); } if(args > 1 && !IS_ZERO(sp+1-args)) @@ -444,6 +584,44 @@ static void file_read(INT32 args) push_int(0); } +#ifdef WITH_OOB +static void file_read_oob(INT32 args) +{ + struct pike_string *tmp; + INT32 all, len; + + if(FD < 0) + error("File not open.\n"); + + if(!args) + { + len=0x7fffffff; + } + else + { + if(sp[-args].type != T_INT) + error("Bad argument 1 to file->read_oob().\n"); + len=sp[-args].u.integer; + if(len<0) + error("Cannot read negative number of characters.\n"); + } + + if(args > 1 && !IS_ZERO(sp+1-args)) + { + all=0; + }else{ + all=1; + } + + pop_n_elems(args); + + if((tmp=do_read_oob(FD, len, all, & ERRNO))) + push_string(tmp); + else + push_int(0); +} +#endif /* WITH_OOB */ + static void file_write_callback(int fd, void *data) { set_write_callback(fd, 0, 0); @@ -453,6 +631,17 @@ static void file_write_callback(int fd, void *data) pop_stack(); } +#ifdef WITH_OOB +static void file_write_oob_callback(int fd, void *data) +{ + set_write_oob_callback(fd, 0, 0); + + assign_svalue_no_free(sp++, & files[fd].id); + apply_svalue(& files[fd].write_oob_callback, 1); + pop_stack(); +} +#endif /* WITH_OOB */ + static void file_write(INT32 args) { INT32 written,i; @@ -516,6 +705,71 @@ static void file_write(INT32 args) push_int(written); } +#ifdef WITH_OOB +static void file_write_oob(INT32 args) +{ + INT32 written,i; + struct pike_string *str; + + if(args<1 || sp[-args].type != T_STRING) + error("Bad argument 1 to file->write().\n"); + + if(args > 1) + { + extern void f_sprintf(INT32); + f_sprintf(args); + args=1; + } + + if(FD < 0) + error("File not open for write_oob.\n"); + + written=0; + str=sp[-args].u.string; + + while(written < str->len) + { + int fd=FD; + THREADS_ALLOW(); + i=fd_send(fd, str->str + written, str->len - written, MSG_OOB); + THREADS_DISALLOW(); + +#ifdef _REENTRANT + if(FD<0) error("File destructed while in file->write_oob.\n"); +#endif + + if(i<0) + { + switch(errno) + { + default: + ERRNO=errno; + pop_n_elems(args); + push_int(-1); + return; + + case EINTR: continue; + case EWOULDBLOCK: break; + } + break; + }else{ + written+=i; + + /* Avoid extra write() */ + if(THIS->open_mode & FILE_NONBLOCKING) + break; + } + } + + if(!IS_ZERO(& THIS->write_oob_callback)) + set_write_oob_callback(FD, file_write_oob_callback, 0); + ERRNO=0; + + pop_n_elems(args); + push_int(written); +} +#endif /* WITH_OOB */ + static int do_close(int fd, int flags) { if(fd == -1) return 1; /* already closed */ @@ -536,6 +790,9 @@ static int do_close(int fd, int flags) if(files[fd].open_mode & FILE_WRITE) { set_read_callback(fd,0,0); +#ifdef WITH_OOB + set_read_oob_callback(fd,0,0); +#endif /* WITH_OOB */ fd_shutdown(fd, 0); files[fd].open_mode &=~ FILE_READ; return 0; @@ -548,6 +805,9 @@ static int do_close(int fd, int flags) if(files[fd].open_mode & FILE_READ) { set_write_callback(fd,0,0); +#ifdef WITH_OOB + set_write_oob_callback(fd,0,0); +#endif /* WITH_OOB */ fd_shutdown(fd, 1); files[fd].open_mode &=~ FILE_WRITE; return 0; @@ -645,7 +905,6 @@ static void file_open(INT32 args) } else { - init_fd(fd,flags | fd_query_properties(fd, FILE_CAPABILITIES)); FD=fd; ERRNO = 0; @@ -763,6 +1022,17 @@ static struct pike_string *simple_do_read(INT32 *amount,int fd) return 0; } +#ifdef WITH_OOB +static struct pike_string *simple_do_read_oob(INT32 *amount,int fd) +{ + char buffer[READ_BUFFER]; + *amount = fd_recv(fd, buffer, READ_BUFFER, MSG_OOB); + /* Note: OOB packets may have zero size */ + if(*amount>=0) return make_shared_binary_string(buffer,*amount); + return 0; +} +#endif /* WITH_OOB */ + static void file_read_callback(int fd, void *data) { struct pike_string *s; @@ -805,6 +1075,44 @@ static void file_read_callback(int fd, void *data) apply_svalue(& files[fd].close_callback, 1); } +#ifdef WITH_OOB +static void file_read_oob_callback(int fd, void *data) +{ + struct pike_string *s; + INT32 i; + +#ifdef DEBUG + if(fd == -1 || fd >= MAX_OPEN_FILEDESCRIPTORS) + fatal("Error in file::read_oob_callback()\n"); +#endif + + /* files[fd].errno=0; */ + + s=simple_do_read_oob(&i, fd); + + /* Note: OOB ackets may have zero size */ + if(i>=0) + { + assign_svalue_no_free(sp++, &files[fd].id); + push_string(s); + apply_svalue(& files[fd].read_oob_callback, 2); + pop_stack(); + return; + } + + if(i < 0) + { + /* files[fd].errno=errno; */ + switch(errno) + { + case EINTR: + case EWOULDBLOCK: + return; + } + } +} +#endif /* WITH_OOB */ + static void file_set_read_callback(INT32 args) { if(FD < 0) @@ -843,6 +1151,46 @@ static void file_set_write_callback(INT32 args) pop_n_elems(args); } +#ifdef WITH_OOB +static void file_set_read_oob_callback(INT32 args) +{ + if(FD < 0) + error("File is not open.\n"); + + if(args < 1) + error("Too few arguments to file->set_read_oob_callback().\n"); + + assign_svalue(& THIS->read_oob_callback, sp-args); + + if(IS_ZERO(& THIS->read_oob_callback)) + { + set_read_oob_callback(FD, 0, 0); + }else{ + set_read_oob_callback(FD, file_read_oob_callback, 0); + } + pop_n_elems(args); +} + +static void file_set_write_oob_callback(INT32 args) +{ + if(FD < 0) + error("File is not open.\n"); + + if(args < 1) + error("Too few arguments to file->set_write_oob_callback().\n"); + + assign_svalue(& THIS->write_oob_callback, sp-args); + + if(IS_ZERO(& THIS->write_oob_callback)) + { + set_write_oob_callback(FD, 0, 0); + }else{ + set_write_oob_callback(FD, file_write_oob_callback, 0); + } + pop_n_elems(args); +} +#endif /* WITH_OOB */ + static void file_set_close_callback(INT32 args) { if(FD < 0) @@ -870,7 +1218,13 @@ static void file_set_nonblocking(INT32 args) switch(args) { +#ifdef WITH_OOB + default: pop_n_elems(args-5); + case 5: file_set_write_oob_callback(1); + case 4: file_set_read_oob_callback(1); +#else /* !WITH_OOB */ default: pop_n_elems(args-3); +#endif /* WITH_OOB */ case 3: file_set_close_callback(1); case 2: file_set_write_callback(1); case 1: file_set_read_callback(1); @@ -888,6 +1242,16 @@ static void file_set_blocking(INT32 args) free_svalue(& THIS->write_callback); THIS->write_callback.type=T_INT; THIS->write_callback.u.integer=0; + +#ifdef WITH_OOB + free_svalue(& THIS->read_oob_callback); + THIS->read_oob_callback.type=T_INT; + THIS->read_oob_callback.u.integer=0; + free_svalue(& THIS->write_oob_callback); + THIS->write_oob_callback.type=T_INT; + THIS->write_oob_callback.u.integer=0; +#endif /* WITH_OOB */ + free_svalue(& THIS->close_callback); THIS->close_callback.type=T_INT; THIS->close_callback.u.integer=0; @@ -896,6 +1260,10 @@ static void file_set_blocking(INT32 args) { set_read_callback(FD, 0, 0); set_write_callback(FD, 0, 0); +#ifdef WITH_OOB + set_read_oob_callback(FD, 0, 0); + set_write_oob_callback(FD, 0, 0); +#endif /* WITH_OOB */ set_nonblocking(FD,0); THIS->open_mode &=~ FILE_NONBLOCKING; } @@ -966,6 +1334,26 @@ static void file_query_write_callback(INT32 args) assign_svalue_no_free(sp++,& THIS->write_callback); } +#ifdef WITH_OOB +static void file_query_read_oob_callback(INT32 args) +{ + if(FD < 0) + error("File not open.\n"); + + pop_n_elems(args); + assign_svalue_no_free(sp++,& THIS->read_oob_callback); +} + +static void file_query_write_oob_callback(INT32 args) +{ + if(FD < 0) + error("File not open.\n"); + + pop_n_elems(args); + assign_svalue_no_free(sp++,& THIS->write_oob_callback); +} +#endif /* WITH_OOB */ + static void file_query_close_callback(INT32 args) { if(FD < 0) @@ -1250,7 +1638,7 @@ static void file_pipe(INT32 args) break; } - error("Cannot create a pipe patching those parameters.\n"); + error("Cannot create a pipe matching those parameters.\n"); }while(0); if(i<0) @@ -1298,6 +1686,10 @@ static void gc_mark_file_struct(struct object *o) { gc_mark_svalues(& THIS->read_callback,1); gc_mark_svalues(& THIS->write_callback,1); +#ifdef WITH_OOB + gc_mark_svalues(& THIS->read_oob_callback,1); + gc_mark_svalues(& THIS->write_oob_callback,1); +#endif /* WITH_OOB */ gc_mark_svalues(& THIS->close_callback,1); gc_mark_svalues(& THIS->id,1); } @@ -1387,6 +1779,12 @@ static void file_dup2(INT32 args) assign_svalue_no_free(& files[fd].read_callback, & THIS->read_callback); assign_svalue_no_free(& files[fd].write_callback, & THIS->write_callback); +#ifdef WITH_OOB + assign_svalue_no_free(& files[fd].read_oob_callback, + & THIS->read_oob_callback); + assign_svalue_no_free(& files[fd].write_oob_callback, + & THIS->write_oob_callback); +#endif /* WITH_OOB */ assign_svalue_no_free(& files[fd].close_callback, & THIS->close_callback); assign_svalue_no_free(& files[fd].id, & THIS->id); @@ -1403,6 +1801,22 @@ static void file_dup2(INT32 args) }else{ set_write_callback(fd, file_write_callback, 0); } + +#ifdef WITH_OOB + if(IS_ZERO(& THIS->read_oob_callback)) + { + set_read_oob_callback(fd, 0,0); + }else{ + set_read_oob_callback(fd, file_read_oob_callback, 0); + } + + if(IS_ZERO(& THIS->write_oob_callback)) + { + set_write_oob_callback(fd, 0,0); + }else{ + set_write_oob_callback(fd, file_write_oob_callback, 0); + } +#endif /* WITH_OOB */ pop_n_elems(args); push_int(1); @@ -1909,6 +2323,28 @@ void mark_ids(struct callback *foo, void *bar, void *gazonk) tmp=0; } +#ifdef WITH_OOB + if(query_read_oob_callback(e)!=file_read_oob_callback) + { + gc_check_svalues( & files[e].read_oob_callback, 1); + }else{ +#ifdef DEBUG + debug_gc_xmark_svalues( & files[e].read_oob_callback, 1, "File->read_oob_callback"); +#endif + tmp=0; + } + + if(query_write_oob_callback(e)!=file_write_oob_callback) + { + gc_check_svalues( & files[e].write_oob_callback, 1); + }else{ +#ifdef DEBUG + debug_gc_xmark_svalues( & files[e].write_oob_callback, 1, "File->write_callback"); +#endif + tmp=0; + } +#endif /* WITH_OOB */ + if(tmp) { gc_check_svalues( & files[e].id, 1); @@ -1954,6 +2390,10 @@ void pike_module_init(void) add_function("close",file_close,"function(string|void:int)",0); add_function("read",file_read,"function(int|void,int|void:int|string)",0); add_function("write",file_write,"function(string,void|mixed...:int)",0); +#ifdef WITH_OOB + add_function("read_oob",file_read_oob,"function(int|void,int|void:int|string)",0); + add_function("write_oob",file_write_oob,"function(string,void|mixed...:int)",0); +#endif /* WITH_OOB */ add_function("seek",file_seek,"function(int,int|void,int|void:int)",0); add_function("tell",file_tell,"function(:int)",0); @@ -1961,9 +2401,17 @@ void pike_module_init(void) add_function("errno",file_errno,"function(:int)",0); add_function("set_close_on_exec",file_set_close_on_exec,"function(int:void)",0); +#ifdef WITH_OOB + add_function("set_nonblocking",file_set_nonblocking,"function(mixed|void,mixed|void,mixed|void,mixed|void,mixed|void:void)",0); +#else /* !WITH_OOB */ add_function("set_nonblocking",file_set_nonblocking,"function(mixed|void,mixed|void,mixed|void:void)",0); +#endif /* WITH_OOB */ add_function("set_read_callback",file_set_read_callback,"function(mixed:void)",0); add_function("set_write_callback",file_set_write_callback,"function(mixed:void)",0); +#ifdef WITH_OOB + add_function("set_read_oob_callback",file_set_read_oob_callback,"function(mixed:void)",0); + add_function("set_write_oob_callback",file_set_write_oob_callback,"function(mixed:void)",0); +#endif /* WITH_OOB */ add_function("set_close_callback",file_set_close_callback,"function(mixed:void)",0); add_function("set_blocking",file_set_blocking,"function(:void)",0); @@ -1973,6 +2421,10 @@ void pike_module_init(void) add_function("query_id",file_query_id,"function(:mixed)",0); add_function("query_read_callback",file_query_read_callback,"function(:mixed)",0); add_function("query_write_callback",file_query_write_callback,"function(:mixed)",0); +#ifdef WITH_OOB + add_function("query_read_oob_callback",file_query_read_oob_callback,"function(:mixed)",0); + add_function("query_write_oob_callback",file_query_write_oob_callback,"function(:mixed)",0); +#endif /* WITH_OOB */ add_function("query_close_callback",file_query_close_callback,"function(:mixed)",0); add_function("dup",file_dup,"function(:object)",0); diff --git a/src/modules/files/file.h b/src/modules/files/file.h index 8a59b2b8a9..967cd6c74e 100644 --- a/src/modules/files/file.h +++ b/src/modules/files/file.h @@ -30,6 +30,10 @@ struct my_file struct svalue id; struct svalue read_callback; struct svalue write_callback; +#ifdef WITH_OOB + struct svalue read_oob_callback; + struct svalue write_oob_callback; +#endif /* WITH_OOB */ struct svalue close_callback; #ifdef HAVE_FD_FLOCK struct object *key; -- GitLab