/event-compat.c

https://github.com/hyper/stashd · C · 232 lines · 167 code · 50 blank · 15 comment · 48 complexity · b51cbf22c097cc146d4475a47ec642bf MD5 · raw file

  1. #include "event-compat.h"
  2. #include <assert.h>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #if ( _EVENT_NUMERIC_VERSION < 0x02000000 )
  8. // event_new is a 2.0 function that creates a new event, sets it and then returns the pointer to the new event structure. 1.4 does not have that function, so we wrap an event_set here instead.
  9. struct event * event_new(struct event_base *evbase, evutil_socket_t sfd, short flags, void (*fn)(int, short, void *), void *arg) {
  10. struct event *ev;
  11. assert(evbase && sfd >= 0 && flags != 0 && fn);
  12. ev = calloc(1, sizeof(*ev));
  13. assert(ev);
  14. event_set(ev, sfd, flags, fn, arg);
  15. event_base_set(evbase, ev);
  16. return(ev);
  17. }
  18. void event_free(struct event *ev)
  19. {
  20. assert(ev);
  21. event_del(ev);
  22. free(ev);
  23. }
  24. struct event * evsignal_new(struct event_base *evbase, int sig, void (*fn)(int, short, void *), void *arg)
  25. {
  26. struct event *ev;
  27. ev = event_new(evbase, sig, EV_SIGNAL|EV_PERSIST, fn, arg);
  28. assert(ev);
  29. return(ev);
  30. }
  31. struct event * evtimer_new(struct event_base *evbase, void (*fn)(int, short, void *), void *arg)
  32. {
  33. struct event *ev;
  34. assert(evbase && fn);
  35. ev = calloc(1, sizeof(*ev));
  36. assert(ev);
  37. event_set(ev, -1, EV_TIMEOUT, fn, arg);
  38. event_base_set(evbase, ev);
  39. return(ev);
  40. }
  41. // pulled in from libevent 2.0.3 (alpha) to add compatibility for older libevents.
  42. int evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *outlen) {
  43. int port;
  44. char buf[128];
  45. const char *cp, *addr_part, *port_part;
  46. int is_ipv6;
  47. /* recognized formats are:
  48. * [ipv6]:port
  49. * ipv6
  50. * [ipv6]
  51. * ipv4:port
  52. * ipv4
  53. */
  54. cp = strchr(ip_as_string, ':');
  55. if (*ip_as_string == '[') {
  56. int len;
  57. if (!(cp = strchr(ip_as_string, ']'))) { return -1; }
  58. len = cp-(ip_as_string + 1);
  59. if (len > (int)sizeof(buf)-1) { return -1; }
  60. memcpy(buf, ip_as_string+1, len);
  61. buf[len] = '\0';
  62. addr_part = buf;
  63. if (cp[1] == ':') port_part = cp+2;
  64. else port_part = NULL;
  65. is_ipv6 = 1;
  66. } else if (cp && strchr(cp+1, ':')) {
  67. is_ipv6 = 1;
  68. addr_part = ip_as_string;
  69. port_part = NULL;
  70. } else if (cp) {
  71. is_ipv6 = 0;
  72. if (cp - ip_as_string > (int)sizeof(buf)-1) { return -1; }
  73. memcpy(buf, ip_as_string, cp-ip_as_string);
  74. buf[cp-ip_as_string] = '\0';
  75. addr_part = buf;
  76. port_part = cp+1;
  77. } else {
  78. addr_part = ip_as_string;
  79. port_part = NULL;
  80. is_ipv6 = 0;
  81. }
  82. if (port_part == NULL) { port = 0; }
  83. else {
  84. port = atoi(port_part);
  85. if (port <= 0 || port > 65535) { return -1; }
  86. }
  87. if (!addr_part) return -1; /* Should be impossible. */
  88. struct sockaddr_in sin;
  89. memset(&sin, 0, sizeof(sin));
  90. sin.sin_family = AF_INET;
  91. sin.sin_port = htons(port);
  92. if (1 != inet_pton(AF_INET, addr_part, &sin.sin_addr)) return -1;
  93. if (sizeof(sin) > *outlen) return -1;
  94. memset(out, 0, *outlen);
  95. memcpy(out, &sin, sizeof(sin));
  96. *outlen = sizeof(sin);
  97. return 0;
  98. }
  99. // static void accept_conn_cb_old(evutil_socket_t fd, const short flags, void *ctx);
  100. static void evconn_cb(int ls_sfd, short flags, void *arg)
  101. {
  102. struct evconnlistener *listener;
  103. socklen_t addrlen;
  104. struct sockaddr addr;
  105. evutil_socket_t sfd;
  106. assert(ls_sfd >= 0);
  107. assert(flags == EV_READ);
  108. assert(arg);
  109. listener = arg;
  110. assert(listener->handle >= 0);
  111. assert(listener->handle == ls_sfd);
  112. addrlen = sizeof(addr);
  113. if ((sfd = accept(listener->handle, (struct sockaddr *)&addr, &addrlen)) == -1) {
  114. // somehow the accept failed... need to handle it gracefully.
  115. assert(0);
  116. }
  117. else {
  118. // void (*fn)(struct evconnlistener *, int, struct sockaddr *, int, void *ctx)
  119. assert(listener->fn);
  120. assert(listener->arg);
  121. listener->fn(listener, sfd, &addr, addrlen, listener->arg);
  122. }
  123. }
  124. // simulate the listener stuff from libevent2.
  125. // static void accept_conn_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *address, int socklen, void *ctx);
  126. struct evconnlistener * evconnlistener_new_bind(struct event_base *evbase, void (*fn)(struct evconnlistener *, int, struct sockaddr *, int, void *), void *arg, int flags, int queues, struct sockaddr *sin, int slen )
  127. {
  128. struct evconnlistener *listener = NULL;
  129. int sfd;
  130. int error;
  131. int sockflags =1;
  132. struct linger ling = {0, 0};
  133. assert(evbase && fn);
  134. assert(flags == (LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE));
  135. assert(sin && slen > 0);
  136. sfd = socket(AF_INET, SOCK_STREAM, 0);
  137. setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&sockflags, sizeof(sockflags));
  138. error = setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&sockflags, sizeof(sockflags));
  139. assert(error == 0);
  140. error = setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
  141. assert(error == 0);
  142. #ifdef TCP_NODELAY
  143. error = setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&sockflags, sizeof(sockflags));
  144. assert(error == 0);
  145. #endif
  146. if (bind(sfd, sin, slen) == -1) {
  147. close(sfd);
  148. sfd = -1;
  149. assert(listener == NULL);
  150. }
  151. else {
  152. if (listen(sfd, 5) == -1) {
  153. close(sfd);
  154. sfd = -1;
  155. assert(listener == NULL);
  156. }
  157. else {
  158. // we've got a listener.
  159. listener = calloc(1, sizeof(*listener));
  160. assert(listener);
  161. listener->handle = sfd;
  162. listener->listen_event = event_new(evbase, sfd, EV_READ | EV_PERSIST, evconn_cb, (void *)listener);
  163. event_add(listener->listen_event, NULL);
  164. listener->fn = fn;
  165. listener->arg = arg;
  166. }
  167. }
  168. return(listener);
  169. }
  170. void evconnlistener_free(struct evconnlistener * listener)
  171. {
  172. assert(listener);
  173. assert(listener->handle >= 0);
  174. if(listener->handle >= 0) {
  175. assert(listener->listen_event);
  176. event_del(listener->listen_event);
  177. close(listener->handle);
  178. listener->handle = -1;
  179. }
  180. free(listener);
  181. }
  182. #endif