evutils.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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)
  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, -1,
  49. (struct sockaddr*)&sin, sizeof(sin));
  50. if (!listener) {
  51. perror("Unable to create listener");
  52. return NULL;
  53. }
  54. int localfd = evconnlistener_get_fd(listener);
  55. if (boundport) {
  56. socklen_t addrsize = sizeof(sin);
  57. if (getsockname(localfd, (struct sockaddr*)&sin, &addrsize)) {
  58. perror("Unable to learn local port");
  59. return NULL;
  60. }
  61. *boundport = sin.sin_port;
  62. }
  63. return listener;
  64. }
  65. // Create a client connection to the given 6-byte ipport (4 byte IP, 2
  66. // byte port in network byte order).
  67. struct bufferevent *client_create(struct event_base *evbase,
  68. unsigned char ipport[6], bufferevent_event_cb event_handler)
  69. {
  70. // Create a Controller client socket
  71. struct sockaddr_in client_sin;
  72. client_sin.sin_family = AF_INET;
  73. memmove(&client_sin.sin_addr.s_addr, ipport, 4);
  74. memmove(&client_sin.sin_port, ipport+4, 2);
  75. struct bufferevent *client_bev = bufferevent_socket_new(evbase,
  76. -1, BEV_OPT_CLOSE_ON_FREE);
  77. if (bufferevent_socket_connect(client_bev,
  78. (struct sockaddr *)&client_sin, sizeof(client_sin)) < 0) {
  79. bufferevent_free(client_bev);
  80. fprintf(stderr, "Unable to connect to server\n");
  81. return NULL;
  82. }
  83. bufferevent_setcb(client_bev, NULL, NULL, event_handler, NULL);
  84. return client_bev;
  85. }
  86. // Create a client connection to a controller, with event_handler set as
  87. // the event callback. It will be called when the connection succeeds or
  88. // fails. This function calls the libevent main loop, so it will only return
  89. // when the program is finished.
  90. int controller_client(const char *controller_host,
  91. unsigned short controller_port, bufferevent_event_cb event_handler)
  92. {
  93. struct event_base *evbase = event_base_new();
  94. // Create a Controller client socket
  95. struct sockaddr_in controller_sin;
  96. controller_sin.sin_family = AF_INET;
  97. controller_sin.sin_addr.s_addr = hostlookup(controller_host);
  98. if (controller_sin.sin_addr.s_addr == 0) {
  99. fprintf(stderr, "Unknown host %s\n", controller_host);
  100. return 1;
  101. }
  102. controller_sin.sin_port = htons(controller_port);
  103. struct bufferevent *controller_bev = bufferevent_socket_new(evbase,
  104. -1, BEV_OPT_CLOSE_ON_FREE);
  105. if (bufferevent_socket_connect(controller_bev,
  106. (struct sockaddr *)&controller_sin, sizeof(controller_sin)) < 0) {
  107. bufferevent_free(controller_bev);
  108. fprintf(stderr, "Unable to connect to controller\n");
  109. return 1;
  110. }
  111. bufferevent_setcb(controller_bev, NULL, NULL, event_handler, NULL);
  112. event_base_dispatch(evbase);
  113. return 0;
  114. }