thermferm/server.c

changeset 43
24e731bb2e08
parent 42
01b96a24ae7c
child 44
f37d73940699
equal deleted inserted replaced
42:01b96a24ae7c 43:24e731bb2e08
27 27
28 extern bool my_shutdown; 28 extern bool my_shutdown;
29 extern bool debug; 29 extern bool debug;
30 extern int lcdHandle; 30 extern int lcdHandle;
31 extern unsigned char lcdbuf[MAX_LCDS][20][4]; 31 extern unsigned char lcdbuf[MAX_LCDS][20][4];
32 32 extern sys_config Config;
33 33 extern int clients;
34 int sock = -1; 34
35 int s; /* connected socket */
36 int ls; /* listen socket */
37
38 struct sockaddr_in myaddr_in; /* for local socket address */
39 struct sockaddr_in peeraddr_in; /* for peer socket address */
40
41 struct hostent *hp;
42
43 #define SS_BUFSIZE 1024
44 #define SS_TIMEOUT 300
35 45
36 46
37 char *exe_cmd(char *); 47 char *exe_cmd(char *);
38 48
39 49
56 return (char *)"ERROR"; 66 return (char *)"ERROR";
57 } 67 }
58 68
59 69
60 70
61 void do_cmd(char *cmd) 71 int server_init(void)
62 { 72 {
63 char buf[1024]; 73 int optval = 1;
64 int slen, tries = 0; 74
65 75 memset((char *)&myaddr_in, 0, sizeof(struct sockaddr_in));
76 memset((char *)&peeraddr_in, 0, sizeof(struct sockaddr_in));
77 myaddr_in.sin_family = AF_INET;
78 myaddr_in.sin_addr.s_addr = INADDR_ANY;
79 myaddr_in.sin_port = htons(Config.my_port);
80
81 ls = socket(AF_INET, SOCK_STREAM, 0);
82 if (ls == -1) {
83 syslog(LOG_NOTICE, "Can't create listen socket: %s", strerror(errno));
84 fprintf(stderr, "Can't create listen socket: %s\n", strerror(errno));
85 return 1;
86 }
87
88 if (setsockopt(ls, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1) {
89 syslog(LOG_NOTICE, "Can't setsockopt SO_KEEPALIVE socket: %s", strerror(errno));
90 close(ls);
91 return 1;
92 }
93
94 if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) {
95 syslog(LOG_NOTICE, "Can't setsockopt SO_REUSEADDR socket: %s", strerror(errno));
96 close(ls);
97 return 1;
98 }
99
100 if (bind(ls, (struct sockaddr *)&myaddr_in, sizeof(struct sockaddr_in)) == -1) {
101 syslog(LOG_NOTICE, "Can't bind to listen socket: %s", strerror(errno));
102 close(ls);
103 return 1;
104 }
105
106 syslog(LOG_NOTICE, "listen socket created %d", ls);
66 if (debug) 107 if (debug)
67 fprintf(stdout, "do_cmd(%s)\n", cmd); 108 fprintf(stdout, "listen socket created %d\n", ls);
68 109
69 snprintf(buf, 1024, "%s", exe_cmd(cmd)); 110
70 111 return 0;
112 }
113
114
115
116 /*
117 * Send message to client
118 */
119 int srv_send(const char *format, ...)
120 {
121 char out[SS_BUFSIZE];
122 va_list va_ptr;
123
124 if (s == -1)
125 return -1;
126
127 va_start(va_ptr, format);
128 vsnprintf(out, SS_BUFSIZE-1, format, va_ptr);
129 va_end(va_ptr);
130
131 if (send(s, out, strlen(out), 0) != strlen(out)) {
132 syslog(LOG_NOTICE, "srv_send failed");
133 return -1;
134 }
135
136 if (send(s, (char *)"\r\n", 2, 0) != 2) {
137 syslog(LOG_NOTICE, "srv_send failed");
138 return -1;
139 }
140
141 syslog(LOG_NOTICE, "send: \"%s\"", out);
142 return 0;
143 }
144
145
146
147 void cmd_die(int onsig)
148 {
149 syslog(LOG_NOTICE, "Server process die on signal %d", onsig);
150 close(s);
151 exit(0);
152 }
153
154
155
156 void cmd_server(void)
157 {
158 char *hostname, buf[SS_BUFSIZE];
159 int i, rc, rlen, timer;
160 socklen_t fromlen;
161 struct pollfd pfd[1];
162
163 /*
164 * Close listen socket
165 */
166 close(ls);
167 /*
168 * Install private signal handler.
169 */
170 for (i = 0; i < NSIG; i++) {
171 if ((i == SIGHUP) || (i == SIGPIPE) || (i == SIGBUS) || (i == SIGILL) || (i == SIGSEGV))
172 signal(i, (void (*))cmd_die);
173 else
174 signal(i, SIG_IGN);
175 }
176
177 hp = gethostbyaddr ((char *) &peeraddr_in.sin_addr, sizeof(struct in_addr), peeraddr_in.sin_family);
178 if (hp == NULL) {
179 hostname = inet_ntoa(peeraddr_in.sin_addr);
180 } else {
181 hostname = hp->h_name;
182 }
183
184 clients++;
185 syslog(LOG_NOTICE, "Start new client connection (%d) from %s port %u", clients, hostname, ntohs(peeraddr_in.sin_port));
186 timer = SS_TIMEOUT * 4;
187
188 /*
189 * Receive loop
190 */
191 for (;;) {
192 /*
193 * Poll socket until a define timeout of 0,25 second.
194 */
195 pfd[0].fd = s;
196 pfd[0].events = POLLIN;
197 pfd[0].revents = 0;
198 rc = poll(pfd, 1, 250);
199
200 if (rc == -1) {
201 /*
202 * Poll can be interrupted by a finished child so that's not a real error.
203 */
204 if (errno != EINTR) {
205 syslog(LOG_NOTICE, "poll() rc=%d sock=%d events=%04x", rc, s, pfd[0].revents);
206 }
207 } else if (rc) {
208 if (pfd[0].revents & POLLIN) {
209 memset((char *)&buf, 0, SS_BUFSIZE);
210 fromlen = sizeof(peeraddr_in);
211 rlen = recvfrom(s, buf, sizeof(buf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen);
212 if (rlen == -1) {
213 syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno));
214 } else {
215 for (i = 0; i < strlen(buf); i++) {
216 if (buf[i] == '\n')
217 buf[i] = '\0';
218 if (buf[i] == '\r')
219 buf[i] = '\0';
220 }
221 timer = SS_TIMEOUT * 4;
222 if (strlen(buf)) {
223 syslog(LOG_NOTICE, "recv: \"%s\"", buf);
224
225 /*
226 * Process command from the client
227 */
228 srv_send(exe_cmd(buf));
229 }
230 }
231 } else {
232 syslog(LOG_NOTICE, "poll other event");
233 }
234
235 } else {
236 /*
237 * Poll timeout, do some housekeeping
238 */
239 if (timer) {
240 timer--;
241 } else {
242 /* Inactivity timeout */
243 break;
244 }
245 if (my_shutdown) {
246 break;
247 }
248 }
249 }
250 }
251
252
253
254 PI_THREAD (my_server_loop)
255 {
256 socklen_t addrlen;
257
258 syslog(LOG_NOTICE, "Thread my_server_loop started");
71 if (debug) 259 if (debug)
72 fprintf(stdout, "do_cmd() reply=\"%s\" len=%d\n", buf, strlen(buf)); 260 fprintf(stdout, "Thread my_server_loop started\n");
73 261
262 /*
263 * Loop forever until the external shutdown variable is set.
264 */
74 for (;;) { 265 for (;;) {
75 // slen = sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&from, fromlen); 266
76 267 addrlen = sizeof(struct sockaddr_in);
77 if (debug) 268 /*
78 fprintf(stdout, "do_cmd() slen=%d tries=%d %s\n", slen, tries, strerror(errno)); 269 * This call will block until a new connection
79 // if (slen == -1) 270 * arrives. Then it will return the address of
80 // syslog(LOG_NOTICE, "do_cmd(): sendto error %d %s", tries, from.sun_path); 271 * the connecting peer, and a new socket
81 else if (slen != strlen(buf)) 272 * descriptor, s, for that connection.
82 syslog(LOG_NOTICE, "do_cmd(): send %d of %d bytes, try=%d", slen, strlen(buf), tries); 273 */
83 else 274 s = accept(ls, (struct sockaddr *)&peeraddr_in, &addrlen);
84 return; 275 if (s == -1) {
85 tries++; 276 syslog(LOG_NOTICE, "my_server_loop accept failed %s", strerror(errno));
86 if (tries == 3) 277 if (debug)
87 return; 278 fprintf(stdout, "my_server_loop accept failed %s\n", strerror(errno));
88 else 279 return 1;
89 sleep(1); 280 }
90 } 281
91 } 282 switch (fork()) {
92 283 case -1: /*
93 284 * Can't fork, just continue.
285 */
286 return 1;
287 case 0: /*
288 * Child process, the commandline server.
289 */
290 cmd_server();
291 return 0;
292 default: /*
293 * Daemon process comes here. The daemon
294 * needs to remember to close the new
295 * accept socket after forking the child.
296 */
297 close(s);
298 }
299
300 if (my_shutdown) {
301 syslog(LOG_NOTICE, "Thread my_server_loop stopped");
302 if (debug)
303 fprintf(stdout, "Thread my_server_loop stopped\n");
304 return 0;
305 }
306
307 }
308 }
309
310
311

mercurial