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.
 
 
 
 
 

210 Zeilen
7.2 KiB

  1. /*!
  2. * \file client.c
  3. *
  4. * \author Christos Choutouridis AEM:8997 <cchoutou@ece.auth.gr>
  5. */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <time.h>
  11. #include <sys/select.h>
  12. #include <fcntl.h>
  13. #include <errno.h>
  14. #include "client.h"
  15. static bool_t ping (devAEM_t dev) {
  16. char_t cmd[72];
  17. devIP_t ip = AEM2ip (dev);
  18. // ask host to ping and make a little pre-process before take the answer
  19. sprintf (cmd,
  20. "test $(ping -c1 -w%d %u.%u.%u.%u| grep received |cut -d' ' -f4) = 1",
  21. settings.pingTimeout, ip.A, ip.B, ip.C, ip.D
  22. );
  23. return (system(cmd) == 0) ? true:false;
  24. }
  25. static size_t seeker (void) {
  26. size_t cnt =0; // count devices on range
  27. log_debug ("Debug: Pinging devices...\n");
  28. for (int i=0 ; i<AEMLIST_SIZE ; ++i) {
  29. if (devList[i].dev == settings.me) {// Don't ping me, I'm not here, go away...
  30. devList[i].dev = false;
  31. continue;
  32. }
  33. if (ping (devList[i].dev)) { // Noc noc....
  34. devList[i].onRange = true; // Who's there?
  35. ++cnt; // No one, bye bye!
  36. log_debug ("Debug: Device %u found\n", devList[i].dev);
  37. }
  38. else
  39. devList[i].onRange = false; // Where is everybody?
  40. }
  41. log_debug ("Debug: %d devices found\n", cnt);
  42. return cnt;
  43. }
  44. static bool_t sendMsg (devAEM_t dev, cMsg_t* msg) {
  45. int sock;
  46. sockaddr_in_t srvAddr;
  47. timeval_t timeout = settings.sendTimeout;
  48. long arg;
  49. bool_t ret = true; // have faith
  50. // Make address
  51. memset(&srvAddr, 0, sizeof (srvAddr));
  52. srvAddr.sin_family= AF_INET;
  53. srvAddr.sin_port= htons (settings.port);
  54. srvAddr.sin_addr.s_addr = htonl (devAEM2addr (dev));
  55. devIP_t ip = AEM2ip (dev);
  56. // Create socket for sending
  57. if ((sock = socket (PF_INET, SOCK_STREAM, 0)) == -1)
  58. return false;
  59. log_debug ("Debug: Socket for sending to %u.%u.%u.%u created\n", ip.A, ip.B, ip.C, ip.D);
  60. do {
  61. // Set non-blocking connect
  62. if((arg = fcntl(sock, F_GETFL, NULL)) < 0) {
  63. ret = false;
  64. log_debug ("Debug: Reading socket's file status failed\n");
  65. break;
  66. }
  67. if(fcntl(sock, F_SETFL, arg | O_NONBLOCK) < 0) {
  68. ret = false;
  69. log_debug ("Debug: Set socket to non-blocking mode failed\n");
  70. break;
  71. }
  72. log_debug ("Debug: Socket switched to non-blocking mode\n");
  73. // Trying to connect with timeout
  74. log_debug ("Debug: Try to connect with timeout\n");
  75. if (connect (sock, (sockaddr_t*)&srvAddr, sizeof(srvAddr)) == -1) {
  76. if (errno == EINPROGRESS) {
  77. fd_set myset;
  78. FD_ZERO (&myset);
  79. FD_SET (sock, &myset);
  80. if (select (sock+1, NULL, &myset, NULL, &timeout) <= 0) {
  81. ret = false;
  82. log_debug ("Debug: Connection failed in select()\n");
  83. break;
  84. }
  85. // Socket selected for write
  86. int valopt;
  87. socklen_t lon = sizeof(int);
  88. if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
  89. ret = false;
  90. log_debug ("Debug: Reading socket's options failed\n");
  91. break;
  92. }
  93. // Check the value returned...
  94. if (valopt) {
  95. ret = false;
  96. log_debug ("Debug: Delayed connection failed\n");
  97. break;
  98. }
  99. }
  100. else {
  101. ret = false;
  102. log_debug ("Debug: Connection failed in select()\n");
  103. break;
  104. }
  105. }
  106. log_debug ("Debug: Connection to %u.%u.%u.%u succeed\n", ip.A, ip.B, ip.C, ip.D);
  107. // Set to blocking mode again...
  108. if( (arg = fcntl(sock, F_GETFL, NULL)) < 0) {
  109. ret = false;
  110. log_debug ("Debug: Reading socket's file status failed\n");
  111. break;
  112. }
  113. arg &= (~O_NONBLOCK);
  114. if( fcntl(sock, F_SETFL, arg) < 0) {
  115. ret = false;
  116. log_debug ("Debug: Set socket back to blocking mode failed\n");
  117. break;
  118. }
  119. log_debug ("Debug: Socket switched to blocking mode\n");
  120. // send the data with timeout
  121. if (setsockopt (sock, SOL_SOCKET, SO_SNDTIMEO, (void*)&timeout, sizeof(timeout)) == -1) {
  122. ret = false;
  123. log_debug ("Debug: Setting send timeout failed\n");
  124. break;
  125. }
  126. log_debug ("Debug: Setting send timeout succeed\n");
  127. if (send (sock, msg->text, strlen(msg->text), MSG_CONFIRM) == -1) {
  128. ret = false;
  129. log_debug ("Debug: Sending failed\n");
  130. break;
  131. }
  132. log_debug ("Debug: Sending succeed\n");
  133. } while (0);
  134. close (sock);
  135. log_debug ("Debug: Closing socket\n");
  136. return ret;
  137. }
  138. static status_t client (void) {
  139. msg_t msg; // new message buffer
  140. while (true) {
  141. sleep (settings.msgInterval); // Idle until the time comes
  142. memset ((void*)&msg, 0, sizeof (msg)); // create a new message
  143. cMsg_make (&msg.cMsg);
  144. msg.sender = settings.me;
  145. log_debug ("Debug: Message created for %d\n", msg.cMsg.to);
  146. statsUpdateCreate (&msg);
  147. msgList_acquire (); // try to lock resources
  148. mIter_t at = msgList_add (&msgList, &msg); // Add message to msgList
  149. log_debug ("Debug: Message added to msgList at %d\n", at);
  150. if (!seeker ()) { // If we are alone skip the rest
  151. msgList_release (); // but unlock resources first
  152. continue;
  153. }
  154. log_debug ("Debug: Devices found on range\n");
  155. mIter_t it = msgList_begin (&msgList); // get a message iterator
  156. // begin with old messages first
  157. // for each message -> for each recipient
  158. for (size_t i=0 ; i<msgList_size(&msgList) ; ++i, msgList_preInc (&it)) {
  159. for (size_t j=0 ; j<AEMLIST_SIZE ; ++j) {
  160. // check when to send
  161. if (devList[j].onRange // is on range
  162. && !msgList.m[it].recipients[j] // we haven't send the message to that device
  163. && msgList.m[it].cMsg.to != settings.me // the message it's not for me
  164. ) {
  165. if (sendMsg (devList[j].dev, &msgList.m[it].cMsg)) {
  166. msgList.m[it].recipients[j] = true;
  167. statsUpdateOut (&msg, devList[j].dev);
  168. log_debug ("Debug: Send message to device %u succeed\n", devList[j].dev);
  169. }
  170. else {
  171. log_debug ("Debug: Send message to device %u failed\n", devList[j].dev);
  172. }
  173. //^ we try to send the message and mark the transmission on success
  174. // if send fail, don't worry it may succeed the next time.
  175. }
  176. }
  177. }
  178. msgList_release (); // Unlock resources
  179. }
  180. return MSG_ERROR;
  181. }
  182. void* pthClient (void* ptr) {
  183. (void)&ptr; // use parameter
  184. if (client () == MSG_ERROR)
  185. exit(1); // we should not be here, client never returns
  186. return NULL;
  187. }