server.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * server.cpp
  3. *
  4. * Created on: Jan 4, 2018
  5. * Author: Philipp Hinz
  6. * based on: https://gist.github.com/suyash/2488ff6996c98a8ee3a84fe3198a6f85
  7. */
  8. #include <arpa/inet.h>
  9. #include <netinet/in.h>
  10. #include <stdbool.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #include <pthread.h>
  16. #include "server.h"
  17. #include "logger.h"
  18. #include "hal.h"
  19. #include "coffee.h"
  20. #include "stripe.h"
  21. #include "events.h"
  22. /**
  23. * TCP Uses 2 types of sockets, the connection socket and the listen socket.
  24. * The Goal is to separate the connection phase from the data exchange phase.
  25. * */
  26. int listen_sock;
  27. int sock;
  28. char buffer_ok[] = "OK\n";
  29. /**
  30. * Just sends an ACK message back
  31. */
  32. void sendACK() {
  33. send(sock, buffer_ok, strlen(buffer_ok), 0);
  34. }
  35. /**
  36. * Closes all active connections
  37. */
  38. void serverTerminate(event_t *e) {
  39. close(sock);
  40. close(listen_sock);
  41. }
  42. /**
  43. * Main thread to handle networking stuff
  44. * @param *threadid Thread ID
  45. */
  46. void* serverThread(void* threadid) {
  47. sleep(1); // Wait for other components to initialize
  48. // socket address used for the server
  49. struct sockaddr_in server_address;
  50. memset(&server_address, 0, sizeof(server_address));
  51. server_address.sin_family = AF_INET;
  52. // htons: host to network short: transforms a value in host byte
  53. // ordering format to a short value in network byte ordering format
  54. server_address.sin_port = htons(SERVER_PORT);
  55. // htonl: host to network long: same as htons but to long
  56. server_address.sin_addr.s_addr = htonl(INADDR_ANY);
  57. // create a TCP socket, creation returns -1 on failure
  58. if ((listen_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  59. logger_error("could not create listen socket\n");
  60. pthread_exit(0);
  61. }
  62. // bind it to listen to the incoming connections on the created server
  63. // address, will return -1 on error
  64. if ((bind(listen_sock, (struct sockaddr *) &server_address,
  65. sizeof(server_address))) < 0) {
  66. logger_error("could not bind socket\n");
  67. pthread_exit(0);
  68. }
  69. int wait_size = 16; // maximum number of waiting clients, after which
  70. // dropping begins
  71. if (listen(listen_sock, wait_size) < 0) {
  72. logger_error("could not open socket for listening\n");
  73. pthread_exit(0);
  74. }
  75. event_subscribe("terminate", &serverTerminate);
  76. logger(V_BASIC, "Now listening for commands on port %d\n", SERVER_PORT);
  77. // socket address used to store client address
  78. struct sockaddr_in client_address;
  79. unsigned int client_address_len = 0;
  80. // run indefinitely
  81. while (true) {
  82. // open a new socket to transmit data per connection
  83. if ((sock = accept(listen_sock, (struct sockaddr *) &client_address,
  84. &client_address_len)) < 0) {
  85. logger_error("could not open a socket to accept data\n");
  86. pthread_exit(0);
  87. }
  88. int n = 0;
  89. int len = 0, maxlen = 100, lastlen = 0;
  90. char buffer[maxlen];
  91. char cmd[maxlen];
  92. char *pcmd = cmd;
  93. char *pbuffer = buffer;
  94. strncpy(buffer, "", maxlen);
  95. strncpy(cmd, "", maxlen);
  96. logger(V_HAL, "client connected with ip address: %s\n",
  97. inet_ntoa(client_address.sin_addr));
  98. // keep running as long as the client keeps the connection open
  99. while ((n = recv(sock, pbuffer, maxlen, 0)) > 0) {
  100. pbuffer += n;
  101. maxlen -= n;
  102. len += n;
  103. strncpy(cmd, buffer, len - 1);
  104. cmd[len - 1] = '\0';
  105. pcmd = &cmd[lastlen];
  106. logger(V_SPI, "received %d bytes: '%s' (cmd: %s)\n", len, buffer,
  107. pcmd);
  108. if (!strcmp(SERVER_CMD_ON, pcmd)) {
  109. if (getState() == STATE_OFF) {
  110. halSendSignal(SigInt0Rls);
  111. sendACK();
  112. }
  113. } else if (!strcmp(SERVER_CMD_OFF, pcmd)) {
  114. if (getState() != STATE_OFF) {
  115. halSendSignal(SigInt1RlsLong);
  116. sendACK();
  117. }
  118. } else if (!strcmp(SERVER_CMD_BREW, pcmd)) {
  119. if (getState() == STATE_IDLE || getState() == STATE_HEATING) {
  120. halSendSignal(SigInt1Rls);
  121. sendACK();
  122. }
  123. } else if (!strcmp(SERVER_CMD_STATUS, pcmd)) {
  124. char tmp[] = "0\n";
  125. tmp[0] += getState();
  126. send(sock, tmp, sizeof(tmp), 0);
  127. } else if (!strcmp(SERVER_CMD_STRIPEON, pcmd)) {
  128. stripeOn();
  129. sendACK();
  130. } else if (!strcmp(SERVER_CMD_STRIPEOFF, pcmd)) {
  131. stripeOff();
  132. sendACK();
  133. }
  134. lastlen = len;
  135. // echo received content back
  136. //send(sock, buffer, len, 0);
  137. }
  138. close(sock);
  139. }
  140. close(listen_sock);
  141. pthread_exit(EXIT_SUCCESS);
  142. }