Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /*- |
michael@0 | 2 | * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. |
michael@0 | 3 | * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. |
michael@0 | 4 | * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. |
michael@0 | 5 | * |
michael@0 | 6 | * Redistribution and use in source and binary forms, with or without |
michael@0 | 7 | * modification, are permitted provided that the following conditions are met: |
michael@0 | 8 | * |
michael@0 | 9 | * a) Redistributions of source code must retain the above copyright notice, |
michael@0 | 10 | * this list of conditions and the following disclaimer. |
michael@0 | 11 | * |
michael@0 | 12 | * b) Redistributions in binary form must reproduce the above copyright |
michael@0 | 13 | * notice, this list of conditions and the following disclaimer in |
michael@0 | 14 | * the documentation and/or other materials provided with the distribution. |
michael@0 | 15 | * |
michael@0 | 16 | * c) Neither the name of Cisco Systems, Inc. nor the names of its |
michael@0 | 17 | * contributors may be used to endorse or promote products derived |
michael@0 | 18 | * from this software without specific prior written permission. |
michael@0 | 19 | * |
michael@0 | 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
michael@0 | 22 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
michael@0 | 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
michael@0 | 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
michael@0 | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
michael@0 | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
michael@0 | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
michael@0 | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
michael@0 | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
michael@0 | 30 | * THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 31 | */ |
michael@0 | 32 | |
michael@0 | 33 | #if defined(__Userspace__) |
michael@0 | 34 | #include <sys/types.h> |
michael@0 | 35 | #if !defined (__Userspace_os_Windows) |
michael@0 | 36 | #include <sys/wait.h> |
michael@0 | 37 | #include <unistd.h> |
michael@0 | 38 | #include <pthread.h> |
michael@0 | 39 | #endif |
michael@0 | 40 | #if defined(__Userspace_os_NaCl) |
michael@0 | 41 | #include <sys/select.h> |
michael@0 | 42 | #endif |
michael@0 | 43 | #include <stdlib.h> |
michael@0 | 44 | #include <string.h> |
michael@0 | 45 | #include <stdio.h> |
michael@0 | 46 | #include <errno.h> |
michael@0 | 47 | #include <netinet/sctp_sysctl.h> |
michael@0 | 48 | #include <netinet/sctp_pcb.h> |
michael@0 | 49 | #else |
michael@0 | 50 | #include <netinet/sctp_os.h> |
michael@0 | 51 | #include <netinet/sctp_callout.h> |
michael@0 | 52 | #include <netinet/sctp_pcb.h> |
michael@0 | 53 | #endif |
michael@0 | 54 | |
michael@0 | 55 | /* |
michael@0 | 56 | * Callout/Timer routines for OS that doesn't have them |
michael@0 | 57 | */ |
michael@0 | 58 | #if defined(__APPLE__) || defined(__Userspace__) |
michael@0 | 59 | int ticks = 0; |
michael@0 | 60 | #else |
michael@0 | 61 | extern int ticks; |
michael@0 | 62 | #endif |
michael@0 | 63 | |
michael@0 | 64 | /* |
michael@0 | 65 | * SCTP_TIMERQ_LOCK protects: |
michael@0 | 66 | * - SCTP_BASE_INFO(callqueue) |
michael@0 | 67 | * - sctp_os_timer_current: current timer in process |
michael@0 | 68 | * - sctp_os_timer_next: next timer to check |
michael@0 | 69 | */ |
michael@0 | 70 | static sctp_os_timer_t *sctp_os_timer_current = NULL; |
michael@0 | 71 | static sctp_os_timer_t *sctp_os_timer_next = NULL; |
michael@0 | 72 | |
michael@0 | 73 | void |
michael@0 | 74 | sctp_os_timer_init(sctp_os_timer_t *c) |
michael@0 | 75 | { |
michael@0 | 76 | bzero(c, sizeof(*c)); |
michael@0 | 77 | } |
michael@0 | 78 | |
michael@0 | 79 | void |
michael@0 | 80 | sctp_os_timer_start(sctp_os_timer_t *c, int to_ticks, void (*ftn) (void *), |
michael@0 | 81 | void *arg) |
michael@0 | 82 | { |
michael@0 | 83 | /* paranoia */ |
michael@0 | 84 | if ((c == NULL) || (ftn == NULL)) |
michael@0 | 85 | return; |
michael@0 | 86 | |
michael@0 | 87 | SCTP_TIMERQ_LOCK(); |
michael@0 | 88 | /* check to see if we're rescheduling a timer */ |
michael@0 | 89 | if (c->c_flags & SCTP_CALLOUT_PENDING) { |
michael@0 | 90 | if (c == sctp_os_timer_next) { |
michael@0 | 91 | sctp_os_timer_next = TAILQ_NEXT(c, tqe); |
michael@0 | 92 | } |
michael@0 | 93 | TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe); |
michael@0 | 94 | /* |
michael@0 | 95 | * part of the normal "stop a pending callout" process |
michael@0 | 96 | * is to clear the CALLOUT_ACTIVE and CALLOUT_PENDING |
michael@0 | 97 | * flags. We don't bother since we are setting these |
michael@0 | 98 | * below and we still hold the lock. |
michael@0 | 99 | */ |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | /* |
michael@0 | 103 | * We could unlock/splx here and lock/spl at the TAILQ_INSERT_TAIL, |
michael@0 | 104 | * but there's no point since doing this setup doesn't take much time. |
michael@0 | 105 | */ |
michael@0 | 106 | if (to_ticks <= 0) |
michael@0 | 107 | to_ticks = 1; |
michael@0 | 108 | |
michael@0 | 109 | c->c_arg = arg; |
michael@0 | 110 | c->c_flags = (SCTP_CALLOUT_ACTIVE | SCTP_CALLOUT_PENDING); |
michael@0 | 111 | c->c_func = ftn; |
michael@0 | 112 | c->c_time = ticks + to_ticks; |
michael@0 | 113 | TAILQ_INSERT_TAIL(&SCTP_BASE_INFO(callqueue), c, tqe); |
michael@0 | 114 | SCTP_TIMERQ_UNLOCK(); |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | int |
michael@0 | 118 | sctp_os_timer_stop(sctp_os_timer_t *c) |
michael@0 | 119 | { |
michael@0 | 120 | SCTP_TIMERQ_LOCK(); |
michael@0 | 121 | /* |
michael@0 | 122 | * Don't attempt to delete a callout that's not on the queue. |
michael@0 | 123 | */ |
michael@0 | 124 | if (!(c->c_flags & SCTP_CALLOUT_PENDING)) { |
michael@0 | 125 | c->c_flags &= ~SCTP_CALLOUT_ACTIVE; |
michael@0 | 126 | SCTP_TIMERQ_UNLOCK(); |
michael@0 | 127 | return (0); |
michael@0 | 128 | } |
michael@0 | 129 | c->c_flags &= ~(SCTP_CALLOUT_ACTIVE | SCTP_CALLOUT_PENDING); |
michael@0 | 130 | if (c == sctp_os_timer_next) { |
michael@0 | 131 | sctp_os_timer_next = TAILQ_NEXT(c, tqe); |
michael@0 | 132 | } |
michael@0 | 133 | TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe); |
michael@0 | 134 | SCTP_TIMERQ_UNLOCK(); |
michael@0 | 135 | return (1); |
michael@0 | 136 | } |
michael@0 | 137 | |
michael@0 | 138 | static void |
michael@0 | 139 | sctp_handle_tick(int delta) |
michael@0 | 140 | { |
michael@0 | 141 | sctp_os_timer_t *c; |
michael@0 | 142 | void (*c_func)(void *); |
michael@0 | 143 | void *c_arg; |
michael@0 | 144 | |
michael@0 | 145 | SCTP_TIMERQ_LOCK(); |
michael@0 | 146 | /* update our tick count */ |
michael@0 | 147 | ticks += delta; |
michael@0 | 148 | c = TAILQ_FIRST(&SCTP_BASE_INFO(callqueue)); |
michael@0 | 149 | while (c) { |
michael@0 | 150 | if (c->c_time <= ticks) { |
michael@0 | 151 | sctp_os_timer_next = TAILQ_NEXT(c, tqe); |
michael@0 | 152 | TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe); |
michael@0 | 153 | c_func = c->c_func; |
michael@0 | 154 | c_arg = c->c_arg; |
michael@0 | 155 | c->c_flags &= ~SCTP_CALLOUT_PENDING; |
michael@0 | 156 | sctp_os_timer_current = c; |
michael@0 | 157 | SCTP_TIMERQ_UNLOCK(); |
michael@0 | 158 | c_func(c_arg); |
michael@0 | 159 | SCTP_TIMERQ_LOCK(); |
michael@0 | 160 | sctp_os_timer_current = NULL; |
michael@0 | 161 | c = sctp_os_timer_next; |
michael@0 | 162 | } else { |
michael@0 | 163 | c = TAILQ_NEXT(c, tqe); |
michael@0 | 164 | } |
michael@0 | 165 | } |
michael@0 | 166 | sctp_os_timer_next = NULL; |
michael@0 | 167 | SCTP_TIMERQ_UNLOCK(); |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | #if defined(__APPLE__) |
michael@0 | 171 | void |
michael@0 | 172 | sctp_timeout(void *arg SCTP_UNUSED) |
michael@0 | 173 | { |
michael@0 | 174 | sctp_handle_tick(SCTP_BASE_VAR(sctp_main_timer_ticks)); |
michael@0 | 175 | sctp_start_main_timer(); |
michael@0 | 176 | } |
michael@0 | 177 | #endif |
michael@0 | 178 | |
michael@0 | 179 | #if defined(__Userspace__) |
michael@0 | 180 | #define TIMEOUT_INTERVAL 10 |
michael@0 | 181 | |
michael@0 | 182 | void * |
michael@0 | 183 | user_sctp_timer_iterate(void *arg) |
michael@0 | 184 | { |
michael@0 | 185 | for (;;) { |
michael@0 | 186 | #if defined (__Userspace_os_Windows) |
michael@0 | 187 | Sleep(TIMEOUT_INTERVAL); |
michael@0 | 188 | #else |
michael@0 | 189 | struct timeval timeout; |
michael@0 | 190 | |
michael@0 | 191 | timeout.tv_sec = 0; |
michael@0 | 192 | timeout.tv_usec = 1000 * TIMEOUT_INTERVAL; |
michael@0 | 193 | select(0, NULL, NULL, NULL, &timeout); |
michael@0 | 194 | #endif |
michael@0 | 195 | if (SCTP_BASE_VAR(timer_thread_should_exit)) { |
michael@0 | 196 | break; |
michael@0 | 197 | } |
michael@0 | 198 | sctp_handle_tick(MSEC_TO_TICKS(TIMEOUT_INTERVAL)); |
michael@0 | 199 | } |
michael@0 | 200 | return (NULL); |
michael@0 | 201 | } |
michael@0 | 202 | |
michael@0 | 203 | void |
michael@0 | 204 | sctp_start_timer(void) |
michael@0 | 205 | { |
michael@0 | 206 | /* |
michael@0 | 207 | * No need to do SCTP_TIMERQ_LOCK_INIT(); |
michael@0 | 208 | * here, it is being done in sctp_pcb_init() |
michael@0 | 209 | */ |
michael@0 | 210 | #if defined (__Userspace_os_Windows) |
michael@0 | 211 | if ((SCTP_BASE_VAR(timer_thread) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)user_sctp_timer_iterate, NULL, 0, NULL)) == NULL) { |
michael@0 | 212 | SCTP_PRINTF("ERROR; Creating ithread failed\n"); |
michael@0 | 213 | } |
michael@0 | 214 | #else |
michael@0 | 215 | int rc; |
michael@0 | 216 | |
michael@0 | 217 | rc = pthread_create(&SCTP_BASE_VAR(timer_thread), NULL, user_sctp_timer_iterate, NULL); |
michael@0 | 218 | if (rc) { |
michael@0 | 219 | SCTP_PRINTF("ERROR; return code from pthread_create() is %d\n", rc); |
michael@0 | 220 | } |
michael@0 | 221 | #endif |
michael@0 | 222 | } |
michael@0 | 223 | |
michael@0 | 224 | #endif |