00001
00002
00003 #ifdef USE_PCNFS
00004 #undef USE_PCNFS
00005 #endif
00006
00007 #include "rcs_defs.hh"
00008
00009 #ifdef EXTERN_C_STD_HEADERS
00010 extern "C"
00011 {
00012 #endif
00013 #include <stdlib.h>
00014 #include <string.h>
00015 #ifndef UNDER_CE
00016 #include <errno.h>
00017 #include <signal.h>
00018 #include <ctype.h>
00019 #else
00020 #include "rcs_ce.h"
00021 #endif
00022
00023 #ifndef irix6
00024 #include <math.h>
00025 #else
00026
00027
00028 extern double fmod (double, double);
00029 #endif
00030
00031 #ifdef EXTERN_C_STD_HEADERS
00032 }
00033 #endif
00034
00035 #include "rem_msg.hh"
00036 #include "rcs_prnt.hh"
00037 #include "cmsdiag.hh"
00038
00039
00040 #define DEFAULT_MAX_CONSECUTIVE_TIMEOUTS (-1)
00041
00042
00043 #include "timer.hh"
00044
00045 #include "tcpmem.hh"
00046
00047 #include "recvn.h"
00048 #include "sendn.h"
00049 #include "tcp_opts.hh"
00050 #include "sokintrf.h"
00051
00052
00053 #ifndef UNDER_CE
00054 #include "crypt2.hh"
00055 #endif
00056
00057
00058 int tcpmem_sigpipe_count = 0;
00059 int last_sig = 0;
00060
00061 void
00062 tcpmem_sigpipe_handler (int sig)
00063 {
00064 last_sig = sig;
00065 tcpmem_sigpipe_count++;
00066 }
00067
00068
00069 TCPMEM::TCPMEM (char *_bufline, char *_procline):
00070 CMS (_bufline, _procline)
00071 {
00072 #if defined(_Windows) && !defined(USE_PCNFS)
00073 WSA_count++;
00074 #endif
00075 if (load_socket_interface () < 0)
00076 {
00077 rcs_print_error ("Can't load socket interface.\n");
00078 status = CMS_LIBRARY_UNAVAILABLE_ERROR;
00079 }
00080 max_consecutive_timeouts = DEFAULT_MAX_CONSECUTIVE_TIMEOUTS;
00081 char *max_consecutive_timeouts_string;
00082 max_consecutive_timeouts_string = strstr (ProcessLine, "max_timeouts=");
00083 polling = (NULL != strstr (proclineupper, "POLL"));
00084 socket_fd = 0;
00085 reconnect_needed = 0;
00086 autoreconnect = 1;
00087 #ifndef UNDER_CE
00088 old_handler = (void (*)(int)) SIG_ERR;
00089 #endif
00090 sigpipe_count = 0;
00091 subscription_count = 0;
00092 read_serial_number = 0;
00093 write_serial_number = 0;
00094 read_socket_fd = 0;
00095 write_socket_fd = 0;
00096 if (NULL != max_consecutive_timeouts_string)
00097 {
00098 max_consecutive_timeouts_string += strlen ("max_timeouts=");
00099 if (!strncmp (max_consecutive_timeouts_string, "INF", 3))
00100 {
00101 max_consecutive_timeouts = -1;
00102 }
00103 else
00104 {
00105 #ifndef UNDER_CE
00106 max_consecutive_timeouts =
00107 strtol (max_consecutive_timeouts_string, (char **) NULL, 0);
00108 #else
00109 max_consecutive_timeouts = atol (max_consecutive_timeouts_string);
00110 #endif
00111 }
00112 }
00113
00114 char *sub_info_string = NULL;
00115 poll_interval_millis = 30000;
00116 subscription_type = CMS_NO_SUBSCRIPTION;
00117 sub_info_string = strstr (ProcessLine, "sub=");
00118 if (NULL != sub_info_string)
00119 {
00120 if (!strncmp (sub_info_string + 4, "none", 4))
00121 {
00122 subscription_type = CMS_NO_SUBSCRIPTION;
00123 }
00124 else if (!strncmp (sub_info_string + 4, "var", 3))
00125 {
00126 subscription_type = CMS_VARIABLE_SUBSCRIPTION;
00127 }
00128 else
00129 {
00130 #ifndef UNDER_CE
00131 poll_interval_millis =
00132 ((int) (atof (sub_info_string + 4) * 1000.0));
00133 #else
00134 poll_interval_millis =
00135 ((int) (RCS_CE_ATOF (sub_info_string + 4) * 1000.0));
00136 #endif
00137 subscription_type = CMS_POLLED_SUBSCRIPTION;
00138 }
00139 }
00140 if (NULL != strstr (ProcessLine, "noreconnect"))
00141 {
00142 autoreconnect = 0;
00143 }
00144
00145 #ifndef VXWORKS
00146 server_host_entry = NULL;
00147 #endif
00148
00149
00150 memset (&server_socket_address, 0, sizeof (server_socket_address));
00151 server_socket_address.sin_family = AF_INET;
00152 server_socket_address.sin_port = dl_htons (((u_short) tcp_port_number));
00153 int hostname_was_address = 0;
00154 char bufferhost_first_char = BufferHost[0];
00155 if (bufferhost_first_char >= '0' && bufferhost_first_char <= '9')
00156 {
00157 server_socket_address.sin_addr.s_addr = dl_inet_addr (BufferHost);
00158 if (server_socket_address.sin_addr.s_addr != 0 &&
00159 ((long) server_socket_address.sin_addr.s_addr) != -1)
00160 {
00161 hostname_was_address = 1;
00162 }
00163 }
00164
00165 if (!hostname_was_address)
00166 {
00167
00168 #ifndef VXWORKS
00169 dl_gethostbyname (BufferHost, &server_host_entry);
00170 if (NULL == server_host_entry)
00171 {
00172 status = CMS_CONFIG_ERROR;
00173 autoreconnect = 0;
00174 #if defined(_WINDOWS) && !defined(gnuwin32)
00175 rcs_print_sys_error (WSAGETLASTERROR_ERROR_SOURCE,
00176 "gethostbyname error");
00177 #endif
00178 rcs_print_error ("TCPMEM: Couldn't get host address for (%s).\n",
00179 BufferHost);
00180 return;
00181 }
00182 #ifdef __MSDOS__
00183 server_socket_address.sin_addr.s_addr =
00184 *((u_long *) server_host_entry->h_addr_list[0]);
00185 #else
00186 server_socket_address.sin_addr.s_addr =
00187 *((int *) server_host_entry->h_addr_list[0]);
00188 #endif
00189 server_socket_address.sin_family = server_host_entry->h_addrtype;
00190 #else
00191 server_socket_address.sin_addr.s_addr = hostGetByName (BufferHost);
00192 if (server_socket_address.sin_addr.s_addr == ERROR)
00193 {
00194 autoreconnect = 0;
00195 rcs_print_error ("TCPMEM: Couldn't get host address for (%s).\n",
00196 BufferHost);
00197 status = CMS_CONFIG_ERROR;
00198 return;
00199 }
00200 #endif
00201 }
00202 rcs_print_debug (PRINT_CMS_CONFIG_INFO,
00203 "Using server on %s with IP address %s and port %d.\n",
00204 BufferHost,
00205 dl_inet_ntoa (server_socket_address.sin_addr),
00206 tcp_port_number);
00207
00208
00209 reconnect ();
00210
00211 if (status >= 0 &&
00212 (min_compatible_version > 2.58 || min_compatible_version < 1e-6))
00213 {
00214 verify_bufname ();
00215 if (status < 0)
00216 {
00217 rcs_print_error ("TCPMEM: verify_bufname() failed.\n");
00218 }
00219 }
00220
00221 if (status >= 0 && enable_diagnostics &&
00222 (min_compatible_version > 3.71 || min_compatible_version < 1e-6))
00223 {
00224 send_diag_info ();
00225 }
00226 }
00227
00228
00229 void
00230 TCPMEM::send_diag_info ()
00231 {
00232 if (polling)
00233 {
00234 return;
00235 }
00236 if (NULL == dpi)
00237 {
00238 return;
00239 }
00240 disable_sigpipe ();
00241
00242 set_socket_fds (read_socket_fd);
00243 memset (diag_info_buf, 0, 88);
00244 *((u_long *) diag_info_buf) = dl_htonl ((u_long) serial_number);
00245 *((u_long *) diag_info_buf + 1) =
00246 dl_htonl ((u_long) REMOTE_CMS_SET_DIAG_INFO_REQUEST_TYPE);
00247 *((u_long *) diag_info_buf + 2) = dl_htonl ((u_long) buffer_number);
00248 strncpy (diag_info_buf + 20, dpi->name, 16);
00249 strncpy (diag_info_buf + 36, dpi->host_sysinfo, 32);
00250 *((u_long *) (diag_info_buf + 68)) = dl_htonl ((u_long) dpi->pid);
00251 *((u_long *) (diag_info_buf + 72)) = dl_htonl ((u_long) connection_number);
00252 memcpy (diag_info_buf + 76, &(dpi->rcslib_ver), 8);
00253 *((u_long *) (diag_info_buf + 84)) = 0x11223344;
00254 if (sendn (socket_fd, diag_info_buf, 88, 0, timeout) < 0)
00255 {
00256 reconnect_needed = 1;
00257 fatal_error_occurred = 1;
00258 reenable_sigpipe ();
00259 status = CMS_MISC_ERROR;
00260 return;
00261 }
00262 serial_number++;
00263 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
00264 "TCPMEM sending request: fd = %d, serial_number=%d, request_type=%d, buffer_number=%d\n",
00265 socket_fd, serial_number,
00266 dl_ntohl (*((u_long *) diag_info_buf + 1)), buffer_number);
00267 reenable_sigpipe ();
00268
00269 }
00270
00271 void
00272 TCPMEM::verify_bufname ()
00273 {
00274 if (polling)
00275 {
00276 return;
00277 }
00278 disable_sigpipe ();
00279
00280 set_socket_fds (read_socket_fd);
00281
00282 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
00283 *((u_long *) temp_buffer + 1) =
00284 dl_htonl ((u_long) REMOTE_CMS_GET_BUF_NAME_REQUEST_TYPE);
00285 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
00286 if (sendn (socket_fd, temp_buffer, 20, 0, timeout) < 0)
00287 {
00288 reconnect_needed = 1;
00289 fatal_error_occurred = 1;
00290 reenable_sigpipe ();
00291 status = CMS_MISC_ERROR;
00292 return;
00293 }
00294 serial_number++;
00295 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
00296 "TCPMEM sending request: fd = %d, serial_number=%d, request_type=%d, buffer_number=%d\n",
00297 socket_fd, serial_number,
00298 dl_ntohl (*((u_long *) temp_buffer + 1)), buffer_number);
00299 if (recvn (socket_fd, temp_buffer, 40, 0, timeout, &recvd_bytes) < 0)
00300 {
00301 if (recvn_timedout)
00302 {
00303 bytes_to_throw_away = 40;
00304 return;
00305 }
00306 }
00307 returned_serial_number = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
00308 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
00309 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
00310 socket_fd, returned_serial_number, buffer_number);
00311 if (returned_serial_number != serial_number)
00312 {
00313 rcs_print_error
00314 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
00315 returned_serial_number, serial_number);
00316 reconnect_needed = 1;
00317 fatal_error_occurred = 1;
00318 reenable_sigpipe ();
00319 status = CMS_MISC_ERROR;
00320 return;
00321 }
00322 status = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
00323 if (status < 0)
00324 {
00325 return;
00326 }
00327 if (strncmp (temp_buffer + 8, BufferName, 31))
00328 {
00329 rcs_print_error
00330 ("TCPMEM: The buffer (%s) is registered on TCP port %d of host %s with buffer number %d.\n",
00331 ((char *) temp_buffer + 8), tcp_port_number, BufferHost,
00332 buffer_number);
00333 rcs_print_error
00334 ("TCPMEM: However, this process (%s) is attempting to connect to the buffer %s at the same location.\n",
00335 ProcessName, BufferName);
00336 status = CMS_RESOURCE_CONFLICT_ERROR;
00337 return;
00338 }
00339 reenable_sigpipe ();
00340 }
00341
00342
00343 CMS_DIAGNOSTICS_INFO *
00344 TCPMEM::get_diagnostics_info ()
00345 {
00346 if (polling)
00347 {
00348 return (NULL);
00349 }
00350 disable_sigpipe ();
00351
00352 if (((int) handle_old_replies ()) < 0)
00353 {
00354 reenable_sigpipe ();
00355 return (NULL);
00356 }
00357
00358 set_socket_fds (read_socket_fd);
00359
00360 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
00361 *((u_long *) temp_buffer + 1) =
00362 dl_htonl ((u_long) REMOTE_CMS_GET_DIAG_INFO_REQUEST_TYPE);
00363 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
00364 if (sendn (socket_fd, temp_buffer, 20, 0, timeout) < 0)
00365 {
00366 reconnect_needed = 1;
00367 fatal_error_occurred = 1;
00368 reenable_sigpipe ();
00369 status = CMS_MISC_ERROR;
00370 return (NULL);
00371 }
00372 memset (temp_buffer, 0, 0x2000);
00373 serial_number++;
00374 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
00375 "TCPMEM sending request: fd = %d, serial_number=%d, request_type=%d, buffer_number=%d\n",
00376 socket_fd, serial_number,
00377 dl_ntohl (*((u_long *) temp_buffer + 1)), buffer_number);
00378 if (recvn (socket_fd, temp_buffer, 32, 0, -1.0, &recvd_bytes) < 0)
00379 {
00380 if (recvn_timedout)
00381 {
00382 bytes_to_throw_away = 32;
00383 }
00384 return (NULL);
00385 }
00386 recvd_bytes = 0;
00387 returned_serial_number = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
00388 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
00389 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
00390 socket_fd, returned_serial_number, buffer_number);
00391 if (returned_serial_number != serial_number)
00392 {
00393 rcs_print_error
00394 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
00395 returned_serial_number, serial_number);
00396 reconnect_needed = 1;
00397 fatal_error_occurred = 1;
00398 reenable_sigpipe ();
00399 status = CMS_MISC_ERROR;
00400 return (NULL);
00401 }
00402 status = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
00403 if (status < 0)
00404 {
00405 return (NULL);
00406 }
00407 if (NULL == di)
00408 {
00409 di = new CMS_DIAGNOSTICS_INFO ();
00410 di->dpis = new RCS_LINKED_LIST ();
00411 }
00412 else
00413 {
00414 di->dpis->delete_members ();
00415 }
00416 di->last_writer_dpi = NULL;
00417 di->last_reader_dpi = NULL;
00418 di->last_writer = dl_ntohl (*((u_long *) temp_buffer + 2));
00419 di->last_reader = dl_ntohl (*((u_long *) temp_buffer + 3));
00420 double server_time;
00421 memcpy (&server_time, temp_buffer + 16, 8);
00422 double local_time = etime ();
00423 double diff_time = local_time - server_time;
00424 int dpi_count = dl_ntohl (*((u_long *) temp_buffer + 6));
00425 int dpi_max_size = dl_ntohl (*((u_long *) temp_buffer + 7));
00426 if (dpi_max_size > 32 && dpi_max_size < 0x2000)
00427 {
00428 if (recvn
00429 (socket_fd, temp_buffer + 32, dpi_max_size - 32, 0, -1.0,
00430 &recvd_bytes) < 0)
00431 {
00432 if (recvn_timedout)
00433 {
00434 bytes_to_throw_away = dpi_max_size - 32;
00435 return (NULL);
00436 }
00437 }
00438 recvd_bytes = 0;
00439 int dpi_offset = 32;
00440 CMS_DIAG_PROC_INFO cms_dpi;
00441 for (int i = 0; i < dpi_count && dpi_offset < dpi_max_size; i++)
00442 {
00443 memset (&cms_dpi, 0, sizeof (CMS_DIAG_PROC_INFO));
00444 memcpy (cms_dpi.name, temp_buffer + dpi_offset, 16);
00445 dpi_offset += 16;
00446 memcpy (cms_dpi.host_sysinfo, temp_buffer + dpi_offset, 32);
00447 dpi_offset += 32;
00448 cms_dpi.pid =
00449 dl_ntohl (*((u_long *) ((char *) temp_buffer + dpi_offset)));
00450 dpi_offset += 4;
00451 memcpy (&(cms_dpi.rcslib_ver), temp_buffer + dpi_offset, 8);
00452 dpi_offset += 8;
00453 cms_dpi.access_type =
00454 (CMS_INTERNAL_ACCESS_TYPE)
00455 dl_ntohl (*((u_long *) ((char *) temp_buffer + dpi_offset)));
00456 dpi_offset += 4;
00457 cms_dpi.msg_id =
00458 dl_ntohl (*((u_long *) ((char *) temp_buffer + dpi_offset)));
00459 dpi_offset += 4;
00460 cms_dpi.msg_size =
00461 dl_ntohl (*((u_long *) ((char *) temp_buffer + dpi_offset)));
00462 dpi_offset += 4;
00463 cms_dpi.msg_type =
00464 dl_ntohl (*((u_long *) ((char *) temp_buffer + dpi_offset)));
00465 dpi_offset += 4;
00466 cms_dpi.number_of_accesses =
00467 dl_ntohl (*((u_long *) ((char *) temp_buffer + dpi_offset)));
00468 dpi_offset += 4;
00469 cms_dpi.number_of_new_messages =
00470 dl_ntohl (*((u_long *) ((char *) temp_buffer + dpi_offset)));
00471 dpi_offset += 4;
00472 memcpy (&(cms_dpi.bytes_moved), temp_buffer + dpi_offset, 8);
00473 dpi_offset += 8;
00474 memcpy (&(cms_dpi.bytes_moved_across_socket),
00475 temp_buffer + dpi_offset, 8);
00476 dpi_offset += 8;
00477 memcpy (&(cms_dpi.last_access_time), temp_buffer + dpi_offset, 8);
00478 if (cmsdiag_timebias_set)
00479 {
00480 cms_dpi.last_access_time += diff_time - cmsdiag_timebias;
00481 }
00482 dpi_offset += 8;
00483 memcpy (&(cms_dpi.first_access_time), temp_buffer + dpi_offset, 8);
00484 if (cmsdiag_timebias_set)
00485 {
00486 cms_dpi.first_access_time += diff_time - cmsdiag_timebias;
00487 }
00488 dpi_offset += 8;
00489 memcpy (&(cms_dpi.min_difference), temp_buffer + dpi_offset, 8);
00490 dpi_offset += 8;
00491 memcpy (&(cms_dpi.max_difference), temp_buffer + dpi_offset, 8);
00492 dpi_offset += 8;
00493 di->dpis->store_at_tail (&cms_dpi, sizeof (CMS_DIAG_PROC_INFO), 1);
00494 int is_last_writer =
00495 dl_ntohl (*((u_long *) ((char *) temp_buffer + dpi_offset)));
00496 dpi_offset += 4;
00497 if (is_last_writer)
00498 {
00499 di->last_writer_dpi =
00500 (CMS_DIAG_PROC_INFO *) di->dpis->get_tail ();
00501 }
00502 int is_last_reader =
00503 dl_ntohl (*((u_long *) ((char *) temp_buffer + dpi_offset)));
00504 dpi_offset += 4;
00505 if (is_last_reader)
00506 {
00507 di->last_reader_dpi =
00508 (CMS_DIAG_PROC_INFO *) di->dpis->get_tail ();
00509 }
00510 }
00511 }
00512 reenable_sigpipe ();
00513 return di;
00514 }
00515
00516
00517 void
00518 TCPMEM::reconnect ()
00519 {
00520 if (socket_fd > 0)
00521 {
00522 disconnect ();
00523 }
00524 subscription_count = 0;
00525 timedout_request = NO_REMOTE_CMS_REQUEST;
00526 bytes_to_throw_away = 0;
00527 recvd_bytes = 0;
00528 socket_fd = 0;
00529 waiting_for_message = 0;
00530 waiting_message_size = 0;
00531 waiting_message_id = 0;
00532 serial_number = 0;
00533
00534 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Creating socket . . .\n");
00535
00536 socket_fd = dl_socket (AF_INET, SOCK_STREAM, 0);
00537 if (socket_fd < 0)
00538 {
00539 #ifndef UNDER_CE
00540 rcs_print_error ("TCPMEM: Error from socket() (errno = %d:%s)\n",
00541 errno, strerror (errno));
00542
00543 #else
00544 rcs_print_error ("TCPMEM: Error from socket()\n");
00545 #endif
00546
00547 status = CMS_CREATE_ERROR;
00548 return;
00549 }
00550 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Setting socket options . . . \n");
00551 if (set_tcp_socket_options (socket_fd) < 0)
00552 {
00553 return;
00554 }
00555 struct timeval tm;
00556 int socket_ret;
00557 double start_time, current_time;
00558 fd_set fds;
00559 sockaddr_in cli_addr;
00560 cli_addr.sin_family = AF_INET;
00561 cli_addr.sin_addr.s_addr = dl_htonl (INADDR_ANY);
00562 cli_addr.sin_port = dl_htons (0);
00563 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Binding . . . \n");
00564 if (dl_bind (socket_fd, (struct sockaddr *) &cli_addr, sizeof (cli_addr)) <
00565 0)
00566 {
00567 #if defined(_Windows) && !defined(USE_PCNFS) && !defined(gnuwin32)
00568 rcs_print_error ("TCPMEM: bind error %d\n", dl_WSAGetLastError ());
00569 #else
00570 rcs_print_error ("TCPMEM: bind error %d = %s\n", errno,
00571 strerror (errno));
00572 #endif
00573 status = CMS_CREATE_ERROR;
00574 }
00575 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Connecting . . .\n");
00576 if (dl_connect (socket_fd, (struct sockaddr *) &server_socket_address,
00577 sizeof (server_socket_address)) < 0)
00578 {
00579 if (
00580 #ifdef gnuwin32
00581 EINPROGRESS == errno
00582 #else
00583 #ifdef _Windows
00584 WSAEWOULDBLOCK == dl_WSAGetLastError ()
00585 #else
00586 #ifdef MSDOS
00587 EWOULDBLOCK == tk_geterrno (socket_fd)
00588 #else
00589 EINPROGRESS == errno
00590 #endif
00591 #endif
00592 #endif
00593 )
00594 {
00595 #ifdef _Windows
00596 tm.tv_sec = 0;
00597 tm.tv_usec = 0;
00598 #else
00599 tm.tv_sec = (long) timeout;
00600 tm.tv_sec = (long) (fmod (timeout, 1.0) * 1e6);
00601 #endif
00602 FD_ZERO (&fds);
00603 RCS_FD_SET (socket_fd, &fds);
00604 start_time = etime ();
00605 while (!(socket_ret = dl_select (socket_fd + 1,
00606 (fd_set *) NULL,
00607 &fds, (fd_set *) NULL, &tm)))
00608 {
00609 RCS_FD_SET (socket_fd, &fds);
00610 esleep (0.001);
00611 current_time = etime ();
00612 if (current_time - start_time > timeout && timeout >= 0.0)
00613 {
00614 if (!reconnect_needed)
00615 {
00616 rcs_print_error
00617 ("TCPMEM: Timed out waiting for connection.\n");
00618 }
00619 status = CMS_NO_SERVER_ERROR;
00620 return;
00621 }
00622 }
00623 #if defined(_Windows) && !defined(gnuwin32)
00624 if (socket_ret == SOCKET_ERROR)
00625 {
00626 rcs_print_error ("select error: %d\n", dl_WSAGetLastError ());
00627 rcs_print_error ("TCPMEM: Couldn't connect.\n");
00628 status = CMS_NO_SERVER_ERROR;
00629 return;
00630 }
00631 #else
00632 if (-1 == socket_ret)
00633 {
00634 #ifndef UNDER_CE
00635 rcs_print_error ("select error: %d -- %s\n", errno,
00636 strerror (errno));
00637 #endif
00638 rcs_print_error ("TCPMEM: Couldn't connect.\n");
00639 status = CMS_NO_SERVER_ERROR;
00640 return;
00641 }
00642 #endif
00643 }
00644 else
00645 {
00646 #if defined(_Windows) && !defined(gnuwin32)
00647 rcs_print_error ("connect error: %d\n", dl_WSAGetLastError ());
00648 #else
00649 rcs_print_error ("connect error: %d -- %s\n", errno,
00650 strerror (errno));
00651 #endif
00652 rcs_print_error
00653 ("TCPMEM: Error trying to connect to TCP port %d of host %s(%s). sin_family=%d\n",
00654 dl_ntohs (server_socket_address.sin_port), BufferHost,
00655 dl_inet_ntoa (server_socket_address.sin_addr),
00656 server_socket_address.sin_family);
00657 status = CMS_NO_SERVER_ERROR;
00658 return;
00659 }
00660 }
00661 read_socket_fd = socket_fd;
00662
00663 memset (temp_buffer, 0, 32);
00664 if (total_subdivisions > 1)
00665 {
00666 subscription_type = CMS_NO_SUBSCRIPTION;
00667 }
00668
00669 if (subscription_type != CMS_NO_SUBSCRIPTION)
00670 {
00671 verify_bufname ();
00672 if (status < 0)
00673 {
00674 rcs_print_error ("TCPMEM: verify_bufname() failed\n");
00675 return;
00676 }
00677 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
00678 *((u_long *) temp_buffer + 1) =
00679 dl_htonl ((u_long) REMOTE_CMS_SET_SUBSCRIPTION_REQUEST_TYPE);
00680 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
00681 *((u_long *) temp_buffer + 3) = dl_htonl ((u_long) subscription_type);
00682 *((u_long *) temp_buffer + 4) =
00683 dl_htonl ((u_long) poll_interval_millis);
00684 if (sendn (socket_fd, temp_buffer, 20, 0, 30) < 0)
00685 {
00686 rcs_print_error ("Can`t setup subscription.\n");
00687 subscription_type = CMS_NO_SUBSCRIPTION;
00688 }
00689 else
00690 {
00691 serial_number++;
00692 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
00693 "TCPMEM sending request: fd = %d, serial_number=%d, request_type=%d, buffer_number=%d\n",
00694 socket_fd, serial_number,
00695 dl_ntohl (*((u_long *) temp_buffer + 1)),
00696 buffer_number);
00697 memset (temp_buffer, 0, 20);
00698 recvd_bytes = 0;
00699 if (recvn (socket_fd, temp_buffer, 8, 0, 30, &recvd_bytes) < 0)
00700 {
00701 rcs_print_error ("Can`t setup subscription.\n");
00702 subscription_type = CMS_NO_SUBSCRIPTION;
00703 }
00704 if (!dl_ntohl (*((u_long *) temp_buffer) + 1))
00705 {
00706 rcs_print_error ("Can`t setup subscription.\n");
00707 subscription_type = CMS_NO_SUBSCRIPTION;
00708 }
00709
00710 bytes_to_throw_away = 8 - recvd_bytes;
00711 if (bytes_to_throw_away < 0 || bytes_to_throw_away > 8)
00712 {
00713 bytes_to_throw_away = 0;
00714 }
00715 recvd_bytes = 0;
00716 }
00717 memset (temp_buffer, 0, 20);
00718 }
00719 if (subscription_type != CMS_NO_SUBSCRIPTION)
00720 {
00721 polling = 1;
00722 }
00723
00724
00725 if (polling)
00726 {
00727 make_tcp_socket_nonblocking (socket_fd);
00728 write_socket_fd = dl_socket (AF_INET, SOCK_STREAM, 0);
00729 if (write_socket_fd < 0)
00730 {
00731 #ifndef UNDER_CE
00732 rcs_print_error ("TCPMEM: Error from socket() (errno = %d:%s)\n",
00733 errno, strerror (errno));
00734 #else
00735 rcs_print_error ("TCPMEM: Error from socket()\n");
00736 #endif
00737 status = CMS_CREATE_ERROR;
00738 return;
00739 }
00740 rcs_print_debug (PRINT_CMS_CONFIG_INFO,
00741 "Setting socket options . . . \n");
00742 if (set_tcp_socket_options (write_socket_fd) < 0)
00743 {
00744 return;
00745 }
00746 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Binding . . . \n");
00747 if (dl_bind
00748 (write_socket_fd, (struct sockaddr *) &cli_addr,
00749 sizeof (cli_addr)) < 0)
00750 {
00751 #if defined(_Windows) && !defined(USE_PCNFS) && !defined(gnuwin32)
00752 rcs_print_error ("TCPMEM: bind error %d\n", dl_WSAGetLastError ());
00753 #else
00754 rcs_print_error ("TCPMEM: bind error %d = %s\n", errno,
00755 strerror (errno));
00756 #endif
00757 status = CMS_CREATE_ERROR;
00758 }
00759 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Connecting . . .\n");
00760 if (dl_connect
00761 (write_socket_fd, (struct sockaddr *) &server_socket_address,
00762 sizeof (server_socket_address)) < 0)
00763 {
00764 if (
00765 #ifdef gnuwin32
00766 EINPROGRESS == errno
00767 #else
00768 #ifdef _Windows
00769 WSAEWOULDBLOCK == dl_WSAGetLastError ()
00770 #else
00771 #ifdef MSDOS
00772 EWOULDBLOCK == tk_geterrno (write_socket_fd)
00773 #else
00774 EINPROGRESS == errno
00775 #endif
00776 #endif
00777 #endif
00778 )
00779 {
00780 FD_ZERO (&fds);
00781 RCS_FD_SET (write_socket_fd, &fds);
00782 start_time = etime ();
00783 while (!(socket_ret = dl_select (write_socket_fd + 1,
00784 (fd_set *) NULL,
00785 &fds, (fd_set *) NULL, &tm)))
00786 {
00787 RCS_FD_SET (write_socket_fd, &fds);
00788 esleep (0.001);
00789 current_time = etime ();
00790 if (current_time - start_time > timeout && timeout >= 0.0)
00791 {
00792 rcs_print_error
00793 ("TCPMEM: Timed out waiting for connection.\n");
00794 status = CMS_NO_SERVER_ERROR;
00795 return;
00796 }
00797 }
00798 #if defined(_Windows) && !defined(gnuwin32)
00799 if (socket_ret == SOCKET_ERROR)
00800 {
00801 rcs_print_error ("select error: %d\n",
00802 dl_WSAGetLastError ());
00803 rcs_print_error ("TCPMEM: Couldn't connect.\n");
00804 status = CMS_NO_SERVER_ERROR;
00805 return;
00806 }
00807 #else
00808 if (-1 == socket_ret)
00809 {
00810 #ifndef UNDER_CE
00811 rcs_print_error ("select error: %d -- %s\n", errno,
00812 strerror (errno));
00813 #endif
00814 rcs_print_error ("TCPMEM: Couldn't connect.\n");
00815 status = CMS_NO_SERVER_ERROR;
00816 return;
00817 }
00818 #endif
00819 }
00820 else
00821 {
00822 #if defined(_Windows) && !defined(gnuwin32)
00823 rcs_print_error ("connect error: %d\n", dl_WSAGetLastError ());
00824 #else
00825 rcs_print_error ("connect error: %d -- %s\n", errno,
00826 strerror (errno));
00827 #endif
00828 rcs_print_error
00829 ("TCPMEM: Error trying to connect to TCP port %d of host %s.\n",
00830 dl_ntohs (server_socket_address.sin_port), BufferHost);
00831 }
00832 }
00833 timeout = 0;
00834 }
00835 else
00836 {
00837 write_socket_fd = read_socket_fd;
00838 }
00839 reconnect_needed = 0;
00840 fatal_error_occurred = 0;
00841
00842 }
00843
00844 TCPMEM::~TCPMEM ()
00845 {
00846 disconnect ();
00847
00848 #if defined(_Windows) && !defined(USE_PCNFS)
00849 if (WSA_count == 0)
00850 {
00851 unload_socket_interface ();
00852 }
00853 WSA_count--;
00854 #endif
00855
00856 }
00857
00858 void
00859 TCPMEM::disconnect ()
00860 {
00861 if (write_socket_fd > 0 && write_socket_fd != socket_fd)
00862 {
00863 if (status != CMS_CONFIG_ERROR && status != CMS_CREATE_ERROR)
00864 {
00865 if (delete_totally)
00866 {
00867 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
00868 *((u_long *) temp_buffer + 1) =
00869 dl_htonl ((u_long) REMOTE_CMS_CLEAN_REQUEST_TYPE);
00870 *((u_long *) temp_buffer + 2) =
00871 dl_htonl ((u_long) buffer_number);
00872 sendn (write_socket_fd, temp_buffer, 20, 0, -1);
00873 }
00874 }
00875 dl_closesocket (write_socket_fd);
00876 write_socket_fd = 0;
00877 }
00878
00879 if (socket_fd > 0)
00880 {
00881 if (status != CMS_CONFIG_ERROR && status != CMS_CREATE_ERROR)
00882 {
00883 if (delete_totally)
00884 {
00885 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
00886 *((u_long *) temp_buffer + 1) =
00887 dl_htonl ((u_long) REMOTE_CMS_CLEAN_REQUEST_TYPE);
00888 *((u_long *) temp_buffer + 2) =
00889 dl_htonl ((u_long) buffer_number);
00890 sendn (socket_fd, temp_buffer, 20, 0, -1);
00891 }
00892 }
00893 dl_closesocket (socket_fd);
00894 socket_fd = 0;
00895 }
00896 }
00897
00898
00899 CMS_STATUS
00900 TCPMEM::handle_old_replies ()
00901 {
00902 long message_size;
00903
00904 timedout_request_writeid = 0;
00905 switch (timedout_request)
00906 {
00907 case REMOTE_CMS_READ_REQUEST_TYPE:
00908 if (!waiting_for_message)
00909 {
00910 if (recvn (socket_fd, temp_buffer, 20, 0, timeout, &recvd_bytes) <
00911 0)
00912 {
00913 if (recvn_timedout)
00914 {
00915 if (polling)
00916 {
00917 return status;
00918 }
00919 else
00920 {
00921 consecutive_timeouts++;
00922 if (consecutive_timeouts > max_consecutive_timeouts &&
00923 max_consecutive_timeouts > 0)
00924 {
00925 rcs_print_error
00926 ("CMS: %d consecutive timeouts have occurred. -- Stop trying.\n",
00927 consecutive_timeouts);
00928 fatal_error_occurred = 1;
00929 reconnect_needed = 1;
00930 }
00931 return (status = CMS_TIMED_OUT);
00932 }
00933 }
00934 else
00935 {
00936 recvd_bytes = 0;
00937 fatal_error_occurred = 1;
00938 return (status = CMS_MISC_ERROR);
00939 }
00940 }
00941 recvd_bytes = 0;
00942 returned_serial_number =
00943 (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
00944 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
00945 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
00946 socket_fd, returned_serial_number, buffer_number);
00947 if (returned_serial_number != serial_number)
00948 {
00949 rcs_print_error
00950 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
00951 returned_serial_number, serial_number);
00952 if (subscription_type == CMS_NO_SUBSCRIPTION)
00953 {
00954 fatal_error_occurred = 1;
00955 reconnect_needed = 1;
00956 return (status = CMS_MISC_ERROR);
00957 }
00958 else
00959 {
00960 serial_number = returned_serial_number;
00961 }
00962 }
00963 message_size = dl_ntohl (*((u_long *) temp_buffer + 2));
00964 timedout_request_status =
00965 (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
00966 timedout_request_writeid = dl_ntohl (*((u_long *) temp_buffer + 3));
00967 header.was_read = dl_ntohl (*((u_long *) temp_buffer + 4));
00968 if (message_size > max_encoded_message_size)
00969 {
00970 rcs_print_error ("Recieved message is too big. (%ld > %ld)\n",
00971 message_size, max_encoded_message_size);
00972 fatal_error_occurred = 1;
00973 reconnect_needed = 1;
00974 return (status = CMS_INSUFFICIENT_SPACE_ERROR);
00975 }
00976 }
00977 else
00978 {
00979 message_size = waiting_message_size;
00980 }
00981 if (message_size > 0)
00982 {
00983 if (recvn
00984 (socket_fd, encoded_data, message_size, 0, timeout,
00985 &recvd_bytes) < 0)
00986 {
00987 if (recvn_timedout)
00988 {
00989 if (!waiting_for_message)
00990 {
00991 waiting_message_id = timedout_request_writeid;
00992 waiting_message_size = message_size;
00993 }
00994 waiting_for_message = 1;
00995 timedout_request_writeid = 0;
00996 if (polling)
00997 {
00998 return status;
00999 }
01000 else
01001 {
01002 consecutive_timeouts++;
01003 if (consecutive_timeouts > max_consecutive_timeouts &&
01004 max_consecutive_timeouts > 0)
01005 {
01006 rcs_print_error
01007 ("CMS: %d consecutive timeouts have occurred. -- Stop trying.\n",
01008 consecutive_timeouts);
01009 fatal_error_occurred = 1;
01010 reconnect_needed = 1;
01011 }
01012 return (status = CMS_TIMED_OUT);
01013 }
01014 }
01015 else
01016 {
01017 recvd_bytes = 0;
01018 fatal_error_occurred = 1;
01019 reconnect_needed = 1;
01020 return (status = CMS_MISC_ERROR);
01021 }
01022 }
01023 recvd_bytes = 0;
01024 if (waiting_for_message)
01025 {
01026 timedout_request_writeid = waiting_message_id;
01027 }
01028 }
01029 break;
01030
01031 case REMOTE_CMS_WRITE_REQUEST_TYPE:
01032 case REMOTE_CMS_CHECK_IF_READ_REQUEST_TYPE:
01033 if (timedout_request == REMOTE_CMS_WRITE_REQUEST_TYPE &&
01034 (min_compatible_version > 2.58 || min_compatible_version < 1e-6 ||
01035 confirm_write))
01036 {
01037 break;
01038 }
01039 if (recvn (socket_fd, temp_buffer, 12, 0, timeout, &recvd_bytes) < 0)
01040 {
01041 if (recvn_timedout)
01042 {
01043 consecutive_timeouts++;
01044 if (consecutive_timeouts > max_consecutive_timeouts &&
01045 max_consecutive_timeouts > 0)
01046 {
01047 rcs_print_error
01048 ("CMS: %d consecutive timeouts have occurred. -- Stop trying.\n",
01049 consecutive_timeouts);
01050 reconnect_needed = 1;
01051 fatal_error_occurred = 1;
01052 }
01053 reconnect_needed = 1;
01054 return (status = CMS_TIMED_OUT);
01055 }
01056 else
01057 {
01058 fatal_error_occurred = 1;
01059 reconnect_needed = 1;
01060 return (status = CMS_MISC_ERROR);
01061 }
01062 }
01063 recvd_bytes = 0;
01064 returned_serial_number =
01065 (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
01066 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
01067 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
01068 socket_fd, returned_serial_number, buffer_number);
01069 if (returned_serial_number != serial_number)
01070 {
01071 rcs_print_error
01072 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
01073 returned_serial_number, serial_number);
01074 reconnect_needed = 1;
01075 if (subscription_type == CMS_NO_SUBSCRIPTION)
01076 {
01077 return (status = CMS_MISC_ERROR);
01078 }
01079 }
01080 break;
01081
01082 case REMOTE_CMS_CLEAR_REQUEST_TYPE:
01083 if (recvn (socket_fd, temp_buffer, 4, 0, timeout, &recvd_bytes) < 0)
01084 {
01085 if (recvn_timedout)
01086 {
01087 consecutive_timeouts++;
01088 reconnect_needed = 1;
01089 if (consecutive_timeouts > max_consecutive_timeouts &&
01090 max_consecutive_timeouts > 0)
01091 {
01092 rcs_print_error
01093 ("CMS: %d consecutive timeouts have occurred. -- Stop trying.\n",
01094 consecutive_timeouts);
01095 fatal_error_occurred = 1;
01096 }
01097 return (status = CMS_TIMED_OUT);
01098 }
01099 else
01100 {
01101 reconnect_needed = 1;
01102 fatal_error_occurred = 1;
01103 return (status = CMS_MISC_ERROR);
01104 }
01105 }
01106 recvd_bytes = 0;
01107 returned_serial_number =
01108 (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
01109 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
01110 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
01111 socket_fd, returned_serial_number, buffer_number);
01112 if (returned_serial_number != serial_number)
01113 {
01114 rcs_print_error
01115 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
01116 returned_serial_number, serial_number);
01117 reconnect_needed = 1;
01118 if (subscription_type == CMS_NO_SUBSCRIPTION)
01119 {
01120 return (status = CMS_MISC_ERROR);
01121 }
01122 }
01123 break;
01124
01125
01126
01127 case NO_REMOTE_CMS_REQUEST:
01128 default:
01129 break;
01130 }
01131 if (bytes_to_throw_away > 0)
01132 {
01133 if (recvn
01134 (socket_fd, encoded_data, bytes_to_throw_away, 0, timeout,
01135 &recvd_bytes) < 0)
01136 {
01137 if (recvn_timedout)
01138 {
01139 consecutive_timeouts++;
01140 if (consecutive_timeouts > max_consecutive_timeouts &&
01141 max_consecutive_timeouts > 0)
01142 {
01143 rcs_print_error
01144 ("CMS: %d consecutive timeouts have occurred. -- Stop trying.\n",
01145 consecutive_timeouts);
01146 fatal_error_occurred = 1;
01147 reconnect_needed = 1;
01148 }
01149 return (status = CMS_TIMED_OUT);
01150 }
01151 else
01152 {
01153 recvd_bytes = 0;
01154 fatal_error_occurred = 1;
01155 reconnect_needed = 1;
01156 return (status = CMS_MISC_ERROR);
01157 }
01158 }
01159 recvd_bytes = 0;
01160 }
01161 bytes_to_throw_away = 0;
01162 timedout_request = NO_REMOTE_CMS_REQUEST;
01163 consecutive_timeouts = 0;
01164 waiting_for_message = 0;
01165 waiting_message_size = 0;
01166 waiting_message_id = 0;
01167 recvd_bytes = 0;
01168 return status;
01169 }
01170
01171 CMS_STATUS
01172 TCPMEM::read ()
01173 {
01174 long message_size, id;
01175 REMOTE_CMS_REQUEST_TYPE last_timedout_request;
01176
01177
01178 if (!read_permission_flag)
01179 {
01180 rcs_print_error ("CMS: %s was not configured to read %s\n",
01181 ProcessName, BufferName);
01182 return (status = CMS_PERMISSIONS_ERROR);
01183 }
01184
01185 if (reconnect_needed && autoreconnect)
01186 {
01187 reconnect ();
01188 }
01189
01190 if (reconnect_needed)
01191 {
01192 return (status = CMS_MISC_ERROR);
01193 }
01194 disable_sigpipe ();
01195
01196 if (subscription_type != CMS_NO_SUBSCRIPTION)
01197 {
01198 set_socket_fds (read_socket_fd);
01199 timedout_request = REMOTE_CMS_READ_REQUEST_TYPE;
01200 if (subscription_count < 1)
01201 {
01202 serial_number++;
01203 }
01204 handle_old_replies ();
01205 check_id (timedout_request_writeid);
01206 if (status == CMS_READ_OK)
01207 {
01208 serial_number++;
01209 }
01210 subscription_count++;
01211 reenable_sigpipe ();
01212 return status;
01213 }
01214
01215 if (timedout_request == NO_REMOTE_CMS_REQUEST)
01216 {
01217 set_socket_fds (read_socket_fd);
01218 }
01219 if (fatal_error_occurred)
01220 {
01221 if (status >= 0)
01222 {
01223 status = CMS_MISC_ERROR;
01224 }
01225 reenable_sigpipe ();
01226 return (status);
01227 }
01228 if (socket_fd <= 0)
01229 {
01230 rcs_print_error ("TCPMEM::read: Invalid socket descriptor. (%d)\n",
01231 socket_fd);
01232 fatal_error_occurred = 1;
01233 reconnect_needed = 1;
01234 reenable_sigpipe ();
01235 return (status = CMS_MISC_ERROR);
01236 }
01237 last_timedout_request = timedout_request;
01238 if (((int) handle_old_replies ()) < 0)
01239 {
01240 reenable_sigpipe ();
01241 return status;
01242 }
01243 if (polling && last_timedout_request == REMOTE_CMS_READ_REQUEST_TYPE)
01244 {
01245 check_id (timedout_request_writeid);
01246 reenable_sigpipe ();
01247 return status;
01248 }
01249 set_socket_fds (read_socket_fd);
01250
01251 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
01252 *((u_long *) temp_buffer + 1) =
01253 dl_htonl ((u_long) REMOTE_CMS_READ_REQUEST_TYPE);
01254 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
01255 *((u_long *) temp_buffer + 3) = dl_htonl ((u_long) CMS_READ_ACCESS);
01256 *((u_long *) temp_buffer + 4) = dl_htonl ((u_long) in_buffer_id);
01257
01258 int send_header_size = 20;
01259 if (total_subdivisions > 1)
01260 {
01261 *((u_long *) temp_buffer + 5) = dl_htonl ((u_long) current_subdivision);
01262 send_header_size = 24;
01263 }
01264 if (sendn (socket_fd, temp_buffer, send_header_size, 0, timeout) < 0)
01265 {
01266 rcs_print_error ("TCPMEM: Can't send READ request to server.\n");
01267 reconnect_needed = 1;
01268 fatal_error_occurred = 1;
01269 reenable_sigpipe ();
01270 return (status = CMS_MISC_ERROR);
01271 }
01272 serial_number++;
01273 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
01274 "TCPMEM sending request: fd = %d, serial_number=%d, request_type=%d, buffer_number=%d\n",
01275 socket_fd, serial_number,
01276 dl_ntohl (*((u_long *) temp_buffer + 1)), buffer_number);
01277
01278 if (recvn (socket_fd, temp_buffer, 20, 0, timeout, &recvd_bytes) < 20)
01279 {
01280 if (recvn_timedout)
01281 {
01282 timedout_request = REMOTE_CMS_READ_REQUEST_TYPE;
01283 if (polling)
01284 {
01285 return (status = CMS_READ_OLD);
01286 }
01287 else
01288 {
01289 consecutive_timeouts = 1;
01290 reenable_sigpipe ();
01291 return (status = CMS_TIMED_OUT);
01292 }
01293 }
01294 else
01295 {
01296 recvd_bytes = 0;
01297 reconnect_needed = 1;
01298 fatal_error_occurred = 1;
01299 reenable_sigpipe ();
01300 return (status = CMS_MISC_ERROR);
01301 }
01302 }
01303 recvd_bytes = 0;
01304 returned_serial_number = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
01305 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
01306 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
01307 socket_fd, returned_serial_number, buffer_number);
01308
01309 if (returned_serial_number != serial_number)
01310 {
01311 rcs_print_error
01312 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
01313 returned_serial_number, serial_number);
01314 reconnect_needed = 1;
01315 if (subscription_type == CMS_NO_SUBSCRIPTION)
01316 {
01317 fatal_error_occurred = 1;
01318 reenable_sigpipe ();
01319 return (status = CMS_MISC_ERROR);
01320 }
01321 }
01322 status = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
01323 message_size = dl_ntohl (*((u_long *) temp_buffer + 2));
01324 id = dl_ntohl (*((u_long *) temp_buffer + 3));
01325 header.was_read = dl_ntohl (*((u_long *) temp_buffer + 4));
01326 if (message_size > max_encoded_message_size)
01327 {
01328 rcs_print_error ("Recieved message is too big. (%ld > %ld)\n",
01329 message_size, max_encoded_message_size);
01330 fatal_error_occurred = 1;
01331 reconnect_needed = 1;
01332 reenable_sigpipe ();
01333 return (status = CMS_MISC_ERROR);
01334 }
01335 if (message_size > 0)
01336 {
01337 if (recvn
01338 (socket_fd, encoded_data, message_size, 0, timeout,
01339 &recvd_bytes) < 0)
01340 {
01341 if (recvn_timedout)
01342 {
01343 if (!waiting_for_message)
01344 {
01345 waiting_message_id = id;
01346 waiting_message_size = message_size;
01347 }
01348 waiting_for_message = 1;
01349 timedout_request = REMOTE_CMS_READ_REQUEST_TYPE;
01350 if (polling)
01351 {
01352 reenable_sigpipe ();
01353 return (status = CMS_READ_OLD);
01354 }
01355 else
01356 {
01357 reenable_sigpipe ();
01358 return (status = CMS_TIMED_OUT);
01359 }
01360 }
01361 else
01362 {
01363 recvd_bytes = 0;
01364 fatal_error_occurred = 1;
01365 reconnect_needed = 1;
01366 reenable_sigpipe ();
01367 return (status = CMS_MISC_ERROR);
01368 }
01369 }
01370 }
01371 recvd_bytes = 0;
01372 check_id (id);
01373 reenable_sigpipe ();
01374 return (status);
01375 }
01376
01377
01378 CMS_STATUS
01379 TCPMEM::blocking_read (double _blocking_timeout)
01380 {
01381 blocking_timeout = _blocking_timeout;
01382 long message_size, id;
01383 REMOTE_CMS_REQUEST_TYPE last_timedout_request;
01384 long timeout_millis;
01385 int orig_print_recvn_timeout_errors = print_recvn_timeout_errors;
01386 print_recvn_timeout_errors = 0;
01387
01388
01389 if (!read_permission_flag)
01390 {
01391 rcs_print_error ("CMS: %s was not configured to read %s\n",
01392 ProcessName, BufferName);
01393 return (status = CMS_PERMISSIONS_ERROR);
01394 }
01395
01396 if (blocking_timeout < 0)
01397 {
01398 timeout_millis = -1;
01399 }
01400 else
01401 {
01402 timeout_millis = (u_long) (blocking_timeout * 1000.0);
01403 }
01404
01405 if (reconnect_needed && autoreconnect)
01406 {
01407 reconnect ();
01408 }
01409
01410 if (reconnect_needed)
01411 {
01412 print_recvn_timeout_errors = orig_print_recvn_timeout_errors;
01413 return (status = CMS_MISC_ERROR);
01414 }
01415 disable_sigpipe ();
01416 double orig_timeout = timeout;
01417
01418 if (subscription_type != CMS_NO_SUBSCRIPTION)
01419 {
01420 if (blocking_timeout < -1e-6 || blocking_timeout > 1e-6)
01421 {
01422 make_tcp_socket_blocking (read_socket_fd);
01423 timeout = blocking_timeout;
01424 }
01425 set_socket_fds (read_socket_fd);
01426 if (subscription_count < 1)
01427 {
01428 serial_number++;
01429 }
01430 timedout_request = REMOTE_CMS_READ_REQUEST_TYPE;
01431 handle_old_replies ();
01432 check_id (timedout_request_writeid);
01433 if (status == CMS_READ_OK)
01434 {
01435 serial_number++;
01436 }
01437 subscription_count++;
01438 reenable_sigpipe ();
01439 if (blocking_timeout < -1e-6 || blocking_timeout > 1e-6)
01440 {
01441 make_tcp_socket_nonblocking (read_socket_fd);
01442 timeout = orig_timeout;
01443 }
01444 print_recvn_timeout_errors = orig_print_recvn_timeout_errors;
01445 return status;
01446 }
01447
01448 if (timedout_request == NO_REMOTE_CMS_REQUEST)
01449 {
01450 set_socket_fds (read_socket_fd);
01451 }
01452 if (fatal_error_occurred)
01453 {
01454 if (status >= 0)
01455 {
01456 status = CMS_MISC_ERROR;
01457 }
01458 reenable_sigpipe ();
01459 print_recvn_timeout_errors = orig_print_recvn_timeout_errors;
01460 return (status);
01461 }
01462 if (socket_fd <= 0)
01463 {
01464 rcs_print_error ("TCPMEM::read: Invalid socket descriptor. (%d)\n",
01465 socket_fd);
01466 fatal_error_occurred = 1;
01467 reconnect_needed = 1;
01468 reenable_sigpipe ();
01469 print_recvn_timeout_errors = orig_print_recvn_timeout_errors;
01470 return (status = CMS_MISC_ERROR);
01471 }
01472 last_timedout_request = timedout_request;
01473 if (((int) handle_old_replies ()) < 0)
01474 {
01475 reenable_sigpipe ();
01476 print_recvn_timeout_errors = orig_print_recvn_timeout_errors;
01477 return status;
01478 }
01479 if (polling && last_timedout_request == REMOTE_CMS_READ_REQUEST_TYPE)
01480 {
01481 check_id (timedout_request_writeid);
01482 reenable_sigpipe ();
01483 print_recvn_timeout_errors = orig_print_recvn_timeout_errors;
01484 return status;
01485 }
01486 set_socket_fds (read_socket_fd);
01487
01488 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
01489 *((u_long *) temp_buffer + 1) =
01490 dl_htonl ((u_long) REMOTE_CMS_BLOCKING_READ_REQUEST_TYPE);
01491 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
01492 *((u_long *) temp_buffer + 3) = dl_htonl ((u_long) CMS_READ_ACCESS);
01493 *((u_long *) temp_buffer + 4) = dl_htonl ((u_long) in_buffer_id);
01494 *((u_long *) temp_buffer + 5) = dl_htonl ((u_long) timeout_millis);
01495
01496 int send_header_size = 24;
01497 if (total_subdivisions > 1)
01498 {
01499 *((u_long *) temp_buffer + 6) = dl_htonl ((u_long) current_subdivision);
01500 send_header_size = 28;
01501 }
01502 if (sendn (socket_fd, temp_buffer, send_header_size, 0, blocking_timeout) <
01503 0)
01504 {
01505 rcs_print_error
01506 ("TCPMEM: Can't send BLOCKING_READ request to server.\n");
01507 reconnect_needed = 1;
01508 fatal_error_occurred = 1;
01509 reenable_sigpipe ();
01510 print_recvn_timeout_errors = orig_print_recvn_timeout_errors;
01511 return (status = CMS_MISC_ERROR);
01512 }
01513 serial_number++;
01514 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
01515 "TCPMEM sending request: fd = %d, serial_number=%d, "
01516 "request_type=%d, buffer_number=%d\n",
01517 socket_fd, serial_number,
01518 dl_ntohl (*((u_long *) temp_buffer + 1)), buffer_number);
01519 if (recvn (socket_fd, temp_buffer, 20, 0, blocking_timeout, &recvd_bytes) <
01520 0)
01521 {
01522 print_recvn_timeout_errors = orig_print_recvn_timeout_errors;
01523 if (recvn_timedout)
01524 {
01525 timedout_request = REMOTE_CMS_READ_REQUEST_TYPE;
01526 if (polling)
01527 {
01528 return (status = CMS_READ_OLD);
01529 }
01530 else
01531 {
01532 consecutive_timeouts = 1;
01533 reenable_sigpipe ();
01534 return (status = CMS_TIMED_OUT);
01535 }
01536 }
01537 else
01538 {
01539 recvd_bytes = 0;
01540 reconnect_needed = 1;
01541 fatal_error_occurred = 1;
01542 reenable_sigpipe ();
01543 return (status = CMS_MISC_ERROR);
01544 }
01545 }
01546 print_recvn_timeout_errors = orig_print_recvn_timeout_errors;
01547 recvd_bytes = 0;
01548 returned_serial_number = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
01549 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
01550 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
01551 socket_fd, returned_serial_number, buffer_number);
01552
01553 if (returned_serial_number != serial_number)
01554 {
01555 rcs_print_error
01556 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
01557 returned_serial_number, serial_number);
01558 reconnect_needed = 1;
01559 if (subscription_type == CMS_NO_SUBSCRIPTION)
01560 {
01561 fatal_error_occurred = 1;
01562 reenable_sigpipe ();
01563 return (status = CMS_MISC_ERROR);
01564 }
01565 }
01566 status = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
01567 message_size = dl_ntohl (*((u_long *) temp_buffer + 2));
01568 id = dl_ntohl (*((u_long *) temp_buffer + 3));
01569 header.was_read = dl_ntohl (*((u_long *) temp_buffer + 4));
01570 if (message_size > max_encoded_message_size)
01571 {
01572 rcs_print_error ("Recieved message is too big. (%ld > %ld)\n",
01573 message_size, max_encoded_message_size);
01574 fatal_error_occurred = 1;
01575 reconnect_needed = 1;
01576 reenable_sigpipe ();
01577 return (status = CMS_MISC_ERROR);
01578 }
01579 if (message_size > 0)
01580 {
01581 if (recvn
01582 (socket_fd, encoded_data, message_size, 0, blocking_timeout,
01583 &recvd_bytes) < 0)
01584 {
01585 if (recvn_timedout)
01586 {
01587 if (!waiting_for_message)
01588 {
01589 waiting_message_id = id;
01590 waiting_message_size = message_size;
01591 }
01592 waiting_for_message = 1;
01593 timedout_request = REMOTE_CMS_READ_REQUEST_TYPE;
01594 if (polling)
01595 {
01596 reenable_sigpipe ();
01597 return (status = CMS_READ_OLD);
01598 }
01599 else
01600 {
01601 reenable_sigpipe ();
01602 return (status = CMS_TIMED_OUT);
01603 }
01604 }
01605 else
01606 {
01607 recvd_bytes = 0;
01608 fatal_error_occurred = 1;
01609 reconnect_needed = 1;
01610 reenable_sigpipe ();
01611 return (status = CMS_MISC_ERROR);
01612 }
01613 }
01614 }
01615 recvd_bytes = 0;
01616 check_id (id);
01617 reenable_sigpipe ();
01618 return (status);
01619 }
01620
01621 void
01622 TCPMEM::reenable_sigpipe ()
01623 {
01624 #ifndef MSDOS
01625 if (old_handler != ((void (*)(int)) SIG_ERR))
01626 {
01627 signal (SIGPIPE, old_handler);
01628 }
01629 old_handler = (void (*)(int)) SIG_ERR;
01630 if (tcpmem_sigpipe_count > sigpipe_count)
01631 {
01632 sigpipe_count = tcpmem_sigpipe_count;
01633 reconnect_needed = 1;
01634 }
01635 #endif
01636 }
01637
01638 void
01639 TCPMEM::disable_sigpipe ()
01640 {
01641 #ifndef MSDOS
01642 if (!autoreconnect)
01643 {
01644 return;
01645 }
01646 old_handler = signal (SIGPIPE, tcpmem_sigpipe_handler);
01647 if (tcpmem_sigpipe_count > sigpipe_count)
01648 {
01649 sigpipe_count = tcpmem_sigpipe_count;
01650 }
01651 #endif
01652 }
01653
01654
01655 CMS_STATUS
01656 TCPMEM::peek ()
01657 {
01658
01659 if (!read_permission_flag)
01660 {
01661 rcs_print_error ("CMS: %s was not configured to read %s\n",
01662 ProcessName, BufferName);
01663 return (status = CMS_PERMISSIONS_ERROR);
01664 }
01665
01666 if (reconnect_needed && autoreconnect)
01667 {
01668 reconnect ();
01669 }
01670
01671 if (reconnect_needed)
01672 {
01673 return (status = CMS_MISC_ERROR);
01674 }
01675 disable_sigpipe ();
01676
01677 long message_size, id;
01678 REMOTE_CMS_REQUEST_TYPE last_timedout_request;
01679 if (subscription_type != CMS_NO_SUBSCRIPTION)
01680 {
01681 set_socket_fds (read_socket_fd);
01682 timedout_request = REMOTE_CMS_READ_REQUEST_TYPE;
01683 if (subscription_count < 1)
01684 {
01685 serial_number++;
01686 }
01687 handle_old_replies ();
01688 check_id (timedout_request_writeid);
01689 if (status == CMS_READ_OK)
01690 {
01691 serial_number++;
01692 }
01693 reenable_sigpipe ();
01694 subscription_count++;
01695 return status;
01696 }
01697
01698 if (timedout_request == NO_REMOTE_CMS_REQUEST)
01699 {
01700 set_socket_fds (read_socket_fd);
01701 }
01702
01703 if (fatal_error_occurred)
01704 {
01705 if (status >= 0)
01706 {
01707 status = CMS_MISC_ERROR;
01708 }
01709 reenable_sigpipe ();
01710 return (status);
01711 }
01712 if (socket_fd <= 0)
01713 {
01714 reconnect_needed = 1;
01715 rcs_print_error ("TCPMEM::read: Invalid socket descriptor. (%d)\n",
01716 socket_fd);
01717 reenable_sigpipe ();
01718 return (status = CMS_MISC_ERROR);
01719 }
01720 last_timedout_request = timedout_request;
01721 if (((int) handle_old_replies ()) < 0)
01722 {
01723 reenable_sigpipe ();
01724 return status;
01725 }
01726 if (polling && last_timedout_request == REMOTE_CMS_READ_REQUEST_TYPE)
01727 {
01728 check_id (timedout_request_writeid);
01729 reenable_sigpipe ();
01730 return status;
01731 }
01732 set_socket_fds (read_socket_fd);
01733
01734 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
01735 *((u_long *) temp_buffer + 1) =
01736 dl_htonl ((u_long) REMOTE_CMS_READ_REQUEST_TYPE);
01737 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
01738 *((u_long *) temp_buffer + 3) = dl_htonl ((u_long) CMS_PEEK_ACCESS);
01739 *((u_long *) temp_buffer + 4) = dl_htonl ((u_long) in_buffer_id);
01740 int send_header_size = 20;
01741 if (total_subdivisions > 1)
01742 {
01743 *((u_long *) temp_buffer + 5) = dl_htonl ((u_long) current_subdivision);
01744 send_header_size = 24;
01745 }
01746 if (sendn (socket_fd, temp_buffer, send_header_size, 0, timeout) < 0)
01747 {
01748 rcs_print_error ("TCPMEM: Can't send PEEK request to server.\n");
01749 reconnect_needed = 1;
01750 reenable_sigpipe ();
01751 return (status = CMS_MISC_ERROR);
01752 }
01753 serial_number++;
01754 if (recvn (socket_fd, temp_buffer, 20, 0, timeout, &recvd_bytes) < 0)
01755 {
01756 if (recvn_timedout)
01757 {
01758 timedout_request = REMOTE_CMS_READ_REQUEST_TYPE;
01759 if (polling)
01760 {
01761 reenable_sigpipe ();
01762 return (status = CMS_READ_OLD);
01763 }
01764 else
01765 {
01766 consecutive_timeouts = 1;
01767 reenable_sigpipe ();
01768 return (status = CMS_TIMED_OUT);
01769 }
01770 }
01771 else
01772 {
01773 recvd_bytes = 0;
01774 fatal_error_occurred = 1;
01775 reconnect_needed = 1;
01776 reenable_sigpipe ();
01777 return (status = CMS_MISC_ERROR);
01778 }
01779 }
01780 recvd_bytes = 0;
01781 returned_serial_number = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
01782 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
01783 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
01784 socket_fd, returned_serial_number, buffer_number);
01785
01786 if (returned_serial_number != serial_number)
01787 {
01788 rcs_print_error
01789 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
01790 returned_serial_number, serial_number);
01791 reconnect_needed = 1;
01792 if (subscription_type == CMS_NO_SUBSCRIPTION)
01793 {
01794 reenable_sigpipe ();
01795 return (status = CMS_MISC_ERROR);
01796 }
01797 }
01798 status = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
01799 message_size = dl_ntohl (*((u_long *) temp_buffer + 2));
01800 id = dl_ntohl (*((u_long *) temp_buffer + 3));
01801 header.was_read = dl_ntohl (*((u_long *) temp_buffer + 4));
01802 if (message_size > max_encoded_message_size)
01803 {
01804 reconnect_needed = 1;
01805 rcs_print_error ("Recieved message is too big. (%ld > %ld)\n",
01806 message_size, max_encoded_message_size);
01807 reenable_sigpipe ();
01808 return (status = CMS_MISC_ERROR);
01809 }
01810 if (message_size > 0)
01811 {
01812 if (recvn
01813 (socket_fd, encoded_data, message_size, 0, timeout,
01814 &recvd_bytes) < 0)
01815 {
01816 if (recvn_timedout)
01817 {
01818 if (!waiting_for_message)
01819 {
01820 waiting_message_id = id;
01821 waiting_message_size = message_size;
01822 }
01823 waiting_for_message = 1;
01824 timedout_request = REMOTE_CMS_READ_REQUEST_TYPE;
01825 if (polling)
01826 {
01827 reenable_sigpipe ();
01828 return (status = CMS_READ_OLD);
01829 }
01830 else
01831 {
01832 reenable_sigpipe ();
01833 return (status = CMS_TIMED_OUT);
01834 }
01835 }
01836 else
01837 {
01838 reconnect_needed = 1;
01839 recvd_bytes = 0;
01840 fatal_error_occurred = 1;
01841 reenable_sigpipe ();
01842 return (status = CMS_MISC_ERROR);
01843 }
01844 }
01845 }
01846 recvd_bytes = 0;
01847 check_id (id);
01848 reenable_sigpipe ();
01849 return (status);
01850 }
01851
01852
01853
01854 CMS_STATUS
01855 TCPMEM::write (void *user_data)
01856 {
01857
01858 if (!write_permission_flag)
01859
01860 {
01861 rcs_print_error ("CMS: %s was not configured to write to %s\n",
01862 ProcessName, BufferName);
01863 return (status = CMS_PERMISSIONS_ERROR);
01864 }
01865
01866 if (reconnect_needed && autoreconnect)
01867 {
01868 reconnect ();
01869 }
01870
01871 if (!force_raw)
01872 {
01873 user_data = encoded_data;
01874 }
01875
01876 if (reconnect_needed)
01877 {
01878 return (status = CMS_MISC_ERROR);
01879 }
01880
01881 if (fatal_error_occurred)
01882 {
01883 if (status >= 0)
01884 {
01885 status = CMS_MISC_ERROR;
01886 }
01887 return (status);
01888 }
01889
01890 disable_sigpipe ();
01891
01892 if (socket_fd <= 0)
01893 {
01894 rcs_print_error ("TCPMEM::write: Invalid socket descriptor. (%d)\n",
01895 socket_fd);
01896 reenable_sigpipe ();
01897 return (status = CMS_MISC_ERROR);
01898 }
01899 if (((int) handle_old_replies ()) < 0)
01900 {
01901 reenable_sigpipe ();
01902 return status;
01903 }
01904 set_socket_fds (write_socket_fd);
01905
01906
01907 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
01908 *((u_long *) temp_buffer + 1) =
01909 dl_htonl ((u_long) REMOTE_CMS_WRITE_REQUEST_TYPE);
01910 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
01911 *((u_long *) temp_buffer + 3) = dl_htonl ((u_long) CMS_WRITE_ACCESS);
01912 *((u_long *) temp_buffer + 4) = dl_htonl ((u_long) header.in_buffer_size);
01913 int send_header_size = 20;
01914 if (total_subdivisions > 1)
01915 {
01916 *((u_long *) temp_buffer + 5) = dl_htonl ((u_long) current_subdivision);
01917 send_header_size = 24;
01918 }
01919 if (header.in_buffer_size < 0x2000 - 20 && header.in_buffer_size > 0)
01920 {
01921 memcpy (temp_buffer + send_header_size, user_data,
01922 header.in_buffer_size);
01923 if (sendn
01924 (socket_fd, temp_buffer, header.in_buffer_size + send_header_size,
01925 0, timeout) < 0)
01926 {
01927 rcs_print_error
01928 ("TCPMEM: Failed to send message of size %d + header of size %d to the server.\n",
01929 header.in_buffer_size, send_header_size);
01930 reconnect_needed = 1;
01931 reenable_sigpipe ();
01932 return (status = CMS_MISC_ERROR);
01933 }
01934 }
01935 else
01936 {
01937 if (sendn (socket_fd, temp_buffer, send_header_size, 0, timeout) < 0)
01938 {
01939 rcs_print_error ("TCPMEM: Failed to send header to server.\n");
01940 reconnect_needed = 1;
01941 reenable_sigpipe ();
01942 return (status = CMS_MISC_ERROR);
01943 }
01944 if (header.in_buffer_size > 0)
01945 {
01946 if (sendn (socket_fd, user_data, header.in_buffer_size, 0, timeout)
01947 < 0)
01948 {
01949 reconnect_needed = 1;
01950 reenable_sigpipe ();
01951 return (status = CMS_MISC_ERROR);
01952 }
01953 }
01954 }
01955 serial_number++;
01956 if ((min_compatible_version < 2.58 && min_compatible_version > 1e-6)
01957 || confirm_write)
01958 {
01959 if (recvn (socket_fd, temp_buffer, 12, 0, timeout, &recvd_bytes) < 0)
01960 {
01961 if (recvn_timedout)
01962 {
01963 timedout_request = REMOTE_CMS_WRITE_REQUEST_TYPE;
01964 consecutive_timeouts = 1;
01965 reenable_sigpipe ();
01966 return (status = CMS_TIMED_OUT);
01967 }
01968 else
01969 {
01970 recvd_bytes = 0;
01971 reconnect_needed = 1;
01972 fatal_error_occurred = 1;
01973 reenable_sigpipe ();
01974 return (status = CMS_MISC_ERROR);
01975 }
01976 }
01977 recvd_bytes = 0;
01978 returned_serial_number =
01979 (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
01980 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
01981 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
01982 socket_fd, returned_serial_number, buffer_number);
01983
01984 if (returned_serial_number != serial_number)
01985 {
01986 rcs_print_error
01987 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
01988 returned_serial_number, serial_number);
01989 reconnect_needed = 1;
01990 if (subscription_type == CMS_NO_SUBSCRIPTION)
01991 {
01992 reenable_sigpipe ();
01993 return (status = CMS_MISC_ERROR);
01994 }
01995 }
01996 status = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
01997 header.was_read = dl_ntohl (*((u_long *) temp_buffer + 2));
01998 }
01999 else
02000 {
02001 header.was_read = 0;
02002 status = CMS_WRITE_OK;
02003 returned_serial_number = serial_number;
02004 }
02005 reenable_sigpipe ();
02006 return (status);
02007 }
02008
02009 CMS_STATUS
02010 TCPMEM::write_if_read (void *user_data)
02011 {
02012
02013 if (!write_permission_flag)
02014
02015 {
02016 rcs_print_error ("CMS: %s was not configured to write to %s\n",
02017 ProcessName, BufferName);
02018 return (status = CMS_PERMISSIONS_ERROR);
02019 }
02020
02021 if (reconnect_needed && autoreconnect)
02022 {
02023 reconnect ();
02024 }
02025 if (!force_raw)
02026 {
02027 user_data = encoded_data;
02028 }
02029
02030 if (reconnect_needed)
02031 {
02032 return (status = CMS_MISC_ERROR);
02033 }
02034
02035 if (fatal_error_occurred)
02036 {
02037 if (status >= 0)
02038 {
02039 status = CMS_MISC_ERROR;
02040 }
02041 return (status);
02042 }
02043 disable_sigpipe ();
02044
02045 if (socket_fd <= 0)
02046 {
02047 rcs_print_error ("TCPMEM::write: Invalid socket descriptor. (%d)\n",
02048 socket_fd);
02049 reenable_sigpipe ();
02050 return (status = CMS_MISC_ERROR);
02051 }
02052 if (((int) handle_old_replies ()) < 0)
02053 {
02054 reenable_sigpipe ();
02055 return status;
02056 }
02057
02058 set_socket_fds (write_socket_fd);
02059
02060 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
02061 *((u_long *) temp_buffer + 1) =
02062 dl_htonl ((u_long) REMOTE_CMS_WRITE_REQUEST_TYPE);
02063 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
02064 *((u_long *) temp_buffer + 3) =
02065 dl_htonl ((u_long) CMS_WRITE_IF_READ_ACCESS);
02066 *((u_long *) temp_buffer + 4) = dl_htonl ((u_long) header.in_buffer_size);
02067 int send_header_size = 20;
02068 if (total_subdivisions > 1)
02069 {
02070 *((u_long *) temp_buffer + 5) = dl_htonl ((u_long) current_subdivision);
02071 send_header_size = 24;
02072 }
02073 if (header.in_buffer_size < 0x2000 - 20 && header.in_buffer_size > 0)
02074 {
02075 memcpy (temp_buffer + 20, user_data, header.in_buffer_size);
02076 if (sendn
02077 (socket_fd, temp_buffer, header.in_buffer_size + send_header_size,
02078 0, timeout) < 0)
02079 {
02080 reconnect_needed = 1;
02081 reenable_sigpipe ();
02082 return (status = CMS_MISC_ERROR);
02083 }
02084 }
02085 else
02086 {
02087 if (sendn (socket_fd, temp_buffer, send_header_size, 0, timeout) < 0)
02088 {
02089 reconnect_needed = 1;
02090 reenable_sigpipe ();
02091 return (status = CMS_MISC_ERROR);
02092 }
02093 if (header.in_buffer_size > 0)
02094 {
02095 if (sendn (socket_fd, user_data, header.in_buffer_size, 0, timeout)
02096 < 0)
02097 {
02098 reconnect_needed = 1;
02099 reenable_sigpipe ();
02100 return (status = CMS_MISC_ERROR);
02101 }
02102 }
02103 }
02104 serial_number++;
02105 if ((min_compatible_version < 2.58 && min_compatible_version > 1e-6) ||
02106 confirm_write)
02107 {
02108 if (recvn (socket_fd, temp_buffer, 12, 0, timeout, &recvd_bytes) < 0)
02109 {
02110 if (recvn_timedout)
02111 {
02112 timedout_request = REMOTE_CMS_WRITE_REQUEST_TYPE;
02113 consecutive_timeouts = 1;
02114 reenable_sigpipe ();
02115 return (status = CMS_TIMED_OUT);
02116 }
02117 else
02118 {
02119 recvd_bytes = 0;
02120 fatal_error_occurred = 1;
02121 reconnect_needed = 1;
02122 reenable_sigpipe ();
02123 return (status = CMS_MISC_ERROR);
02124 }
02125 }
02126 recvd_bytes = 0;
02127 returned_serial_number =
02128 (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
02129 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
02130 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
02131 socket_fd, returned_serial_number, buffer_number);
02132 if (returned_serial_number != serial_number)
02133 {
02134 rcs_print_error
02135 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
02136 returned_serial_number, serial_number);
02137 reconnect_needed = 1;
02138 if (subscription_type == CMS_NO_SUBSCRIPTION)
02139 {
02140 reenable_sigpipe ();
02141 return (status = CMS_MISC_ERROR);
02142 }
02143 }
02144 status = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
02145 header.was_read = dl_ntohl (*((u_long *) temp_buffer + 2));
02146 }
02147 else
02148 {
02149 header.was_read = 0;
02150 status = CMS_WRITE_OK;
02151 returned_serial_number = 0;
02152 }
02153 reenable_sigpipe ();
02154 return (status);
02155 }
02156
02157 int
02158 TCPMEM::check_if_read ()
02159 {
02160 if (reconnect_needed && autoreconnect)
02161 {
02162 reconnect ();
02163 }
02164
02165 if (reconnect_needed)
02166 {
02167 return (status = CMS_MISC_ERROR);
02168 }
02169
02170 if (fatal_error_occurred)
02171 {
02172 if (status >= 0)
02173 {
02174 status = CMS_MISC_ERROR;
02175 }
02176 return (status);
02177 }
02178
02179 disable_sigpipe ();
02180
02181 if (socket_fd <= 0)
02182 {
02183 rcs_print_error
02184 ("TCPMEM::check_if_read: Invalid socket descriptor. (%d)\n",
02185 socket_fd);
02186 reenable_sigpipe ();
02187 return (status = CMS_MISC_ERROR);
02188 }
02189 if (((int) handle_old_replies ()) < 0)
02190 {
02191 reenable_sigpipe ();
02192 return 0;
02193 }
02194
02195 set_socket_fds (write_socket_fd);
02196
02197 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
02198 *((u_long *) temp_buffer + 1) =
02199 dl_htonl ((u_long) REMOTE_CMS_CHECK_IF_READ_REQUEST_TYPE);
02200 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
02201 int send_header_size = 20;
02202 if (total_subdivisions > 1)
02203 {
02204 *((u_long *) temp_buffer + 3) = dl_htonl ((u_long) current_subdivision);
02205 }
02206 if (sendn (socket_fd, temp_buffer, send_header_size, 0, timeout) < 0)
02207 {
02208 status = CMS_MISC_ERROR;
02209 reconnect_needed = 1;
02210 reenable_sigpipe ();
02211 return (0);
02212 }
02213 serial_number++;
02214 if (recvn (socket_fd, temp_buffer, 12, 0, timeout, &recvd_bytes) < 0)
02215 {
02216 if (recvn_timedout)
02217 {
02218 timedout_request = REMOTE_CMS_CHECK_IF_READ_REQUEST_TYPE;
02219 consecutive_timeouts = 1;
02220 status = CMS_TIMED_OUT;
02221 reenable_sigpipe ();
02222 return 0;
02223 }
02224 else
02225 {
02226 recvd_bytes = 0;
02227 fatal_error_occurred = 1;
02228 status = CMS_MISC_ERROR;
02229 reenable_sigpipe ();
02230 return 0;
02231 }
02232 }
02233 recvd_bytes = 0;
02234 returned_serial_number = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
02235 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
02236 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
02237 socket_fd, returned_serial_number, buffer_number);
02238 if (returned_serial_number != serial_number)
02239 {
02240 rcs_print_error
02241 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
02242 returned_serial_number, serial_number);
02243 reenable_sigpipe ();
02244 return (status = CMS_MISC_ERROR);
02245 }
02246 status = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
02247 header.was_read = dl_ntohl (*((u_long *) temp_buffer + 2));
02248 reenable_sigpipe ();
02249 return (header.was_read);
02250 }
02251
02252
02253 CMS_STATUS
02254 TCPMEM::clear ()
02255 {
02256 if (reconnect_needed && autoreconnect)
02257 {
02258 reconnect ();
02259 }
02260
02261 if (reconnect_needed)
02262 {
02263 return (status = CMS_MISC_ERROR);
02264 }
02265
02266 if (fatal_error_occurred)
02267 {
02268 if (status >= 0)
02269 {
02270 status = CMS_MISC_ERROR;
02271 }
02272 return (status);
02273 }
02274 if (socket_fd <= 0)
02275 {
02276 rcs_print_error ("TCPMEM::clear: Invalid socket descriptor. (%d)\n",
02277 socket_fd);
02278 reconnect_needed = 1;
02279 return (status = CMS_MISC_ERROR);
02280 }
02281 if (((int) handle_old_replies ()) < 0)
02282 {
02283 return status;
02284 }
02285
02286 set_socket_fds (write_socket_fd);
02287
02288 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
02289 *((u_long *) temp_buffer + 1) =
02290 dl_htonl ((u_long) REMOTE_CMS_CLEAR_REQUEST_TYPE);
02291 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
02292 *((u_long *) temp_buffer + 3) = dl_htonl ((u_long) current_subdivision);
02293
02294 if (sendn (socket_fd, temp_buffer, 20, 0, timeout) < 0)
02295 {
02296 reconnect_needed = 1;
02297 return (status = CMS_MISC_ERROR);
02298 }
02299 serial_number++;
02300 if (recvn (socket_fd, temp_buffer, 8, 0, timeout, &recvd_bytes) < 0)
02301 {
02302 if (recvn_timedout)
02303 {
02304 timedout_request = REMOTE_CMS_CLEAR_REQUEST_TYPE;
02305 consecutive_timeouts = 1;
02306 return (status = CMS_TIMED_OUT);
02307 }
02308 else
02309 {
02310 fatal_error_occurred = 1;
02311 reconnect_needed = 1;
02312 return (status = CMS_MISC_ERROR);
02313 }
02314 }
02315 returned_serial_number = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
02316 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
02317 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
02318 socket_fd, returned_serial_number, buffer_number);
02319
02320 if (returned_serial_number != serial_number)
02321 {
02322 rcs_print_error
02323 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
02324 returned_serial_number, serial_number);
02325 reconnect_needed = 1;
02326 return (status = CMS_MISC_ERROR);
02327 }
02328 status = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer + 1));
02329 header.was_read = dl_ntohl (*((u_long *) temp_buffer + 2));
02330 return (status);
02331 }
02332
02333
02334 int
02335 TCPMEM::login (const char *name, const char *passwd)
02336 {
02337 #ifndef UNDER_CE
02338 if (fatal_error_occurred)
02339 {
02340 if (status >= 0)
02341 {
02342 status = CMS_MISC_ERROR;
02343 }
02344 return (status);
02345 }
02346 if (socket_fd <= 0)
02347 {
02348 rcs_print_error ("TCPMEM::write: Invalid socket descriptor. (%d)\n",
02349 socket_fd);
02350 return (status = CMS_MISC_ERROR);
02351 }
02352 int handle_old_reply_ret = 0;
02353
02354 while (timedout_request != NO_REMOTE_CMS_REQUEST && !handle_old_reply_ret)
02355 {
02356 handle_old_reply_ret = handle_old_replies ();
02357 }
02358 if (handle_old_reply_ret < 0)
02359 {
02360 return 0;
02361 }
02362 set_socket_fds (write_socket_fd);
02363 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
02364 *((u_long *) temp_buffer + 1) =
02365 dl_htonl ((u_long) REMOTE_CMS_GET_KEYS_REQUEST_TYPE);
02366 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
02367 if (sendn (socket_fd, temp_buffer, 20, 0, 30.0) < 0)
02368 {
02369 return 0;
02370 }
02371 memset (temp_buffer, 0, 20);
02372 strncpy (((char *) temp_buffer), name, 16);
02373 if (sendn (socket_fd, temp_buffer, 16, 0, 30.0) < 0)
02374 {
02375 return (status = CMS_MISC_ERROR);
02376 }
02377 serial_number++;
02378 if (recvn (socket_fd, temp_buffer, 20, 0, 30.0, &recvd_bytes) < 0)
02379 {
02380 return 0;
02381 }
02382 recvd_bytes = 0;
02383 returned_serial_number = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
02384 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
02385 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
02386 socket_fd, returned_serial_number, buffer_number);
02387 if (returned_serial_number != serial_number)
02388 {
02389 rcs_print_error
02390 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
02391 returned_serial_number, serial_number);
02392 return (0);
02393 }
02394 char *crypt1_ret = rcs_crypt (passwd, ((char *) temp_buffer) + 4);
02395 if (NULL == crypt1_ret)
02396 {
02397 rcs_print_error ("TCPMEM::login() crypt function failed.\n");
02398 return 0;
02399 }
02400 char passwd_pass1[16];
02401 strncpy (passwd_pass1, crypt1_ret, 16);
02402 char *crypt2_ret = rcs_crypt (passwd_pass1, ((char *) temp_buffer) + 12);
02403 if (NULL == crypt2_ret)
02404 {
02405 rcs_print_error ("TCPMEM::login() crypt function failed.\n");
02406 return (0);
02407 }
02408 char passwd_pass2[16];
02409 strncpy (passwd_pass2, crypt2_ret, 16);
02410
02411 *((u_long *) temp_buffer) = dl_htonl ((u_long) serial_number);
02412 *((u_long *) temp_buffer + 1) =
02413 dl_htonl ((u_long) REMOTE_CMS_LOGIN_REQUEST_TYPE);
02414 *((u_long *) temp_buffer + 2) = dl_htonl ((u_long) buffer_number);
02415 if (sendn (socket_fd, temp_buffer, 20, 0, 30.0) < 0)
02416 {
02417 return 0;
02418 }
02419 memset (temp_buffer, 0, 20);
02420 strncpy (((char *) temp_buffer), name, 16);
02421 if (sendn (socket_fd, temp_buffer, 16, 0, 30.0) < 0)
02422 {
02423 return (status = CMS_MISC_ERROR);
02424 }
02425 if (sendn (socket_fd, passwd_pass2, 16, 0, 30.0) < 0)
02426 {
02427 return (status = CMS_MISC_ERROR);
02428 }
02429 serial_number++;
02430 if (recvn (socket_fd, temp_buffer, 8, 0, 30.0, &recvd_bytes) < 0)
02431 {
02432 return 0;
02433 }
02434 recvd_bytes = 0;
02435 returned_serial_number = (CMS_STATUS) dl_ntohl (*((u_long *) temp_buffer));
02436 rcs_print_debug (PRINT_ALL_SOCKET_REQUESTS,
02437 "TCPMEM recieved_reply: fd = %d, serial_number=%d, buffer_number=%d\n",
02438 socket_fd, returned_serial_number, buffer_number);
02439 if (returned_serial_number != serial_number)
02440 {
02441 rcs_print_error
02442 ("TCPMEM: Returned serial number(%d) does not match expected serial number(%d).\n",
02443 returned_serial_number, serial_number);
02444 return (status = CMS_MISC_ERROR);
02445 }
02446 int success = dl_ntohl (*((u_long *) temp_buffer + 1));
02447 return (success);
02448 #else
02449 return 0;
02450 #endif
02451 }
02452
02453
02454 void
02455 TCPMEM::set_socket_fds (int new_fd)
02456 {
02457 if (socket_fd == read_socket_fd)
02458 {
02459 read_serial_number = serial_number;
02460 }
02461 if (socket_fd == write_socket_fd)
02462 {
02463 write_serial_number = serial_number;
02464 }
02465 socket_fd = new_fd;
02466 if (socket_fd == read_socket_fd)
02467 {
02468 serial_number = read_serial_number;
02469 }
02470 if (socket_fd == write_socket_fd)
02471 {
02472 serial_number = write_serial_number;
02473 }
02474 }