buffer.c
上传用户:jnmzc84
上传日期:2022-08-08
资源大小:35k
文件大小:10k
源码类别:

网络编程

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2002, 2003 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. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30. #ifdef WIN32
  31. #include <winsock2.h>
  32. #include <windows.h>
  33. #endif
  34. #ifdef HAVE_VASPRINTF
  35. /* If we have vasprintf, we need to define this before we include stdio.h. */
  36. #define _GNU_SOURCE
  37. #endif
  38. #include <sys/types.h>
  39. #ifdef HAVE_SYS_TIME_H
  40. #include <sys/time.h>
  41. #endif
  42. #ifdef HAVE_SYS_IOCTL_H
  43. #include <sys/ioctl.h>
  44. #endif
  45. #include <assert.h>
  46. #include <errno.h>
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #ifdef HAVE_STDARG_H
  51. #include <stdarg.h>
  52. #endif
  53. #ifdef HAVE_UNISTD_H
  54. #include <unistd.h>
  55. #endif
  56. #include "evbuffer.h"
  57. struct evbuffer *
  58. evbuffer_new(void)
  59. {
  60. struct evbuffer *buffer;
  61. buffer = calloc(1, sizeof(struct evbuffer));
  62. return (buffer);
  63. }
  64. void
  65. evbuffer_free(struct evbuffer *buffer)
  66. {
  67. if (buffer->orig_buffer != NULL)
  68. free(buffer->orig_buffer);
  69. free(buffer);
  70. }
  71. /* 
  72.  * This is a destructive add.  The data from one buffer moves into
  73.  * the other buffer.
  74.  */
  75. #define SWAP(x,y) do { 
  76. (x)->buffer = (y)->buffer; 
  77. (x)->orig_buffer = (y)->orig_buffer; 
  78. (x)->misalign = (y)->misalign; 
  79. (x)->totallen = (y)->totallen; 
  80. (x)->off = (y)->off; 
  81. } while (0)
  82. int
  83. evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
  84. {
  85. int res;
  86. /* Short cut for better performance */
  87. if (outbuf->off == 0) {
  88. struct evbuffer tmp;
  89. size_t oldoff = inbuf->off;
  90. /* Swap them directly */
  91. SWAP(&tmp, outbuf);
  92. SWAP(outbuf, inbuf);
  93. SWAP(inbuf, &tmp);
  94. /* 
  95.  * Optimization comes with a price; we need to notify the
  96.  * buffer if necessary of the changes. oldoff is the amount
  97.  * of data that we transfered from inbuf to outbuf
  98.  */
  99. if (inbuf->off != oldoff && inbuf->cb != NULL)
  100. (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
  101. if (oldoff && outbuf->cb != NULL)
  102. (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
  103. return (0);
  104. }
  105. res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
  106. if (res == 0) {
  107. /* We drain the input buffer on success */
  108. evbuffer_drain(inbuf, inbuf->off);
  109. }
  110. return (res);
  111. }
  112. int
  113. evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
  114. {
  115. char *buffer;
  116. size_t space;
  117. size_t oldoff = buf->off;
  118. int sz;
  119. va_list aq;
  120. /* make sure that at least some space is available */
  121. evbuffer_expand(buf, 64);
  122. for (;;) {
  123. size_t used = buf->misalign + buf->off;
  124. buffer = (char *)buf->buffer + buf->off;
  125. assert(buf->totallen >= used);
  126. space = buf->totallen - used;
  127. #ifndef va_copy
  128. #define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list))
  129. #endif
  130. va_copy(aq, ap);
  131. #ifdef WIN32
  132. sz = vsnprintf(buffer, space - 1, fmt, aq);
  133. buffer[space - 1] = '';
  134. #else
  135. sz = vsnprintf(buffer, space, fmt, aq);
  136. #endif
  137. va_end(aq);
  138. if (sz < 0)
  139. return (-1);
  140. if (sz < space) {
  141. buf->off += sz;
  142. if (buf->cb != NULL)
  143. (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
  144. return (sz);
  145. }
  146. if (evbuffer_expand(buf, sz + 1) == -1)
  147. return (-1);
  148. }
  149. /* NOTREACHED */
  150. }
  151. int
  152. evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
  153. {
  154. int res = -1;
  155. va_list ap;
  156. va_start(ap, fmt);
  157. res = evbuffer_add_vprintf(buf, fmt, ap);
  158. va_end(ap);
  159. return (res);
  160. }
  161. /* Reads data from an event buffer and drains the bytes read */
  162. int
  163. evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
  164. {
  165. size_t nread = datlen;
  166. if (nread >= buf->off)
  167. nread = buf->off;
  168. memcpy(data, buf->buffer, nread);
  169. evbuffer_drain(buf, nread);
  170. return (nread);
  171. }
  172. /*
  173.  * Reads a line terminated by either 'rn', 'nr' or 'r' or 'n'.
  174.  * The returned buffer needs to be freed by the called.
  175.  */
  176. char *
  177. evbuffer_readline(struct evbuffer *buffer)
  178. {
  179. u_char *data = EVBUFFER_DATA(buffer);
  180. size_t len = EVBUFFER_LENGTH(buffer);
  181. char *line;
  182. unsigned int i;
  183. for (i = 0; i < len; i++) {
  184. if (data[i] == 'r' || data[i] == 'n')
  185. break;
  186. }
  187. if (i == len)
  188. return (NULL);
  189. if ((line = malloc(i + 1)) == NULL) {
  190. fprintf(stderr, "%s: out of memoryn", __func__);
  191. evbuffer_drain(buffer, i);
  192. return (NULL);
  193. }
  194. memcpy(line, data, i);
  195. line[i] = '';
  196. /*
  197.  * Some protocols terminate a line with 'rn', so check for
  198.  * that, too.
  199.  */
  200. if ( i < len - 1 ) {
  201. char fch = data[i], sch = data[i+1];
  202. /* Drain one more character if needed */
  203. if ( (sch == 'r' || sch == 'n') && sch != fch )
  204. i += 1;
  205. }
  206. evbuffer_drain(buffer, i + 1);
  207. return (line);
  208. }
  209. /* Adds data to an event buffer */
  210. static void
  211. evbuffer_align(struct evbuffer *buf)
  212. {
  213. memmove(buf->orig_buffer, buf->buffer, buf->off);
  214. buf->buffer = buf->orig_buffer;
  215. buf->misalign = 0;
  216. }
  217. /* Expands the available space in the event buffer to at least datlen */
  218. int
  219. evbuffer_expand(struct evbuffer *buf, size_t datlen)
  220. {
  221. size_t need = buf->misalign + buf->off + datlen;
  222. /* If we can fit all the data, then we don't have to do anything */
  223. if (buf->totallen >= need)
  224. return (0);
  225. /*
  226.  * If the misalignment fulfills our data needs, we just force an
  227.  * alignment to happen.  Afterwards, we have enough space.
  228.  */
  229. if (buf->misalign >= datlen) {
  230. evbuffer_align(buf);
  231. } else {
  232. void *newbuf;
  233. size_t length = buf->totallen;
  234. if (length < 256)
  235. length = 256;
  236. while (length < need)
  237. length <<= 1;
  238. if (buf->orig_buffer != buf->buffer)
  239. evbuffer_align(buf);
  240. if ((newbuf = realloc(buf->buffer, length)) == NULL)
  241. return (-1);
  242. buf->orig_buffer = buf->buffer = newbuf;
  243. buf->totallen = length;
  244. }
  245. return (0);
  246. }
  247. int
  248. evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)
  249. {
  250. size_t need = buf->misalign + buf->off + datlen;
  251. size_t oldoff = buf->off;
  252. if (buf->totallen < need) {
  253. if (evbuffer_expand(buf, datlen) == -1)
  254. return (-1);
  255. }
  256. memcpy(buf->buffer + buf->off, data, datlen);
  257. buf->off += datlen;
  258. if (datlen && buf->cb != NULL)
  259. (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
  260. return (0);
  261. }
  262. void
  263. evbuffer_drain(struct evbuffer *buf, size_t len)
  264. {
  265. size_t oldoff = buf->off;
  266. if (len >= buf->off) {
  267. buf->off = 0;
  268. buf->buffer = buf->orig_buffer;
  269. buf->misalign = 0;
  270. goto done;
  271. }
  272. buf->buffer += len;
  273. buf->misalign += len;
  274. buf->off -= len;
  275.  done:
  276. /* Tell someone about changes in this buffer */
  277. if (buf->off != oldoff && buf->cb != NULL)
  278. (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
  279. }
  280. /*
  281.  * Reads data from a file descriptor into a buffer.
  282.  */
  283. #define EVBUFFER_MAX_READ 4096
  284. int
  285. evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
  286. {
  287. u_char *p;
  288. size_t oldoff = buf->off;
  289. int n = EVBUFFER_MAX_READ;
  290. #if defined(FIONREAD)
  291. #ifdef WIN32
  292. long lng = n;
  293. if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) == 0) {
  294. #else
  295. if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) {
  296. #endif
  297. n = EVBUFFER_MAX_READ;
  298. } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
  299. /*
  300.  * It's possible that a lot of data is available for
  301.  * reading.  We do not want to exhaust resources
  302.  * before the reader has a chance to do something
  303.  * about it.  If the reader does not tell us how much
  304.  * data we should read, we artifically limit it.
  305.  */
  306. if (n > buf->totallen << 2)
  307. n = buf->totallen << 2;
  308. if (n < EVBUFFER_MAX_READ)
  309. n = EVBUFFER_MAX_READ;
  310. }
  311. #endif
  312. if (howmuch < 0 || howmuch > n)
  313. howmuch = n;
  314. /* If we don't have FIONREAD, we might waste some space here */
  315. if (evbuffer_expand(buf, howmuch) == -1)
  316. return (-1);
  317. /* We can append new data at this point */
  318. p = buf->buffer + buf->off;
  319. #ifndef WIN32
  320. n = read(fd, p, howmuch);
  321. #else
  322. n = recv(fd, p, howmuch, 0);
  323. #endif
  324. if (n == -1)
  325. return (-1);
  326. if (n == 0)
  327. return (0);
  328. buf->off += n;
  329. /* Tell someone about changes in this buffer */
  330. if (buf->off != oldoff && buf->cb != NULL)
  331. (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
  332. return (n);
  333. }
  334. int
  335. evbuffer_write(struct evbuffer *buffer, int fd)
  336. {
  337. int n;
  338. #ifndef WIN32
  339. n = write(fd, buffer->buffer, buffer->off);
  340. #else
  341. n = send(fd, buffer->buffer, buffer->off, 0);
  342. #endif
  343. if (n == -1)
  344. return (-1);
  345. if (n == 0)
  346. return (0);
  347. evbuffer_drain(buffer, n);
  348. return (n);
  349. }
  350. u_char *
  351. evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
  352. {
  353. u_char *search = buffer->buffer, *end = search + buffer->off;
  354. u_char *p;
  355. while (search < end &&
  356.     (p = memchr(search, *what, end - search)) != NULL) {
  357. if (p + len > end)
  358. break;
  359. if (memcmp(p, what, len) == 0)
  360. return (p);
  361. search = p + 1;
  362. }
  363. return (NULL);
  364. }
  365. void evbuffer_setcb(struct evbuffer *buffer,
  366.     void (*cb)(struct evbuffer *, size_t, size_t, void *),
  367.     void *cbarg)
  368. {
  369. buffer->cb = cb;
  370. buffer->cbarg = cbarg;
  371. }