client.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /**
  2. * This file client.c, handles clients of the WOE server.
  3. */
  4. #define _POSIX_C_SOURCE 200801L
  5. #define _POSIX_SOURCE 200801L
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <netdb.h>
  10. #include <poll.h>
  11. #include <unistd.h>
  12. #include <errno.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <ctype.h>
  17. #include "libtelnet.h"
  18. #include "monolog.h"
  19. #include "rh.h"
  20. #include "client.h"
  21. #include "server.h"
  22. struct woe_client * woe_client_alloc() {
  23. return calloc(sizeof(struct woe_client), 1);
  24. }
  25. struct woe_client * woe_client_init(struct woe_client * client,
  26. struct woe_server * server, int index, int socket,
  27. struct sockaddr_in *addr, socklen_t addrlen) {
  28. if (!client) return NULL;
  29. client->server = server;
  30. client->sock = socket;
  31. client->addr = *addr;
  32. client->addrlen = addrlen;
  33. client->busy = !0;
  34. return client;
  35. }
  36. struct woe_client * woe_client_new(struct woe_server * server, int index, int socket,
  37. struct sockaddr_in *addr, socklen_t addrlen) {
  38. struct woe_client * client = woe_client_alloc();
  39. return woe_client_init(client, server, index, socket, addr, addrlen);
  40. }
  41. struct woe_client * woe_client_done(struct woe_client * client) {
  42. /* Do nothing yet, refactor later. */
  43. if (!client) return NULL;
  44. if (client->telnet) telnet_free(client->telnet);
  45. client->sock = -1;
  46. client->telnet = NULL;
  47. LOG_NOTE("Connection to client %d closed.\n", client->index);
  48. client->index = -1;
  49. return client;
  50. }
  51. struct woe_client * woe_client_free(struct woe_client * client) {
  52. woe_client_done(client);
  53. free(client);
  54. return NULL;
  55. }
  56. int woe_client_send(struct woe_client * client, const char *buffer, unsigned int size) {
  57. int res;
  58. if (!client) return 1;
  59. /* ignore on invalid socket */
  60. if (client->sock < 0) return 2;
  61. /* send data */
  62. while (size > 0) {
  63. if ((res = send(client->sock, buffer, size, 0)) == -1) {
  64. if (errno != EINTR && errno != ECONNRESET) {
  65. LOG_ERROR("send() failed: %s\n", strerror(errno));
  66. return 3;
  67. } else {
  68. return 0;
  69. }
  70. } else if (res == 0) {
  71. LOG_ERROR("send() unexpectedly returned 0\n");
  72. return 4;
  73. }
  74. /* Update pointer and size to see if we've got more to send */
  75. buffer += res;
  76. size -= res;
  77. }
  78. return 0;
  79. }
  80. int woe_client_input(struct woe_client * cli, const char *buffer, size_t size) {
  81. mrb_state * mrb;
  82. LOG_NOTE("Received input for client %d\n", cli->index);
  83. mrb = woe_server_get_mrb(cli->server);
  84. if (mrb) {
  85. rh_run_toplevel(mrb, "woe_on_input", "is", cli->index, buffer, size);
  86. }
  87. return 0;
  88. }
  89. int woe_client_zmp(struct woe_client * cli, int argc, const char *argv[]) {
  90. unsigned int i;
  91. mrb_state * mrb;
  92. LOG_NOTE("Received ZMP reply for client %d\n", cli->index);
  93. mrb = woe_server_get_mrb(cli->server);
  94. if (mrb) {
  95. rh_run_toplevel(mrb, "woe_begin_zmp", "ii", cli->index, argc);
  96. for (i=0; i < argc; i++) {
  97. rh_run_toplevel(mrb, "woe_zmp_arg", "iiz", cli->index, i, argv[i]);
  98. }
  99. rh_run_toplevel(mrb, "woe_finish_zmp", "ii", cli->index, argc);
  100. }
  101. return 0;
  102. }
  103. int woe_client_iac(struct woe_client * cli, int cmd) {
  104. mrb_state * mrb;
  105. LOG_NOTE("Received iac for client %d %d\n", cli->index, cmd);
  106. mrb = woe_server_get_mrb(cli->server);
  107. if (mrb) {
  108. rh_run_toplevel(mrb, "woe_on_iac", "i", cli->index, cmd);
  109. }
  110. return 0;
  111. }
  112. int woe_client_negotiate(struct woe_client * cli, int how, int option) {
  113. mrb_state * mrb;
  114. LOG_NOTE("Received negotiate for client %d %d %d\n", cli->index, how, option);
  115. mrb = woe_server_get_mrb(cli->server);
  116. if (mrb) {
  117. rh_run_toplevel(mrb, "woe_on_negotiate", "iii", cli->index, how, option);
  118. }
  119. return 0;
  120. }
  121. int woe_client_subnegotiate(struct woe_client * cli, const char * buf, int len, int telopt) {
  122. mrb_state * mrb;
  123. LOG_NOTE("Received subnegotiate for client %d\n", cli->index);
  124. mrb = woe_server_get_mrb(cli->server);
  125. if (mrb) {
  126. rh_run_toplevel(mrb, "woe_on_subnegotiate", "iis", cli->index, telopt, buf, len);
  127. }
  128. return 0;
  129. }
  130. int woe_client_ttype(struct woe_client * cli, int cmd, const char * name) {
  131. mrb_state * mrb;
  132. LOG_NOTE("Received ttype for client %d %d %s\n", cli->index, cmd, name);
  133. mrb = woe_server_get_mrb(cli->server);
  134. if (mrb) {
  135. rh_run_toplevel(mrb, "woe_on_ttype", "iz", cli->index, cmd, name);
  136. }
  137. return 0;
  138. }
  139. int woe_client_error(struct woe_client * cli, int code, const char * msg) {
  140. mrb_state * mrb;
  141. LOG_NOTE("Received error for client %d %d %s\n", cli->index, code, msg);
  142. mrb = woe_server_get_mrb(cli->server);
  143. if (mrb) {
  144. rh_run_toplevel(mrb, "woe_on_error", "iz\n", cli->index, code, msg);
  145. }
  146. return 0;
  147. }
  148. int woe_client_warning(struct woe_client * cli, int code, const char * msg) {
  149. mrb_state * mrb;
  150. LOG_NOTE("Received warning for client %d %d %s\n", cli->index, code, msg);
  151. mrb = woe_server_get_mrb(cli->server);
  152. if (mrb) {
  153. rh_run_toplevel(mrb, "woe_on_warning", "iz", cli->index, code, msg);
  154. }
  155. return 0;
  156. }
  157. int woe_client_compress(struct woe_client * cli, int state) {
  158. mrb_state * mrb;
  159. LOG_NOTE("Received compress for client %d %d\n", cli->index, state);
  160. mrb = woe_server_get_mrb(cli->server);
  161. if (mrb) {
  162. rh_run_toplevel(mrb, "woe_on_compress", "ii", cli->index, state);
  163. }
  164. return 0;
  165. }
  166. int woe_client_environ(struct woe_client * cli, int cmd, const struct telnet_environ_t *values, size_t size) {
  167. int i;
  168. mrb_state * mrb;
  169. LOG_NOTE("Received environ for client %d %d\n", cli->index, cmd);
  170. mrb = woe_server_get_mrb(cli->server);
  171. if (mrb) {
  172. rh_run_toplevel(mrb, "woe_begin_environ", "iii", cli->index, cmd, size);
  173. for (i=0; i < size; i++) {
  174. rh_run_toplevel(mrb, "woe_environ_arg", "iiizz", cli->index, i, values[i].type, values[i].var, values[i].value);
  175. }
  176. rh_run_toplevel(mrb, "woe_finish_environ", "iii", cli->index, cmd, size);
  177. }
  178. return 0;
  179. }
  180. int woe_client_mssp(struct woe_client * cli, const struct telnet_environ_t *values, size_t size) {
  181. int i;
  182. mrb_state * mrb;
  183. LOG_NOTE("Received mssp for client %d\n", cli->index);
  184. mrb = woe_server_get_mrb(cli->server);
  185. if (mrb) {
  186. rh_run_toplevel(mrb, "woe_begin_mssp", "ii", cli->index, size);
  187. for (i=0; i < size; i++) {
  188. rh_run_toplevel(mrb, "woe_mssp_arg", "iiizz", cli->index, i, values[i].type, values[i].var, values[i].value);
  189. }
  190. rh_run_toplevel(mrb, "woe_finish_mssp", "iii", cli->index, size);
  191. }
  192. return 0;
  193. }