1 /*
2 
3     Copyright (C) 2009,2015,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 <ctype.h>
23 #include <errno.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 
28 #include "biosig-network.h"
29 
30 #ifdef _WIN32
31 #define TC (char*)	// WINSOCK's send and recv require (char*)buf
32 
33 #if 0
34 /*
35 	these functions have a different name under windows,
36 	MinGW für windows requires these
37 */
38 int creat(const char *path, mode_t mode) {
39 //	return(OpenFile(path, O_WRONLY|O_CREAT|O_TRUNC, mode));
40 	return(OpenFile(path, , OF_WRITE|OF_CREAT ));
41 }
42 ssize_t write(int fildes, const void *buf, size_t nbyte) {
43 	ssize_t sz;
44 	WriteFile(fildes, buf, nbyte, &sz, NULL)
45 	return(sz);
46 }
47 int close(int fildes) {
48 	return(CloseFile(fildes)); {
49 }
50 // the following ones are not used
51 /*
52 int open(const char *path, int oflag) {
53 	return(OpenFile(path, oflag));
54 }
55 int open(const char *path, int oflag, mode_t mode ) {
56 	return(OpenFile(path, oflag, mode));
57 }
58 ssize_t read(int fildes, const void *buf, size_t nbyte) {
59 	return(ReadFile(fildes, buf, nbyte));
60 }
61 */
62 #endif
63 
64 #else
65 #define TC
66 #endif
67 
68 uint64_t B4C_ID=0;	// ID of currently open file
69 const char *B4C_HOSTNAME = NULL;
70 uint32_t SERVER_STATE; // state of server, useful for preliminary error checking
71 
72 /*
73 	converts 64bit integer into hex string
74 */
c64ta(uint64_t ID,char * txt)75 int c64ta(uint64_t ID, char *txt) {
76 	const char hex[] = "0123456789abcdef";
77 	int k=(BSCS_ID_BITLEN>>2)-1;
78 	for (; k>=0; k--) {
79 		txt[k] = hex[ID & 0x0f];
80 		ID>>=4;
81 	}
82 	txt[BSCS_ID_BITLEN>>2] = 0;
83 	if (VERBOSE_LEVEL>8) fprintf(stdout,"c64ta: ID=%016"PRIx64" TXT=%s\n",ID,txt);
84 	return 0;
85 }
86 
87 
88 /*
89 	converts hex string into 64bit integer
90 */
cat64(char * txt,uint64_t * id)91 int cat64(char* txt, uint64_t *id) {
92 	uint64_t ID = 0;
93 	int k = 0;
94 	for (; txt[k] && (k<(BSCS_ID_BITLEN>>2));k++) {
95 		ID<<=4;
96 		if (isdigit(txt[k]))
97 			ID += txt[k]-'0';
98 		else if (isxdigit(txt[k]))
99 			ID += toupper(txt[k])-'A'+10;
100 		else {
101 			*id = -1;
102 			return(-1);
103 		}
104 	}
105 	*id = ID;
106 	if (VERBOSE_LEVEL>8) fprintf(stdout,"cat64: ID=%016"PRIx64" TXT=%s\n",ID,txt);
107 	return(0);
108 }
109 
110 
111 // get sockaddr, IPv4 or IPv6:
get_in_addr(struct sockaddr * sa)112 void *get_in_addr(struct sockaddr *sa)
113 {
114 	if (sa->sa_family == AF_INET) {
115 		return &(((struct sockaddr_in*)sa)->sin_addr);
116 	}
117 #ifndef _WIN32
118 	return &(((struct sockaddr_in6*)sa)->sin6_addr);
119 #else
120 	return(NULL);
121 #endif
122 }
123 
124 
125 /****************************************************************************************
126 	OPEN CONNECTION TO SERVER
127  ****************************************************************************************/
bscs_connect(const char * hostname)128 int bscs_connect(const char* hostname) {
129 
130 	int sd;
131     	struct sockaddr_in localAddr;
132 
133 	if (hostname==NULL) hostname = "129.27.3.99";
134 	B4C_HOSTNAME = hostname;
135 
136 #ifdef _WIN32
137 	WSADATA wsadata;
138 	if (WSAStartup(MAKEWORD(1,1), &wsadata) == SOCKET_ERROR) {
139 		fprintf(stderr,"Error creating socket.");
140 		return(BSCS_CANNOT_CONNECT);
141 	}
142 #endif
143 
144 	int status;
145 
146 #if 1	// IPv4 and IPv6
147 	struct addrinfo hints;
148 	struct addrinfo *result, *p;
149 
150 	memset(&hints, 0, sizeof(struct addrinfo));
151 	hints.ai_family   = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
152 	hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
153 	hints.ai_flags    = 0;
154 	hints.ai_protocol = 0;          /* Any protocol */
155 
156 	status = getaddrinfo(hostname, NULL, &hints, &result);
157 	if (status != 0) {
158 	        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
159 	   	return(BSCS_UNKNOWN_HOST);
160    	}
161 
162 	// loop through all the results and connect to the first we can
163 #ifndef NI_MAXHOST
164 #define NI_MAXHOST 1025
165 #endif
166 	for(p = result; p != NULL; p = p->ai_next) {
167         	char hostname1[NI_MAXHOST] = "";
168         	int error = getnameinfo(p->ai_addr, p->ai_addrlen, hostname1, NI_MAXHOST, NULL, 0, 0);
169         	if (*hostname1)
170         		printf("hostname: %s\n", hostname1);
171 
172 		if ((sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
173 			perror("client: socket");
174 			continue;
175 		}
176 		if (connect(sd, p->ai_addr, p->ai_addrlen) != -1)
177 			break;
178 
179 		close(sd);
180     	}
181 	if (p == NULL) {
182 		fprintf(stderr, "client: failed to connect\n");
183 #ifdef _WIN32
184 		WSACleanup();
185 #endif
186 		return(BSCS_CANNOT_CONNECT);
187 	}
188 
189 	char s[INET6_ADDRSTRLEN];
190 #if !defined(_WIN32)
191 	// FIXME: does not compile with MXE for TARGET "i686-w64-mingw32.static"
192 	inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof(s));
193 #else
194 	strcpy(s," [Icannot get server name - NET_NTOP() not available]");
195 #endif
196     	printf("client: connecting to %s\n", s);
197 
198 	freeaddrinfo(result);   // all done with this structure
199 
200 #else
201 
202 	// IPv4 only
203     	struct hostent *h;
204     	struct sockaddr_in sain;
205 
206 
207    	h = gethostbyname(hostname);
208    	if(h==NULL) return(BSCS_UNKNOWN_HOST);
209 
210    	sain.sin_family = h->h_addrtype;
211    	memcpy((char *) &sain.sin_addr.s_addr, h->h_addr_list[0],h->h_length);
212    	sain.sin_port = htons(SERVER_PORT);
213 
214    	/* create socket */
215    	sd = socket(AF_INET, SOCK_STREAM, 0);
216    	if(sd<0) return(BSCS_CANNOT_OPEN_SOCKET);
217 
218    	/* bind any port number */
219    	localAddr.sin_family = AF_INET;
220    	localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
221    	localAddr.sin_port = htons(0);
222 
223    	/* connect to server */
224    	int rc = connect(sd, (struct sockaddr *) &sain, sizeof(sain));
225    	if(rc<0) return(BSCS_CANNOT_CONNECT);
226 
227 #endif
228 
229 	/* identification */
230 	mesg_t msg;
231 	recv(sd,TC&msg,8,0);
232 	int len = be32toh(msg.LEN);
233 	if ((msg.STATE & (VER_MASK|CMD_MASK)) != (BSCS_VERSION_01 | BSCS_SEND_MSG))	// currently only V0.1 is supported
234 	{
235 		close(sd);
236 		return(BSCS_SERVER_NOT_SUPPORTED);
237 	}
238 
239 	char *greeting = (char*)malloc(len+1);
240 	recv(sd,greeting,len,0);
241 	greeting[len]=0;
242 	//fprintf(stdout,"%s",greeting);
243 	free(greeting);
244    	return(sd);
245 }
246 
247 
248 
249 /****************************************************************************************
250 	CLOSE CONNECTION TO SERVER
251  ****************************************************************************************/
bscs_disconnect(int sd)252 int bscs_disconnect(int sd) {
253 	close(sd);
254 #ifdef _WIN32
255 	WSACleanup();
256 #endif
257 }
258 
259 
send_packet(int sd,uint32_t state,uint32_t len,void * load)260 int send_packet(int sd, uint32_t state, uint32_t len, void* load) {
261 	mesg_t msg;
262 	msg.STATE = state;
263 	msg.LEN = htobe32(len);
264 	send(sd, TC &msg, 8, 0);
265 	if (len>0) send(sd, TC load, len, 0);
266 }
267 
268 
269 /*
270 	stores a bscs link file on client side for the
271 	currently open network file is stored in the directory "/tmp/"
272 */
savelink(const char * filename)273 int savelink(const char* filename) {
274 
275 	if ((SERVER_STATE & STATE_MASK)==STATE_INIT) return(-1);
276 
277 	char *logpath = "/tmp/";		// perhaps some other directory
278 	const char *ext = ".bscs";
279 	const char *fn = strrchr(filename,FILESEP);
280 	if (fn==NULL) fn = filename;
281 	else fn++;
282 
283 	size_t l1 = strlen(logpath);
284 	size_t l2 = strlen(fn);
285 	size_t l3 = strlen(ext);
286 	size_t l4 = 10;
287 	char *logfile = (char*)malloc(l1+l2+l3+l4+1);
288 	memcpy(logfile, logpath, l1);
289 	memcpy(logfile+l1, fn, l2);
290 	strcpy(logfile+l1+l2, ext);
291 	int k=0;
292 	size_t sl = strlen(logfile);
293 
294 	FILE *fid;
295 	// check whether file already exists
296 	while ((fid=fopen(logfile,"r")) != NULL) {
297 		fclose(fid);
298 		snprintf(logfile+sl, l4, ".%i", k);
299 		k++;
300 	}
301 	errno = 0; 	// fopen caused errno=2; reset errno
302 
303 fprintf(stdout,"savelink %s\n",logfile);
304 
305 	fid = fopen(logfile,"w");
306 	fprintf(fid,"bscs://%s/%016"PRIx64"\n",B4C_HOSTNAME,B4C_ID);
307 	fclose(fid);
308 	free(logfile);
309 
310 }
311 
312 
313 /****************************************************************************************
314 	OPEN FILE with ID
315  ****************************************************************************************/
bscs_open(int sd,uint64_t * ID)316 int bscs_open(int sd, uint64_t* ID) {
317 
318 	if (SERVER_STATE != STATE_INIT) return(BSCS_ERROR);
319 
320 	size_t LEN;
321 	mesg_t msg;
322 
323 	if (*ID==0) {
324 		msg.STATE = BSCS_VERSION_01 | BSCS_OPEN_W | STATE_INIT | BSCS_NO_ERROR;
325 		LEN   = 0;
326 	}
327 	else {
328 		msg.STATE = BSCS_VERSION_01 | BSCS_OPEN_R | STATE_INIT | BSCS_NO_ERROR;
329 		*(uint64_t*)&msg.LOAD  = leu64p(ID);
330 		LEN = BSCS_ID_BITLEN>>3;
331 	}
332 
333 	if (VERBOSE_LEVEL>8) fprintf(stdout,"open: %16"PRIx64" %016"PRIx64"\n",*ID,*(uint64_t*)&(msg.LOAD));
334 
335 	msg.LEN   = htobe32(LEN);
336 	int s = send(sd, TC &msg, LEN+8, 0);
337 
338 	// wait for reply
339 	ssize_t count = 0;
340 	count = recv(sd, TC &msg, 8, 0);
341 	LEN = be32toh(msg.LEN);
342 	SERVER_STATE = msg.STATE & STATE_MASK;
343 
344 	if (VERBOSE_LEVEL>8) fprintf(stdout,"BSCS_OPEN %i:%"PRIiPTR": ID=%16"PRIx64" LEN=%"PRIx32" STATE=0x%08"PRIx32"\n",s,count,*ID,msg.LEN,be32toh(msg.STATE));
345 
346 	if ((*ID==0) && (LEN==8) && (msg.STATE==(BSCS_VERSION_01 | BSCS_OPEN_W | BSCS_REPLY | STATE_OPEN_WRITE_HDR | BSCS_NO_ERROR)) )
347 	{
348 		// write access: get new ID
349 		count += recv(sd, TC ID, LEN, 0);
350 
351 		*ID = htole64(*ID);
352 		B4C_ID = *ID;
353 		return(0);
354 	}
355 
356 	if ((*ID != 0) && (LEN==0) && (msg.STATE==(BSCS_VERSION_01 | BSCS_OPEN_R | BSCS_REPLY | STATE_OPEN_READ | BSCS_NO_ERROR)) )
357 	{
358 		; // read access
359 		return(0);
360 	}
361 
362 	uint8_t buf[8];
363 	count = 0;
364 	while (LEN > (size_t)count) {
365 		count += recv(sd, TC &buf, min(8,LEN-count), 0);
366 	 	// invalid packet or error opening file
367 	}
368 
369 	if (VERBOSE_LEVEL>7) 	fprintf(stdout,"ERR: state= %08"PRIx32" %08"PRIx32" len=%"PRIiPTR"\n",htobe32(msg.STATE),BSCS_VERSION_01 | BSCS_OPEN_R | BSCS_REPLY | STATE_OPEN_READ | BSCS_NO_ERROR,LEN);
370 
371 	return(msg.STATE);
372 }
373 
374 /****************************************************************************************
375 	CLOSE FILE
376  ****************************************************************************************/
bscs_close(int sd)377 int bscs_close(int sd) {
378 	int s;
379 	size_t LEN;
380 	mesg_t msg;
381 
382 	msg.STATE = BSCS_VERSION_01 | BSCS_CLOSE | BSCS_NO_ERROR | SERVER_STATE;
383 if (VERBOSE_LEVEL>8) fprintf(stdout,"close1: %08"PRIx32" \n",msg.STATE);
384 	msg.LEN   = htobe32(0);
385 if (VERBOSE_LEVEL>8) fprintf(stdout,"close2: %08"PRIx32" %"PRIiPTR" %"PRIi32"\n",msg.STATE,sizeof(msg),msg.LEN);
386 
387 	s = send(sd, TC &msg, 8, 0);
388 
389 if (VERBOSE_LEVEL>8) fprintf(stdout,"close3: %08"PRIx32" %i\n",msg.STATE,s);
390 
391 	// wait for reply
392 	s = recv(sd, TC &msg, 8, 0);
393 	LEN = be32toh(msg.LEN);
394 	SERVER_STATE = msg.STATE & STATE_MASK;
395 
396 if (VERBOSE_LEVEL>8) fprintf(stdout,"s=%i state= %08"PRIx32" len=%"PRIiPTR" %i  %08"PRIx32"\n",s,msg.STATE & ~STATE_MASK,LEN,s,(BSCS_VERSION_01 | BSCS_CLOSE | BSCS_REPLY));
397 
398 	if ((LEN==0) && ((msg.STATE & ~STATE_MASK)==(BSCS_VERSION_01 | BSCS_CLOSE | BSCS_REPLY | BSCS_NO_ERROR)) )
399 		// close without error
400 		return(0);
401 
402 	if ((LEN==0) && ((msg.STATE & ~STATE_MASK & ~ERR_MASK)==(BSCS_VERSION_01 | BSCS_CLOSE | BSCS_REPLY)) )
403 		// close with error
404 		return(msg.STATE & ERR_MASK);
405 
406 	 	// invalid packet or error opening file
407 	if (VERBOSE_LEVEL>8) 	fprintf(stdout,"ERR: state= %08"PRIx32" len=%"PRIiPTR"\n",msg.STATE,LEN);
408 	return(msg.STATE);
409 }
410 
411 /****************************************************************************************
412 	SEND HEADER
413  ****************************************************************************************/
bscs_send_hdr(int sd,HDRTYPE * hdr)414 int bscs_send_hdr(int sd, HDRTYPE *hdr) {
415 /* hdr->AS.Header must contain GDF header information
416    hdr->HeadLen   must contain header length
417   -------------------------------------------------------------- */
418 	// ToDo: convert HDR into AS.Header
419 
420 	if (SERVER_STATE != STATE_OPEN_WRITE_HDR) return(BSCS_ERROR);
421 
422 	mesg_t msg;
423 
424 	hdr->TYPE = GDF;
425 	hdr->FLAG.ANONYMOUS = 1; 	// do not store name
426 	struct2gdfbin(hdr);
427 
428 	msg.STATE = BSCS_VERSION_01 | BSCS_SEND_HDR | STATE_OPEN_WRITE_HDR | BSCS_NO_ERROR;
429 	msg.LEN   = htobe32(hdr->HeadLen);
430 	int s = send(sd, TC &msg, 8, 0);
431 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND HDR  %i %i\n",hdr->HeadLen,s);
432 	s = send(sd, TC hdr->AS.Header, hdr->HeadLen, 0);
433 
434 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND HDR %i %i\n",hdr->HeadLen,s);
435 
436 	// wait for reply
437 	ssize_t count = recv(sd, TC &msg, 8, 0);
438 
439 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND HDR %i %i %"PRIiPTR" %08"PRIx32"\n",hdr->HeadLen,s,count,msg.STATE);
440 
441 	size_t LEN = be32toh(msg.LEN);
442 	SERVER_STATE = msg.STATE & STATE_MASK;
443 
444 	if ((LEN==0) && (msg.STATE==(BSCS_VERSION_01 | BSCS_SEND_HDR | BSCS_REPLY | STATE_OPEN_WRITE | BSCS_NO_ERROR)) )
445 		// close without error
446 		return(0);
447 	if ((LEN==0) && ((msg.STATE & ~ERR_MASK)==(BSCS_VERSION_01 | BSCS_SEND_HDR | BSCS_REPLY | STATE_OPEN_WRITE_HDR)) )
448 		// could not write header
449 		return((msg.STATE & ~ERR_MASK) | BSCS_ERROR_COULD_NOT_WRITE_HDR);
450 
451 	 	// invalid packet or error opening file
452 	return(msg.STATE);
453 }
454 
455 /****************************************************************************************
456 	SEND DATA
457  ****************************************************************************************/
bscs_send_dat(int sd,void * buf,size_t len)458 int bscs_send_dat(int sd, void* buf, size_t len ) {
459 
460 	if (SERVER_STATE != STATE_OPEN_WRITE) return(BSCS_ERROR);
461 
462 	size_t LEN;
463 	mesg_t msg;
464 	msg.STATE = BSCS_VERSION_01 | BSCS_SEND_DAT | STATE_OPEN_WRITE | BSCS_NO_ERROR;
465 	msg.LEN   = htobe32(len);
466 
467 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND DAT %"PRIiPTR" %08"PRIx32"\n",len,msg.STATE);
468 
469 	ssize_t s;
470 	s = send(sd, TC &msg, 8, 0);
471 	s = send(sd, TC buf, len, 0);
472 	if (errno) fprintf(stdout,"SND DAT ERR=%i %s\n",errno,strerror(errno));
473 
474 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND DAT %"PRIiPTR" %08"PRIx32" %"PRIiPTR" \n",len,msg.STATE,s);
475 
476 	// wait for reply
477 	s = recv(sd, TC &msg, 8, 0);
478 	LEN = be32toh(msg.LEN);
479 	SERVER_STATE = msg.STATE & STATE_MASK;
480 
481 if (VERBOSE_LEVEL>8) fprintf(stdout,"SND DAT RPLY %"PRIiPTR" %08"PRIx32" \n",s,msg.STATE);
482 
483 	if ((LEN==0) && (msg.STATE==(BSCS_VERSION_01 | BSCS_SEND_DAT | BSCS_REPLY | STATE_OPEN_WRITE | BSCS_NO_ERROR)) )
484 		// end without error
485 		return(0);
486 
487 	if (LEN>0)
488 		return (BSCS_VERSION_01 | BSCS_SEND_DAT | BSCS_REPLY | STATE_OPEN_WRITE | BSCS_INCORRECT_REPLY_PACKET_LENGTH);
489 
490 	if ((msg.STATE & ~ERR_MASK)==(BSCS_VERSION_01 | BSCS_SEND_DAT | BSCS_REPLY | STATE_OPEN_WRITE))
491 		// could not write header
492 		return ((msg.STATE & ~ERR_MASK) | BSCS_ERROR_COULD_NOT_WRITE_DAT);
493 
494  	// invalid packet or error opening file
495 	return(msg.STATE);
496 }
497 
498 /****************************************************************************************
499 	SEND EVENTS
500  ****************************************************************************************/
bscs_send_evt(int sd,HDRTYPE * hdr)501 int bscs_send_evt(int sd, HDRTYPE *hdr) {
502 
503 	if (SERVER_STATE != STATE_OPEN_WRITE) return(BSCS_ERROR);
504 
505 	int sze;
506 	char flag;
507 
508 	size_t LEN;
509 	mesg_t msg;
510 
511 	if ((hdr->EVENT.DUR!=NULL) && (hdr->EVENT.CHN!=NULL)) {
512 		sze = 12;
513 		flag = 3;
514 	} else {
515 		sze = 6;
516 		flag = 1;
517 	}
518 
519 	size_t len = hdrEVT2rawEVT(hdr);
520 
521 if (VERBOSE_LEVEL>8) fprintf(stdout,"write evt: len=%"PRIiPTR"\n",len);
522 
523 	msg.STATE = BSCS_VERSION_01 | BSCS_SEND_EVT | STATE_OPEN_WRITE | BSCS_NO_ERROR;
524 	msg.LEN   = htobe32(len);
525 	int s1 = send(sd, TC &msg, 8, 0);
526 	int s2 = send(sd, TC hdr->AS.rawEventData, len, 0);
527 
528 if (VERBOSE_LEVEL>8) fprintf(stdout,"write evt2: %08"PRIx32" len=%"PRIiPTR"\n",msg.STATE,len);
529 
530 	// wait for reply
531 	ssize_t count = recv(sd, TC &msg, 8, 0);
532 	LEN = be32toh(msg.LEN);
533 	SERVER_STATE = msg.STATE & STATE_MASK;
534 
535 if (VERBOSE_LEVEL>8) fprintf(stdout,"write evt2: %08"PRIx32" len=%"PRIiPTR" count=%"PRIiPTR"\n",msg.STATE,LEN,count);
536 
537 	if ((LEN==0) && (msg.STATE==(BSCS_VERSION_01 | BSCS_SEND_EVT | BSCS_REPLY | STATE_OPEN_WRITE | BSCS_NO_ERROR)) )
538 		// close without error
539 		return(0);
540 
541 	if (LEN>0)
542 		return (BSCS_VERSION_01 | BSCS_SEND_EVT | BSCS_REPLY | STATE_OPEN_WRITE | BSCS_INCORRECT_REPLY_PACKET_LENGTH);
543 
544 	if (msg.STATE & ERR_MASK)
545 		// could not write evt
546 		return (BSCS_ERROR_COULD_NOT_WRITE_EVT);
547 
548  	// invalid packet or error opening file
549 	return(msg.STATE);
550 }
551 
552 /****************************************************************************************
553 	REQUEST HEADER
554  ****************************************************************************************/
bscs_requ_hdr(int sd,HDRTYPE * hdr)555 int bscs_requ_hdr(int sd, HDRTYPE *hdr) {
556 	mesg_t msg;
557 	int count;
558 
559 
560 	if (SERVER_STATE != STATE_OPEN_READ) return(BSCS_ERROR);
561 
562 	msg.STATE = BSCS_VERSION_01 | BSCS_REQU_HDR | BSCS_NO_ERROR | (SERVER_STATE & STATE_MASK);
563 	msg.LEN   = 0;
564 	count = send(sd, TC &msg, 8, 0);
565 
566    	count = recv(sd, TC &msg, 8, 0);
567 	hdr->HeadLen   = be32toh(msg.LEN);
568     	hdr->AS.Header = (uint8_t*)realloc(hdr->AS.Header,hdr->HeadLen);
569     	hdr->TYPE      = GDF;
570 	count = 0;
571 	while (hdr->HeadLen > (size_t)count) {
572 		count += recv(sd, TC hdr->AS.Header+count, hdr->HeadLen-count, 0);
573 	}
574 
575 if (VERBOSE_LEVEL>8) fprintf(stdout,"REQ HDR: %i %s\n",count,GetFileTypeString(hdr->TYPE));
576 
577 	hdr->FLAG.ANONYMOUS = 1; 	// do not store name
578 	gdfbin2struct(hdr);
579 
580 
581    	return(count-hdr->HeadLen);
582 }
583 
584 /****************************************************************************************
585 	REQUEST DATA
586  ****************************************************************************************/
bscs_requ_dat(int sd,size_t start,size_t length,HDRTYPE * hdr)587 ssize_t bscs_requ_dat(int sd, size_t start, size_t length, HDRTYPE *hdr) {
588 /*
589 	bufsiz should be equal to hdr->AS.bpb*length
590 */
591 	mesg_t msg;
592 	size_t LEN;
593 
594 	if (SERVER_STATE != STATE_OPEN_READ) return(BSCS_ERROR);
595 
596 	msg.STATE = BSCS_VERSION_01 | BSCS_REQU_DAT | BSCS_NO_ERROR | (SERVER_STATE & STATE_MASK);
597 	msg.LEN   = htobe32(8);
598 
599 
600 	leu32a(length,msg.LOAD+0);
601 	leu32a(start, msg.LOAD+4);
602 	int s = send(sd, TC &msg, 16, 0);
603 
604 	ssize_t count = recv(sd, TC &msg, 8, 0);
605 	LEN = be32toh(msg.LEN);
606 
607 	hdr->AS.rawdata = (uint8_t*) realloc(hdr->AS.rawdata,LEN);
608 	count = 0;
609 	while (LEN > (size_t)count) {
610 		count += recv(sd, TC hdr->AS.rawdata+count, LEN-count, 0);
611 	}
612 
613 	hdr->AS.first = start;
614 if (VERBOSE_LEVEL>8) fprintf(stdout,"REQ DAT: %"PRIiPTR" %i\n",count,hdr->AS.bpb);
615 	hdr->AS.length= (hdr->AS.bpb ? (size_t)count/hdr->AS.bpb : length);
616 if (VERBOSE_LEVEL>8) fprintf(stdout,"REQ DAT: %"PRIiPTR" %"PRIiPTR"\n",hdr->AS.first,hdr->AS.length);
617 
618 	return(0);
619 }
620 
621 
622 /****************************************************************************************
623 	REQUEST EVENT TABLE
624  ****************************************************************************************/
bscs_requ_evt(int sd,HDRTYPE * hdr)625 int bscs_requ_evt(int sd, HDRTYPE *hdr) {
626 	mesg_t msg;
627 	size_t LEN;
628 
629 if (VERBOSE_LEVEL>8) fprintf(stdout,"REQ EVT %08x %08x\n",SERVER_STATE, STATE_OPEN_READ);
630 
631 	if (SERVER_STATE != STATE_OPEN_READ) return(BSCS_ERROR);
632 
633 	msg.STATE = BSCS_VERSION_01 | BSCS_REQU_EVT | BSCS_NO_ERROR | (SERVER_STATE & STATE_MASK);
634 	msg.LEN   = htobe32(0);
635 	int s = send(sd, TC &msg, 8, 0);
636 
637 	// wait for reply
638 	s = recv(sd, TC &msg, 8, 0);
639 	LEN = be32toh(msg.LEN);
640 
641 if (VERBOSE_LEVEL>8) fprintf(stdout,"REQ EVT: %i %"PRIiPTR" \n",s,LEN);
642 
643 	if (LEN>0) {
644 	    	hdr->AS.rawEventData = (uint8_t*)realloc(hdr->AS.rawEventData,LEN);
645 		int count = 0;
646 		while (LEN > (size_t)count) {
647 			count += recv(sd, TC hdr->AS.rawEventData+count, LEN-count, 0);
648 		}
649 		rawEVT2hdrEVT(hdr, count); // TODO: replace this function because it is inefficient
650    	}
651 
652 if (VERBOSE_LEVEL>8) fprintf(stdout,"REQ EVT: %i %"PRIiPTR" \n",s,LEN);
653 #if 0
654 			uint8_t *buf = hdr->AS.rawEventData;
655 			if (hdr->VERSION < 1.94) {
656 				if (buf[1] | buf[2] | buf[3])
657 					hdr->EVENT.SampleRate = buf[1] + (buf[2] + buf[3]*256.0)*256.0;
658 				else {
659 					fprintf(stdout,"Warning GDF v1: SampleRate in Eventtable is not set in %s !!!\n",hdr->FileName);
660 					hdr->EVENT.SampleRate = hdr->SampleRate;
661 				}
662 				hdr->EVENT.N = leu32p(buf + 4);
663 			}
664 			else	{
665 				hdr->EVENT.N = buf[1] + (buf[2] + buf[3]*256)*256;
666 				hdr->EVENT.SampleRate = lef32p(buf + 4);
667 			}
668 			int sze = (buf[0]>1) ? 12 : 6;
669 
670 	 		hdr->EVENT.POS = (uint32_t*) realloc(hdr->EVENT.POS, hdr->EVENT.N*sizeof(*hdr->EVENT.POS) );
671 			hdr->EVENT.TYP = (uint16_t*) realloc(hdr->EVENT.TYP, hdr->EVENT.N*sizeof(*hdr->EVENT.TYP) );
672 #endif
673 
674 
675 	return(0);
676 }
677 
678 /****************************************************************************************
679 	PUT FILE
680  ****************************************************************************************/
bscs_put_file(int sd,char * filename)681 int bscs_put_file(int sd, char *filename) {
682 
683 	size_t LEN;
684 	mesg_t msg;
685 
686 
687 	if (SERVER_STATE != STATE_OPEN_WRITE_HDR) return(BSCS_ERROR);
688 
689 	struct stat FileBuf;
690 	stat(filename,&FileBuf);
691 	LEN = FileBuf.st_size;
692 
693 if (VERBOSE_LEVEL>8) fprintf(stdout,"PUT FILE(1) %s\n",filename);
694 
695 //	int sdi = open(filename,O_RDONLY);
696 //	if (sdi<=0) return(BSCS_ERROR);
697 
698 	FILE *fid = fopen(filename,"r");
699 	if (fid==NULL) return(BSCS_ERROR);
700 
701 
702 	msg.STATE = BSCS_VERSION_01 | BSCS_PUT_FILE | STATE_OPEN_WRITE_HDR | BSCS_NO_ERROR;
703 	msg.LEN   = htobe32(LEN);
704 	int s1 = send(sd, TC &msg, 8, 0);
705 
706 //if (VERBOSE_LEVEL>8) fprintf(stdout,"PUT FILE(2) %i %i\n",LEN,sdi);
707 
708 	const unsigned BUFLEN = 1024;
709 	char buf[BUFLEN];
710 	size_t count = 0;
711 	while (count<LEN) {
712 		//size_t len  = read(sdi, buf, min(LEN-count,BUFLEN));
713 		size_t len  = fread( buf, 1, min(LEN - count, BUFLEN), fid);
714 		count += send(sd, buf, len, 0);
715 //		fprintf(stdout,"\b\b\b\b%02i%% ",100.0*count/LEN);
716 	}
717 	//close(sdi);
718 	fclose(fid);
719 
720 	if (LEN-count) fprintf(stdout,"file size and number of sent bytes do not fit");
721 
722 	// wait for reply
723 	count = recv(sd, TC &msg, 8, 0);
724 	LEN = be32toh(msg.LEN);
725 	SERVER_STATE = msg.STATE & STATE_MASK;
726 
727 	if (VERBOSE_LEVEL>7) fprintf(stdout,"%"PRIiPTR" LEN=%"PRIiPTR" %08x %08x %08x %08x\n",count,LEN,msg.STATE, BSCS_PUT_FILE | BSCS_REPLY , STATE_INIT, (BSCS_VERSION_01 | BSCS_PUT_FILE | BSCS_REPLY | STATE_INIT | BSCS_NO_ERROR));
728 
729 	if ((LEN==0) && (msg.STATE==(BSCS_VERSION_01 | BSCS_PUT_FILE | BSCS_REPLY | STATE_INIT | BSCS_NO_ERROR)) )
730 		// close without error
731 		return(0);
732 
733 	if (LEN>0)
734 		return (BSCS_VERSION_01 | BSCS_PUT_FILE | BSCS_REPLY | STATE_INIT | BSCS_ERROR);
735 
736  	// invalid packet or error opening file
737 	return(msg.STATE);
738 }
739 
740 /****************************************************************************************
741 	GET FILE
742  ****************************************************************************************/
bscs_get_file(int sd,uint64_t ID,char * filename)743 int bscs_get_file(int sd, uint64_t ID, char *filename) {
744 
745 	size_t LEN;
746 	mesg_t msg;
747 
748 #if _WIN32
749 	mode_t mode = S_IRUSR | S_IWUSR;
750 #else
751 	mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
752 #endif
753 
754 	int sdo = creat(filename, mode);
755 
756 	if (VERBOSE_LEVEL>7) fprintf(stdout,"get file (1) %i\n",sdo);
757 
758 	msg.STATE = BSCS_VERSION_01 | BSCS_GET_FILE | STATE_INIT | BSCS_NO_ERROR;
759 	leu64a(ID, &msg.LOAD);
760 	LEN = BSCS_ID_BITLEN>>3;
761 	msg.LEN   = htobe32(LEN);
762 	int s = send(sd, TC &msg, LEN+8, 0);
763 
764 	if (VERBOSE_LEVEL>7) fprintf(stdout,"get file (1)\n");
765 
766 	// wait for reply
767 	ssize_t count = recv(sd, TC &msg, 8, 0);
768 	LEN = be32toh(msg.LEN);
769 	SERVER_STATE = msg.STATE & STATE_MASK;
770 
771 	if (VERBOSE_LEVEL>7) fprintf(stdout,"get file (3) %"PRIiPTR"\n",LEN);
772 
773 	const unsigned BUFLEN = 1024;
774 	char buf[BUFLEN];
775 	count = 0;
776 	size_t len = 0;
777 	while ((size_t)count < LEN) {
778 		size_t len = recv(sd, buf, min(LEN - count,BUFLEN), 0);
779 		count+=write(sdo,buf,len);
780 	}
781 	if (VERBOSE_LEVEL>7) fprintf(stdout,"get file (1) %"PRIiPTR"\n",count);
782 
783 	close(sdo);
784 	if (LEN-count)
785 		return(msg.STATE);
786 	else
787 		// close without error
788 		return(0);
789 
790 }
791 
792 /****************************************************************************************
793 	NO OPERATION
794  ****************************************************************************************/
bscs_nop(int sd)795 int bscs_nop(int sd) {
796 
797 	size_t LEN;
798 	mesg_t msg;
799 
800 	msg.STATE = BSCS_NOP | SERVER_STATE;
801 	msg.LEN = htobe32(0);
802 	int s = send(sd, TC &msg, 8, 0);
803 
804 
805 }
806 
807