/*
Unix SMB/CIFS implementation.
- main select loop and event handling
- Copyright (C) Andrew Tridgell 2003
+
+ generalised event loop handling
+
+ Copyright (C) Andrew Tridgell 2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/*
- please read the comments in events.c before modifying
-*/
+struct event_context;
+struct fd_event;
+struct timed_event;
-struct event_context {
- /* list of filedescriptor events */
- struct fd_event {
- struct event_context *event_ctx;
- struct fd_event *next, *prev;
- int fd;
- uint16_t flags; /* see EVENT_FD_* flags */
- void (*handler)(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags);
- void *private;
- } *fd_events;
+/* event handler types */
+typedef void (*event_fd_handler_t)(struct event_context *, struct fd_event *,
+ struct timeval , uint16_t , void *);
+typedef void (*event_timed_handler_t)(struct event_context *, struct timed_event *,
+ struct timeval , void *);
- /* list of timed events */
- struct timed_event {
- struct event_context *event_ctx;
- struct timed_event *next, *prev;
- struct timeval next_event;
- void (*handler)(struct event_context *ev, struct timed_event *te,
- struct timeval t);
- void *private;
- } *timed_events;
+struct event_context *event_context_init(TALLOC_CTX *mem_ctx);
- /* list of loop events - called on each select() */
- struct loop_event {
- struct event_context *event_ctx;
- struct loop_event *next, *prev;
- void (*handler)(struct event_context *ev, struct loop_event *le,
- struct timeval t);
- void *private;
- } *loop_events;
+struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags, event_fd_handler_t handler,
+ void *private);
- /* list of signal events */
- struct signal_event {
- struct event_context *event_ctx;
- struct signal_event *next, *prev;
- int signum;
- void (*handler)(struct event_context *ev, struct signal_event *se, int signum, void *sigarg);
- void *private;
- } *signal_events;
+struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ struct timeval next_event,
+ event_timed_handler_t handler,
+ void *private);
- /* the maximum file descriptor number in fd_events */
- int maxfd;
+int event_loop_once(struct event_context *ev);
+int event_loop_wait(struct event_context *ev);
- /* information for exiting from the event loop */
- struct {
- BOOL exit_now;
- int code;
- } exit;
+uint16_t event_fd_flags(struct fd_event *fde);
+void event_fd_setflags(struct fd_event *fde, uint16_t flags);
- /* This is the talloc parent for all concrete event structures in this
- * event context. This makes merging easy. */
- void *events;
+/* bits for file descriptor event flags */
+#define EVENT_FD_READ 1
+#define EVENT_FD_WRITE 2
- /* this is changed by the destructors for any event type. It
- is used to detect event destruction by event handlers,
- which means the code that is calling all event handles
- needs to assume that the linked list is no longer valid
- */
- uint32_t destruction_count;
-};
+#define EVENT_FD_WRITEABLE(fde) \
+ event_fd_setflags(fde, event_fd_flags(fde) | EVENT_FD_WRITE)
+#define EVENT_FD_READABLE(fde) \
+ event_fd_setflags(fde, event_fd_flags(fde) | EVENT_FD_READ)
+#define EVENT_FD_NOT_WRITEABLE(fde) \
+ event_fd_setflags(fde, event_fd_flags(fde) & ~EVENT_FD_WRITE)
+#define EVENT_FD_NOT_READABLE(fde) \
+ event_fd_setflags(fde, event_fd_flags(fde) & ~EVENT_FD_WRITE)
-/* bits for fd_event.flags */
-#define EVENT_FD_READ 1
-#define EVENT_FD_WRITE 2
}
if ((ldap_conn->out_buffer.length > 0)||(ldap_conn->sasl_out_buffer.length > 0)) {
- conn->event.fde->flags |= EVENT_FD_WRITE;
+ EVENT_FD_WRITEABLE(conn->event.fde);
}
return;
}
if (ldap_conn->out_buffer.length == 0 && ldap_conn->sasl_out_buffer.length == 0) {
- conn->event.fde->flags &= ~EVENT_FD_WRITE;
+ EVENT_FD_NOT_WRITEABLE(conn->event.fde);
}
return;
# End SUBSYSTEM LIBCRYPTO
##############################
+##############################
+# Start SUBSYSTEM LIBEVENTS
+[SUBSYSTEM::LIBEVENTS]
+NOPROTO = YES
+INIT_OBJ_FILES = lib/events.o
+REQUIRED_SUBSYSTEMS = LIBTALLOC
+# End SUBSYSTEM LIBEVENTS
+##############################
+
##############################
# Start SUBSYSTEM LIBBASIC
[SUBSYSTEM::LIBBASIC]
lib/pam_errors.o \
intl/lang_tdb.o \
lib/mutex.o \
- lib/events.o \
lib/server_mutex.o \
lib/idtree.o \
lib/unix_privs.o \
register one of the possible event types and implement that event
somewhere else.
- There are 4 types of event handling that are handled in this module:
+ There are 2 types of event handling that are handled in this module:
1) a file descriptor becoming readable or writeable. This is mostly
used for network sockets, but can be used for any type of file
like. When they are called the handler can choose to set the time
for the next event. If next_event is not set then the event is removed.
- 3) an event that happens every time through the select loop. These
- sorts of events should be very fast, as they will occur a
- lot. Mostly used for things like destroying a talloc context or
- checking a signal flag.
-
- 4) an event triggered by a signal. These can be one shot or
- repeated. You can have more than one handler registered for a
- single signal if you want to.
-
To setup a set of events you first need to create a event_context
structure using the function event_context_init(); This returns a
'struct event_context' that you use in all subsequent calls.
Finally, you call event_loop_wait() to block waiting for one of the
events to occor. In normal operation event_loop_wait() will loop
- forever, unless you call event_loop_exit() from inside one of your
- handler functions.
+ forever.
*/
#include "dlinklist.h"
#include "events.h"
+
+/*
+ please read the comments in events.c before modifying
+*/
+
+
+struct event_context {
+ /* list of filedescriptor events */
+ struct fd_event {
+ struct event_context *event_ctx;
+ struct fd_event *next, *prev;
+ int fd;
+ uint16_t flags; /* see EVENT_FD_* flags */
+ event_fd_handler_t handler;
+ void *private;
+ } *fd_events;
+
+ /* list of timed events */
+ struct timed_event {
+ struct event_context *event_ctx;
+ struct timed_event *next, *prev;
+ struct timeval next_event;
+ event_timed_handler_t handler;
+ void *private;
+ } *timed_events;
+
+ /* the maximum file descriptor number in fd_events */
+ int maxfd;
+
+ /* information for exiting from the event loop */
+ int exit_code;
+
+ /* this is changed by the destructors for any event type. It
+ is used to detect event destruction by event handlers,
+ which means the code that is calling all event handles
+ needs to assume that the linked list is no longer valid
+ */
+ uint32_t destruction_count;
+};
+
/*
create a event_context structure. This must be the first events
call, and all subsequent calls pass this event_context as the first
ev = talloc_zero(mem_ctx, struct event_context);
if (!ev) return NULL;
- ev->events = talloc_new(ev);
-
return ev;
}
-/*
- destroy an events context, also destroying any remaining events
-*/
-void event_context_destroy(struct event_context *ev)
-{
- talloc_free(ev);
-}
-
-
/*
recalculate the maxfd
*/
add a fd based event
return NULL on failure (memory allocation error)
*/
-struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0,
- TALLOC_CTX *mem_ctx)
+struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ int fd, uint16_t flags, event_fd_handler_t handler,
+ void *private)
{
- struct fd_event *e = talloc(ev->events, struct fd_event);
+ struct fd_event *e = talloc(ev, struct fd_event);
if (!e) return NULL;
- *e = *e0;
- DLIST_ADD(ev->fd_events, e);
+
e->event_ctx = ev;
+ e->fd = fd;
+ e->flags = flags;
+ e->handler = handler;
+ e->private = private;
+
+ DLIST_ADD(ev->fd_events, e);
+
if (e->fd > ev->maxfd) {
ev->maxfd = e->fd;
}
+
talloc_set_destructor(e, event_fd_destructor);
if (mem_ctx) {
talloc_steal(mem_ctx, e);
}
-static int event_timed_destructor(void *ptr)
+/*
+ return the fd event flags
+*/
+uint16_t event_fd_flags(struct fd_event *fde)
{
- struct timed_event *te = talloc_get_type(ptr, struct timed_event);
- DLIST_REMOVE(te->event_ctx->timed_events, te);
- te->event_ctx->destruction_count++;
- return 0;
+ return fde->flags;
}
/*
- add a timed event
- return NULL on failure (memory allocation error)
+ set the fd event flags
*/
-struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e0,
- TALLOC_CTX *mem_ctx)
+void event_fd_setflags(struct fd_event *fde, uint16_t flags)
{
- struct timed_event *e = talloc(ev->events, struct timed_event);
- if (!e) return NULL;
- *e = *e0;
- e->event_ctx = ev;
- DLIST_ADD(ev->timed_events, e);
- talloc_set_destructor(e, event_timed_destructor);
- if (mem_ctx) {
- talloc_steal(mem_ctx, e);
- }
- return e;
+ fde->flags = flags;
}
-static int event_loop_destructor(void *ptr)
+/*
+ destroy a timed event
+*/
+static int event_timed_destructor(void *ptr)
{
- struct loop_event *le = talloc_get_type(ptr, struct loop_event);
- DLIST_REMOVE(le->event_ctx->loop_events, le);
- le->event_ctx->destruction_count++;
+ struct timed_event *te = talloc_get_type(ptr, struct timed_event);
+ DLIST_REMOVE(te->event_ctx->timed_events, te);
+ te->event_ctx->destruction_count++;
return 0;
}
/*
- add a loop event
+ add a timed event
return NULL on failure (memory allocation error)
*/
-struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e0,
- TALLOC_CTX *mem_ctx)
+struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
+ struct timeval next_event,
+ event_timed_handler_t handler,
+ void *private)
{
- struct loop_event *e = talloc(ev->events, struct loop_event);
+ struct timed_event *e = talloc(ev, struct timed_event);
if (!e) return NULL;
- *e = *e0;
- e->event_ctx = ev;
- DLIST_ADD(ev->loop_events, e);
- talloc_set_destructor(e, event_loop_destructor);
+
+ e->event_ctx = ev;
+ e->next_event = next_event;
+ e->handler = handler;
+ e->private = private;
+
+ DLIST_ADD(ev->timed_events, e);
+ talloc_set_destructor(e, event_timed_destructor);
if (mem_ctx) {
talloc_steal(mem_ctx, e);
}
return e;
}
-/*
- tell the event loop to exit with the specified code
-*/
-void event_loop_exit(struct event_context *ev, int code)
-{
- ev->exit.exit_now = True;
- ev->exit.code = code;
-}
-
/*
do a single event loop using the events defined in ev this function
*/
{
fd_set r_fds, w_fds;
struct fd_event *fe;
- struct loop_event *le;
struct timed_event *te, *te_next;
int selrtn;
- struct timeval tval, t, *tvalp=NULL;
+ struct timeval tval, t, *tvalp;
uint32_t destruction_count = ev->destruction_count;
- t = timeval_current();
-
- /* the loop events are called on each loop. Be careful to allow the
- event to remove itself */
- for (le=ev->loop_events;le;) {
- struct loop_event *next = le->next;
- le->handler(ev, le, t);
- if (destruction_count != ev->destruction_count) break;
- le = next;
- }
-
FD_ZERO(&r_fds);
FD_ZERO(&w_fds);
fe = next;
}
- /* start with a reasonable max timeout */
- tval.tv_sec = 0;
- tval.tv_usec = 0;
+ tvalp = NULL;
+ t = timeval_current();
/* work out the right timeout for all timed events */
for (te=ev->timed_events;te;te=te_next) {
the event, so this must be a bug. This is a
fatal error. */
DEBUG(0,("EBADF on event_loop_once - exiting\n"));
- ev->exit.code = EBADF;
+ ev->exit_code = EBADF;
return -1;
}
if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ;
if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE;
if (flags) {
- fe->handler(ev, fe, t, flags);
+ fe->handler(ev, fe, t, flags, fe->private);
if (destruction_count != ev->destruction_count) {
break;
}
struct timed_event *next = te->next;
if (timeval_compare(&te->next_event, &t) >= 0) {
te->next_event = timeval_zero();
- te->handler(ev, te, t);
+ te->handler(ev, te, t, te->private);
if (destruction_count != ev->destruction_count) {
break;
}
*/
int event_loop_wait(struct event_context *ev)
{
- ZERO_STRUCT(ev->exit);
+ ev->exit_code = 0;
ev->maxfd = EVENT_INVALID_MAXFD;
- ev->exit.exit_now = False;
-
- while (ev->fd_events && !ev->exit.exit_now) {
+ while (ev->fd_events && ev->exit_code == 0) {
if (event_loop_once(ev) != 0) {
break;
}
}
- return ev->exit.code;
+ return ev->exit_code;
}
handle IO for a single message
*/
static void messaging_recv_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct messaging_rec *rec = fde->private;
+ struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec);
struct messaging_context *msg = rec->msg;
NTSTATUS status;
handle a new incoming connection
*/
static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct messaging_context *msg = fde->private;
+ struct messaging_context *msg = talloc_get_type(private,
+ struct messaging_context);
struct messaging_rec *rec;
NTSTATUS status;
- struct fd_event fde2;
rec = talloc(msg, struct messaging_rec);
if (rec == NULL) {
}
talloc_steal(rec, rec->sock);
- rec->msg = msg;
- rec->ndone = 0;
+ rec->msg = msg;
+ rec->ndone = 0;
rec->header.length = 0;
- rec->path = msg->path;
-
- fde2.private = rec;
- fde2.fd = socket_get_fd(rec->sock);
- fde2.flags = EVENT_FD_READ;
- fde2.handler = messaging_recv_handler;
-
- rec->fde = event_add_fd(msg->event.ev, &fde2, rec);
+ rec->path = msg->path;
+ rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock),
+ EVENT_FD_READ, messaging_recv_handler, rec);
}
/*
handle IO for sending a message
*/
static void messaging_send_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct messaging_rec *rec = fde->private;
+ struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec);
NTSTATUS status;
if (rec->ndone < sizeof(rec->header)) {
when the servers listen queue is full we use this to backoff the message
*/
static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te,
- struct timeval t)
+ struct timeval t, void *private)
{
- struct messaging_rec *rec = te->private;
+ struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec);
struct messaging_context *msg = rec->msg;
NTSTATUS status;
- struct fd_event fde;
status = try_connect(rec);
if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
/* backoff again */
- te->next_event = timeval_add(&t, 0, MESSAGING_BACKOFF);
+ event_add_timed(msg->event.ev, rec,
+ timeval_add(&t, 0, MESSAGING_BACKOFF),
+ messaging_backoff_handler, rec);
return;
}
return;
}
- fde.private = rec;
- fde.fd = socket_get_fd(rec->sock);
- fde.flags = EVENT_FD_WRITE;
- fde.handler = messaging_send_handler;
-
- rec->fde = event_add_fd(msg->event.ev, &fde, rec);
-
- messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE);
+ rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock),
+ EVENT_FD_WRITE, messaging_send_handler, rec);
}
{
struct messaging_rec *rec;
NTSTATUS status;
- struct fd_event fde;
rec = talloc(msg, struct messaging_rec);
if (rec == NULL) {
status = try_connect(rec);
if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
/* backoff on this message - the servers listen queue is full */
- struct timed_event te;
- te.next_event = timeval_current_ofs(0, MESSAGING_BACKOFF);
- te.handler = messaging_backoff_handler;
- te.private = rec;
- event_add_timed(msg->event.ev, &te, rec);
+ event_add_timed(msg->event.ev, rec,
+ timeval_current_ofs(0, MESSAGING_BACKOFF),
+ messaging_backoff_handler, rec);
return NT_STATUS_OK;
}
return status;
}
- fde.private = rec;
- fde.fd = socket_get_fd(rec->sock);
- fde.flags = EVENT_FD_WRITE;
- fde.handler = messaging_send_handler;
-
- rec->fde = event_add_fd(msg->event.ev, &fde, rec);
-
- messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE);
+ rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock),
+ EVENT_FD_WRITE, messaging_send_handler, rec);
return NT_STATUS_OK;
}
{
struct messaging_context *msg;
NTSTATUS status;
- struct fd_event fde;
msg = talloc(mem_ctx, struct messaging_context);
if (msg == NULL) {
return NULL;
}
- fde.private = msg;
- fde.fd = socket_get_fd(msg->sock);
- fde.flags = EVENT_FD_READ;
- fde.handler = messaging_listen_handler;
-
msg->event.ev = talloc_reference(msg, ev);
- msg->event.fde = event_add_fd(ev, &fde, msg);
+ msg->event.fde = event_add_fd(ev, msg, socket_get_fd(msg->sock),
+ EVENT_FD_READ, messaging_listen_handler, msg);
talloc_set_destructor(msg, messaging_destructor);
*/
#include "includes.h"
+#include "events.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/composite/composite.h"
[SUBSYSTEM::LIBCLI_COMPOSITE_BASE]
ADD_OBJ_FILES = \
libcli/composite/composite.o
+REQUIRED_SUBSYSTEMS = LIBEVENTS
[SUBSYSTEM::LIBCLI_COMPOSITE]
ADD_OBJ_FILES = \
libcli/nbt/namequery.o \
libcli/nbt/nameregister.o \
libcli/nbt/namerefresh.o
-REQUIRED_SUBSYSTEMS = LIBNDR_RAW NDR_NBT SOCKET LIBCLI_COMPOSITE_BASE
+REQUIRED_SUBSYSTEMS = LIBNDR_RAW NDR_NBT SOCKET LIBCLI_COMPOSITE_BASE LIBEVENTS
[SUBSYSTEM::LIBCLI_RESOLVE]
ADD_OBJ_FILES = \
req->te = NULL;
}
if (req->nbtsock->send_queue == NULL) {
- req->nbtsock->fde->flags &= ~EVENT_FD_WRITE;
+ EVENT_FD_NOT_WRITEABLE(req->nbtsock->fde);
}
if (req->nbtsock->num_pending == 0 &&
req->nbtsock->incoming.handler == NULL) {
- req->nbtsock->fde->flags &= ~EVENT_FD_READ;
+ EVENT_FD_NOT_READABLE(req->nbtsock->fde);
}
return 0;
}
talloc_free(req);
} else {
req->state = NBT_REQUEST_WAIT;
- nbtsock->fde->flags |= EVENT_FD_READ;
+ EVENT_FD_READABLE(nbtsock->fde);
nbtsock->num_pending++;
}
}
- nbtsock->fde->flags &= ~EVENT_FD_WRITE;
+ EVENT_FD_NOT_WRITEABLE(nbtsock->fde);
talloc_free(tmp_ctx);
return;
handle fd events on a nbt_name_socket
*/
static void nbt_name_socket_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct nbt_name_socket *nbtsock = talloc_get_type(fde->private,
+ struct nbt_name_socket *nbtsock = talloc_get_type(private,
struct nbt_name_socket);
if (flags & EVENT_FD_WRITE) {
nbt_name_socket_send(nbtsock);
{
struct nbt_name_socket *nbtsock;
NTSTATUS status;
- struct fd_event fde;
nbtsock = talloc(mem_ctx, struct nbt_name_socket);
if (nbtsock == NULL) goto failed;
nbtsock->num_pending = 0;
nbtsock->incoming.handler = NULL;
- fde.fd = socket_get_fd(nbtsock->sock);
- fde.flags = 0;
- fde.handler = nbt_name_socket_handler;
- fde.private = nbtsock;
- nbtsock->fde = event_add_fd(nbtsock->event_ctx, &fde, nbtsock);
+ nbtsock->fde = event_add_fd(nbtsock->event_ctx, nbtsock,
+ socket_get_fd(nbtsock->sock), 0,
+ nbt_name_socket_handler, nbtsock);
return nbtsock;
handle a request timeout
*/
static void nbt_name_socket_timeout(struct event_context *ev, struct timed_event *te,
- struct timeval t)
+ struct timeval t, void *private)
{
- struct nbt_name_request *req = talloc_get_type(te->private,
+ struct nbt_name_request *req = talloc_get_type(private,
struct nbt_name_request);
nbt_name_request_destructor(req);
if (req->num_replies == 0) {
BOOL allow_multiple_replies)
{
struct nbt_name_request *req;
- struct timed_event te;
int id;
NTSTATUS status;
request->name_trn_id = id;
req->name_trn_id = id;
- te.next_event = timeout;
- te.handler = nbt_name_socket_timeout;
- te.private = req;
- req->te = event_add_timed(nbtsock->event_ctx, &te, req);
+ req->te = event_add_timed(nbtsock->event_ctx, req, timeout,
+ nbt_name_socket_timeout, req);
talloc_set_destructor(req, nbt_name_request_destructor);
NDR_PRINT_DEBUG(nbt_name_packet, request);
}
- nbtsock->fde->flags |= EVENT_FD_WRITE;
+ EVENT_FD_WRITEABLE(nbtsock->fde);
return req;
DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *);
- nbtsock->fde->flags |= EVENT_FD_WRITE;
+ EVENT_FD_WRITEABLE(nbtsock->fde);
return NT_STATUS_OK;
{
nbtsock->incoming.handler = handler;
nbtsock->incoming.private = private;
- nbtsock->fde->flags |= EVENT_FD_READ;
+ EVENT_FD_READABLE(nbtsock->fde);
return NT_STATUS_OK;
}
}
static NTSTATUS smbcli_sock_connect_one(struct smbcli_socket *sock,
- const char *hostaddr, int port);
+ const char *hostaddr, int port,
+ struct composite_context *c);
/*
handle socket write events during an async connect. These happen when the OS
has either completed the connect() or has returned an error
*/
static void smbcli_sock_connect_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct composite_context *c = talloc_get_type(fde->private, struct composite_context);
+ struct composite_context *c = talloc_get_type(private, struct composite_context);
struct clisocket_connect *conn = talloc_get_type(c->private, struct clisocket_connect);
int i;
conn->port_num = i;
c->status = smbcli_sock_connect_one(conn->sock,
conn->dest_host,
- conn->iports[i]);
+ conn->iports[i], c);
if (NT_STATUS_IS_OK(c->status) ||
NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- conn->sock->event.fde->private = c;
return;
}
}
try to connect to the given address/port
*/
static NTSTATUS smbcli_sock_connect_one(struct smbcli_socket *sock,
- const char *hostaddr, int port)
+ const char *hostaddr, int port,
+ struct composite_context *c)
{
- struct fd_event fde;
NTSTATUS status;
if (sock->sock) {
/* we initially look for write - see the man page on
non-blocking connect */
- fde.fd = socket_get_fd(sock->sock);
- fde.flags = EVENT_FD_WRITE;
- fde.handler = smbcli_sock_connect_handler;
- fde.private = sock;
-
- sock->event.fde = event_add_fd(sock->event.ctx, &fde, sock);
+ sock->event.fde = event_add_fd(sock->event.ctx, sock, socket_get_fd(sock->sock),
+ EVENT_FD_WRITE, smbcli_sock_connect_handler, c);
sock->port = port;
- set_blocking(fde.fd, False);
+ set_blocking(socket_get_fd(sock->sock), False);
return socket_connect(sock->sock, NULL, 0, hostaddr, port, 0);
}
conn->sock->port = conn->iports[i];
c->status = smbcli_sock_connect_one(sock,
conn->dest_host,
- conn->iports[i]);
+ conn->iports[i], c);
if (NT_STATUS_IS_OK(c->status) ||
NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- sock->event.fde->private = c;
return c;
}
}
/*
an event has happened on the socket
*/
-static void smbcli_transport_event_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+static void smbcli_transport_event_handler(struct event_context *ev,
+ struct fd_event *fde,
+ struct timeval t,
+ uint16_t flags, void *private)
{
- struct smbcli_transport *transport = fde->private;
-
+ struct smbcli_transport *transport = talloc_get_type(private,
+ struct smbcli_transport);
if (flags & EVENT_FD_READ) {
smbcli_transport_process_recv(transport);
return;
/* take over event handling from the socket layer - it only
handles events up until we are connected */
- transport->socket->event.fde->handler = smbcli_transport_event_handler;
- transport->socket->event.fde->private = transport;
- transport->socket->event.fde->flags = EVENT_FD_READ;
+ talloc_free(transport->socket->event.fde);
+ transport->socket->event.fde = event_add_fd(transport->socket->event.ctx,
+ transport->socket,
+ socket_get_fd(transport->socket->sock),
+ EVENT_FD_READ,
+ smbcli_transport_event_handler,
+ transport);
talloc_set_destructor(transport, transport_destructor);
*/
static void smbcli_transport_write_enable(struct smbcli_transport *transport)
{
- transport->socket->event.fde->flags |= EVENT_FD_WRITE;
+ struct fd_event *fde = transport->socket->event.fde;
+ EVENT_FD_WRITEABLE(fde);
}
/*
*/
static void smbcli_transport_write_disable(struct smbcli_transport *transport)
{
- transport->socket->event.fde->flags &= ~EVENT_FD_WRITE;
+ struct fd_event *fde = transport->socket->event.fde;
+ EVENT_FD_NOT_WRITEABLE(fde);
}
/*
}
static void idle_handler(struct event_context *ev,
- struct timed_event *te, struct timeval t)
+ struct timed_event *te, struct timeval t, void *private)
{
- struct smbcli_transport *transport = te->private;
- te->next_event = timeval_add(&te->next_event, 0, transport->idle.period);
+ struct smbcli_transport *transport = talloc_get_type(private,
+ struct smbcli_transport);
+ struct timeval next = timeval_add(&t, 0, transport->idle.period);
+ transport->socket->event.te = event_add_timed(transport->socket->event.ctx,
+ transport,
+ next,
+ idle_handler, transport);
transport->idle.func(transport, transport->idle.private);
}
uint64_t period,
void *private)
{
- struct timed_event te;
transport->idle.func = idle_func;
transport->idle.private = private;
transport->idle.period = period;
talloc_free(transport->socket->event.te);
}
- te.next_event = timeval_current_ofs(0, period);
- te.handler = idle_handler;
- te.private = transport;
transport->socket->event.te = event_add_timed(transport->socket->event.ctx,
- &te, transport);
+ transport,
+ timeval_current_ofs(0, period),
+ idle_handler, transport);
}
/*
#include "includes.h"
#include "libcli/raw/libcliraw.h"
#include "dlinklist.h"
+#include "events.h"
/* we over allocate the data buffer to prevent too many realloc calls */
#define REQ_OVER_ALLOCATION 0
handle a read event on the pipe
*/
static void pipe_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct composite_context *c = talloc_get_type(fde->private, struct composite_context);
+ struct composite_context *c = talloc_get_type(private, struct composite_context);
struct host_state *state = talloc_get_type(c->private, struct host_state);
char address[128];
int ret;
struct host_state *state;
NTSTATUS status;
int fd[2] = { -1, -1 };
- struct fd_event fde;
int ret;
c = talloc_zero(NULL, struct composite_context);
/* we need to put the child in our event context so
we know when the gethostbyname() has finished */
- fde.fd = state->child_fd;
- fde.flags = EVENT_FD_READ;
- fde.handler = pipe_handler;
- fde.private = c;
- state->fde = event_add_fd(c->event_ctx, &fde, state);
+ state->fde = event_add_fd(c->event_ctx, state, state->child_fd, EVENT_FD_READ,
+ pipe_handler, c);
if (state->fde == NULL) {
close(fd[0]);
close(fd[1]);
*/
#include "includes.h"
+#include "events.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/composite/composite.h"
#include "includes.h"
#include "dlinklist.h"
+#include "events.h"
#include "librpc/gen_ndr/ndr_epmapper.h"
#include "librpc/gen_ndr/ndr_dcerpc.h"
p->transport.recv_data(p, NULL, status);
}
- sock->fde->flags &= ~(EVENT_FD_WRITE | EVENT_FD_READ);
+ talloc_free(sock->fde);
}
/*
}
if (sock->pending_send == NULL) {
- sock->fde->flags &= ~EVENT_FD_WRITE;
+ EVENT_FD_NOT_WRITEABLE(sock->fde);
}
}
sock->recv.received = 0;
sock->recv.pending_count--;
if (sock->recv.pending_count == 0) {
- sock->fde->flags &= ~EVENT_FD_READ;
+ EVENT_FD_NOT_READABLE(sock->fde);
}
}
called when a IO is triggered by the events system
*/
static void sock_io_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct dcerpc_connection *p = fde->private;
+ struct dcerpc_connection *p = talloc_get_type(private, struct dcerpc_connection);
struct sock_private *sock = p->transport.private;
if (flags & EVENT_FD_WRITE) {
sock->recv.pending_count++;
if (sock->recv.pending_count == 1) {
- sock->fde->flags |= EVENT_FD_READ;
+ EVENT_FD_READABLE(sock->fde);
}
return NT_STATUS_OK;
}
DLIST_ADD_END(sock->pending_send, blob, struct sock_blob *);
- sock->fde->flags |= EVENT_FD_WRITE;
+ EVENT_FD_WRITEABLE(sock->fde);
if (trigger_read) {
sock_send_read(p);
{
struct sock_private *sock;
struct socket_context *socket_ctx;
- struct fd_event fde;
NTSTATUS status;
sock = talloc(c, struct sock_private);
sock->recv.data = data_blob(NULL, 0);
sock->recv.pending_count = 0;
- fde.fd = socket_get_fd(sock->sock);
- fde.flags = 0;
- fde.handler = sock_io_handler;
- fde.private = c;
-
- sock->fde = event_add_fd(sock->event_ctx, &fde, sock);
+ sock->fde = event_add_fd(sock->event_ctx, sock, socket_get_fd(sock->sock),
+ 0, sock_io_handler, c);
c->transport.private = sock;
handle name refresh timer events
*/
static void name_refresh_handler(struct event_context *ev, struct timed_event *te,
- struct timeval t)
+ struct timeval t, void *private)
{
- struct nbt_iface_name *iname = talloc_get_type(te->private, struct nbt_iface_name);
+ struct nbt_iface_name *iname = talloc_get_type(private, struct nbt_iface_name);
struct nbt_interface *iface = iname->iface;
struct nbt_name_refresh io;
struct nbt_name_request *req;
*/
static void nbt_start_refresh_timer(struct nbt_iface_name *iname)
{
- struct timed_event te;
uint32_t refresh_time;
uint32_t max_refresh_time = lp_parm_int(-1, "nbtd", "max_refresh_time", 7200);
refresh_time = MIN(max_refresh_time, iname->ttl/2);
- te.next_event = timeval_current_ofs(refresh_time, 0);
- te.handler = name_refresh_handler;
- te.private = iname;
-
- event_add_timed(iname->iface->nbtsrv->task->event_ctx, &te, iname);
+ event_add_timed(iname->iface->nbtsrv->task->event_ctx,
+ iname,
+ timeval_current_ofs(refresh_time, 0),
+ name_refresh_handler, iname);
}
a handler for read events on a connection to a backend server
*/
static void cifs_socket_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct cvfs_private *private = fde->private;
- struct smbsrv_tcon *tcon = private->tcon;
+ struct cvfs_private *cvfs = talloc_get_type(private, struct cvfs_private);
+ struct smbsrv_tcon *tcon = cvfs->tcon;
- DEBUG(5,("cifs_socket_handler event on fd %d\n", fde->fd));
-
- if (!smbcli_transport_process(private->transport)) {
+ if (!smbcli_transport_process(cvfs->transport)) {
/* the connection to our server is dead */
talloc_free(tcon);
}
const char *host, *user, *pass, *domain, *remote_share;
struct smb_composite_connect io;
struct composite_context *creq;
+ struct fd_event *fde;
/* Here we need to determine which server to connect to.
* For now we use parametric options, type cifs.
/* we need to receive oplock break requests from the server */
smbcli_oplock_handler(private->transport, oplock_handler, private);
- private->transport->socket->event.fde->handler = cifs_socket_handler;
- private->transport->socket->event.fde->private = private;
+ /* take over event handling for this socket */
+ talloc_free(private->transport->socket->event.fde);
+ fde = event_add_fd(private->transport->socket->event.ctx,
+ private,
+ socket_get_fd(private->transport->socket->sock),
+ EVENT_FD_READ | EVENT_FD_WRITE,
+ cifs_socket_handler,
+ private);
+ private->transport->socket->event.fde = fde;
+
private->map_generic = lp_parm_bool(req->tcon->service,
"cifs", "mapgeneric", False);
receive a timeout on a message wait
*/
static void pvfs_wait_timeout(struct event_context *ev,
- struct timed_event *te, struct timeval t)
+ struct timed_event *te, struct timeval t, void *private)
{
- struct pvfs_wait *pwait = te->private;
+ struct pvfs_wait *pwait = talloc_get_type(private, struct pvfs_wait);
struct smbsrv_request *req = pwait->req;
pwait->reason = PVFS_WAIT_TIMEOUT;
void (*fn)(void *, enum pvfs_wait_notice),
void *private)
{
- struct timed_event te;
struct pvfs_wait *pwait;
pwait = talloc(pvfs, struct pvfs_wait);
pwait->pvfs = pvfs;
/* setup a timer */
- te.next_event = end_time;
- te.handler = pvfs_wait_timeout;
- te.private = pwait;
- pwait->te = event_add_timed(pwait->ev, &te, pwait);
+ pwait->te = event_add_timed(pwait->ev, pwait, end_time,
+ pvfs_wait_timeout, pwait);
/* register with the messaging subsystem for this message
type */
if (call->conn->call_list && call->conn->call_list->replies) {
if (call->conn->srv_conn &&
call->conn->srv_conn->event.fde) {
- call->conn->srv_conn->event.fde->flags |= EVENT_FD_WRITE;
+ EVENT_FD_WRITEABLE(call->conn->srv_conn->event.fde);
}
}
}
if (dce_conn->call_list && dce_conn->call_list->replies) {
- conn->event.fde->flags |= EVENT_FD_WRITE;
+ EVENT_FD_WRITEABLE(conn->event.fde);
}
}
}
if (!dce_conn->call_list || !dce_conn->call_list->replies) {
- conn->event.fde->flags &= ~EVENT_FD_WRITE;
+ EVENT_FD_NOT_WRITEABLE(conn->event.fde);
}
}
struct echo_TestSleep *r;
};
-static void echo_TestSleep_handler(struct event_context *ev, struct timed_event *te, struct timeval t)
+static void echo_TestSleep_handler(struct event_context *ev, struct timed_event *te,
+ struct timeval t, void *private)
{
- struct echo_TestSleep_private *p = te->private;
+ struct echo_TestSleep_private *p = talloc_get_type(private,
+ struct echo_TestSleep_private);
struct echo_TestSleep *r = p->r;
NTSTATUS status;
static long echo_TestSleep(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestSleep *r)
{
- struct timed_event te;
struct echo_TestSleep_private *p;
if (!(dce_call->state_flags & DCESRV_CALL_STATE_FLAG_MAY_ASYNC)) {
p->dce_call = dce_call;
p->r = r;
- te.handler = echo_TestSleep_handler;
- te.private = p;
- te.next_event = timeval_add(&dce_call->time, r->in.seconds, 0);
-
- event_add_timed(dce_call->event_ctx, &te, p);
+ event_add_timed(dce_call->event_ctx, p,
+ timeval_add(&dce_call->time, r->in.seconds, 0),
+ echo_TestSleep_handler, p);
dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
return 0;
ready for write events */
DLIST_ADD_END(req->smb_conn->pending_send, req, struct smbsrv_request *);
- req->smb_conn->connection->event.fde->flags |= EVENT_FD_WRITE;
+ EVENT_FD_WRITEABLE(req->smb_conn->connection->event.fde);
}
/*
status = receive_smb_request(smb_conn, t);
if (NT_STATUS_IS_ERR(status)) {
- conn->event.fde->flags = 0;
+ talloc_free(conn->event.fde);
smbsrv_terminate_connection(smb_conn, nt_errstr(status));
return;
}
/* if no more requests are pending to be sent then
we should stop select for write */
if (smb_conn->pending_send == NULL) {
- conn->event.fde->flags &= ~EVENT_FD_WRITE;
+ EVENT_FD_NOT_WRITEABLE(conn->event.fde);
}
}
{
static const struct process_model_critical_sizes critical_sizes = {
PROCESS_MODEL_VERSION,
- sizeof(struct model_ops),
- sizeof(struct event_context),
- sizeof(struct fd_event)
+ sizeof(struct model_ops)
};
return &critical_sizes;
struct process_model_critical_sizes {
int interface_version;
int sizeof_model_ops;
- int sizeof_event_context;
- int sizeof_fd_event;
};
*/
#include "includes.h"
+#include "events.h"
#include "version.h"
#include "dynconfig.h"
#include "lib/cmdline/popt_common.h"
the select loop has indicated that a stream is ready for IO
*/
static void stream_io_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct stream_connection *conn = talloc_get_type(fde->private,
+ struct stream_connection *conn = talloc_get_type(private,
struct stream_connection);
if (flags & EVENT_FD_WRITE) {
conn->ops->send_handler(conn, t, flags);
uint32_t server_id, void *private)
{
struct stream_socket *stream_socket = talloc_get_type(private, struct stream_socket);
- struct fd_event fde;
struct stream_connection *srv_conn;
srv_conn = talloc_zero(ev, struct stream_connection);
talloc_steal(srv_conn, sock);
- fde.private = srv_conn;
- fde.fd = socket_get_fd(sock);
- fde.flags = EVENT_FD_READ;
- fde.handler = stream_io_handler;
-
srv_conn->private = stream_socket->private;
srv_conn->model_ops = stream_socket->model_ops;
srv_conn->event.ctx = ev;
- srv_conn->event.fde = &fde;
srv_conn->socket = sock;
srv_conn->server_id = server_id;
srv_conn->ops = stream_socket->ops;
- srv_conn->event.fde = event_add_fd(ev, &fde, srv_conn);
+ srv_conn->event.fde = event_add_fd(ev, srv_conn, socket_get_fd(sock),
+ EVENT_FD_READ,
+ stream_io_handler, srv_conn);
if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {
stream_terminate_connection(srv_conn, "denied by access rules");
called when someone opens a connection to one of our listening ports
*/
static void stream_accept_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+ struct timeval t, uint16_t flags, void *private)
{
- struct stream_socket *stream_socket = talloc_get_type(fde->private, struct stream_socket);
+ struct stream_socket *stream_socket = talloc_get_type(private, struct stream_socket);
/* ask the process model to create us a process for this new
connection. When done, it calls stream_new_connection()
{
NTSTATUS status;
struct stream_socket *stream_socket;
- struct fd_event fde;
int i;
stream_socket = talloc_zero(event_context, struct stream_socket);
return status;
}
- /* we are only interested in read events on the listen socket */
- fde.fd = socket_get_fd(stream_socket->sock);
- fde.flags = EVENT_FD_READ;
- fde.private = stream_socket;
- fde.handler = stream_accept_handler;
-
- event_add_fd(event_context, &fde, stream_socket->sock);
+ event_add_fd(event_context, stream_socket->sock,
+ socket_get_fd(stream_socket->sock),
+ EVENT_FD_READ, stream_accept_handler, stream_socket);
stream_socket->private = talloc_reference(stream_socket, private);
stream_socket->ops = stream_ops;
*/
#include "includes.h"
+#include "events.h"
enum {MY_PING=1000, MY_PONG, MY_EXIT};
talloc_free(msg_ctx);
- event_context_destroy(ev);
+ talloc_free(ev);
return ret;
}
*/
#include "includes.h"
+#include "events.h"
#include "libcli/nbt/libnbt.h"
#include "librpc/gen_ndr/ndr_nbt.h"
*/
#include "includes.h"
+#include "events.h"
#include "libcli/raw/libcliraw.h"
#include "libcli/composite/composite.h"
*/
#include "includes.h"
+#include "events.h"
#include "librpc/gen_ndr/ndr_echo.h"
*/
#include "includes.h"
+#include "events.h"
#include "librpc/gen_ndr/ndr_netlogon.h"
#include "auth/auth.h"
DLIST_ADD_END(wbconn->queue, q, struct send_queue *);
- conn->event.fde->flags |= EVENT_FD_WRITE;
+ EVENT_FD_WRITEABLE(conn->event.fde);
}
/*
}
}
- conn->event.fde->flags &= ~EVENT_FD_WRITE;
+ EVENT_FD_NOT_WRITEABLE(conn->event.fde);
}
static const struct stream_server_ops winbind_stream_ops = {