command.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #include <pthread.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <arpa/inet.h>
  11. #include <netdb.h>
  12. #include <errno.h>
  13. static const unsigned short CommandPort = 4000;
  14. static int SelfPipe[2];
  15. extern char *JpegCapture(int fd, char *tokenPtr);
  16. extern char *VideoCapture(int fd, char *tokenPtr);
  17. extern char *AudioCapture(int fd, char *tokenPtr);
  18. extern char *MotorMove(int fd, char *tokenPtr);
  19. extern char *WaitMotion(int fd, char *tokenPtr);
  20. extern char *IrLed(int fd, char *tokenPtr);
  21. extern char *AudioPlay(int fd, char *tokenPtr);
  22. struct CommandTableSt {
  23. const char *cmd;
  24. char * (*func)(int, char *);
  25. };
  26. struct CommandTableSt CommandTable[] = {
  27. { "video", &VideoCapture },
  28. { "audio", &AudioCapture },
  29. { "jpeg", &JpegCapture },
  30. { "move", &MotorMove },
  31. { "waitMotion", &WaitMotion },
  32. { "irled", &IrLed },
  33. { "aplay", &AudioPlay },
  34. };
  35. void CommandResponse(int fd, const char *res) {
  36. unsigned char buf[256];
  37. buf[0] = strlen(res) + 1;
  38. buf[1] = fd;
  39. strncpy((char *)buf + 2, res, 253);
  40. write(SelfPipe[1], &buf, buf[0] + 2);
  41. }
  42. static void *CommandThread(void *arg) {
  43. static const int MaxConnect = 255;
  44. int maxFd = 0;
  45. fd_set targetFd;
  46. int listenSocket = socket(AF_INET, SOCK_STREAM, 0);
  47. if(listenSocket < 0) {
  48. fprintf(stderr, "socket : %s\n", strerror(errno));
  49. return NULL;
  50. }
  51. int sock_optval = 1;
  52. if(setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR,
  53. &sock_optval, sizeof(sock_optval)) == -1) {
  54. fprintf(stderr, "setsockopt : %s\n", strerror(errno));
  55. close(listenSocket);
  56. return NULL;
  57. }
  58. struct sockaddr_in saddr;
  59. saddr.sin_family = AF_INET;
  60. saddr.sin_port = htons(CommandPort);
  61. saddr.sin_addr.s_addr = htonl(INADDR_ANY);
  62. if(bind(listenSocket, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
  63. fprintf(stderr, "bind : %s\n", strerror(errno));
  64. close(listenSocket);
  65. return NULL;
  66. }
  67. if(listen(listenSocket, MaxConnect) == -1) {
  68. fprintf(stderr, "listen : %s\n", strerror(errno));
  69. close(listenSocket);
  70. return NULL;
  71. }
  72. FD_ZERO(&targetFd);
  73. FD_SET(listenSocket, &targetFd);
  74. maxFd = listenSocket;
  75. FD_SET(SelfPipe[0], &targetFd);
  76. maxFd = (SelfPipe[0] > maxFd) ? SelfPipe[0] : maxFd;
  77. if(maxFd >= MaxConnect) maxFd = MaxConnect - 1;
  78. while(1) {
  79. fd_set checkFDs;
  80. memcpy(&checkFDs, &targetFd, sizeof(targetFd));
  81. if(select(maxFd + 1, &checkFDs, NULL, NULL, NULL) == -1) {
  82. fprintf(stderr, "select error : %s\n", strerror(errno));
  83. } else {
  84. for(int fd = maxFd; fd >= 0; fd--) {
  85. if(FD_ISSET(fd, &checkFDs)) {
  86. if(fd == SelfPipe[0]) {
  87. while(1) {
  88. unsigned char buf[256];
  89. int length = read(SelfPipe[0], buf, 2);
  90. if(length <= 1) break;
  91. int resSize = buf[0];
  92. int resFd = buf[1];
  93. length = read(SelfPipe[0], buf, resSize);
  94. if(length < resSize) break;
  95. char *res = (char *)buf;
  96. if(strlen(res)) {
  97. strcat(res, "\n");
  98. send(resFd, res, strlen(res) + 1, 0);
  99. }
  100. close(resFd);
  101. FD_CLR(resFd, &targetFd);
  102. }
  103. } else if(fd == listenSocket) {
  104. struct sockaddr_in dstAddr;
  105. int len = sizeof(dstAddr);
  106. int newSocket = accept(fd, (struct sockaddr *)&dstAddr, (socklen_t *)&len);
  107. if(newSocket < 0) {
  108. fprintf(stderr, "Socket::Accept Error\n");
  109. continue;
  110. }
  111. if(strcmp(inet_ntoa(dstAddr.sin_addr), "127.0.0.1")) {
  112. fprintf(stderr, "Rejected request from %s\n", inet_ntoa(dstAddr.sin_addr));
  113. close(newSocket);
  114. continue;
  115. }
  116. int flag = fcntl(newSocket, F_GETFL, 0);
  117. fcntl(newSocket, F_SETFL, O_NONBLOCK|flag);
  118. FD_SET(newSocket, &targetFd);
  119. maxFd = (newSocket > maxFd) ? newSocket : maxFd;
  120. if(maxFd >= MaxConnect) maxFd = MaxConnect - 1;
  121. } else {
  122. char buf[256];
  123. int size = recv(fd, buf, 255, 0);
  124. if(!size) {
  125. FD_CLR(fd, &targetFd);
  126. break;
  127. }
  128. if(size < 0) {
  129. close(fd);
  130. FD_CLR(fd, &targetFd);
  131. break;
  132. }
  133. buf[size] = 0;
  134. char *tokenPtr;
  135. char *p = strtok_r(buf, " \t\r\n", &tokenPtr);
  136. if(!p) continue;
  137. int executed = 0;
  138. for(int i = 0; i < sizeof(CommandTable) / sizeof(struct CommandTableSt); i++) {
  139. if(!strcasecmp(p, CommandTable[i].cmd)) {
  140. char *res = (*CommandTable[i].func)(fd, tokenPtr);
  141. if(res) {
  142. send(fd, res, strlen(res) + 1, 0);
  143. char cr = '\n';
  144. send(fd, &cr, 1, 0);
  145. close(fd);
  146. FD_CLR(fd, &targetFd);
  147. }
  148. executed = 1;
  149. break;
  150. }
  151. }
  152. if(!executed) {
  153. char *res = "error";
  154. send(fd, res, strlen(res) + 1, 0);
  155. close(fd);
  156. FD_CLR(fd, &targetFd);
  157. fprintf(stderr, "command error : %s\n", p);
  158. }
  159. }
  160. }
  161. }
  162. }
  163. }
  164. }
  165. static void __attribute ((constructor)) command_init(void) {
  166. if(pipe(SelfPipe)) {
  167. fprintf(stderr, "pipe error\n");
  168. return;
  169. }
  170. int flag = fcntl(SelfPipe[0], F_GETFL, 0);
  171. fcntl(SelfPipe[0], F_SETFL, O_NONBLOCK|flag);
  172. flag = fcntl(SelfPipe[1], F_GETFL, 0);
  173. fcntl(SelfPipe[1], F_SETFL, O_NONBLOCK|flag);
  174. pthread_t thread;
  175. pthread_create(&thread, NULL, CommandThread, NULL);
  176. }