server.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. # if !defined(_POSIX_SOURCE)
  2. # define _POSIX_SOURCE
  3. # endif
  4. # if !defined(_BSD_SOURCE)
  5. # define _BSD_SOURCE
  6. # endif
  7. # include <sys/socket.h>
  8. # include <netinet/in.h>
  9. # include <arpa/inet.h>
  10. # include <netdb.h>
  11. # include <poll.h>
  12. # include <unistd.h>
  13. #include <errno.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <ctype.h>
  18. #include "client.h"
  19. #include "timer.h"
  20. #include "server.h"
  21. #include "monolog.h"
  22. #include "libtelnet.h"
  23. #include "rh.h"
  24. static const telnet_telopt_t woe_telnet_opts[] = {
  25. { TELNET_TELOPT_COMPRESS2, TELNET_WILL, TELNET_DONT },
  26. { TELNET_TELOPT_ECHO , TELNET_WONT, TELNET_DONT },
  27. { -1, 0, 0 }
  28. };
  29. #define WOE_SERVER_BUFFER_SIZE 10000
  30. #define WOE_SERVER_LISTEN_BACKLOG 8
  31. struct woe_server {
  32. char buffer[WOE_SERVER_BUFFER_SIZE];
  33. short listen_port;
  34. int listen_sock;
  35. int busy;
  36. struct sockaddr_in addr;
  37. socklen_t addrlen;
  38. mrb_state * mrb;
  39. struct pollfd pfd[WOE_CLIENTS_MAX + 1];
  40. struct woe_client * clients[WOE_CLIENTS_MAX];
  41. struct woe_timer * timers[WOE_TIMERS_MAX];
  42. void (*event_handler) (telnet_t *telnet, telnet_event_t *ev, void *user_data);
  43. void (*disconnect_handler) (struct woe_server * srv, struct woe_client * cli, void *user_data);
  44. };
  45. int woe_server_disconnect(struct woe_server * srv, struct woe_client * client);
  46. int woe_send(int sock, const char *buffer, unsigned int size) {
  47. int res;
  48. if (sock == -1)
  49. return -1;
  50. /* send data */
  51. while (size > 0) {
  52. if ((res = send(sock, buffer, size, 0)) == -1) {
  53. if (errno != EINTR && errno != ECONNRESET) {
  54. LOG_ERROR("send() failed: %s\n", strerror(errno));
  55. return -2;
  56. } else {
  57. return 0;
  58. }
  59. } else if (res == 0) {
  60. LOG_ERROR("send() unexpectedly returned 0\n");
  61. return -3;
  62. }
  63. /* update pointer and size to see if we've got more to send */
  64. buffer += res;
  65. size -= res;
  66. }
  67. return 0;
  68. }
  69. static void woe_event_handler(telnet_t *telnet, telnet_event_t *ev, void *user_data) {
  70. struct woe_client * client = (struct woe_client *) user_data;
  71. switch (ev->type) {
  72. /* data received */
  73. case TELNET_EV_DATA:
  74. woe_client_input(client, ev->data.buffer, ev->data.size);
  75. /* telnet_negotiate(telnet, TELNET_WONT, TELNET_TELOPT_ECHO);
  76. telnet_negotiate(telnet, TELNET_WILL, TELNET_TELOPT_ECHO); */
  77. break;
  78. /* data must be sent */
  79. case TELNET_EV_SEND:
  80. woe_send(client->sock, ev->data.buffer, ev->data.size);
  81. break;
  82. /* enable compress2 if accepted by client */
  83. case TELNET_EV_DO:
  84. if (ev->neg.telopt == TELNET_TELOPT_COMPRESS2) telnet_begin_compress2(telnet);
  85. woe_client_negotiate(client, TELNET_DO, ev->neg.telopt);
  86. break;
  87. case TELNET_EV_DONT:
  88. woe_client_negotiate(client, TELNET_DONT, ev->neg.telopt);
  89. break;
  90. case TELNET_EV_WILL:
  91. woe_client_negotiate(client, TELNET_WILL, ev->neg.telopt);
  92. break;
  93. case TELNET_EV_WONT:
  94. woe_client_negotiate(client, TELNET_WONT, ev->neg.telopt);
  95. break;
  96. case TELNET_EV_IAC:
  97. woe_client_iac(client, ev->iac.cmd);
  98. break;
  99. case TELNET_EV_SUBNEGOTIATION:
  100. woe_client_subnegotiate(client, ev->sub.buffer, ev->sub.size, ev->sub.telopt);
  101. break;
  102. case TELNET_EV_TTYPE:
  103. woe_client_ttype(client, ev->ttype.cmd, ev->ttype.name);
  104. break;
  105. case TELNET_EV_COMPRESS:
  106. woe_client_compress(client, ev->compress.state);
  107. break;
  108. case TELNET_EV_ENVIRON:
  109. woe_client_environ(client, ev->environ.cmd, ev->environ.values, ev->environ.size);
  110. break;
  111. case TELNET_EV_MSSP:
  112. woe_client_mssp(client, ev->mssp.values, ev->mssp.size);
  113. break;
  114. /* warning */
  115. case TELNET_EV_WARNING:
  116. LOG_WARNING("Telnet warning for client %d %s.\n", client->index, ev->error.msg);
  117. woe_client_warning(client, ev->error.errcode, ev->error.msg);
  118. break;
  119. /* error */
  120. case TELNET_EV_ERROR:
  121. LOG_ERROR("Telnet error for client %d %s.\n", client->index, ev->error.msg);
  122. woe_client_error(client, ev->error.errcode, ev->error.msg);
  123. woe_server_disconnect(client->server, client);
  124. break;
  125. case TELNET_EV_ZMP:
  126. woe_client_zmp(client, ev->zmp.argc, ev->zmp.argv);
  127. break;
  128. default:
  129. LOG_NOTE("Ignored telnet event %d.\n", ev->type);
  130. /* ignore */
  131. break;
  132. }
  133. }
  134. void woe_server_request_shutdown(struct woe_server * srv) {
  135. if (srv) srv->busy = 0;
  136. }
  137. int woe_server_busy(struct woe_server * srv) {
  138. if (!srv) return 0;
  139. return srv->busy;
  140. }
  141. struct woe_server * woe_server_free(struct woe_server * srv) {
  142. int index;
  143. close(srv->listen_sock);
  144. for (index = 0; index < WOE_CLIENTS_MAX; ++index) {
  145. woe_server_remove_client(srv, index);
  146. }
  147. for (index = 0; index < WOE_TIMERS_MAX; ++index) {
  148. woe_server_remove_timer(srv, index);
  149. }
  150. free(srv);
  151. return NULL;
  152. }
  153. struct woe_server * woe_server_init(struct woe_server * srv, int port) {
  154. int index;
  155. if (!srv) return NULL;
  156. srv->listen_sock = -1;
  157. srv->listen_port = port;
  158. srv->busy = !0;
  159. srv->mrb = NULL;
  160. memset(srv->buffer , '\0' , sizeof(srv->buffer));
  161. memset(srv->pfd , 0 , sizeof(srv->pfd));
  162. memset(&srv->addr , 0 , sizeof(srv->addr));
  163. for (index = 0; index < WOE_CLIENTS_MAX; ++index) {
  164. srv->clients[index] = NULL;
  165. }
  166. for (index = 0; index < WOE_TIMERS_MAX; ++index) {
  167. srv->timers[index] = NULL;
  168. }
  169. srv->event_handler = woe_event_handler;
  170. return srv;
  171. }
  172. struct woe_server * woe_server_new(int port) {
  173. struct woe_server * srv = calloc(1, sizeof(struct woe_server));
  174. if (!srv) return NULL;
  175. return woe_server_init(srv, port);
  176. }
  177. static const telnet_telopt_t telopts[] = {
  178. { TELNET_TELOPT_COMPRESS2, TELNET_WILL, TELNET_DONT },
  179. { -1, 0, 0 }
  180. };
  181. struct woe_server * woe_server_set_mrb(struct woe_server * srv, mrb_state * mrb) {
  182. if (!srv) return NULL;
  183. srv->mrb = mrb;
  184. return srv;
  185. }
  186. mrb_state * woe_server_get_mrb(struct woe_server * srv) {
  187. if (!srv) return NULL;
  188. return srv->mrb;
  189. }
  190. /** Sets up the server to listen at its configured port. */
  191. int woe_server_listen(struct woe_server * srv) {
  192. int res;
  193. /* create listening socket */
  194. if ((srv->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  195. LOG_ERROR("socket() failed: %s\n", strerror(errno));
  196. return 1;
  197. }
  198. /* Reuse address option */
  199. res = 1;
  200. if (setsockopt(srv->listen_sock, SOL_SOCKET, SO_REUSEADDR, (void*)&res, sizeof(res))
  201. == -1) {
  202. LOG_ERROR("setsockopt() failed: %s\n", strerror(errno));
  203. return 2;
  204. }
  205. /* Bind to listening addr/port */
  206. srv->addr.sin_family = AF_INET;
  207. srv->addr.sin_addr.s_addr = INADDR_ANY;
  208. srv->addr.sin_port = htons(srv->listen_port);
  209. if (bind(srv->listen_sock, (struct sockaddr *)&srv->addr, sizeof(srv->addr)) == -1) {
  210. LOG_ERROR("setsockopt() failed: %s\n", strerror(errno));
  211. return 3;
  212. }
  213. /* listen for clients */
  214. if (listen(srv->listen_sock, WOE_SERVER_LISTEN_BACKLOG) == -1) {
  215. fprintf(stderr, "listen() failed: %s\n", strerror(errno));
  216. return 4;
  217. }
  218. LOG_NOTE("Listening on port %d\n", srv->listen_port);
  219. /* Initialize listening descriptors */
  220. srv->pfd[WOE_CLIENTS_MAX].fd = srv->listen_sock;
  221. srv->pfd[WOE_CLIENTS_MAX].events = POLLIN;
  222. return 0;
  223. }
  224. /** Returns one of the clients of the server or NULL if not in use or out of
  225. * range */
  226. struct woe_client * woe_server_get_client(struct woe_server * srv, int index) {
  227. if (!srv) return NULL;
  228. if (index < 0) return NULL;
  229. if (index >= WOE_CLIENTS_MAX) return NULL;
  230. return srv->clients[index];
  231. }
  232. /** Stores a client of the server at the given index*/
  233. struct woe_client * woe_server_put_client(struct woe_server * srv, int index, struct woe_client * cli) {
  234. if (!srv) return NULL;
  235. if (!cli) return NULL;
  236. if (index < 0) return NULL;
  237. if (index >= WOE_CLIENTS_MAX) return NULL;
  238. if (srv->clients[index]) {
  239. woe_client_free(srv->clients[index]);
  240. }
  241. srv->clients[index] = cli;
  242. return cli;
  243. }
  244. /** Removes a client of the server at the given index*/
  245. struct woe_client * woe_server_remove_client(struct woe_server * srv, int index) {
  246. if (!srv) return NULL;
  247. if (index < 0) return NULL;
  248. if (index >= WOE_CLIENTS_MAX) return NULL;
  249. if (srv->clients[index]) {
  250. woe_client_free(srv->clients[index]);
  251. }
  252. srv->clients[index] = NULL;
  253. return NULL;
  254. }
  255. /** Returns one of the timers of the server or NULL if not in use or out of
  256. * range */
  257. struct woe_timer * woe_server_get_timer(struct woe_server * srv, int index) {
  258. if (!srv) return NULL;
  259. if (index < 0) return NULL;
  260. if (index >= WOE_CLIENTS_MAX) return NULL;
  261. return srv->timers[index];
  262. }
  263. /** Stores a timer of the server at the given index*/
  264. struct woe_timer * woe_server_put_timer(struct woe_server * srv, int index, struct woe_timer * tim) {
  265. if (!srv) return NULL;
  266. if (!tim) return NULL;
  267. if (index < 0) return NULL;
  268. if (index >= WOE_TIMERS_MAX) return NULL;
  269. if (srv->timers[index]) {
  270. woe_timer_free(srv->timers[index]);
  271. }
  272. srv->timers[index] = tim;
  273. return tim;
  274. }
  275. /** Removes a timer of the server at the given index*/
  276. struct woe_timer * woe_server_remove_timer(struct woe_server * srv, int index) {
  277. if (!srv) return NULL;
  278. if (index < 0) return NULL;
  279. if (index >= WOE_TIMERS_MAX) return NULL;
  280. if (srv->timers[index]) {
  281. woe_timer_free(srv->timers[index]);
  282. }
  283. srv->timers[index] = NULL;
  284. return NULL;
  285. }
  286. /** Find an index to put a newtimerr and returns a pointer to it.
  287. * Returns -1 if no free space is available.
  288. **/
  289. int woe_server_get_available_timer_index(struct woe_server * srv) {
  290. int i;
  291. for (i = 0; i < WOE_TIMERS_MAX; ++i) {
  292. struct woe_timer * timer = woe_server_get_timer(srv, i);
  293. if (!timer) {
  294. return i;
  295. }
  296. }
  297. return -1;
  298. }
  299. /** Creates a new timer for this server. Return null if no memory or no space
  300. * for a new timer. */
  301. struct woe_timer * woe_server_make_new_timer(struct woe_server * srv) {
  302. struct woe_timer * new;
  303. int index = woe_server_get_available_timer_index(srv);
  304. if (index < 0) return NULL;
  305. new = woe_timer_new(srv, index);
  306. return woe_server_put_timer(srv, index, new);
  307. }
  308. /** Creates a new timr and returns it's id. */
  309. int woe_server_make_new_timer_id(struct woe_server * srv) {
  310. struct woe_timer * new = woe_server_make_new_timer(srv);
  311. if (!new) return -1;
  312. return new->index;
  313. }
  314. /** Find an index to put a new user and returns a pointer to it.
  315. * Returns -1 if no free space is available.
  316. **/
  317. int woe_server_get_available_client_index(struct woe_server * srv) {
  318. int i;
  319. for (i = 0; i < WOE_CLIENTS_MAX; ++i) {
  320. struct woe_client * client = woe_server_get_client(srv, i);
  321. if (!client) {
  322. return i;
  323. }
  324. }
  325. return -1;
  326. }
  327. /** Creates a new client for this server. Return null if no memory or no space
  328. * for a new client. */
  329. struct woe_client * woe_server_make_new_client(struct woe_server * srv,
  330. int socket, struct sockaddr_in *addr, socklen_t addrlen) {
  331. struct woe_client * new;
  332. int index = woe_server_get_available_client_index(srv);
  333. if (index < 0) return NULL;
  334. new = woe_client_new(srv, index, socket, addr, addrlen);
  335. return woe_server_put_client(srv, index, new);
  336. }
  337. /** Sets a timer's values by id */
  338. int woe_server_set_timer_value(struct woe_server * srv, int index, double value, double interval) {
  339. struct woe_timer * tim;
  340. tim = woe_server_get_timer(srv, index);
  341. if (!tim) return -1;
  342. return woe_timer_set(tim, value, interval);
  343. }
  344. /** Gets a timer's values by id */
  345. int woe_server_get_timer_value(struct woe_server * srv, int index, double * value, double * interval) {
  346. struct woe_timer * tim;
  347. tim = woe_server_get_timer(srv, index);
  348. if (!tim) return -1;
  349. return woe_timer_get(tim, value, interval);
  350. }
  351. /* Handles a new connection to this server. */
  352. int woe_server_handle_connect(struct woe_server * srv) {
  353. struct woe_client * client;
  354. int res;
  355. struct sockaddr_in addr;
  356. socklen_t addrlen;
  357. /* accept the connection */
  358. addrlen = sizeof(addr);
  359. if ((res = accept(srv->listen_sock, (struct sockaddr *)&addr, &addrlen)) == -1) {
  360. LOG_ERROR("accept() failed: %s\n", strerror(errno));
  361. return 1;
  362. }
  363. LOG_NOTE("Connection received.\n");
  364. client = woe_server_make_new_client(srv, res, &addr, addrlen);
  365. /* No space for a new client */
  366. if (!client) {
  367. LOG_WARNING("Connection rejected (too many users or OOM)\n");
  368. write(res, "Too many users.\r\n", 14);
  369. close(res);
  370. return 2;
  371. }
  372. /* init, welcome */
  373. client->telnet = telnet_init(woe_telnet_opts, srv->event_handler, 0, client);
  374. if (!client->telnet) {
  375. LOG_ERROR("Could not initialize telnet connection for user.");
  376. woe_server_disconnect(srv, client);
  377. return 3;
  378. }
  379. /*telnet_negotiate(client->telnet, TELNET_DO, TELNET_TELOPT_ECHO);*/
  380. telnet_negotiate(client->telnet, TELNET_WILL, TELNET_TELOPT_COMPRESS2);
  381. telnet_printf(client->telnet, "Welcome to WOE!\r\n");
  382. /* telnet_negotiate(client->telnet, TELNET_WILL, TELNET_TELOPT_ECHO); */
  383. if (srv->mrb) {
  384. rh_run_toplevel(srv->mrb, "woe_on_connect", "i", client->index);
  385. }
  386. return 0;
  387. }
  388. /** Sends a telnet command to the numbered client. */
  389. int woe_server_iac(struct woe_server * srv, int client, int command) {
  390. struct woe_client * pclient;
  391. if (!srv) return -1;
  392. pclient = woe_server_get_client(srv, client);
  393. if (!pclient) return -2;
  394. telnet_iac(pclient->telnet, command);
  395. return 0;
  396. }
  397. /** Send a telnet negotiation to the numbered client. */
  398. int woe_server_negotiate(struct woe_server * srv, int client, int how, int option) {
  399. struct woe_client * pclient;
  400. if (!srv) return -1;
  401. pclient = woe_server_get_client(srv, client);
  402. if (!pclient) return -2;
  403. telnet_negotiate(pclient->telnet, how, option);
  404. return 0;
  405. }
  406. /** Sends a telnet start of subnegotiation to the numbered client. */
  407. int woe_server_begin_sb(struct woe_server * srv, int client, int telopt) {
  408. struct woe_client * pclient;
  409. if (!srv) return -1;
  410. pclient = woe_server_get_client(srv, client);
  411. if (!pclient) return -2;
  412. telnet_begin_sb(pclient->telnet, telopt);
  413. return 0;
  414. }
  415. /** Sends a telnet end of subnegotiation to the numbered client. */
  416. int woe_server_finish_sb(struct woe_server * srv, int client) {
  417. struct woe_client * pclient;
  418. if (!srv) return -1;
  419. pclient = woe_server_get_client(srv, client);
  420. if (!pclient) return -2;
  421. telnet_finish_sb(pclient->telnet);
  422. return 0;
  423. }
  424. /** Sends a complete telnet subnegotiation buffer to the numbered client. */
  425. int woe_server_subnegotiation(struct woe_server * srv, int client, int telopt, char * buffer, int size) {
  426. struct woe_client * pclient;
  427. if (!srv) return -1;
  428. pclient = woe_server_get_client(srv, client);
  429. if (!pclient) return -2;
  430. telnet_subnegotiation(pclient->telnet, telopt, buffer, size);
  431. return 0;
  432. }
  433. /** Begin sending compressed data to the to the numbered client. */
  434. int woe_server_begin_compress2(struct woe_server * srv, int client) {
  435. struct woe_client * pclient;
  436. if (!srv) return -1;
  437. pclient = woe_server_get_client(srv, client);
  438. if (!pclient) return -2;
  439. telnet_begin_compress2(pclient->telnet);
  440. return 0;
  441. }
  442. /** Send formated output with newline escaping to the to the numbered client. */
  443. int woe_server_vprintf(struct woe_server * srv, int client, const char *fmt, va_list va) {
  444. struct woe_client * pclient;
  445. if (!srv) return -1;
  446. pclient = woe_server_get_client(srv, client);
  447. if (!pclient) return -2;
  448. telnet_vprintf(pclient->telnet, fmt, va);
  449. return 0;
  450. }
  451. /** Send formated output with newline escaping to the to the numbered client. */
  452. int woe_server_printf(struct woe_server * srv, int client, const char *fmt, ...) {
  453. va_list va;
  454. int res;
  455. struct woe_client * pclient;
  456. if (!srv) return -1;
  457. pclient = woe_server_get_client(srv, client);
  458. if (!pclient) return -2;
  459. va_start(va, fmt);
  460. telnet_vprintf(pclient->telnet, fmt, va);
  461. va_end(va);
  462. return 0;
  463. }
  464. /** Send formated output without newline escaping to the to the numbered client. */
  465. int woe_server_raw_vprintf(struct woe_server * srv, int client, const char *fmt, va_list va) {
  466. struct woe_client * pclient;
  467. if (!srv) return -1;
  468. pclient = woe_server_get_client(srv, client);
  469. if (!pclient) return -2;
  470. telnet_raw_vprintf(pclient->telnet, fmt, va);
  471. return 0;
  472. }
  473. /** Send formated output without newline escaping to the to the numbered client. */
  474. int woe_server_raw_printf(struct woe_server * srv, int client, const char *fmt, ...) {
  475. va_list va;
  476. int res;
  477. struct woe_client * pclient;
  478. if (!srv) return -1;
  479. pclient = woe_server_get_client(srv, client);
  480. if (!pclient) return -2;
  481. va_start(va, fmt);
  482. res = telnet_raw_vprintf(pclient->telnet, fmt, va);
  483. va_end(va);
  484. return 0;
  485. }
  486. /** Begin a NEW-ENVIRON subnegotiation with the numbered client. */
  487. int woe_server_begin_newenviron(struct woe_server * srv, int client, int type) {
  488. struct woe_client * pclient;
  489. if (!srv) return -1;
  490. pclient = woe_server_get_client(srv, client);
  491. if (!pclient) return -2;
  492. telnet_begin_newenviron(pclient->telnet, type);
  493. return 0;
  494. }
  495. /** Send a NEW-ENVIRON variable name or value to the numbered client. */
  496. int woe_server_newenviron_value(struct woe_server * srv, int client, int type, char * value) {
  497. struct woe_client * pclient;
  498. if (!srv) return -1;
  499. pclient = woe_server_get_client(srv, client);
  500. if (!pclient) return -2;
  501. telnet_newenviron_value(pclient->telnet, type, value);
  502. return 0;
  503. }
  504. /** Finish a NEW-ENVIRON subnegotiation with the numbered client. */
  505. int woe_server_finish_newenviron(struct woe_server * srv, int client) {
  506. struct woe_client * pclient;
  507. if (!srv) return -1;
  508. pclient = woe_server_get_client(srv, client);
  509. if (!pclient) return -2;
  510. telnet_finish_newenviron(pclient->telnet);
  511. return 0;
  512. }
  513. /** Send a TERMINAL-TYPE SEND command to the numbered client. */
  514. int woe_server_ttype_send(struct woe_server * srv, int client) {
  515. struct woe_client * pclient;
  516. if (!srv) return -1;
  517. pclient = woe_server_get_client(srv, client);
  518. if (!pclient) return -2;
  519. telnet_ttype_send(pclient->telnet);
  520. return 0;
  521. }
  522. /** Send a TERMINAL-TYPE IS command to the numbered client. */
  523. int woe_server_ttype_is(struct woe_server * srv, int client, char * ttype) {
  524. struct woe_client * pclient;
  525. if (!srv) return -1;
  526. pclient = woe_server_get_client(srv, client);
  527. if (!pclient) return -2;
  528. telnet_ttype_is(pclient->telnet, ttype);
  529. return 0;
  530. }
  531. /** Send a ZMP command to the numbered client. */
  532. int woe_server_send_zmp(struct woe_server * srv, int client, int argc, const char ** argv) {
  533. struct woe_client * pclient;
  534. if (!srv) return -1;
  535. pclient = woe_server_get_client(srv, client);
  536. if (!pclient) return -2;
  537. telnet_send_zmp(pclient->telnet, argc, argv);
  538. return 0;
  539. }
  540. /** Send a ZMP command to the numbered client. */
  541. int woe_server_send_vzmpv(struct woe_server * srv, int client, va_list va) {
  542. struct woe_client * pclient;
  543. if (!srv) return -1;
  544. pclient = woe_server_get_client(srv, client);
  545. if (!pclient) return -2;
  546. telnet_send_vzmpv(pclient->telnet, va);
  547. return 0;
  548. }
  549. /** Send a ZMP command to the numbered client. */
  550. int woe_server_send_zmpv(struct woe_server * srv, int client, ...) {
  551. va_list va;
  552. struct woe_client * pclient;
  553. if (!srv) return -1;
  554. pclient = woe_server_get_client(srv, client);
  555. if (!pclient) return -2;
  556. va_start(va, client);
  557. telnet_send_vzmpv(pclient->telnet, va);
  558. va_end(va);
  559. return 0;
  560. }
  561. /** Begin sending a ZMP command to the numbered client. */
  562. int woe_server_begin_zmp(struct woe_server * srv, int client, const char * cmd) {
  563. struct woe_client * pclient;
  564. if (!srv) return -1;
  565. pclient = woe_server_get_client(srv, client);
  566. if (!pclient) return -2;
  567. telnet_begin_zmp(pclient->telnet, cmd);
  568. return 0;
  569. }
  570. /** Send a ZMP command argument to the numbered client. */
  571. int woe_server_zmp_arg(struct woe_server * srv, int client, const char * arg) {
  572. struct woe_client * pclient;
  573. if (!srv) return -1;
  574. pclient = woe_server_get_client(srv, client);
  575. if (!pclient) return -2;
  576. telnet_zmp_arg(pclient->telnet, arg);
  577. return 0;
  578. }
  579. /** Finish sending a ZMP command to the numbered client. */
  580. int woe_server_finish_zmp(struct woe_server * srv, int client, const char * cmd) {
  581. struct woe_client * pclient;
  582. if (!srv) return -1;
  583. pclient = woe_server_get_client(srv, client);
  584. if (!pclient) return -2;
  585. telnet_finish_zmp(pclient->telnet);
  586. return 0;
  587. }
  588. /** Disconnect a client from the server. */
  589. int woe_server_disconnect(struct woe_server * srv, struct woe_client * client) {
  590. int index;
  591. if (!srv) return 1;
  592. if (!client) return 2;
  593. close(client->sock);
  594. if (srv->disconnect_handler) {
  595. srv->disconnect_handler(srv, client, NULL);
  596. }
  597. index = client->index;
  598. if (srv->mrb) {
  599. rh_run_toplevel(srv->mrb, "woe_on_disconnect", "i", index);
  600. }
  601. /* Get rid of client, will also free memory asociated. */
  602. woe_server_remove_client(srv, index);
  603. return 0;
  604. }
  605. /** Forcfullly disconnect a client from the server by id.
  606. * Set a quit flag that woe_server_update will check. */
  607. int woe_server_disconnect_id(struct woe_server * srv, int id) {
  608. struct woe_client * client = woe_server_get_client(srv, id);
  609. if (!client) return -1;
  610. client->busy = 0;
  611. return 0;
  612. }
  613. /** Polls the server once and updates any of the clients if needed. */
  614. int woe_server_update(struct woe_server * srv, int timeout) {
  615. int i, res;
  616. /* Check timers for readiness. */
  617. for (i = 0; i < WOE_TIMERS_MAX; ++i) {
  618. struct woe_timer * timer = woe_server_get_timer(srv, i);
  619. if (woe_timer_passed(timer)) {
  620. woe_timer_callback(timer);
  621. }
  622. }
  623. /* Disconnect clients that should quit */
  624. for (i = 0; i < WOE_CLIENTS_MAX; ++i) {
  625. struct woe_client * client = woe_server_get_client(srv, i);
  626. if (!client) continue;
  627. if (!client->busy) {
  628. woe_server_disconnect(srv, client);
  629. }
  630. }
  631. /* prepare for poll */
  632. memset(srv->pfd , 0 , sizeof(srv->pfd));
  633. for (i = 0; i != WOE_CLIENTS_MAX; ++i) {
  634. struct woe_client * client = woe_server_get_client(srv, i);
  635. if (client) {
  636. srv->pfd[i].fd = client->sock;
  637. srv->pfd[i].events = POLLIN;
  638. } else {
  639. srv->pfd[i].fd = -1;
  640. srv->pfd[i].events = 0;
  641. }
  642. }
  643. /* Also listen for connnect events. */
  644. srv->pfd[WOE_CLIENTS_MAX].fd = srv->listen_sock;
  645. srv->pfd[WOE_CLIENTS_MAX].events = POLLIN;
  646. /* Poll for activity */
  647. res = poll(srv->pfd, WOE_CLIENTS_MAX + 1, timeout);
  648. /* Check for time out */
  649. if (res == 0) {
  650. /* Time out but that's OK. */
  651. return 0;
  652. }
  653. /* Log errors. */
  654. if (res == -1 && errno != EINTR) {
  655. LOG_ERROR("poll() failed: %s\n", strerror(errno));
  656. return 1;
  657. }
  658. /* Handle new connection connection */
  659. if (srv->pfd[WOE_CLIENTS_MAX].revents & POLLIN) {
  660. woe_server_handle_connect(srv);
  661. }
  662. /* Read from clients */
  663. for (i = 0; i < WOE_CLIENTS_MAX; ++i) {
  664. struct woe_client * client = woe_server_get_client(srv, i);
  665. if (!client) continue;
  666. /* Input from clients. */
  667. if (srv->pfd[i].revents & POLLIN) {
  668. res = recv(client->sock, srv->buffer, sizeof(srv->buffer), 0);
  669. if (res < 0) {
  670. LOG_ERROR("recv(client) failed: %s\n", strerror(errno));
  671. } else if (res == 0) {
  672. /* Disconnect the client. */
  673. woe_server_disconnect(srv, client);
  674. } else {
  675. /* Let telnet lib process incoming data. */
  676. telnet_recv(client->telnet, srv->buffer, res);
  677. // telnet_send(client->telnet, srv->buffer, res);
  678. // telnet_send(telnet, ev->data.buffer, ev->data.size);
  679. }
  680. }
  681. }
  682. return 0;
  683. }
  684. int woe_server_send_to_client(struct woe_server * srv, int client, char * data, size_t size) {
  685. struct woe_client * pclient = woe_server_get_client(srv, client);
  686. if (!pclient) return -1;
  687. telnet_send(pclient->telnet, data, size);
  688. return size;
  689. }