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