A messenger application for Raspberry Pi Zerofor A.U.TH (Real time Embedded systems).
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 

137 linhas
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. }