A clone of btpd with my configuration changes.

414 lines
9.5 KiB

  1. /*
  2. * Copyright (c) 2002-2004 Niels Provos <provos@citi.umich.edu>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  18. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  19. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  21. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <sys/types.h>
  28. #ifdef HAVE_CONFIG_H
  29. #include "config.h"
  30. #endif
  31. #ifdef HAVE_SYS_TIME_H
  32. #include <sys/time.h>
  33. #endif
  34. #include <errno.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #ifdef HAVE_STDARG_H
  39. #include <stdarg.h>
  40. #endif
  41. #include "event.h"
  42. /* prototypes */
  43. void bufferevent_setwatermark(struct bufferevent *, short, size_t, size_t);
  44. void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
  45. static int
  46. bufferevent_add(struct event *ev, int timeout)
  47. {
  48. struct timeval tv, *ptv = NULL;
  49. if (timeout) {
  50. timerclear(&tv);
  51. tv.tv_sec = timeout;
  52. ptv = &tv;
  53. }
  54. return (event_add(ev, ptv));
  55. }
  56. /*
  57. * This callback is executed when the size of the input buffer changes.
  58. * We use it to apply back pressure on the reading side.
  59. */
  60. void
  61. bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now,
  62. void *arg) {
  63. struct bufferevent *bufev = arg;
  64. /*
  65. * If we are below the watermark then reschedule reading if it's
  66. * still enabled.
  67. */
  68. if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) {
  69. evbuffer_setcb(buf, NULL, NULL);
  70. if (bufev->enabled & EV_READ)
  71. bufferevent_add(&bufev->ev_read, bufev->timeout_read);
  72. }
  73. }
  74. static void
  75. bufferevent_readcb(int fd, short event, void *arg)
  76. {
  77. struct bufferevent *bufev = arg;
  78. int res = 0;
  79. short what = EVBUFFER_READ;
  80. size_t len;
  81. int howmuch = -1;
  82. if (event == EV_TIMEOUT) {
  83. what |= EVBUFFER_TIMEOUT;
  84. goto error;
  85. }
  86. /*
  87. * If we have a high watermark configured then we don't want to
  88. * read more data than would make us reach the watermark.
  89. */
  90. if (bufev->wm_read.high != 0)
  91. howmuch = bufev->wm_read.high;
  92. res = evbuffer_read(bufev->input, fd, howmuch);
  93. if (res == -1) {
  94. if (errno == EAGAIN || errno == EINTR)
  95. goto reschedule;
  96. /* error case */
  97. what |= EVBUFFER_ERROR;
  98. } else if (res == 0) {
  99. /* eof case */
  100. what |= EVBUFFER_EOF;
  101. }
  102. if (res <= 0)
  103. goto error;
  104. bufferevent_add(&bufev->ev_read, bufev->timeout_read);
  105. /* See if this callbacks meets the water marks */
  106. len = EVBUFFER_LENGTH(bufev->input);
  107. if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
  108. return;
  109. if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
  110. struct evbuffer *buf = bufev->input;
  111. event_del(&bufev->ev_read);
  112. /* Now schedule a callback for us */
  113. evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
  114. return;
  115. }
  116. /* Invoke the user callback - must always be called last */
  117. if (bufev->readcb != NULL)
  118. (*bufev->readcb)(bufev, bufev->cbarg);
  119. return;
  120. reschedule:
  121. bufferevent_add(&bufev->ev_read, bufev->timeout_read);
  122. return;
  123. error:
  124. (*bufev->errorcb)(bufev, what, bufev->cbarg);
  125. }
  126. static void
  127. bufferevent_writecb(int fd, short event, void *arg)
  128. {
  129. struct bufferevent *bufev = arg;
  130. int res = 0;
  131. short what = EVBUFFER_WRITE;
  132. if (event == EV_TIMEOUT) {
  133. what |= EVBUFFER_TIMEOUT;
  134. goto error;
  135. }
  136. if (EVBUFFER_LENGTH(bufev->output)) {
  137. res = evbuffer_write(bufev->output, fd);
  138. if (res == -1) {
  139. #ifndef WIN32
  140. /*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
  141. *set errno. thus this error checking is not portable*/
  142. if (errno == EAGAIN ||
  143. errno == EINTR ||
  144. errno == EINPROGRESS)
  145. goto reschedule;
  146. /* error case */
  147. what |= EVBUFFER_ERROR;
  148. #else
  149. goto reschedule;
  150. #endif
  151. } else if (res == 0) {
  152. /* eof case */
  153. what |= EVBUFFER_EOF;
  154. }
  155. if (res <= 0)
  156. goto error;
  157. }
  158. if (EVBUFFER_LENGTH(bufev->output) != 0)
  159. bufferevent_add(&bufev->ev_write, bufev->timeout_write);
  160. /*
  161. * Invoke the user callback if our buffer is drained or below the
  162. * low watermark.
  163. */
  164. if (bufev->writecb != NULL &&
  165. EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
  166. (*bufev->writecb)(bufev, bufev->cbarg);
  167. return;
  168. reschedule:
  169. if (EVBUFFER_LENGTH(bufev->output) != 0)
  170. bufferevent_add(&bufev->ev_write, bufev->timeout_write);
  171. return;
  172. error:
  173. (*bufev->errorcb)(bufev, what, bufev->cbarg);
  174. }
  175. /*
  176. * Create a new buffered event object.
  177. *
  178. * The read callback is invoked whenever we read new data.
  179. * The write callback is invoked whenever the output buffer is drained.
  180. * The error callback is invoked on a write/read error or on EOF.
  181. *
  182. * Both read and write callbacks maybe NULL. The error callback is not
  183. * allowed to be NULL and have to be provided always.
  184. */
  185. struct bufferevent *
  186. bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb,
  187. everrorcb errorcb, void *cbarg)
  188. {
  189. struct bufferevent *bufev;
  190. if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL)
  191. return (NULL);
  192. if ((bufev->input = evbuffer_new()) == NULL) {
  193. free(bufev);
  194. return (NULL);
  195. }
  196. if ((bufev->output = evbuffer_new()) == NULL) {
  197. evbuffer_free(bufev->input);
  198. free(bufev);
  199. return (NULL);
  200. }
  201. event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev);
  202. event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev);
  203. bufev->readcb = readcb;
  204. bufev->writecb = writecb;
  205. bufev->errorcb = errorcb;
  206. bufev->cbarg = cbarg;
  207. /*
  208. * Set to EV_WRITE so that using bufferevent_write is going to
  209. * trigger a callback. Reading needs to be explicitly enabled
  210. * because otherwise no data will be available.
  211. */
  212. bufev->enabled = EV_WRITE;
  213. return (bufev);
  214. }
  215. int
  216. bufferevent_priority_set(struct bufferevent *bufev, int priority)
  217. {
  218. if (event_priority_set(&bufev->ev_read, priority) == -1)
  219. return (-1);
  220. if (event_priority_set(&bufev->ev_write, priority) == -1)
  221. return (-1);
  222. return (0);
  223. }
  224. /* Closing the file descriptor is the responsibility of the caller */
  225. void
  226. bufferevent_free(struct bufferevent *bufev)
  227. {
  228. event_del(&bufev->ev_read);
  229. event_del(&bufev->ev_write);
  230. evbuffer_free(bufev->input);
  231. evbuffer_free(bufev->output);
  232. free(bufev);
  233. }
  234. /*
  235. * Returns 0 on success;
  236. * -1 on failure.
  237. */
  238. int
  239. bufferevent_write(struct bufferevent *bufev, void *data, size_t size)
  240. {
  241. int res;
  242. res = evbuffer_add(bufev->output, data, size);
  243. if (res == -1)
  244. return (res);
  245. /* If everything is okay, we need to schedule a write */
  246. if (size > 0 && (bufev->enabled & EV_WRITE))
  247. bufferevent_add(&bufev->ev_write, bufev->timeout_write);
  248. return (res);
  249. }
  250. int
  251. bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
  252. {
  253. int res;
  254. res = bufferevent_write(bufev, buf->buffer, buf->off);
  255. if (res != -1)
  256. evbuffer_drain(buf, buf->off);
  257. return (res);
  258. }
  259. size_t
  260. bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
  261. {
  262. struct evbuffer *buf = bufev->input;
  263. if (buf->off < size)
  264. size = buf->off;
  265. /* Copy the available data to the user buffer */
  266. memcpy(data, buf->buffer, size);
  267. if (size)
  268. evbuffer_drain(buf, size);
  269. return (size);
  270. }
  271. int
  272. bufferevent_enable(struct bufferevent *bufev, short event)
  273. {
  274. if (event & EV_READ) {
  275. if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1)
  276. return (-1);
  277. }
  278. if (event & EV_WRITE) {
  279. if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1)
  280. return (-1);
  281. }
  282. bufev->enabled |= event;
  283. return (0);
  284. }
  285. int
  286. bufferevent_disable(struct bufferevent *bufev, short event)
  287. {
  288. if (event & EV_READ) {
  289. if (event_del(&bufev->ev_read) == -1)
  290. return (-1);
  291. }
  292. if (event & EV_WRITE) {
  293. if (event_del(&bufev->ev_write) == -1)
  294. return (-1);
  295. }
  296. bufev->enabled &= ~event;
  297. return (0);
  298. }
  299. /*
  300. * Sets the read and write timeout for a buffered event.
  301. */
  302. void
  303. bufferevent_settimeout(struct bufferevent *bufev,
  304. int timeout_read, int timeout_write) {
  305. bufev->timeout_read = timeout_read;
  306. bufev->timeout_write = timeout_write;
  307. }
  308. /*
  309. * Sets the water marks
  310. */
  311. void
  312. bufferevent_setwatermark(struct bufferevent *bufev, short events,
  313. size_t lowmark, size_t highmark)
  314. {
  315. if (events & EV_READ) {
  316. bufev->wm_read.low = lowmark;
  317. bufev->wm_read.high = highmark;
  318. }
  319. if (events & EV_WRITE) {
  320. bufev->wm_write.low = lowmark;
  321. bufev->wm_write.high = highmark;
  322. }
  323. /* If the watermarks changed then see if we should call read again */
  324. bufferevent_read_pressure_cb(bufev->input,
  325. 0, EVBUFFER_LENGTH(bufev->input), bufev);
  326. }
  327. int
  328. bufferevent_base_set(struct event_base *base, struct bufferevent *bufev)
  329. {
  330. int res;
  331. res = event_base_set(base, &bufev->ev_read);
  332. if (res == -1)
  333. return (res);
  334. res = event_base_set(base, &bufev->ev_write);
  335. return (res);
  336. }