PageRenderTime 57ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/realtime/src/buffer/src/util.c

https://bitbucket.org/palday/fieldtrip
C | 414 lines | 301 code | 64 blank | 49 comment | 84 complexity | e6409016317352ed38f3c75612503d66 MD5 | raw file
  1. /*
  2. * Copyright (C) 2008, Robert Oostenveld & Christian Hesse
  3. * F.C. Donders Centre for Cognitive Neuroimaging, Radboud University Nijmegen,
  4. * Kapittelweg 29, 6525 EN Nijmegen, The Netherlands
  5. *
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h> /* for strerror */
  10. #include "buffer.h"
  11. #include <pthread.h>
  12. #include "extern.h"
  13. unsigned int bufread(int s, void *buf, unsigned int numel) {
  14. unsigned int numcall = 0, numread = 0, verbose = 0;
  15. int numthis = 0;
  16. while (numread<numel) {
  17. numthis = recv(s, (char*)buf+numread, numel-numread, 0);
  18. if (numthis<0) {
  19. perror("bufread");
  20. break;
  21. }
  22. else if (numthis == 0)
  23. break;
  24. if (verbose>0)
  25. fprintf(stderr, "bufread: read %d bytes\n", numthis);
  26. numread += numthis;
  27. numcall ++;
  28. #ifndef PLATFORM_WIN32 /* SK: I think this shouldn't be necessary on any platform: the sockets are blocking */
  29. if (numread<numel)
  30. usleep(1000);
  31. #endif
  32. }
  33. if (verbose>1)
  34. fprintf(stderr, "bufread: reading the complete buffer required %d calls\n", numcall);
  35. return numread;
  36. }
  37. unsigned int bufwrite(int s, const void *buf, unsigned int numel) {
  38. int numthis = 0;
  39. unsigned int numcall = 0, numwrite = 0, verbose = 0;
  40. while (numwrite<numel) {
  41. numthis = send(s, (char*)buf+numwrite, numel-numwrite, 0);
  42. if (numthis<0) {
  43. perror("bufwrite");
  44. break;
  45. }
  46. else if(numthis == 0)
  47. break;
  48. if (verbose)
  49. fprintf(stderr, "bufwrite: wrote %d bytes\n", numthis);
  50. numwrite += numthis;
  51. numcall ++;
  52. #ifndef PLATFORM_WIN32 /* SK: I think this shouldn't be necessary on any platform: the sockets are blocking */
  53. if (numwrite<numel)
  54. usleep(1000);
  55. #endif
  56. }
  57. if (verbose>1)
  58. fprintf(stderr, "bufwrite: writing the complete buffer required %d calls\n", numcall);
  59. return numwrite;
  60. }
  61. unsigned int append(void **buf1, unsigned int bufsize1, void *buf2, unsigned int bufsize2) {
  62. int verbose = 0;
  63. if (verbose>1) {
  64. pthread_mutex_lock(&mutexappendcount);
  65. appendcount++;
  66. fprintf(stderr, "append: appendcount = %d\n", appendcount);
  67. pthread_mutex_unlock(&mutexappendcount);
  68. }
  69. if (((*buf1)!=NULL) && (bufsize1==0)) {
  70. perror("append err1");
  71. return 0; /* was -1, but this is never checked anyway */
  72. }
  73. else if (((*buf1)==NULL) && (bufsize1!=0)) {
  74. perror("append err2");
  75. return 0; /* was -1, but this is never checked anyway */
  76. }
  77. if ((*buf1)==NULL) {
  78. if (verbose>0)
  79. fprintf(stderr, "append: allocating %d bytes\n", bufsize2);
  80. (*buf1) = malloc(bufsize2);
  81. }
  82. else if ((*buf1)!=NULL) {
  83. if (verbose>0)
  84. fprintf(stderr, "append: reallocating from %d to %d bytes\n", bufsize1, bufsize1+bufsize2);
  85. (*buf1) = realloc((*buf1), bufsize1+bufsize2);
  86. }
  87. memcpy((char*)(*buf1)+bufsize1, buf2, bufsize2);
  88. return (bufsize1+bufsize2);
  89. }
  90. int close_connection(int s) {
  91. int status = 0, verbose = 0;
  92. if (verbose>0)
  93. fprintf(stderr, "close_connection: socket = %d\n", s);
  94. if (s>0)
  95. status = closesocket(s); /* it is a TCP connection */
  96. if (status!=0)
  97. perror("close_connection");
  98. return status;
  99. }
  100. int open_connection(const char *hostname, int port) {
  101. int verbose = 0;
  102. int s, retry;
  103. struct sockaddr_in sa;
  104. struct hostent *host;
  105. #ifdef WIN32
  106. static WSADATA wsa = {0,0}; /* check version fields to only initialise once */
  107. #endif
  108. if (port==0) {
  109. if (verbose>0)
  110. fprintf(stderr, "open_connection: using direct memory copy\n");
  111. return 0;
  112. }
  113. else {
  114. if (verbose>0)
  115. fprintf(stderr, "open_connection: server = %s, port = %d\n", hostname, port);
  116. }
  117. #ifdef WIN32
  118. if (wsa.wVersion == 0) {
  119. /* We only need to do this once ... and actually have a corresponding WSACleanup call somewhere */
  120. if(WSAStartup(MAKEWORD(1, 1), &wsa)) {
  121. fprintf(stderr, "open_connection: cannot start sockets\n");
  122. /* FIXME should this exception be handled more explicitely? */
  123. }
  124. }
  125. #endif
  126. if ((host = gethostbyname(hostname)) == NULL) {
  127. fprintf(stderr, "open_connection: nslookup1 failed on '%s'\n", hostname);
  128. return -1;
  129. }
  130. if (host->h_length == 0) {
  131. fprintf(stderr, "open_connection: nslookup2 failed on '%s'\n", hostname);
  132. return -1;
  133. }
  134. bzero(&sa, sizeof sa);
  135. sa.sin_family = AF_INET;
  136. sa.sin_port = htons(port);
  137. memcpy(&(sa.sin_addr.s_addr), host->h_addr_list[0], sizeof(sa.sin_addr.s_addr));
  138. if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  139. if (verbose>0)
  140. fprintf(stderr, "open_connection: socket = %d\n", s);
  141. perror("open_connection");
  142. return -1;
  143. }
  144. retry = 10;
  145. while (retry>0) {
  146. if (connect(s, (struct sockaddr *)&sa, sizeof sa)<0) {
  147. /* wait 5 miliseconds and try again */
  148. usleep(5000);
  149. retry--;
  150. }
  151. else {
  152. /* this signals that the connection has been made */
  153. retry = -1;
  154. }
  155. }
  156. if (retry==0) {
  157. /* close the socket */
  158. closesocket(s);
  159. /* it failed on mutliple attempts, give up */
  160. return -2;
  161. }
  162. /*
  163. while (connect(s, (struct sockaddr *)&sa, sizeof sa) < 0) {
  164. perror("open_connection connect");
  165. usleep(1000000);
  166. }
  167. */
  168. if (verbose>0)
  169. fprintf(stderr, "open_connection: connected to %s:%d on socket %d\n", hostname, port, s);
  170. #ifdef DISABLE_NAGLE
  171. {
  172. int optval = 1;
  173. setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));
  174. }
  175. #endif
  176. return s;
  177. }
  178. void check_datatypes() {
  179. /* check datatypes */
  180. if (WORDSIZE_CHAR !=1) { fprintf(stderr, "invalid size of CHAR (%d)\n", (int) WORDSIZE_CHAR ); exit(-1); }
  181. if (WORDSIZE_UINT8 !=1) { fprintf(stderr, "invalid size of UINT8 (%d)\n", (int) WORDSIZE_UINT8 ); exit(-1); }
  182. if (WORDSIZE_UINT16 !=2) { fprintf(stderr, "invalid size of UINT16 (%d)\n", (int) WORDSIZE_UINT16 ); exit(-1); }
  183. if (WORDSIZE_UINT32 !=4) { fprintf(stderr, "invalid size of UINT32 (%d)\n", (int) WORDSIZE_UINT32 ); exit(-1); }
  184. if (WORDSIZE_UINT64 !=8) { fprintf(stderr, "invalid size of UINT64 (%d)\n", (int) WORDSIZE_UINT64 ); exit(-1); }
  185. if (WORDSIZE_INT8 !=1) { fprintf(stderr, "invalid size of INT8 (%d)\n", (int) WORDSIZE_INT8 ); exit(-1); }
  186. if (WORDSIZE_INT16 !=2) { fprintf(stderr, "invalid size of INT16 (%d)\n", (int) WORDSIZE_INT16 ); exit(-1); }
  187. if (WORDSIZE_INT32 !=4) { fprintf(stderr, "invalid size of INT32 (%d)\n", (int) WORDSIZE_INT32 ); exit(-1); }
  188. if (WORDSIZE_INT64 !=8) { fprintf(stderr, "invalid size of INT64 (%d)\n", (int) WORDSIZE_INT64 ); exit(-1); }
  189. if (WORDSIZE_FLOAT32 !=4) { fprintf(stderr, "invalid size of FLOAT32 (%d)\n", (int) WORDSIZE_FLOAT32); exit(-1); }
  190. if (WORDSIZE_FLOAT64 !=8) { fprintf(stderr, "invalid size of FLOAT64 (%d)\n", (int) WORDSIZE_FLOAT64); exit(-1); }
  191. if (sizeof(messagedef_t) !=8 ) { fprintf(stderr, "invalid size of messagedef_t\n"); exit(-1); }
  192. if (sizeof(headerdef_t) !=24) { fprintf(stderr, "invalid size of headerdef_t \n"); exit(-1); }
  193. if (sizeof(datadef_t) !=16) { fprintf(stderr, "invalid size of datadef_t \n"); exit(-1); }
  194. if (sizeof(eventdef_t) !=32) { fprintf(stderr, "invalid size of eventdef_t \n"); exit(-1); }
  195. if (sizeof(datasel_t) !=8 ) { fprintf(stderr, "invalid size of datasel_t \n"); exit(-1); }
  196. if (sizeof(eventsel_t) !=8 ) { fprintf(stderr, "invalid size of eventsel_t \n"); exit(-1); }
  197. }
  198. unsigned int wordsize_from_type(UINT32_T data_type) {
  199. switch(data_type) {
  200. case DATATYPE_CHAR:
  201. return WORDSIZE_CHAR;
  202. case DATATYPE_UINT8:
  203. case DATATYPE_INT8:
  204. return WORDSIZE_INT8;
  205. case DATATYPE_UINT16:
  206. case DATATYPE_INT16:
  207. return WORDSIZE_INT16;
  208. case DATATYPE_UINT32:
  209. case DATATYPE_INT32:
  210. return WORDSIZE_INT32;
  211. case DATATYPE_UINT64:
  212. case DATATYPE_INT64:
  213. return WORDSIZE_INT64;
  214. case DATATYPE_FLOAT32:
  215. return WORDSIZE_FLOAT32;
  216. case DATATYPE_FLOAT64:
  217. return WORDSIZE_FLOAT64;
  218. }
  219. return 0;
  220. }
  221. const ft_chunk_t *find_chunk(const void *buf, unsigned int offset0, unsigned int size, UINT32_T chunk_type) {
  222. unsigned int bufpos = offset0;
  223. while (bufpos + sizeof(ft_chunkdef_t) <= size) {
  224. const ft_chunk_t *chunk = (ft_chunk_t *) ((char *)buf + bufpos);
  225. if (chunk->def.type == chunk_type) return chunk;
  226. bufpos += sizeof(ft_chunkdef_t) + chunk->def.size;
  227. }
  228. return NULL;
  229. }
  230. /** Iterate through an array of events and check whether all of them are properly defined,
  231. that is, whether the "type" and "value" fields are of valid type and size, and whether the
  232. "bufsize" fields are correct (that is, fully contained in the passed buffer, and big enough
  233. to hold "type" and "value".
  234. Returns the number of events on success (might also be 0), or
  235. a negative number that indicates in which event definition an error happend,
  236. for example, a return value of -2 means that the first event was ok, but the second event
  237. definition was invalid. This function returns at the first error.
  238. */
  239. int check_event_array(unsigned int size, const void *buf) {
  240. unsigned int offset=0;
  241. int numEvents = 0;
  242. while (offset + sizeof(eventdef_t) <= size) {
  243. const eventdef_t *E;
  244. unsigned int wsType, wsValue;
  245. /* Set our event pointer to the current location within the array */
  246. E = (const eventdef_t *) ((char *) buf + offset);
  247. /* Increase the offset by the size of this event, and check whether it's fully
  248. contained within the given array.
  249. */
  250. offset += sizeof(eventdef_t) + E->bufsize;
  251. if (offset > size) goto error;
  252. /* Check whether "type" and "value" are of known type */
  253. wsType = wordsize_from_type(E->type_type);
  254. if (wsType == 0) goto error;
  255. wsValue = wordsize_from_type(E->value_type);
  256. if (wsValue == 0) goto error;
  257. /* Check whether "type" and "value" are contained in this event's "buf" */
  258. if (wsType * E->type_numel + wsValue * E->value_numel > E->bufsize) goto error;
  259. /* all checks passed, continue at next offset */
  260. ++numEvents;
  261. }
  262. return numEvents;
  263. error:
  264. return -(1+numEvents);
  265. }
  266. #ifdef WIN32
  267. int open_unix_connection(const char *name) {
  268. return -1;
  269. }
  270. #else
  271. int open_unix_connection(const char *name) {
  272. int verbose = 0;
  273. int s, retry;
  274. struct sockaddr_un sa;
  275. bzero(&sa, sizeof(sa));
  276. sa.sun_family = AF_UNIX;
  277. strncpy(sa.sun_path, name, sizeof(sa.sun_path));
  278. s = socket(AF_UNIX, SOCK_STREAM, 0);
  279. if (s < 0) {
  280. perror("open_unix_connection, socket");
  281. return -1;
  282. }
  283. retry = 10;
  284. while (retry>0) {
  285. if (connect(s, (struct sockaddr *)&sa, sizeof(sa))<0) {
  286. /* wait 5 miliseconds and try again */
  287. perror("open_connection");
  288. usleep(5000);
  289. retry--;
  290. } else {
  291. /* this signals that the connection has been made */
  292. retry = -1;
  293. }
  294. }
  295. if (retry==0) {
  296. /* it failed on mutliple attempts, give up */
  297. return -2;
  298. }
  299. if (verbose>0)
  300. fprintf(stderr, "open_unix_connection: connected to %s on socket %d\n", name, s);
  301. return s;
  302. }
  303. #endif
  304. #ifdef WIN32
  305. #ifndef COMPILER_MINGW
  306. /*
  307. * timeval.h 1.0 01/12/19
  308. *
  309. * Defines gettimeofday, timeval, etc. for Win32
  310. *
  311. * By Wu Yongwei
  312. *
  313. */
  314. //#define EPOCHFILETIME (116444736000000000i64)
  315. #define EPOCHFILETIME ((INT64_T) 116444736000000000LL)
  316. #ifdef COMPILER_LCC
  317. VOID STDCALL GetSystemTimeAsFileTime(LPFILETIME);
  318. #endif
  319. int gettimeofday(struct timeval *tv, struct timezone *tz)
  320. {
  321. FILETIME ft;
  322. LARGE_INTEGER li;
  323. INT64_T t;
  324. static int tzflag;
  325. if (tv) {
  326. GetSystemTimeAsFileTime(&ft);
  327. li.LowPart = ft.dwLowDateTime;
  328. li.HighPart = ft.dwHighDateTime;
  329. t = li.QuadPart; /* In 100-nanosecond intervals */
  330. t -= EPOCHFILETIME; /* Offset to the Epoch time */
  331. t /= 10; /* In microseconds */
  332. tv->tv_sec = (long)(t / 1000000);
  333. tv->tv_usec = (long)(t % 1000000);
  334. }
  335. #ifndef COMPILER_LCC
  336. /* LCC that comes with Matlab has problems with _timezone and _daylight,
  337. and we don't need it anyway */
  338. if (tz) {
  339. if (!tzflag) {
  340. _tzset();
  341. tzflag++;
  342. }
  343. tz->tz_minuteswest = _timezone / 60;
  344. tz->tz_dsttime = _daylight;
  345. }
  346. #endif
  347. return 0;
  348. }
  349. #endif
  350. #endif