A messenger application for Raspberry Pi Zerofor A.U.TH (Real time Embedded systems).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

137 lines
4.2 KiB

  1. /*!
  2. * \file listener.c
  3. * \brief Listener related functionality
  4. *
  5. * \author Christos Choutouridis AEM:8997 <cchoutou@ece.auth.gr>
  6. */
  7. #include <sys/socket.h>
  8. #include <arpa/inet.h>
  9. #include <unistd.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include "listener.h"
  14. char_t rx_buffer[4*MSG_TEXT_SIZE]; //!< receive buffer
  15. /*!
  16. * Incoming message handling
  17. * @param d Pointer to sender/client's device
  18. * @param buffer Buffer to message
  19. * @param size Size of message
  20. */
  21. static void listen_handler (devAEM_t dev, char_t* buffer, size_t size) {
  22. msg_t msg;
  23. msg_init (&msg);
  24. cMsg_parse (&msg.cMsg, buffer, size); // parse the message
  25. log_debug("Debug: Message parsed\n");
  26. msgList_acquire ();
  27. mIter_t myCopy = msgList_find (&msgList, &msg); // try to find message in msgList
  28. if (myCopy == -1) {
  29. // We don't have a copy, accept and store it
  30. msgList_add (&msgList, &msg);
  31. statsUpdateIn (&msg, false); // message process
  32. log_msg_io (&msg); // log
  33. }
  34. else {
  35. // We have a copy
  36. // Do not forward a duplicate message to sender, he already has it
  37. msgList.m[myCopy].recipients[devList_getIter (dev)] = true;
  38. statsUpdateIn (&msg, true); // message process
  39. log_debug("Debug: Duplicate message from: %d\n", msg.sender);
  40. }
  41. msgList_release ();
  42. }
  43. /*!
  44. * Listener. This function normally never returns. If it does it is to
  45. * report unrecoverable error.
  46. * @return Error creating server side socket
  47. */
  48. static status_t listener(void) {
  49. int srvSock;
  50. sockaddr_in_t srvAddPort;
  51. // Create socket
  52. memset(&srvAddPort, 0, sizeof(srvAddPort));
  53. srvAddPort.sin_family= AF_INET;
  54. srvAddPort.sin_port= htons(settings.port);
  55. srvAddPort.sin_addr.s_addr = htonl(INADDR_ANY);
  56. // try to create tcp socket
  57. if ((srvSock = socket (PF_INET, SOCK_STREAM, 0)) == -1) {
  58. log_error ("Error: Can not create socket\n");
  59. goto _list_error1;
  60. }
  61. log_debug("Debug: Socket for listening created\n");
  62. // Try to bind socket
  63. if(bind(srvSock, (sockaddr_t *) &srvAddPort, sizeof(srvAddPort)) == -1) {
  64. log_error ("Error: Can not bind socket to port %d\n", settings.port);
  65. goto _list_error0;
  66. }
  67. // try to setup listener. We use DEVICE_LIST_SIZE for pending request
  68. if (listen (srvSock, DEVICE_LIST_SIZE) == -1) {
  69. log_error ("Error: Can not enable socket\n");
  70. goto _list_error0;
  71. }
  72. log_debug("Debug: Listening on [0.0.0.0], port %d\n", settings.port);
  73. while (1) {
  74. sockaddr_in_t clntAddr;
  75. socklen_t clntLen= sizeof(clntAddr);
  76. int clntSock;
  77. int rcvBytes;
  78. // block in accept and get client's connection socket
  79. if ((clntSock = accept (srvSock, (sockaddr_t *)&clntAddr, &clntLen)) == -1) {
  80. continue;
  81. }
  82. // make a device from clients address
  83. devAEM_t dev = addr2devAEM (ntohl(clntAddr.sin_addr.s_addr));
  84. devIP_t ip = AEM2ip (dev);
  85. log_debug (
  86. "Debug: Connection from %u.%u.%u.%u port:%u received\n",
  87. ip.A, ip.B, ip.C, ip.D, clntAddr.sin_port
  88. );
  89. // Block in receive, after the connection is accepted
  90. if ((rcvBytes = recv(clntSock, rx_buffer, sizeof(rx_buffer), 0)) < 0) {
  91. log_error ("Error: Fail to receive from socket\n");
  92. close (clntSock);
  93. continue;
  94. }
  95. rx_buffer[rcvBytes] = '\0'; // add null termination to buffer
  96. close(clntSock); // close the client socket
  97. // call listen handler for the device and message
  98. log_debug (
  99. "Debug: Message from %u.%u.%u.%u port:%u received\n",
  100. ip.A, ip.B, ip.C, ip.D, clntAddr.sin_port
  101. );
  102. listen_handler (dev, rx_buffer, rcvBytes);
  103. }
  104. // Local error return handling
  105. _list_error0:
  106. close(srvSock); // server socket clean up
  107. log_debug ("Debug: Socket for listening closed\n");
  108. _list_error1:
  109. return MSG_ERROR; // report back
  110. }
  111. /*!
  112. * pthread listener wrapper
  113. * @param ptr Not used
  114. */
  115. void* pthListener(void* ptr) {
  116. (void)&ptr; // use parameter
  117. if (listener() == MSG_ERROR)
  118. exit(1); // this is a deal breaker sorry.
  119. return NULL;
  120. }