r7654: - add a timeout to all smb requests (default 60 seconds)
authorAndrew Tridgell <tridge@samba.org>
Thu, 16 Jun 2005 23:19:03 +0000 (23:19 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:18:17 +0000 (13:18 -0500)
 - add a request destructor, to make it safe to destroy a pending
   request with talloc_free()
(This used to be commit 72c6988767249caa585f37fec4c0afbf41557ec2)

source4/libcli/raw/clitransport.c
source4/libcli/raw/libcliraw.h

index 05833b2f9ad5cffdec67ddc0d38adf64a174b2d7..999795b81ee646d0b523165632b24a6aa4c6232d 100644 (file)
@@ -79,6 +79,7 @@ struct smbcli_transport *smbcli_transport_init(struct smbcli_socket *sock,
        transport->options.use_spnego = lp_use_spnego();
        transport->options.max_xmit = lp_max_xmit();
        transport->options.max_mux = lp_maxmux();
+       transport->options.request_timeout = SMB_REQUEST_TIMEOUT;
 
        transport->negotiate.max_xmit = transport->options.max_xmit;
        
@@ -580,6 +581,42 @@ BOOL smbcli_transport_process(struct smbcli_transport *transport)
        return True;
 }
 
+/*
+  handle timeouts of individual smb requests
+*/
+static void smbcli_timeout_handler(struct event_context *ev, struct timed_event *te, 
+                                  struct timeval t, void *private)
+{
+       struct smbcli_request *req = talloc_get_type(private, struct smbcli_request);
+
+       if (req->state == SMBCLI_REQUEST_SEND) {
+               DLIST_REMOVE(req->transport->pending_send, req);
+       }
+       if (req->state == SMBCLI_REQUEST_RECV) {
+               DLIST_REMOVE(req->transport->pending_recv, req);
+       }
+       req->status = NT_STATUS_IO_TIMEOUT;
+       req->state = SMBCLI_REQUEST_ERROR;
+       if (req->async.fn) {
+               req->async.fn(req);
+       }
+}
+
+
+/*
+  destroy a request
+*/
+static int smbcli_request_destructor(void *ptr)
+{
+       struct smbcli_request *req = talloc_get_type(ptr, struct smbcli_request);
+       if (req->state == SMBCLI_REQUEST_SEND) {
+               DLIST_REMOVE(req->transport->pending_send, req);
+       }
+       if (req->state == SMBCLI_REQUEST_RECV) {
+               DLIST_REMOVE(req->transport->pending_recv, req);
+       }
+       return 0;
+}
 
 
 /*
@@ -600,4 +637,13 @@ void smbcli_transport_send(struct smbcli_request *req)
 
        /* make sure we look for write events */
        smbcli_transport_write_enable(req->transport);
+
+       /* add a timeout */
+       if (req->transport->options.request_timeout) {
+               event_add_timed(req->transport->socket->event.ctx, req, 
+                               timeval_current_ofs(req->transport->options.request_timeout, 0), 
+                               smbcli_timeout_handler, req);
+       }
+
+       talloc_set_destructor(req, smbcli_request_destructor);
 }
index d7414a237ec13ae309430e2e0cc8b28cb50f4682..2794a22da26c29a28081940ff627c2a8665a9b22 100644 (file)
@@ -28,6 +28,9 @@ struct smbcli_request;  /* forward declare */
 struct smbcli_session;  /* forward declare */
 struct smbcli_transport;  /* forward declare */
 
+/* default timeout for all smb requests */
+#define SMB_REQUEST_TIMEOUT 60
+
 /* context that will be and has been negotiated between the client and server */
 struct smbcli_negotiate {
        /* 
@@ -88,6 +91,7 @@ struct smbcli_options {
        uint_t use_spnego:1;
        uint32_t max_xmit;
        uint16_t max_mux;
+       int request_timeout;
 };
 
 /* this is the context for the client transport layer */