A messenger application for Raspberry Pi Zerofor A.U.TH (Real time Embedded systems).
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

151 lignes
4.6 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 dev 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. msg.sender = dev;
  25. if (cMsg_parse (&msg.cMsg, buffer, size) == MSG_ERROR) // parse the message
  26. return;
  27. log_debug("Debug: Message parsed\n");
  28. msgList_acquire ();
  29. mIter_t myCopy = msgList_find (&msgList, &msg); // try to find message in msgList
  30. if (myCopy == -1) {
  31. // We don't have a copy, accept and store it
  32. mIter_t slot = msgList_add (&msgList, &msg);
  33. msgList_release ();
  34. statsUpdateIn (&msg, false); // message process
  35. log_msg_in (&msg); // log
  36. // Processing...
  37. devList_acquire();
  38. dIter_t d = devList_getIter (dev);
  39. dIter_t f = devList_getIter (msg.cMsg.from);
  40. devList_release();
  41. msgList_acquire ();
  42. // Do not echo message to sender, he already has it
  43. msgList.m[slot].recipients[d] = true;
  44. // don't push back message to creator, he already has it
  45. msgList.m[slot].recipients[f] = true;
  46. msgList_release ();
  47. }
  48. else {
  49. // We have a copy
  50. msgList_release ();
  51. statsUpdateIn (&msg, true); // message process
  52. log_debug ("Debug: Duplicate message from: %d\n", msg.sender);
  53. }
  54. }
  55. /*!
  56. * Listener. This function normally never returns. If it does it is to
  57. * report unrecoverable error.
  58. * @return Error creating server side socket
  59. */
  60. static status_t listener(void) {
  61. int srvSock;
  62. sockaddr_in_t srvAddPort;
  63. // Create socket
  64. memset(&srvAddPort, 0, sizeof(srvAddPort));
  65. srvAddPort.sin_family= AF_INET;
  66. srvAddPort.sin_port= htons(settings.port);
  67. srvAddPort.sin_addr.s_addr = htonl(INADDR_ANY);
  68. // try to create tcp socket
  69. if ((srvSock = socket (PF_INET, SOCK_STREAM, 0)) == -1) {
  70. log_error ("Error: Can not create socket\n");
  71. goto _list_error1;
  72. }
  73. log_debug("Debug: Socket for listening created\n");
  74. // Try to bind socket
  75. if(bind(srvSock, (sockaddr_t *) &srvAddPort, sizeof(srvAddPort)) == -1) {
  76. log_error ("Error: Can not bind socket to port %d\n", settings.port);
  77. goto _list_error0;
  78. }
  79. // try to setup listener. We use DEVICE_LIST_SIZE for pending request
  80. if (listen (srvSock, DEVICE_LIST_SIZE) == -1) {
  81. log_error ("Error: Can not enable socket\n");
  82. goto _list_error0;
  83. }
  84. log_debug("Debug: Listening on [0.0.0.0], port %d\n", settings.port);
  85. while (1) {
  86. sockaddr_in_t clntAddr;
  87. socklen_t clntLen= sizeof(clntAddr);
  88. int clntSock;
  89. int rcvBytes;
  90. // block in accept and get client's connection socket
  91. if ((clntSock = accept (srvSock, (sockaddr_t *)&clntAddr, &clntLen)) == -1) {
  92. continue;
  93. }
  94. // make a device from clients address
  95. devAEM_t dev = addr2devAEM (ntohl(clntAddr.sin_addr.s_addr));
  96. devIP_t ip = AEM2ip (dev);
  97. log_debug (
  98. "Debug: Connection from %u.%u.%u.%u port:%u received\n",
  99. ip.A, ip.B, ip.C, ip.D, clntAddr.sin_port
  100. );
  101. // Block in receive, after the connection is accepted
  102. if ((rcvBytes = recv(clntSock, rx_buffer, sizeof(rx_buffer), 0)) < 0) {
  103. log_error ("Error: Fail to receive from socket\n");
  104. close (clntSock);
  105. continue;
  106. }
  107. rx_buffer[rcvBytes] = '\0'; // add null termination to buffer
  108. close(clntSock); // close the client socket
  109. // call listen handler for the device and message
  110. log_debug (
  111. "Debug: Message from %u.%u.%u.%u port:%u received\n",
  112. ip.A, ip.B, ip.C, ip.D, clntAddr.sin_port
  113. );
  114. listen_handler (dev, rx_buffer, rcvBytes);
  115. }
  116. // Local error return handling
  117. _list_error0:
  118. close(srvSock); // server socket clean up
  119. log_debug ("Debug: Socket for listening closed\n");
  120. _list_error1:
  121. return MSG_ERROR; // report back
  122. }
  123. /*!
  124. * pthread listener wrapper
  125. * @param ptr Not used
  126. */
  127. void* pthListener(void* ptr) {
  128. (void)&ptr; // use parameter
  129. if (listener() == MSG_ERROR)
  130. exit(1); // this is a deal breaker sorry.
  131. return NULL;
  132. }