1 /*
2 
3     Copyright (C) 2009,2016 Alois Schloegl <alois.schloegl@gmail.com>
4     This file is part of the "BioSig for C/C++" repository
5     (biosig4c++) at http://biosig.sf.net/
6 
7     BioSig is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; either version 3
10     of the License, or (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 
20 */
21 
22 #include "biosig-network.h"
23 
24 #include <ctype.h>
25 #include <dirent.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sys/stat.h>
31 #include <time.h>
32 #include <syslog.h>
33 #include <sys/wait.h>
34 #include <signal.h>
35 
36 #ifdef WITH_MICROMED
37 void sopen_trc_read(HDRTYPE *hdr);
38 #endif
39 #ifdef WITH_PDP
40 void sopen_pdp_read(HDRTYPE *hdr);
41 #endif
42 
43 const char *LOGFILE = "/tmp/biosig/biosigd.log";
44 
45 /*
46 	Key ID table and related functions
47 */
48 struct IDTABLE_T {
49 	uint64_t id;
50 	uint64_t gtime;	// time of file generation
51 	struct sockaddr_in addr;
52 } *IdTablePtr;
53 size_t IdTableLen;
54 
55 
56 /*
57 	compare uint32_t
58 */
u64cmp(const void * a,const void * b)59 int u64cmp(const void *a,const void *b)
60 {
61 	unsigned int k=7;
62 	int r=0;
63 	while (!r && (k<sizeof(uint64_t))) {
64 		r = ((uint8_t*)a)[k] - ((uint8_t*)b)[k];
65 		k--;
66 	}
67 	return(r);
68 }
69 
70 /*
71 	generate new unique id
72  */
GetNewId()73 uint64_t GetNewId() {
74 
75 	int k;
76 	uint64_t c;
77 	FILE *fid = fopen("/dev/urandom","r");
78 	do {
79 		fread(&c,sizeof(c),1,fid);
80 	} while (bsearch(&c, IdTablePtr, IdTableLen, sizeof(IDTABLE_T), &u64cmp));
81 	fclose(fid);
82 
83 	k = IdTableLen;
84 	IdTableLen++;
85 	IdTablePtr = (IDTABLE_T*)realloc(IdTablePtr,IdTableLen*sizeof(IDTABLE_T));
86 	while ((c < IdTablePtr[k].id) && (k>0)) {
87 		IdTablePtr[k].id = IdTablePtr[k-1].id;
88 		k--;
89 	}
90 	IdTablePtr[k].id = c;
91 	IdTablePtr[k].gtime = t_time2gdf_time(time(NULL));
92 //	memcpy(&IdTablePtr[k].addr, addr, sizeof(struct sockaddr_in));
93 
94 	return(c);
95 };
96 
97 
98 /*TODO: semaphore */
LoadIdTable(const char * path)99 size_t LoadIdTable(const char *path) {
100 
101 	IdTableLen = 0;
102 	DIR *d = opendir(path);
103 	if (d==NULL) {
104 		mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
105 		return(0);
106 	}
107 
108 	uint64_t ID;
109 	size_t N=0;
110     	struct dirent *dp;
111     	do {
112         	errno = 0;
113         	if ((dp = readdir(d)) != NULL) {
114 			IdTablePtr = (IDTABLE_T*)realloc(IdTablePtr,(N+1)*sizeof(IDTABLE_T));
115 			cat64(dp->d_name,&ID);
116 			if (ID != 0) {
117 				IdTablePtr[N].id = ID;
118 				N++;
119 			}
120         	}
121 	} while (dp != NULL);
122 	closedir(d);
123 
124 	qsort(IdTablePtr,N,sizeof(IDTABLE_T),&u64cmp);
125 	IdTableLen = N;
126 
127 	fprintf(stdout,"Load Id Table: %i entries found.\n",N);
128 
129 	if (VERBOSE_LEVEL>8)
130 		for (int k=0; k<N; k++)
131 			fprintf(stdout,"%3i %016lx\n",k+1,IdTablePtr[k].id);
132 
133 	return(N);
134 };
135 
136 
sigchld_handler(int s)137 void sigchld_handler(int s)
138 {
139     while(waitpid(-1, NULL, WNOHANG) > 0);
140 }
141 
142 
143 //#define VERBOSE_LEVEL 8
144 
145 const char   path[] = "/tmp/biosig/\0                .gdf";
DoJob(int ns)146 void DoJob(int ns)
147 {
148 		char fullfilename[] = "/tmp/biosig/                .gdf";
149 		const size_t pathlen = strlen(path);
150 		char *filename = fullfilename+pathlen;
151 
152 //    		size_t sizbuf = BSCS_MAX_BUFSIZ+8;
153 		uint8_t inbuf[BSCS_MAX_BUFSIZ+8];
154 		HDRTYPE *hdr = NULL;
155 		uint64_t ID = 0;
156 		uint32_t STATUS = STATE_INIT;
157 		char stopflag = 0;
158 		size_t datalen = 0;
159 		mesg_t msg;
160 
161 		if ((VERBOSE_LEVEL>7) && errno) {
162 			errno = 0;
163 			fprintf(stdout,"## errno=%i %s\n",errno,strerror(errno));
164 		}
165 
166 		/* Create a new SID for the child process */
167 		pid_t sid = setsid();
168 		if (sid < 0) {
169 			exit(-1);
170 		}
171 
172 		/*server identification */
173 		const char *greeting="Hi there,\n this is your experimental BSCS server. \n It is useful for testing the BioSig client-server architecture.\n";
174 		msg.STATE = BSCS_VERSION_01 | BSCS_SEND_MSG | STATE_INIT | BSCS_NO_ERROR;
175 		msg.LEN = htobe32(strlen(greeting));
176 		int s;
177 		s = send(ns,&msg,8,0);
178 		s = send(ns, greeting, strlen(greeting), 0);
179 
180 	    	while (!stopflag) // wait for command
181 		{
182 			fprintf(stdout,":> ");
183 	   		ssize_t count = recv(ns, &msg, 8, 0);
184 			fprintf(stdout,"STATUS=%08x c=%i MSG=%08x len=%i,errno=%i %s\n",STATUS,count,be32toh(msg.STATE),be32toh(msg.LEN),errno,strerror(errno));
185 			size_t  LEN = be32toh(msg.LEN);
186 
187 			FILE *fid = fopen(LOGFILE,"a");
188 			fprintf(stdout,"STATUS=%08x c=%i MSG=%08x len=%i,errno=%i %s\n",STATUS,count,be32toh(msg.STATE),be32toh(msg.LEN),errno,strerror(errno));
189 			fclose(fid);
190 			errno = 0;
191 
192 	   		if (count==0) {
193 				fprintf(stdout,"connection lost! %i %i %i %s\n",stopflag,count,errno,strerror(errno));
194 				LEN = 0;
195 				stopflag=1;
196 				continue;
197 	   		}
198 	   		else if (count<0) {
199 				fprintf(stdout,"invalid packet! %i %i %i %s\n",stopflag,count,errno,strerror(errno));
200 				LEN = 0;
201 	   		}
202 			else if ((msg.STATE & CMD_MASK) == BSCS_NOP)
203 			{	// no operation
204 
205 				count = 0;
206 				while (count<LEN) {
207 			   		count += recv(ns, inbuf, min(BSCS_MAX_BUFSIZ,LEN-count), 0);
208 				}
209 				msg.STATE = BSCS_VERSION_01 | BSCS_NOP | BSCS_REPLY | (msg.STATE & STATE_MASK) | BSCS_NO_ERROR;
210 
211 				// send reply
212 				msg.LEN = htobe32(0);
213 				s = send(ns, &msg, 8, 0);
214 			}
215 
216 			else if ((STATUS == STATE_INIT) &&
217 			    	 ((msg.STATE & ~ERR_MASK) == (BSCS_VERSION_01 | BSCS_OPEN | STATE_INIT)))
218 			{
219 /****************************************************************************************
220 	OPEN FILE with ID
221  ****************************************************************************************/
222 
223 				if (VERBOSE_LEVEL>7) fprintf(stdout,"open %i %i %016lx\n",LEN,count,ID);
224 
225 				hdr = constructHDR(0,0);
226 				if (LEN==0) //|| ((LEN==8) && (ID==0))) 	// no ID, send back id, open(w)
227 				{
228 					ID = GetNewId();
229 					c64ta(ID, filename);
230 					hdr->FLAG.ANONYMOUS = 1; 	// do not store name
231 					STATUS = STATE_OPEN_WRITE_HDR;
232 					msg.STATE = BSCS_VERSION_01 | BSCS_OPEN_W | BSCS_REPLY | STATE_OPEN_WRITE_HDR;
233 					msg.LEN = htobe32(8);
234 					leu64a(ID, &msg.LOAD);
235 					s = send(ns, &msg, 16, 0);
236 
237 		FILE *fid = fopen(LOGFILE,"a");
238 		fprintf(fid,"\t> %s",filename);
239 		fclose(fid);
240 
241 				}
242 				else if (LEN == 8) 		// open(r)
243 				{
244 		   			count = recv(ns, &msg.LOAD, 8, 0);
245 					ID = leu64p((uint8_t*)&msg.LOAD);
246 
247 					c64ta(ID, filename);
248 					// ToDo: replace SOPEN with simple function, e.g. access to event table not needed here
249 					hdr->FLAG.ANONYMOUS = 1; 	// do not store name
250 					hdr->FileName = fullfilename;
251 					hdr = sopen(fullfilename,"r",hdr);
252 					msg.LEN = htobe32(0);
253 					if (hdr->FILE.OPEN==0) {
254 						msg.STATE = BSCS_VERSION_01 | BSCS_OPEN_R | BSCS_REPLY | STATE_INIT | BSCS_ERROR_CANNOT_OPEN_FILE;
255 						STATUS = STATE_INIT;
256 					} else if (serror2(hdr) || (hdr->NRec < 0)) {
257 						sclose(hdr);
258 						msg.STATE = BSCS_VERSION_01 | BSCS_OPEN_R | BSCS_REPLY | STATE_INIT | BSCS_ERROR_CANNOT_OPEN_FILE;
259 						STATUS = STATE_INIT;
260 					} else 	{
261 						msg.STATE = BSCS_VERSION_01 | BSCS_OPEN_R | BSCS_REPLY | STATE_OPEN_READ;
262 						STATUS = STATE_OPEN_READ;
263 					}
264 					s = send(ns, &msg, 8, 0);
265 		FILE *fid = fopen(LOGFILE,"a");
266 		fprintf(fid,"\t< %s",filename);
267 		fclose(fid);
268 				}
269 				else //if (LEN != 8)
270 				{
271 					STATUS = STATE_INIT;
272 					msg.STATE = BSCS_VERSION_01 | BSCS_OPEN_W | BSCS_REPLY | STATE_INIT | BSCS_ERROR_INCORRECT_PACKET_LENGTH;
273 					msg.LEN = htobe32(0);
274 					s = send(ns, &msg, 8, 0);
275 				}
276 			}
277 
278 			else if ((STATUS == (msg.STATE & STATE_MASK)) &&
279 				 (LEN == 0) &&
280 				 ((msg.STATE & (VER_MASK | CMD_MASK)) == (BSCS_VERSION_01 | BSCS_CLOSE)))
281 			{	// close
282 /****************************************************************************************
283 	CLOSE FILE
284  ****************************************************************************************/
285 
286 				if (STATUS != (msg.STATE & STATE_MASK)) fprintf(stdout,"Close: status does not fit\n");
287 
288 				msg.STATE = BSCS_VERSION_01 | BSCS_CLOSE | BSCS_REPLY | STATE_INIT;
289 				msg.LEN = htobe32(0);
290 
291 				if (LEN != 0)
292 					msg.STATE = BSCS_VERSION_01 | BSCS_CLOSE | BSCS_REPLY | STATE_INIT | BSCS_ERROR_INCORRECT_PACKET_LENGTH;
293 
294 				if ((STATUS == STATE_OPEN_WRITE_HDR) || (STATUS == STATE_OPEN_WRITE)) {
295 					if (hdr->NRec != datalen/hdr->AS.bpb)
296 						hdr->NRec = -1; // this triggers sclose to compute the correct size
297 				}
298 
299 				if ((hdr!=NULL) && ((STATUS != STATE_OPEN_READ) || (STATUS != STATE_OPEN_READ)) )
300 					sclose(hdr);
301 
302 				if (STATUS != STATE_INIT) {
303 					destructHDR(hdr);
304 					hdr = NULL;
305 				}
306 
307 				hdr = NULL;
308 				if (serror2(hdr))
309 					msg.STATE = BSCS_VERSION_01 | BSCS_CLOSE | BSCS_REPLY | STATE_INIT | BSCS_ERROR_CLOSE_FILE;
310 
311 				STATUS = STATE_INIT;
312 
313 				s = send(ns, &msg, 8, 0);
314 
315 			}
316 
317 			else if ((STATUS == STATE_OPEN_WRITE_HDR) &&
318 				 ((msg.STATE & ~ERR_MASK) == (BSCS_VERSION_01 | BSCS_SEND_HDR | STATE_OPEN_WRITE_HDR)))
319 			{
320 /****************************************************************************************
321 	SEND HEADER
322  ****************************************************************************************/
323 
324 				//case BSCS_SEND_HDR:  	// send header information
325 				hdr->AS.Header = (uint8_t*)realloc(hdr->AS.Header,LEN);
326 				hdr->HeadLen = LEN;
327 				count = 0;
328 				while (count<LEN) {
329 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND HDR: c=%i,LEN=%i\n",count,LEN);
330 					count += recv(ns, hdr->AS.Header+count, LEN-count, 0);
331 				}
332 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND HDR: c=%i,LEN=%i\n",count,LEN);
333 
334 				hdr->TYPE = GDF;
335 				hdr->FLAG.ANONYMOUS = 1; 	// do not store name
336 				gdfbin2struct(hdr);
337 
338 				hdr->EVENT.N = 0;
339 				hdr->EVENT.POS = NULL;
340 				hdr->EVENT.TYP = NULL;
341 				hdr->EVENT.DUR = NULL;
342 				hdr->EVENT.CHN = NULL;
343 
344 				c64ta(ID, filename);
345 				hdr->FileName  = fullfilename;
346 				hdr->FILE.COMPRESSION = 0;
347 				ifopen(hdr,"w");
348 				hdr->FILE.OPEN = 2;
349 				count=ifwrite(hdr->AS.Header, 1, hdr->HeadLen, hdr);
350 				datalen = 0;
351 
352 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND HDR: count=%i\n",count);
353 
354 				if (errno) {
355 					// check for errors in gdfbin2struct, ifopen and ifwrite
356 					STATUS = STATE_OPEN_WRITE_HDR;
357 					msg.STATE = BSCS_VERSION_01 | BSCS_SEND_HDR | BSCS_REPLY | STATE_OPEN_WRITE_HDR | BSCS_ERROR_COULD_NOT_WRITE_HDR;
358 				}
359 				else {
360 					STATUS = STATE_OPEN_WRITE;
361 					msg.STATE = BSCS_VERSION_01 | BSCS_SEND_HDR | BSCS_REPLY | STATE_OPEN_WRITE;
362 				}
363 				msg.LEN = htobe32(0);
364 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND HDR RPLY: %08x\n",msg.STATE);
365 				s = send(ns, &msg, 8, 0);
366 			}
367 
368 
369 			else if ((STATUS == STATE_OPEN_WRITE) &&
370 				 ((msg.STATE & ~ERR_MASK) == (BSCS_VERSION_01 | BSCS_SEND_DAT | STATE_OPEN_WRITE)))
371 			{
372 /****************************************************************************************
373 	SEND DATA
374  ****************************************************************************************/
375 				//case BSCS_SEND_DAT:   	// send data block
376 				// ToDo: check corrupt packet
377 					count = 0;
378 					while (count<LEN) {
379 						// ToDo: check if streams would be faster
380 						// fprintf(stdout,"SEND_DAT %li %li %li\n",datalen,count,LEN);
381 					   	ssize_t c = recv(ns, inbuf, min(BSCS_MAX_BUFSIZ,LEN-count), 0);
382 						datalen += ifwrite(inbuf, 1, c, hdr);
383 					   	count += c;
384 					}
385 					//STATUS = STATE_OPEN_WRITE;
386 
387 				if (errno) {
388 					// check for errors in ifwrite
389 					msg.STATE = BSCS_VERSION_01 | BSCS_SEND_DAT | BSCS_REPLY | STATE_OPEN_WRITE | BSCS_ERROR_COULD_NOT_WRITE_DAT;
390 				}
391 				else {
392 					msg.STATE = BSCS_VERSION_01 | BSCS_SEND_DAT | BSCS_REPLY | STATE_OPEN_WRITE;
393 				}
394 				msg.LEN = htobe32(0);
395 				s = send(ns, &msg, 8, 0);
396 			}
397 
398 			else if ((STATUS == STATE_OPEN_WRITE) &&
399 				 ((msg.STATE & ~ERR_MASK) == (BSCS_VERSION_01 | BSCS_SEND_EVT | STATE_OPEN_WRITE)))
400 			{
401 /****************************************************************************************
402 	SEND EVENTS
403  ****************************************************************************************/
404 				//case BSCS_SEND_EVT:  	// send event information
405 
406 
407 		   		count = recv(ns, inbuf+8, min(8,LEN), 0);
408 		   		if (count<8) continue;
409 
410 				char  flag = inbuf[8];
411 				int   N = inbuf[9] + (inbuf[10] + inbuf[11]*256)*256;
412 				//float Fs = lef32p(inbuf+12);
413 
414 				if (LEN != (8 + N * (flag==3 ? 12u : 6u)))
415 				{
416 					msg.STATE = BSCS_VERSION_01 | BSCS_SEND_EVT | BSCS_REPLY | STATE_OPEN_WRITE | BSCS_ERROR_INCORRECT_PACKET_LENGTH;
417 				}
418 
419 				else if (N>0) {
420 					size_t n = hdr->EVENT.N;
421 					hdr->EVENT.N += N;
422 	 				hdr->EVENT.POS = (uint32_t*) realloc(hdr->EVENT.POS, hdr->EVENT.N*sizeof(*hdr->EVENT.POS) );
423 					hdr->EVENT.TYP = (uint16_t*) realloc(hdr->EVENT.TYP, hdr->EVENT.N*sizeof(*hdr->EVENT.TYP) );
424 					hdr->EVENT.DUR = (uint32_t*) realloc(hdr->EVENT.DUR, hdr->EVENT.N*sizeof(*hdr->EVENT.DUR) );
425 					hdr->EVENT.CHN = (uint16_t*) realloc(hdr->EVENT.CHN, hdr->EVENT.N*sizeof(*hdr->EVENT.CHN) );
426 
427 					// read EVENT.POS
428 					count = 0;
429 					LEN = N*sizeof(*hdr->EVENT.POS);
430 					while (count < LEN) {
431 						count += recv(ns, (uint8_t*)(hdr->EVENT.POS+n)+count, LEN-count, 0);
432 					}
433 					// read EVENT.TYP
434 					count = 0;
435 					LEN = N*sizeof(*hdr->EVENT.TYP);
436 					while (count < LEN) {
437 						count += recv(ns, (uint8_t*)(hdr->EVENT.TYP+n)+count, LEN-count, 0);
438 					}
439 					// read EVENT.DUR and EVENT.CHN
440 					if (flag==3) {
441 						count = 0;
442 						LEN = N*sizeof(*hdr->EVENT.POS);
443 						while (count < LEN) {
444 							count += recv(ns, (uint8_t*)(hdr->EVENT.DUR+n)+count, LEN-count, 0);
445 						}
446 						count = 0;
447 						LEN = N*sizeof(*hdr->EVENT.TYP);
448 						while (count < LEN) {
449 							count += recv(ns, (uint8_t*)(hdr->EVENT.CHN+n)+count, LEN-count, 0);
450 						}
451 					}
452 					else {
453 						for (size_t k=n; k<hdr->EVENT.N; k++) {
454 							hdr->EVENT.DUR[k] = 0;
455 							hdr->EVENT.CHN[k] = 0;
456 						}
457 					}
458 #if __BYTE_ORDER == __BIG_ENDIAN
459 					// do byte swapping if needed
460 					for (size_t k=n; k<hdr->EVENT.N; k++) {
461 						hdr->EVENT.POS[k] = htole32(hdr->EVENT.POS[k]);
462 						hdr->EVENT.TYP[k] = htole16(hdr->EVENT.TYP[k]);
463 					}
464 					if (flag==3) {
465 						for (size_t k=n; k<hdr->EVENT.N; k++) {
466 							hdr->EVENT.DUR[k] = htole32(hdr->EVENT.DUR[k]);
467 							hdr->EVENT.CHN[k] = htole16(hdr->EVENT.CHN[k]);
468 						}
469 					}
470 #endif
471 					msg.STATE = BSCS_VERSION_01 | BSCS_SEND_EVT | BSCS_REPLY | STATE_OPEN_WRITE;
472 				}
473 				msg.LEN = htobe32(0);
474 				s = send(ns, &msg, 8, 0);
475 			}
476 
477 			else if ((msg.STATE & CMD_MASK) ==  BSCS_SEND_MSG )
478 			{	// might become obsolet (?)
479 				// ToDo: check corrupt packet
480 				count = 0;
481 				ssize_t c=0;
482 				while (count<LEN) {
483 					int len = min(BSCS_MAX_BUFSIZ-1,LEN-count);
484 				   	c = recv(ns, inbuf, len, 0);
485 			   		inbuf[c-1]=0;
486 					fprintf(stdout,"got message <%s>\n",(char*)(inbuf));
487 				   	count += c;
488 				}
489 				//system((char*)(inbuf));
490 			// TODO: reply message
491 			}
492 
493 			else if ((STATUS == STATE_OPEN_READ) &&
494 				 ((msg.STATE & ~ERR_MASK) == (BSCS_VERSION_01 | BSCS_REQU_HDR | STATE_OPEN_READ)))
495 			{
496 /****************************************************************************************
497 	REQUEST HEADER
498  ****************************************************************************************/
499 				msg.STATE = BSCS_VERSION_01 | BSCS_REQU_HDR | BSCS_REPLY | STATE_OPEN_READ;
500 				msg.LEN = htobe32(hdr->HeadLen);
501 				s = send(ns, &msg, 8, 0);
502 				s = send(ns, hdr->AS.Header, hdr->HeadLen, 0);
503 
504 			}
505 
506 			else if ((STATUS == STATE_OPEN_READ) &&
507 				 ((msg.STATE & ~ERR_MASK) == (BSCS_VERSION_01 | BSCS_REQU_DAT | STATE_OPEN_READ)))
508 			{
509 /****************************************************************************************
510 	REQUEST DATA
511  ****************************************************************************************/
512 	   			count += recv(ns, inbuf, 8, 0);
513 		   		size_t length = leu32p(inbuf);
514 		   		size_t start = leu32p(inbuf+4);
515 				sread_raw(start, length, hdr, 0);
516 
517 				length = min(length, hdr->AS.first + hdr->AS.length - start);
518 				msg.STATE = BSCS_VERSION_01 | BSCS_REQU_DAT | BSCS_REPLY | STATE_OPEN_READ;
519 				msg.LEN = htobe32(hdr->AS.bpb*length);
520 				s = send(ns, &msg, 8, 0);
521 				s = send(ns, hdr->AS.rawdata + hdr->AS.bpb*(start-hdr->AS.first), hdr->AS.bpb*length, 0);
522 				//send(ns, hdr->AS.rawdata, (hdr->AS.length-hdr->AS.first)*hdr->AS.bpb,0);
523 			}
524 
525 			else if ((STATUS == STATE_OPEN_READ) &&
526 				 ((msg.STATE & ~ERR_MASK) == (BSCS_VERSION_01 | BSCS_REQU_EVT | STATE_OPEN_READ)))
527 			{
528 /****************************************************************************************
529 	REQUEST EVENT TABLE
530  ****************************************************************************************/
531 				size_t len = 0;
532 				if ((hdr->TYPE == GDF) && (hdr->AS.rawEventData == NULL) && (hdr->NRec>=0)) {
533 					// event table from GDF file
534 					ifseek(hdr, hdr->HeadLen + hdr->AS.bpb*hdr->NRec, SEEK_SET);
535 					// READ EVENTTABLE
536 					hdr->AS.rawEventData = (uint8_t*)realloc(hdr->AS.rawEventData,8);
537 					int c = ifread(hdr->AS.rawEventData, sizeof(uint8_t), 8, hdr);
538 	    				uint8_t *buf = hdr->AS.rawEventData;
539 
540 					if (c<8) {
541 						hdr->EVENT.N = 0;
542 					}
543 					else if (hdr->VERSION < 1.94) {
544 						hdr->EVENT.N = leu32p(buf + 4);
545 					}
546 					else {
547 						hdr->EVENT.N = buf[1] + (buf[2] + buf[3]*256)*256;
548 					}
549 					int sze = (buf[0]>1) ? 12 : 6;
550 					len = 8+hdr->EVENT.N*sze;
551 					hdr->AS.rawEventData = (uint8_t*)realloc(hdr->AS.rawEventData,len);
552 					ifread(hdr->AS.rawEventData+8, 1, len-8, hdr);
553 					ifseek(hdr, hdr->HeadLen+hdr->AS.bpb*hdr->FILE.POS, SEEK_SET);
554 					// note: no conversion to HDR.EVENT structure needed on server-side
555 				}
556 				else if ((hdr->TYPE != GDF) && (hdr->AS.rawEventData == NULL))
557 					len = hdrEVT2rawEVT(hdr);
558 
559 				else if ((hdr->TYPE == GDF) && (hdr->AS.rawEventData != NULL)){
560 					uint8_t *buf = hdr->AS.rawEventData;
561 					if (hdr->VERSION < 1.94)
562 						hdr->EVENT.N = leu32p(buf + 4);
563 					else
564 						hdr->EVENT.N = buf[1] + (buf[2] + buf[3]*256)*256;
565 
566 					int sze = (buf[0]>1) ? 12 : 6;
567 
568 					if (hdr->EVENT.N>0) {
569 						len = 8+sze*hdr->EVENT.N;
570 					}
571 				}
572 
573 				msg.STATE = BSCS_VERSION_01 | BSCS_REQU_HDR | BSCS_REPLY | STATE_OPEN_READ;
574 				if (len <= 8) {
575 					msg.LEN = htobe32(0);
576 					s = send(ns, &msg, 8, 0);
577 				} else {
578 					msg.LEN = htobe32(len);
579 					s = send(ns, &msg, 8, 0);
580 					s = send(ns, hdr->AS.rawEventData, len, 0);
581 				}
582 			}
583 
584 			else if ((STATUS == STATE_OPEN_WRITE_HDR) &&
585 				 ((msg.STATE & ~ERR_MASK) == (BSCS_VERSION_01 | BSCS_PUT_FILE | STATE_OPEN_WRITE_HDR)))
586 			{
587 /****************************************************************************************
588 	PUT FILE
589  ****************************************************************************************/
590 
591 
592 				//case BSCS_PUT_FILE:  	// send header information
593 				uint32_t errcode = 0;
594 
595 				c64ta(ID, filename);
596 				char *f2 = (char*)malloc(strlen(fullfilename)+5);
597 				strcpy(f2,fullfilename);
598 				strcat(f2,".tmp");
599 
600 				/*********** temporary file - not checked *********/
601 				int sdo = open(f2,O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
602 
603 				HDRTYPE *hdr = constructHDR(0,0);
604 				hdr->FileName = f2;
605 #ifdef WITH_PDP
606 				hdr->AS.Header = (uint8_t*) malloc(LEN+1);
607 #endif
608 
609 				const int BUFLEN = 1024;
610 				char buf[BUFLEN];
611 
612 				count  = 0;
613 				while (count<LEN) {
614 					size_t len = recv(ns, buf, min(LEN-count, BUFLEN), 0);
615 #ifdef WITH_PDP
616 					memcpy(hdr->AS.Header+count,buf,len);
617 #endif
618 					count += write(sdo, buf, len);
619 					//fprintf(stdout,"\b\b\b\b%02i%% ",100.0*count/LEN);
620 				}
621 				close(sdo);
622 				hdr->AS.Header[count]=0;
623 				hdr->HeadLen = count;
624 
625 				if (LEN-count) {
626 					errcode = 1;
627 //fprintf(stdout,"errcode=1 %i\n",LEN-count);
628 				}
629 				else {
630 				/************ read temporary file, ... ************/
631 				int status = 0;
632 #ifdef WITH_PDP
633 				sopen_pdp_read(hdr);
634 
635 				sread(NULL,0,hdr->NRec,hdr);	// rawdata -> data.block
636 				status=serror2(hdr);
637 
638 				if (status) {
639 					errcode = 2;
640 #else
641         				{
642 #endif
643 					sopen(f2,"r",hdr);
644 					if ((status=serror2(hdr)))
645 					        errcode = 11;
646 
647 					else {
648 						count = sread(NULL,0,hdr->NRec,hdr);
649 						if ((status=serror2(hdr)))
650 							errcode = 12;
651 
652 						sclose(hdr);
653 						if ((status=serror2(hdr)))
654 							errcode = 13;
655 
656 					}
657 				}
658 
659 				if (VERBOSE_LEVEL>7) fprintf(stdout,"put file: errcode=%i\n",errcode);
660 
661 				/********* ... and convert to GDF file *************/
662 				if (!status) {
663 					hdr->FileName = fullfilename;
664 					hdr->TYPE = GDF;
665 					hdr->VERSION = 2;
666 					sopen(fullfilename,"w",hdr);
667 					if ((status=serror2(hdr))) {
668 						errcode = 21;
669 					} else {
670 						//count = swrite(hdr->data.block, hdr->NRec, hdr);
671 						ifwrite(hdr->AS.rawdata,hdr->AS.bpb,hdr->NRec,hdr);
672 						if ((status=serror2(hdr)))
673 							errcode = 22;
674 						sclose(hdr);
675 						if ((status=serror2(hdr)))
676 							errcode = 23;
677 					}
678 				}
679 
680 				if (VERBOSE_LEVEL>7) fprintf(stdout,"put file: errcode=%i\n",errcode);
681 
682 				}
683 				destructHDR(hdr);
684 				free(f2);
685 
686 				STATUS = STATE_INIT;
687 				msg.STATE = BSCS_VERSION_01 | BSCS_PUT_FILE | BSCS_REPLY | STATE_INIT | htobe32(errcode);
688 				msg.LEN = htobe32(0);
689 				s = send(ns, &msg, 8, 0);
690 			}
691 
692 			else if ((
693 				 (msg.STATE & ~ERR_MASK & ~STATE_MASK) == (BSCS_VERSION_01 | BSCS_GET_FILE)))
694 			{
695 /****************************************************************************************
696 	GET FILE
697  ****************************************************************************************/
698 
699 	   			count = recv(ns, &msg.LOAD, 8, 0);
700 				ID = leu64p((uint8_t*)&msg.LOAD);
701 				c64ta(ID, filename);
702 
703 				if (VERBOSE_LEVEL>7) fprintf(stdout,"get file: %s\n",filename);
704 
705 fprintf(stdout,"get file: %016lx\n",ID);
706 
707 				int sdi = open(fullfilename,O_RDONLY,S_IFREG);
708 
709 fprintf(stdout,"get file: %016lx %i\n",ID,sdi);
710 
711 				if (sdi<0) {
712 					msg.STATE = BSCS_VERSION_01 | BSCS_GET_FILE | BSCS_REPLY | STATUS | BSCS_ERROR_CANNOT_OPEN_FILE;
713 					msg.LEN = htobe32(0);
714 					s = send(ns, &msg, 8, 0);
715 				}
716 				else {
717 					struct stat FileBuf;
718 					stat(fullfilename,&FileBuf);
719 					uint32_t LEN = FileBuf.st_size;
720 
721 					msg.STATE = BSCS_VERSION_01 | BSCS_GET_FILE | BSCS_REPLY | STATUS | BSCS_NO_ERROR;
722 					msg.LEN = htobe32(LEN);
723 					s = send(ns, &msg, 8, 0);
724 
725 					const int BUFLEN = 1024;
726 					char *buf[BUFLEN];
727 					count = 0;
728 					while (count<LEN) {
729 						size_t len = read(sdi, buf, min(LEN-count,BUFLEN));
730 						count += send(ns, buf, len, 0);
731 					}
732 					//if (FileBuf.st_size-count); // TODO: error handling
733 					close(sdi);
734 				}
735 				s = send(ns, &msg, 8, 0);
736 			}
737 
738 			else if ((msg.STATE & CMD_MASK) == BSCS_NOP)
739 			{
740 /****************************************************************************************
741 	NO OPERATION
742  ****************************************************************************************/
743 				;
744 			}
745 
746 
747 			else if (msg.STATE & BSCS_REPLY)
748 			{	// ignore reply messages
749 				;
750 	   		}
751 			else
752 			{
753 				fprintf(stdout,"unknown packet: state=%08x len=%i\n",be32toh(msg.STATE),(int32_t)be32toh(msg.LEN));
754 				msg.STATE = BSCS_VERSION_01 | BSCS_ERROR;
755 				msg.LEN = htobe32(0);
756 				s = send(ns, &msg, 8, 0);
757 			}
758 		}
759 }
760 
761 //int main (int argc, char *argv[]) {
762 int main () {
763 
764 	int sd, ns;
765 	socklen_t fromlen;
766 	int addrlen;
767 	struct sigaction sa;
768 	time_t timer;
769 	pid_t sid;
770 
771 	fprintf(stdout,"01## errno=%i %s\n",errno,strerror(errno));
772 	LoadIdTable(path);
773 	fprintf(stdout,"11## errno=%i %s\n",errno,strerror(errno));
774 
775 	timer=time(NULL);
776 	char *t = asctime(localtime(&timer));
777 	t[24]=0;
778 
779 	FILE *fid = fopen(LOGFILE,"a");
780 	fprintf(fid,"\n%s\tserver started",t);
781 	fclose(fid);
782 
783 
784 #ifdef IPv6	// IPv4 and IPv6
785 	int status;
786 	struct addrinfo hints, *servinfo, *p;
787     	struct sockaddr_storage sain;
788     	char s[INET6_ADDRSTRLEN];
789     	int rv;
790     	int yes=1;
791 
792 
793 	memset(&hints, 0, sizeof hints); // make sure the struct is empty
794 	hints.ai_family = AF_UNSPEC;     // don't care IPv4 or IPv6
795 	hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
796    	hints.ai_flags = AI_PASSIVE; // use my IP
797 
798 
799 	// get ready to connect
800 	status = getaddrinfo(NULL, "SERVER_PORT", &hints, &servinfo);
801    	if(status<0) {
802 	        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
803 	   	return(BSCS_UNKNOWN_HOST);
804 	}
805    	if(servinfo==NULL) return(BSCS_UNKNOWN_HOST);
806 
807     	// loop through all the results and bind to the first we can
808     	for(p = servinfo; p != NULL; p = p->ai_next) {
809         	if ((sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
810 	            perror("server: socket");
811         	    continue;
812         	}
813 
814 	        if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
815 			perror("setsockopt");
816             		exit(1);
817         	}
818 
819         	if (bind(sd, p->ai_addr, p->ai_addrlen) == -1) {
820             		close(sd);
821             		perror("server: bind");
822             		continue;
823         	}
824         	break;
825     	}
826     	if (p == NULL)  {
827         	fprintf(stderr, "server: failed to bind\n");
828 		return(BSCS_CANNOT_BIND_PORT);
829     	}
830 
831     	freeaddrinfo(servinfo); // all done with this structure
832 
833 
834 #else
835 
836     	struct sockaddr_in sain;
837     	fromlen = sizeof(sain);
838 
839     	/*
840     	 * Get a socket to work with.  This socket will
841     	 * be in the UNIX domain, and will be a
842     	 * stream socket.
843     	 */
844     	if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
845         	perror("server: socket");
846         	exit(1);
847     	}
848 
849    	/* bind server port */
850     	sain.sin_family = AF_INET;
851     	sain.sin_addr.s_addr = htonl(INADDR_ANY);
852     	sain.sin_port = htons(SERVER_PORT);
853 
854    	if(bind(sd, (struct sockaddr *) &sain, sizeof(sain))<0) {
855       		perror("cannot bind port ");
856       		return(-1);
857    	}
858 
859 #endif
860 
861     	/*
862     	 * Listen on the socket.
863     	 */
864     	if (listen(sd, 10) < 0) {
865         	perror("server: listen");
866         	exit(1);
867     	}
868 
869  	sa.sa_handler = sigchld_handler; // reap all dead processes
870 	sigemptyset(&sa.sa_mask);
871 	sa.sa_flags = SA_RESTART;
872 	if (sigaction(SIGCHLD, &sa, NULL) == -1) {
873 		perror("sigaction");
874 		exit(1);
875 	}
876 
877 	printf("server: waiting for connections...\n");
878 
879     	while(1) {
880     		/*
881     		 * Accept connections.  When we accept one, ns
882 	    	 * will be connected to the client.  fsain will
883     		 * contain the address of the client.
884 	    	 */
885 	    	fromlen = sizeof(sain);
886 		if ((ns = accept(sd, (struct sockaddr*)&sain, &fromlen)) < 0) {
887         		perror("server: accept");
888 	        	exit(1);
889     		}
890 #ifdef IPv6
891 		inet_ntop(sain.ss_family, get_in_addr((struct sockaddr *)&sain),s, sizeof s);
892 	        printf("server: got connection from %s\n", s);
893 #else
894 		char hostname[100],service[100];
895   		bzero(hostname,100);
896   		bzero(service,100);
897   		addrlen = sizeof(struct sockaddr);
898 		if (getnameinfo((struct sockaddr *)&sain,addrlen,hostname,100,service,100,0) != 0)
899      		{
900 		fprintf(stdout,"--- errno=%i %s\n",errno,strerror(errno));
901 //    			perror("getnameinfo");
902      		}
903 
904 		printf("Connection received from host (%s) on remote port (%s)\n",hostname,service);
905 #endif
906 
907 #ifndef VERBOSE_LEVEL
908 //VERBOSE_LEVEL = 8;
909 #endif
910 
911 		// TODO: LOG FILE
912 
913 		char dst[INET6_ADDRSTRLEN];
914 		inet_ntop(AF_INET, &sain.sin_addr,dst, INET6_ADDRSTRLEN);
915 		timer=time(NULL);
916 		char *t = asctime(localtime(&timer));
917 		t[24]=0;
918 
919 
920 		FILE *fid = fopen(LOGFILE,"a");
921 		fprintf(fid,"\n%s\t%s\t%s",t,dst,hostname);
922 		fclose(fid);
923 
924 	        if (!fork()) { // this is the child process
925 			close(sd); // child doesn't need the listener
926 
927 			/* Change the file mode mask */
928 			umask(0);
929 
930 			/* Change the current working directory.  This prevents the current
931    			   directory from being locked; hence not being able to remove it. */
932 
933 			if ((chdir("/")) < 0) {
934 				syslog( LOG_ERR, "unable to change directory to %s, code %d (%s)","/", errno, strerror(errno) );
935 			        exit(-1);
936 			}
937 
938 			/* Redirect standard files to /dev/null */
939 
940 			freopen( "/dev/null", "r", stdin);
941 			freopen( "/dev/null", "w", stdout);
942 			freopen( "/dev/null", "w", stderr);
943 
944 			if (VERBOSE_LEVEL>7) fprintf(stdout,"server123 err=%i %s\n",errno,strerror(errno));
945 
946 			errno = 0;
947 			DoJob(ns);
948 
949 		    	close(ns);
950         	    	exit(0);
951 	        }
952     		close(ns);
953 	}
954 
955     	close(sd);
956     	exit(0);
957 }
958