command.c 5.8 KB

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