00001
00002
00003
00004
00005
00006
00007 #ifdef USE_PCNFS
00008 #undef USE_PCNFS
00009 #endif
00010
00011 #include "rcs_defs.hh"
00012
00013 #include "recvline.h"
00014 #if (!defined(_Windows) && !defined(MSDOS)) || defined(gnuwin32)
00015 #include <unistd.h>
00016 #include <sys/types.h>
00017 #include <sys/socket.h>
00018 #ifndef VXWORKS
00019 #include <sys/time.h>
00020 #else
00021 #include <sys/times.h>
00022 #endif
00023 #else
00024 #ifdef _Windows
00025 #ifdef USE_OLD_WINSOCK
00026 #include <winsock.h>
00027 #else
00028 #include <winsock2.h>
00029 #endif
00030 #else
00031 #include <tklib.h>
00032 #include <tk_errno.h>
00033 #endif
00034 #endif
00035 #include <stddef.h>
00036 #include <errno.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <math.h>
00040 #include "rcs_prnt.hh"
00041 #include "sokintrf.h"
00042 #include "_timer.h"
00043 #include "dbg_mem.h"
00044
00045
00046 int recvline_timedout = 0;
00047
00048
00049 struct prev_read_info_struct
00050 {
00051 char *buf;
00052 char *ptr;
00053 int fd;
00054 int buf_size;
00055 };
00056
00057 static struct prev_read_info_struct prev_read_info[256];
00058 static int prev_read_infos = 0;
00059 static int initialized = 0;
00060
00061 #ifdef VXWORKS
00062 static int tasklock_recvline_prev_read_info = 1;
00063 #endif
00064
00065 #ifdef VXWORKS
00066 void
00067 print_recvline_prev_read_info ()
00068 {
00069 int i;
00070
00071 for (i = 0; i < 256; i++)
00072 {
00073 if (prev_read_info[i].fd > 1)
00074 {
00075 rcs_print ("fd = %d, buf = %p, ptr = %p, buf_size = %d(0x%X)\n",
00076 prev_read_info[i].fd,
00077 prev_read_info[i].buf,
00078 prev_read_info[i].ptr,
00079 prev_read_info[i].buf_size, prev_read_info[i].buf_size);
00080 rcs_print ("\t buf=%s\n", prev_read_info[i].buf);
00081 rcs_print ("\t ptr=%s\n", prev_read_info[i].ptr);
00082 }
00083 }
00084 }
00085 #endif
00086
00087 void
00088 clean_prev_read_info (int fd)
00089 {
00090 int max_prev_read_info = 0;
00091 int i;
00092
00093 if (fd < 1)
00094 {
00095 return;
00096 }
00097 #ifdef VXWORKS
00098 if (tasklock_recvline_prev_read_info)
00099 taskLock ();
00100 #endif
00101
00102 for (i = 0; i < 256; i++)
00103 {
00104 if (prev_read_info[i].fd == fd)
00105 {
00106 prev_read_info[i].ptr = NULL;
00107 if (NULL != prev_read_info[i].buf)
00108 {
00109 DEBUG_FREE (prev_read_info[i].buf);
00110 prev_read_info[i].buf = NULL;
00111 }
00112 prev_read_info[i].buf_size = 0;
00113 prev_read_info[i].fd = -1;
00114 continue;
00115 }
00116 if (prev_read_info[i].fd > 0)
00117 {
00118 max_prev_read_info = i;
00119 }
00120 }
00121 prev_read_infos = max_prev_read_info;
00122
00123 #ifdef VXWORKS
00124 if (tasklock_recvline_prev_read_info)
00125 taskUnlock ();
00126 #endif
00127
00128 }
00129
00130
00131 int
00132 get_bytes_already_read (int fd)
00133 {
00134 int bytes_left;
00135 int i;
00136
00137 if (fd < 1)
00138 {
00139 return -1;
00140 }
00141
00142 #ifdef VXWORKS
00143 if (tasklock_recvline_prev_read_info)
00144 taskLock ();
00145 #endif
00146
00147 for (i = 0; i < prev_read_infos; i++)
00148 {
00149 if (prev_read_info[i].fd == fd)
00150 {
00151 bytes_left = prev_read_info[i].buf_size -
00152 ((unsigned long) prev_read_info[i].ptr
00153 - (unsigned long) prev_read_info[i].buf);
00154 #ifdef VXWORKS
00155 if (tasklock_recvline_prev_read_info)
00156 taskUnlock ();
00157 #endif
00158 return bytes_left;
00159 }
00160 }
00161
00162 #ifdef VXWORKS
00163 if (tasklock_recvline_prev_read_info)
00164 taskUnlock ();
00165 #endif
00166
00167 return 0;
00168 }
00169
00170
00171 int
00172 recvline (int fd, char *cptr, int maxbytes, int flags, double _timeout,
00173 int *bytes_read_ptr)
00174 {
00175 #if defined(_Windows)
00176 int error_value = 0;
00177 #endif
00178 char *previous_read_ptr = NULL;
00179 char *previous_read_buf = NULL;
00180 char *nptr;
00181 int bytes_read = 0;
00182 int bytes_ready;
00183 int nrecv;
00184 int i;
00185 int select_ret;
00186 char *ptr;
00187 int bytes_left;
00188 double start_time, current_time;
00189 struct timeval timeout_tv;
00190 fd_set recv_fd_set;
00191 int first_empty_slot = -1;
00192 int max_prev_read_info = 0;
00193 int current_prev_read_info = -1;
00194 if (etime_disabled)
00195 {
00196 _timeout = -1.0;
00197 }
00198
00199 if (fd < 1 || cptr == NULL)
00200 {
00201 rcs_print_error ("recvline: Invalid parameter. fd=%d, cptr=%p\n", fd,
00202 cptr);
00203 return -1;
00204 }
00205 recvline_timedout = 0;
00206 timeout_tv.tv_sec = (long) _timeout;
00207 timeout_tv.tv_usec = (long) (_timeout * 1000000.0);
00208 if (timeout_tv.tv_usec >= 1000000)
00209 {
00210 timeout_tv.tv_usec = timeout_tv.tv_usec % 1000000;
00211 }
00212 FD_ZERO (&recv_fd_set);
00213 RCS_FD_SET (fd, &recv_fd_set);
00214
00215 #ifdef VXWORKS
00216 if (tasklock_recvline_prev_read_info)
00217 taskLock ();
00218 #endif
00219
00220 if (!initialized)
00221 {
00222 for (i = 0; i < 256; i++)
00223 {
00224 prev_read_info[i].ptr = NULL;
00225 prev_read_info[i].buf = NULL;
00226 prev_read_info[i].fd = 0;
00227 prev_read_info[i].buf_size = 0;
00228 }
00229 prev_read_infos = 0;
00230 initialized = 1;
00231 }
00232
00233 #ifdef VXWORKS
00234 if (tasklock_recvline_prev_read_info)
00235 taskUnlock ();
00236 #endif
00237
00238
00239 for (i = 0; i < prev_read_infos; i++)
00240 {
00241 if (prev_read_info[i].fd == fd)
00242 {
00243 previous_read_ptr = prev_read_info[i].ptr;
00244 previous_read_buf = prev_read_info[i].buf;
00245 if (NULL == prev_read_info[i].buf || NULL == prev_read_info[i].ptr)
00246 {
00247 rcs_print_error
00248 ("Invalid prev_read_info. buf =%p, ptr=%p, fd = %d, buf_size=%d(0x%X)\n",
00249 prev_read_info[i].buf, prev_read_info[i].ptr,
00250 prev_read_info[i].fd, prev_read_info[i].buf_size,
00251 prev_read_info[i].buf_size);
00252 prev_read_info[i].ptr = NULL;
00253 prev_read_info[i].buf = NULL;
00254 prev_read_info[i].fd = 0;
00255 prev_read_info[i].buf_size = 0;
00256 continue;
00257 }
00258 else if ((unsigned long) previous_read_ptr >
00259 ((unsigned long) previous_read_buf) +
00260 prev_read_info[i].buf_size)
00261 {
00262 rcs_print_error
00263 ("Invalid prev_read_info. buf =%p, ptr=%p, fd = %d, buf_size=%d(0x%X)\n",
00264 prev_read_info[i].buf, prev_read_info[i].ptr,
00265 prev_read_info[i].fd, prev_read_info[i].buf_size,
00266 prev_read_info[i].buf_size);
00267 prev_read_info[i].ptr = NULL;
00268 prev_read_info[i].buf = NULL;
00269 prev_read_info[i].fd = 0;
00270 prev_read_info[i].buf_size = 0;
00271 continue;
00272 }
00273 else if ((unsigned long) previous_read_ptr <
00274 ((unsigned long) previous_read_buf))
00275 {
00276 rcs_print_error
00277 ("Invalid prev_read_info. buf =%p, ptr=%p, fd = %d, buf_size=%d(0x%X)\n",
00278 prev_read_info[i].buf, prev_read_info[i].ptr,
00279 prev_read_info[i].fd, prev_read_info[i].buf_size,
00280 prev_read_info[i].buf_size);
00281 prev_read_info[i].ptr = NULL;
00282 prev_read_info[i].buf = NULL;
00283 prev_read_info[i].fd = 0;
00284 prev_read_info[i].buf_size = 0;
00285 continue;
00286 }
00287
00288 max_prev_read_info = i;
00289 current_prev_read_info = i;
00290 break;
00291 }
00292 if (prev_read_info[i].fd < 1 && first_empty_slot < 0)
00293 {
00294 first_empty_slot = i;
00295 }
00296 else
00297 {
00298 max_prev_read_info = i;
00299 }
00300 }
00301 if (first_empty_slot < 0)
00302 {
00303 first_empty_slot = prev_read_infos;
00304 }
00305 prev_read_infos = max_prev_read_info + 1;
00306
00307
00308 if (previous_read_ptr != NULL)
00309 {
00310 if (*previous_read_ptr != 0)
00311 {
00312 ptr = strchr (previous_read_ptr, '\n');
00313 if (NULL != ptr)
00314 {
00315 *ptr = 0;
00316 bytes_left =
00317 prev_read_info[current_prev_read_info].buf_size -
00318 ((unsigned long) previous_read_ptr -
00319 (unsigned long) previous_read_buf);
00320 if (bytes_left <= 0)
00321 {
00322 rcs_print_error ("Problem with previous_read_ptr.\n");
00323 prev_read_info[current_prev_read_info].ptr = NULL;
00324 prev_read_info[current_prev_read_info].buf = NULL;
00325 prev_read_info[current_prev_read_info].fd = 0;
00326 prev_read_info[current_prev_read_info].buf_size = 0;
00327 return -1;
00328 }
00329 strncpy (cptr, previous_read_ptr, bytes_left);
00330 previous_read_ptr = ptr;
00331 previous_read_ptr++;
00332 bytes_read = strlen (cptr);
00333 if (NULL != bytes_read_ptr)
00334 {
00335 *bytes_read_ptr = bytes_read;
00336 }
00337 bytes_left =
00338 prev_read_info[current_prev_read_info].buf_size -
00339 ((unsigned long) previous_read_ptr -
00340 (unsigned long) previous_read_buf);
00341 if (bytes_left > 0)
00342 {
00343 prev_read_info[current_prev_read_info].ptr =
00344 previous_read_ptr;
00345 if (NULL == prev_read_info[current_prev_read_info].buf
00346 || NULL == prev_read_info[current_prev_read_info].ptr)
00347 {
00348 rcs_print_error
00349 ("Invalid prev_read_info. buf =%p, ptr=%p, fd = %d, buf_size=%d(0x%X)\n",
00350 prev_read_info[current_prev_read_info].buf,
00351 prev_read_info[current_prev_read_info].ptr,
00352 prev_read_info[current_prev_read_info].fd,
00353 prev_read_info[current_prev_read_info].buf_size,
00354 prev_read_info[current_prev_read_info].buf_size);
00355 prev_read_info[current_prev_read_info].ptr = NULL;
00356 prev_read_info[current_prev_read_info].buf = NULL;
00357 prev_read_info[current_prev_read_info].fd = 0;
00358 prev_read_info[current_prev_read_info].buf_size = 0;
00359 return -1;
00360 }
00361 else if ((unsigned long) previous_read_ptr >
00362 ((unsigned long) previous_read_buf) +
00363 prev_read_info[current_prev_read_info].buf_size)
00364 {
00365 rcs_print_error
00366 ("Invalid prev_read_info. buf =%p, ptr=%p, fd = %d, buf_size=%d(0x%X)\n",
00367 prev_read_info[current_prev_read_info].buf,
00368 prev_read_info[current_prev_read_info].ptr,
00369 prev_read_info[current_prev_read_info].fd,
00370 prev_read_info[current_prev_read_info].buf_size,
00371 prev_read_info[current_prev_read_info].buf_size);
00372 prev_read_info[current_prev_read_info].ptr = NULL;
00373 prev_read_info[current_prev_read_info].buf = NULL;
00374 prev_read_info[current_prev_read_info].fd = 0;
00375 prev_read_info[current_prev_read_info].buf_size = 0;
00376 return -1;
00377 }
00378 else if ((unsigned long) previous_read_ptr <
00379 ((unsigned long) previous_read_buf))
00380 {
00381 rcs_print_error
00382 ("Invalid prev_read_info. buf =%p, ptr=%p, fd = %d, buf_size=%d(0x%X)\n",
00383 prev_read_info[current_prev_read_info].buf,
00384 prev_read_info[current_prev_read_info].ptr,
00385 prev_read_info[current_prev_read_info].fd,
00386 prev_read_info[current_prev_read_info].buf_size,
00387 prev_read_info[current_prev_read_info].buf_size);
00388 prev_read_info[current_prev_read_info].ptr = NULL;
00389 prev_read_info[current_prev_read_info].buf = NULL;
00390 prev_read_info[current_prev_read_info].fd = 0;
00391 prev_read_info[current_prev_read_info].buf_size = 0;
00392 return -1;
00393 }
00394 }
00395 else
00396 {
00397 prev_read_info[current_prev_read_info].ptr = NULL;
00398 prev_read_info[current_prev_read_info].fd = 0;
00399 previous_read_buf = NULL;
00400 if (prev_read_info[current_prev_read_info].buf != NULL)
00401 {
00402 DEBUG_FREE (prev_read_info[current_prev_read_info].buf);
00403 prev_read_info[current_prev_read_info].buf = NULL;
00404 }
00405 prev_read_info[current_prev_read_info].buf = NULL;
00406 prev_read_info[current_prev_read_info].buf_size = 0;
00407 }
00408 return bytes_read;
00409 }
00410 else
00411 {
00412 strcpy (cptr, previous_read_ptr);
00413 previous_read_ptr = previous_read_buf;
00414 bytes_read = strlen (cptr);
00415 prev_read_info[current_prev_read_info].ptr = NULL;
00416 prev_read_info[current_prev_read_info].fd = 0;
00417 previous_read_buf = NULL;
00418 if (prev_read_info[current_prev_read_info].buf != NULL)
00419 {
00420 DEBUG_FREE (prev_read_info[current_prev_read_info].buf);
00421 prev_read_info[current_prev_read_info].buf = NULL;
00422 }
00423 prev_read_info[current_prev_read_info].buf = NULL;
00424 prev_read_info[current_prev_read_info].buf_size = 0;
00425 if (current_prev_read_info > first_empty_slot)
00426 {
00427 current_prev_read_info = -1;
00428 }
00429 cptr += bytes_read;
00430 }
00431 }
00432 }
00433
00434 ptr = (char *) cptr;
00435 start_time = etime ();
00436 while (1)
00437 {
00438 if (fabs (_timeout) > 1E-6)
00439 {
00440 if (_timeout > 0)
00441 {
00442 select_ret =
00443 dl_select (fd + 1, &recv_fd_set, (fd_set *) NULL,
00444 (fd_set *) NULL, &timeout_tv);
00445 }
00446 else
00447 {
00448 select_ret =
00449 dl_select (fd + 1, &recv_fd_set, (fd_set *) NULL,
00450 (fd_set *) NULL, NULL);
00451 }
00452 switch (select_ret)
00453 {
00454 case -1:
00455 #if !defined(_Windows) || defined(gnuwin32)
00456 rcs_print_error ("Error in select: %d -> %s\n", errno,
00457 strerror (errno));
00458 #else
00459 rcs_print_error ("Error in select: %d\n",
00460 dl_WSAGetLastError ());
00461 #endif
00462 return -1;
00463
00464 case 0:
00465 rcs_print_error ("Recvline timed out.\n");
00466 recvline_timedout = 1;
00467 return -1;
00468
00469 default:
00470 break;
00471 }
00472 }
00473 #if defined(WIN32) && !defined(gnuwin32)
00474 dl_ioctlsocket (fd, FIONREAD, &bytes_ready);
00475 #else
00476 #ifndef VXWORKS
00477 ioctl (fd, FIONREAD, (caddr_t) & bytes_ready);
00478 #else
00479 ioctl (fd, FIONREAD, (int) &bytes_ready);
00480 #endif
00481 #endif
00482 if (bytes_ready <= 0)
00483 {
00484 if (fabs (_timeout) < 1e-6)
00485 {
00486 recvline_timedout = 1;
00487 if (NULL != bytes_read_ptr)
00488 {
00489 *bytes_read_ptr = bytes_read;
00490 }
00491 return (-1);
00492 }
00493 else
00494 {
00495 rcs_print_error ("recvline: Premature EOF recieved.\n");
00496 return (-1);
00497 }
00498 }
00499 if (bytes_read < 0)
00500 {
00501 bytes_read = 0;
00502 }
00503 if (bytes_ready > maxbytes - bytes_read)
00504 {
00505 bytes_ready = maxbytes - bytes_read;
00506 }
00507 if ((nrecv = dl_recv (fd, ptr, bytes_ready, flags)) == -1)
00508 {
00509 #if (!defined(_WINDOWS) && !defined(MSDOS)) || defined(gnuwin32)
00510 if (errno == EWOULDBLOCK)
00511 {
00512 if (fabs (_timeout) < 1e-6)
00513 {
00514 recvline_timedout = 1;
00515 if (NULL != bytes_read_ptr)
00516 {
00517 *bytes_read_ptr = bytes_read;
00518 }
00519 return (-1);
00520 }
00521 }
00522 else
00523 {
00524 rcs_print_error ("Recv error: %d = %s\n", errno,
00525 strerror (errno));
00526 if (NULL != bytes_read_ptr)
00527 {
00528 *bytes_read_ptr = bytes_read;
00529 }
00530 return (-1);
00531 }
00532 #else
00533 #if defined(_Windows)
00534 error_value = dl_WSAGetLastError ();
00535 if (WSAEWOULDBLOCK != error_value)
00536 {
00537 rcs_print_error ("Recv error: %d\n", error_value);
00538 return (-1);
00539 }
00540 else
00541 {
00542 if (fabs (_timeout) < 1e-6)
00543 {
00544 recvline_timedout = 1;
00545 return (-1);
00546 }
00547 }
00548 #else
00549 error_value = tk_geterrno (fd);
00550 if (EWOULDBLOCK != error_value)
00551 {
00552 rcs_print_error ("Recv error: %d\n", error_value);
00553 return (-1);
00554 }
00555 else
00556 {
00557 if (fabs (_timeout) < 1e-6)
00558 {
00559 recvline_timedout = 1;
00560 return (-1);
00561 }
00562 }
00563 #endif
00564 #endif
00565 continue;
00566 }
00567 else if (nrecv == 0)
00568 {
00569 rcs_print_error ("recvline: Premature EOF recieved.\n");
00570 return (-1);
00571 }
00572 nptr = strchr (ptr, '\n');
00573 if (NULL != nptr)
00574 {
00575 *nptr = 0;
00576 bytes_read += strlen (ptr);
00577 if (NULL != bytes_read_ptr)
00578 {
00579 *bytes_read_ptr = bytes_read;
00580 }
00581 nptr++;
00582 if (nrecv > ((int) (strlen (ptr) + 1)))
00583 {
00584 if (current_prev_read_info < 0)
00585 {
00586 current_prev_read_info = first_empty_slot;
00587 }
00588
00589 prev_read_info[current_prev_read_info].buf = NULL;
00590 prev_read_info[current_prev_read_info].ptr = NULL;
00591 prev_read_info[current_prev_read_info].fd = 0;
00592 prev_read_info[current_prev_read_info].buf_size = 0;
00593 prev_read_info[current_prev_read_info].buf =
00594 DEBUG_MALLOC (nrecv - strlen (ptr));
00595 prev_read_info[current_prev_read_info].buf_size =
00596 nrecv - strlen (ptr);
00597 prev_read_info[current_prev_read_info].fd = fd;
00598 previous_read_buf = prev_read_info[current_prev_read_info].buf;
00599 memcpy (previous_read_buf, nptr, nrecv - (strlen (ptr) + 1));
00600 *(((char *) previous_read_buf) +
00601 prev_read_info[current_prev_read_info].buf_size - 1) = 0;
00602 previous_read_ptr = previous_read_buf;
00603 prev_read_info[current_prev_read_info].ptr = previous_read_ptr;
00604 if (prev_read_infos < current_prev_read_info + 1)
00605 {
00606 prev_read_infos = current_prev_read_info + 1;
00607 }
00608 }
00609 return bytes_read;
00610 }
00611 ptr += nrecv;
00612 bytes_read += nrecv;
00613 if (bytes_read > maxbytes)
00614 {
00615 rcs_print_error ("recvline: Buffer size of %d exceeded.\n",
00616 maxbytes);
00617 return (-1);
00618 }
00619 if (_timeout > 0.0)
00620 {
00621 esleep (0.001);
00622 current_time = etime ();
00623 if (current_time - start_time > _timeout)
00624 {
00625 rcs_print_error
00626 ("recvline: timed out after %lf seconds between %lf and %lf\n",
00627 current_time - start_time, start_time, current_time);
00628 recvline_timedout = 1;
00629 if (NULL != bytes_read_ptr)
00630 {
00631 *bytes_read_ptr = bytes_read;
00632 }
00633 return (-1);
00634 }
00635 }
00636 }
00637 rcs_print_debug (PRINT_SOCKET_READ_SIZE,
00638 "recvline:(%d bytes from %d) %s \n", bytes_read, fd, cptr);
00639
00640 if (NULL != bytes_read_ptr)
00641 {
00642 *bytes_read_ptr = bytes_read;
00643 }
00644 return (bytes_read);
00645 }