A messenger application for Raspberry Pi Zerofor A.U.TH (Real time Embedded systems).
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 

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