evutils.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. extern "C" {
  2. #include <event2/listener.h>
  3. #include <event2/bufferevent.h>
  4. }
  5. #include "evutils.h"
  6. #include <string.h>
  7. #include <netdb.h>
  8. #include <unistd.h>
  9. unsigned int hostlookup(const char *hostname)
  10. {
  11. struct hostent *he = gethostbyname(hostname);
  12. if (!he) {
  13. // Could not resolve hostname
  14. return 0;
  15. }
  16. struct in_addr *addr = (struct in_addr*)(he->h_addr_list[0]);
  17. return addr->s_addr;
  18. }
  19. static unsigned int getlocalIP(void)
  20. {
  21. char hostname[257];
  22. if (gethostname(hostname, 256)) {
  23. // Could not determine hostname
  24. return 0;
  25. }
  26. hostname[256] = '\0';
  27. return hostlookup(hostname);
  28. }
  29. // Create a new listener socket. bindport is the port to bind to (in
  30. // host byte order), or 0 if any port will do. ip and boundport are set
  31. // to the IP and port of the socket, in network byte order.
  32. struct evconnlistener *listener_create(struct event_base *evbase,
  33. unsigned short bindport, evconnlistener_cb cb, void *ctx,
  34. unsigned int *ip, unsigned short *boundport, bool multithread)
  35. {
  36. struct sockaddr_in sin;
  37. sin.sin_family = AF_INET;
  38. sin.sin_addr.s_addr = htonl(0);
  39. sin.sin_port = htons(bindport);
  40. if (ip) {
  41. *ip = getlocalIP();
  42. if (*ip == 0) {
  43. perror("Determining local IP");
  44. return NULL;
  45. }
  46. }
  47. struct evconnlistener *listener = evconnlistener_new_bind(evbase,
  48. cb, ctx, LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE|
  49. (multithread ? LEV_OPT_THREADSAFE : 0),
  50. -1, (struct sockaddr*)&sin, sizeof(sin));
  51. if (!listener) {
  52. perror("Unable to create listener");
  53. return NULL;
  54. }
  55. int localfd = evconnlistener_get_fd(listener);
  56. if (boundport) {
  57. socklen_t addrsize = sizeof(sin);
  58. if (getsockname(localfd, (struct sockaddr*)&sin, &addrsize)) {
  59. perror("Unable to learn local port");
  60. return NULL;
  61. }
  62. *boundport = sin.sin_port;
  63. }
  64. return listener;
  65. }
  66. // Create a client connection to the given 6-byte ipport (4 byte IP, 2
  67. // byte port in network byte order).
  68. struct bufferevent *client_create(struct event_base *evbase,
  69. unsigned char ipport[6], bufferevent_event_cb event_handler,
  70. bool multithread)
  71. {
  72. // Create a Controller client socket
  73. struct sockaddr_in client_sin;
  74. client_sin.sin_family = AF_INET;
  75. memmove(&client_sin.sin_addr.s_addr, ipport, 4);
  76. memmove(&client_sin.sin_port, ipport+4, 2);
  77. struct bufferevent *client_bev = bufferevent_socket_new(evbase,
  78. -1, BEV_OPT_CLOSE_ON_FREE |
  79. (multithread ? BEV_OPT_DEFER_CALLBACKS|BEV_OPT_UNLOCK_CALLBACKS|
  80. BEV_OPT_THREADSAFE : 0));
  81. if (bufferevent_socket_connect(client_bev,
  82. (struct sockaddr *)&client_sin, sizeof(client_sin)) < 0) {
  83. bufferevent_free(client_bev);
  84. fprintf(stderr, "Unable to connect to server\n");
  85. return NULL;
  86. }
  87. bufferevent_setcb(client_bev, NULL, NULL, event_handler, NULL);
  88. return client_bev;
  89. }
  90. // Create a client connection to a controller, with event_handler set as
  91. // the event callback. It will be called when the connection succeeds or
  92. // fails. This function calls the libevent main loop, so it will only return
  93. // when the program is finished.
  94. int controller_client(const char *controller_host,
  95. unsigned short controller_port, bufferevent_event_cb event_handler,
  96. bool multithread)
  97. {
  98. struct event_base *evbase = event_base_new();
  99. // Create a Controller client socket
  100. struct sockaddr_in controller_sin;
  101. controller_sin.sin_family = AF_INET;
  102. controller_sin.sin_addr.s_addr = hostlookup(controller_host);
  103. if (controller_sin.sin_addr.s_addr == 0) {
  104. fprintf(stderr, "Unknown host %s\n", controller_host);
  105. return 1;
  106. }
  107. controller_sin.sin_port = htons(controller_port);
  108. struct bufferevent *controller_bev = bufferevent_socket_new(evbase,
  109. -1, BEV_OPT_CLOSE_ON_FREE|(multithread ? BEV_OPT_THREADSAFE : 0));
  110. if (bufferevent_socket_connect(controller_bev,
  111. (struct sockaddr *)&controller_sin, sizeof(controller_sin)) < 0) {
  112. bufferevent_free(controller_bev);
  113. fprintf(stderr, "Unable to connect to controller\n");
  114. return 1;
  115. }
  116. bufferevent_setcb(controller_bev, NULL, NULL, event_handler, NULL);
  117. event_base_dispatch(evbase);
  118. return 0;
  119. }