00001
00002
00003
00004 #ifdef USE_PCNFS
00005 #undef USE_PCNFS
00006 #endif
00007
00008 #include "rcs_defs.hh"
00009
00010 #ifdef EXTERN_C_STD_HEADERS
00011 extern "C"
00012 {
00013 #endif
00014 #include <stdio.h>
00015 #include <ctype.h>
00016
00017 #ifndef irix6
00018 #include <math.h>
00019 #else
00020
00021
00022 extern double fmod (double, double);
00023 #endif
00024
00025 #include <string.h>
00026 #include <stdlib.h>
00027 #ifdef CenterLine
00028 char *strerror (int errnum);
00029 #endif
00030 #include <errno.h>
00031
00032 #ifdef EXTERN_C_STD_HEADERS
00033 }
00034 #endif
00035
00036 #include "rem_msg.hh"
00037 #include "rcs_prnt.hh"
00038
00039
00040 #define REQUEST_TIMEOUT (2.0)
00041 #include "timer.hh"
00042
00043 #include "stcpmem.hh"
00044
00045 #include "recvline.h"
00046 #include "sendline.h"
00047 #include "stcpopts.hh"
00048 #include "sokintrf.h"
00049 #include "crypt2.hh"
00050
00051
00052
00053 STCPMEM::STCPMEM (char *_bufline, char *_procline):
00054 CMS (_bufline, _procline)
00055 {
00056 #if defined(_Windows) && !defined(USE_PCNFS)
00057 WSA_count++;
00058 #endif
00059 if (load_socket_interface () < 0)
00060 {
00061 rcs_print_error ("Can't load socket interface.\n");
00062 status = CMS_LIBRARY_UNAVAILABLE_ERROR;
00063 }
00064 socket_fd = 0;
00065 read_request_issued = 0;
00066 temp_buffer = NULL;
00067 polling = 0;
00068 lines_to_skip = 0;
00069 bytes_at_beginning_of_line = 0;
00070
00071
00072
00073 if (CMS_DISPLAY_ASCII_ENCODING != neutral_encoding_method)
00074 {
00075 rcs_print_error
00076 ("The neutral_encoding_method must be ASCII_DISPLAY_ENCODING to use STCPMEM.\n");
00077 status = CMS_CONFIG_ERROR;
00078 }
00079
00080
00081 temp_buffer = (char *) malloc (cms_encoded_data_explosion_factor * size);
00082 if (temp_buffer == NULL)
00083 {
00084 rcs_print_error ("Out of memory!\n");
00085 status = CMS_CREATE_ERROR;
00086 return;
00087 }
00088 temp_buffer_size = cms_encoded_data_explosion_factor * size;
00089
00090 #ifndef VXWORKS
00091 server_host_entry = NULL;
00092 #endif
00093 serial_number = 0;
00094
00095
00096 memset (&server_socket_address, 0, sizeof (server_socket_address));
00097 server_socket_address.sin_family = AF_INET;
00098 server_socket_address.sin_port = dl_htons (((u_short) stcp_port_number));
00099
00100 int hostname_was_address = 0;
00101 if (isdigit (BufferHost[0]))
00102 {
00103 server_socket_address.sin_addr.s_addr = dl_inet_addr (BufferHost);
00104 if (server_socket_address.sin_addr.s_addr != 0 &&
00105 ((long) server_socket_address.sin_addr.s_addr) != -1)
00106 {
00107 hostname_was_address = 1;
00108 }
00109 }
00110 if (!hostname_was_address)
00111 {
00112
00113 #ifndef VXWORKS
00114 dl_gethostbyname (BufferHost, &server_host_entry);
00115 if (NULL == server_host_entry)
00116 {
00117 status = CMS_CONFIG_ERROR;
00118 rcs_print_error ("STCPMEM: Couldn't get host address for (%s).\n",
00119 BufferHost);
00120 #if defined(_WINDOWS) && !defined(gnuwin32)
00121 rcs_print_error ("WSA error = %d\n", dl_WSAGetLastError ());
00122 #endif
00123 return;
00124 }
00125 #ifdef __MSDOS__
00126 server_socket_address.sin_addr.s_addr =
00127 *((u_long *) server_host_entry->h_addr_list[0]);
00128 #else
00129 server_socket_address.sin_addr.s_addr =
00130 *((int *) server_host_entry->h_addr_list[0]);
00131 #endif
00132 server_socket_address.sin_family = server_host_entry->h_addrtype;
00133 #else
00134 server_socket_address.sin_addr.s_addr = hostGetByName (BufferHost);
00135 if (server_socket_address.sin_addr.s_addr == ERROR)
00136 {
00137 rcs_print_error ("STCPMEM: Couldn't get host address for (%s).\n",
00138 BufferHost);
00139 status = CMS_CONFIG_ERROR;
00140 return;
00141 }
00142 #endif
00143 }
00144 rcs_print_debug (PRINT_CMS_CONFIG_INFO,
00145 "Using server on %s with IP address %s and port %d.\n",
00146 BufferHost,
00147 dl_inet_ntoa (server_socket_address.sin_addr),
00148 stcp_port_number);
00149
00150 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Creating socket . . .\n");
00151
00152 socket_fd = dl_socket (AF_INET, SOCK_STREAM, 0);
00153 if (socket_fd < 0)
00154 {
00155 rcs_print_error ("STCPMEM: Error from socket() (errno = %d:%s)\n",
00156 errno, strerror (errno));
00157 status = CMS_CREATE_ERROR;
00158 return;
00159 }
00160 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Setting socket options . . . \n");
00161 if (set_stcp_socket_options (socket_fd) < 0)
00162 {
00163 return;
00164 }
00165 sockaddr_in cli_addr;
00166 cli_addr.sin_family = AF_INET;
00167 cli_addr.sin_addr.s_addr = dl_htonl (INADDR_ANY);
00168 cli_addr.sin_port = dl_htons (0);
00169 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Binding . . . \n");
00170 if (dl_bind (socket_fd, (struct sockaddr *) &cli_addr, sizeof (cli_addr)) <
00171 0)
00172 {
00173 #if defined(_Windows) && !defined(USE_PCNFS) && !defined(gnuwin32)
00174 rcs_print_error ("STCPMEM: bind error %d\n", dl_WSAGetLastError ());
00175 #else
00176 rcs_print_error ("STCPMEM: bind error %d = %s\n", errno,
00177 strerror (errno));
00178 #endif
00179 status = CMS_CREATE_ERROR;
00180 }
00181 rcs_print_debug (PRINT_CMS_CONFIG_INFO, "Connecting . . .\n");
00182 if (dl_connect (socket_fd, (struct sockaddr *) &server_socket_address,
00183 sizeof (server_socket_address)) < 0)
00184 {
00185 #if defined(_Windows) && !defined(gnuwin32)
00186 if (WSAEWOULDBLOCK == dl_WSAGetLastError ())
00187 {
00188 #else
00189 if (EINPROGRESS == errno)
00190 {
00191 #endif
00192 struct timeval tm;
00193 int socket_ret;
00194 double start_time, current_time;
00195 #ifdef _Windows
00196 tm.tv_sec = 0;
00197 tm.tv_usec = 0;
00198 #else
00199
00200
00201 if (timeout < 0)
00202 {
00203 tm.tv_sec = 30;
00204 tm.tv_usec = 0;
00205 }
00206 else
00207 {
00208 tm.tv_sec = (long) timeout;
00209 tm.tv_usec = (long) (timeout * 1000000.0);
00210 if (tm.tv_usec >= 1000000)
00211 {
00212 tm.tv_usec = tm.tv_usec % 1000000;
00213 }
00214 }
00215 #endif
00216 fd_set fds;
00217 FD_ZERO (&fds);
00218 RCS_FD_SET (socket_fd, &fds);
00219 start_time = etime ();
00220 while (!
00221 (socket_ret =
00222 dl_select (socket_fd + 1, NULL, &fds, NULL, &tm)))
00223 {
00224 RCS_FD_SET (socket_fd, &fds);
00225 esleep (0.001);
00226 current_time = etime ();
00227 if (current_time - start_time > timeout && timeout >= 0.0)
00228 {
00229 rcs_print_error
00230 ("STCPMEM: Timed out waiting for connection.\n");
00231 status = CMS_NO_SERVER_ERROR;
00232 return;
00233 }
00234 }
00235 #if defined(_Windows) && !defined(gnuwin32)
00236 if (socket_ret == SOCKET_ERROR)
00237 {
00238 rcs_print_error ("select error: %d\n", dl_WSAGetLastError ());
00239 #else
00240 if (socket_ret == -1)
00241 {
00242 rcs_print_error ("select error: %d -- %s\n", errno,
00243 strerror (errno));
00244 #endif
00245 rcs_print_error ("STCPMEM: Couldn't connect.\n");
00246 status = CMS_NO_SERVER_ERROR;
00247 return;
00248 }
00249 }
00250 else
00251 {
00252 #if defined(_WINDOWS) && !defined(gnuwin32)
00253 rcs_print_error ("connect error: %d\n", dl_WSAGetLastError ());
00254 #else
00255 rcs_print_error ("connect error: %d -- %s\n", errno,
00256 strerror (errno));
00257 #endif
00258 rcs_print_error
00259 ("STCPMEM: Error trying to connect to STCP port %d of host %s.\n",
00260 dl_ntohs (server_socket_address.sin_port), BufferHost);
00261 }
00262 }
00263
00264 polling = (NULL != strstr (ProcessLine, "poll"));
00265 if (polling)
00266 {
00267 timeout = 0;
00268 }
00269 }
00270
00271
00272 STCPMEM::~STCPMEM ()
00273 {
00274 if (socket_fd > 0)
00275 {
00276 clean_prev_read_info (socket_fd);
00277 dl_closesocket (socket_fd);
00278 socket_fd = 0;
00279 }
00280 #if defined(_Windows) && !defined(USE_PCNFS)
00281 if (WSA_count == 0)
00282 {
00283 unload_socket_interface ();
00284 }
00285 WSA_count--;
00286 #endif
00287 if (NULL == temp_buffer)
00288 {
00289 delete temp_buffer;
00290 temp_buffer = NULL;
00291 }
00292 }
00293
00294 CMS_STATUS
00295 STCPMEM::skip_lines ()
00296 {
00297
00298 while (lines_to_skip > 0)
00299 {
00300 if (recvline
00301 (socket_fd, ((char *) encoded_data),
00302 cms_encoded_data_explosion_factor * size, 0, timeout, NULL) < 0)
00303 {
00304 if (recvline_timedout)
00305 {
00306 return (status = CMS_TIMED_OUT);
00307 }
00308 else
00309 {
00310 bytes_at_beginning_of_line = 0;
00311 return (status = CMS_MISC_ERROR);
00312 }
00313 }
00314 bytes_at_beginning_of_line = 0;
00315 lines_to_skip--;
00316 }
00317 bytes_at_beginning_of_line = 0;
00318 return (status);
00319 }
00320
00321
00322 CMS_STATUS
00323 STCPMEM::read ()
00324 {
00325 long message_size, id;
00326 id = in_buffer_id;
00327 int read_request_issued_last_time;
00328 char request_string[32];
00329 sprintf (request_string, "read(%d):", (int) buffer_number);
00330
00331 if (socket_fd <= 0)
00332 {
00333 rcs_print_error ("STCPMEM::read: Invalid socket descriptor. (%d)\n",
00334 socket_fd);
00335 return (status = CMS_MISC_ERROR);
00336 }
00337 if (((int) skip_lines ()) < 0)
00338 {
00339 return status;
00340 }
00341
00342 read_request_issued_last_time = read_request_issued;
00343
00344 if (!read_request_issued_last_time || !polling)
00345 {
00346 if (sendline (socket_fd, request_string, 0, timeout) < 0)
00347 {
00348 return (status = CMS_MISC_ERROR);
00349 }
00350 read_request_issued = 1;
00351 read_request_time = etime ();
00352 }
00353
00354 if (read_request_issued_last_time || !polling)
00355 {
00356 read_request_issued = 0;
00357 if (
00358 (message_size =
00359 recvline (socket_fd,
00360 ((char *) encoded_data) + bytes_at_beginning_of_line,
00361 cms_encoded_data_explosion_factor * size, 0, timeout,
00362 &bytes_at_beginning_of_line)) < 0)
00363 {
00364 if (recvline_timedout)
00365 {
00366 if (polling)
00367 {
00368 read_request_issued = 1;
00369 return (status = CMS_READ_OLD);
00370 }
00371 else
00372 {
00373 lines_to_skip++;
00374 bytes_at_beginning_of_line = 0;
00375 return (status = CMS_TIMED_OUT);
00376 }
00377 }
00378 else
00379 {
00380 bytes_at_beginning_of_line = 0;
00381 return (status = CMS_MISC_ERROR);
00382 }
00383 }
00384 bytes_at_beginning_of_line = 0;
00385 if (!strncmp ((char *) encoded_data, "ERR", 3))
00386 {
00387 long errcode;
00388 errcode = strtol (((char *) encoded_data) + 4, NULL, 0);
00389 if (errcode == 0)
00390 {
00391 return (status = CMS_READ_OLD);
00392 }
00393 else
00394 {
00395 return (status = CMS_MISC_ERROR);
00396 }
00397 }
00398 id++;
00399 }
00400 header.was_read = 1;
00401 check_id (id);
00402 return (status);
00403 }
00404
00405
00406 CMS_STATUS
00407 STCPMEM::peek ()
00408 {
00409 long message_size, id;
00410 id = in_buffer_id;
00411 int read_request_issued_last_time;
00412 char request_string[32];
00413 sprintf (request_string, "peek(%d):", (int) buffer_number);
00414
00415 if (socket_fd <= 0)
00416 {
00417 rcs_print_error ("STCPMEM::peek: Invalid socket descriptor. (%d)\n",
00418 socket_fd);
00419 return (status = CMS_MISC_ERROR);
00420 }
00421 if (((int) skip_lines ()) < 0)
00422 {
00423 return status;
00424 }
00425 read_request_issued_last_time = read_request_issued;
00426
00427 if (!read_request_issued_last_time || !polling)
00428 {
00429 if (sendline (socket_fd, request_string, 0, timeout) < 0)
00430 {
00431 return (status = CMS_MISC_ERROR);
00432 }
00433 read_request_issued = 1;
00434 read_request_time = etime ();
00435 }
00436
00437 if (read_request_issued_last_time || !polling)
00438 {
00439 read_request_issued = 0;
00440 if (
00441 (message_size =
00442 recvline (socket_fd,
00443 ((char *) encoded_data) + bytes_at_beginning_of_line,
00444 cms_encoded_data_explosion_factor * size, 0, timeout,
00445 &bytes_at_beginning_of_line)) < 0)
00446 {
00447 if (recvline_timedout)
00448 {
00449 if (polling)
00450 {
00451 read_request_issued = 1;
00452 return (status = CMS_READ_OLD);
00453 }
00454 else
00455 {
00456 lines_to_skip++;
00457 bytes_at_beginning_of_line = 0;
00458 return (status = CMS_TIMED_OUT);
00459 }
00460 }
00461 else
00462 {
00463 bytes_at_beginning_of_line = 0;
00464 return (status = CMS_MISC_ERROR);
00465 }
00466 }
00467 bytes_at_beginning_of_line = 0;
00468 if (!strncmp ((char *) encoded_data, "ERR", 3))
00469 {
00470 long errcode;
00471 errcode = strtol (((char *) encoded_data) + 4, NULL, 0);
00472 if (errcode == 0)
00473 {
00474 return (status = CMS_READ_OLD);
00475 }
00476 else
00477 {
00478 return (status = CMS_MISC_ERROR);
00479 }
00480 }
00481 id++;
00482 }
00483 header.was_read = 1;
00484 check_id (id);
00485 return (status);
00486 }
00487
00488
00489
00490
00491 CMS_STATUS
00492 STCPMEM::write (void *user_data)
00493 {
00494 read_request_issued = 0;
00495 char request_string[32];
00496 sprintf (request_string, "write(%d): ", (int) buffer_number);
00497
00498 if (socket_fd <= 0)
00499 {
00500 rcs_print_error ("STCPMEM::write: Invalid socket descriptor. (%d)\n",
00501 socket_fd);
00502 return (status = CMS_MISC_ERROR);
00503 }
00504 memset (temp_buffer, 0, temp_buffer_size);
00505 strcpy (temp_buffer, request_string);
00506 strcat (temp_buffer, (char *) encoded_data);
00507 if (sendline (socket_fd, temp_buffer, 0, timeout) < 0)
00508 {
00509 return (status = CMS_MISC_ERROR);
00510 }
00511 status = CMS_WRITE_OK;
00512 return (status);
00513 }
00514
00515 CMS_STATUS
00516 STCPMEM::write_if_read (void *user_data)
00517 {
00518 read_request_issued = 0;
00519 char request_string[32];
00520 sprintf (request_string, "write_if_read(%d): ", (int) buffer_number);
00521 static int poll_error_message_sent = 0;
00522 if (socket_fd <= 0)
00523 {
00524 rcs_print_error ("STCPMEM::write: Invalid socket descriptor. (%d)\n",
00525 socket_fd);
00526 return (status = CMS_MISC_ERROR);
00527 }
00528 if (polling)
00529 {
00530 if (poll_error_message_sent < 100)
00531 {
00532 rcs_print_error
00533 ("STCPMEM: Can not write_if_read when polling is enabled.\n");
00534 }
00535 poll_error_message_sent++;
00536 return (status = CMS_MISC_ERROR);
00537 }
00538
00539 memset (temp_buffer, 0, temp_buffer_size);
00540 strcpy (temp_buffer, request_string);
00541 strcat (temp_buffer, (char *) encoded_data);
00542 if (sendline (socket_fd, temp_buffer, 0, timeout) < 0)
00543 {
00544 return (status = CMS_MISC_ERROR);
00545 }
00546 if (recvline (socket_fd, temp_buffer, temp_buffer_size, 0, timeout, NULL) <
00547 0)
00548 {
00549 rcs_print_error ("write_if_read: timed out.\n");
00550 return (status = CMS_TIMED_OUT);
00551 }
00552 if (!strncmp (temp_buffer, "write_if_read_succeeded", 22))
00553 {
00554 return (status = CMS_WRITE_OK);
00555 }
00556 rcs_print_error ("write_if_read_failed %s", temp_buffer);
00557 return (status = CMS_MISC_ERROR);
00558 }
00559
00560 int
00561 STCPMEM::check_if_read ()
00562 {
00563 read_request_issued = 0;
00564 char request_string[32];
00565 sprintf (request_string, "check_if_read(%d): ", (int) buffer_number);
00566
00567 if (socket_fd <= 0)
00568 {
00569 rcs_print_error ("STCPMEM::write: Invalid socket descriptor. (%d)\n",
00570 socket_fd);
00571 return (status = CMS_MISC_ERROR);
00572 }
00573 if (recvline (socket_fd, temp_buffer, temp_buffer_size, 0, timeout, NULL) <
00574 0)
00575 {
00576 status = CMS_TIMED_OUT;
00577 return 0;
00578 }
00579 if (!strncmp (temp_buffer, "was_read", 8))
00580 {
00581 return (1);
00582 }
00583 return (0);
00584 }
00585
00586
00587 CMS_STATUS
00588 STCPMEM::clear ()
00589 {
00590
00591 return (status);
00592 }
00593
00594 int
00595 STCPMEM::login (const char *name, const char *passwd)
00596 {
00597
00598 status = CMS_STATUS_NOT_SET;
00599 double start_time = etime ();
00600 while (read_request_issued
00601 && (status == CMS_STATUS_NOT_SET || status == CMS_TIMED_OUT
00602 || status == CMS_READ_OLD) && start_time - etime () < 60.0)
00603 {
00604 peek ();
00605 }
00606 read_request_issued = 0;
00607 char request_string[32];
00608 sprintf (request_string, "get_keys(%d):%s", (int) buffer_number, name);
00609
00610 if (sendline (socket_fd, request_string, 0, 30.0) < 0)
00611 {
00612 return (status = CMS_MISC_ERROR);
00613 }
00614 if (recvline (socket_fd, temp_buffer, temp_buffer_size, 0, 30.0, NULL) < 0)
00615 {
00616 rcs_print_error ("login: timed out.\n");
00617 return (0);
00618 }
00619 if (strncmp (temp_buffer, "keys:", 5))
00620 {
00621 rcs_print_error
00622 ("Bad reply from server on request for login keys: %s\n",
00623 temp_buffer);
00624 return 0;
00625 }
00626 char key1[8];
00627 memset (key1, 0, 8);
00628 int i = 0;
00629 for (i = 0; i < 8 && temp_buffer[i + 5] != ':'; i++)
00630 {
00631 key1[i] = temp_buffer[i + 5];
00632 }
00633 int key2_offset = i + 6;
00634 char key2[8];
00635 memset (key2, 0, 8);
00636 for (i = 0; i < 8 && temp_buffer[i + key2_offset] != ':'; i++)
00637 {
00638 key2[i] = temp_buffer[i + key2_offset];
00639 }
00640 char passwd_pass1[16];
00641 char *crypt1_ret;
00642 crypt1_ret = rcs_crypt (passwd, key1);
00643 if (NULL == crypt1_ret)
00644 {
00645 rcs_print_error ("STCPMEM:login -- crypt failed.\n");
00646 return 0;
00647 }
00648 strncpy (passwd_pass1, crypt1_ret, 16);
00649 char passwd_pass2[16];
00650 char *crypt2_ret;
00651 crypt2_ret = rcs_crypt (passwd_pass1, key2);
00652 if (NULL == crypt2_ret)
00653 {
00654 rcs_print_error ("STCPMEM:login -- crypt failed.\n");
00655 return 0;
00656 }
00657 strncpy (passwd_pass2, crypt2_ret, 16);
00658 sprintf (request_string, "login(%d):%s:%s", (int) buffer_number, name,
00659 passwd_pass2);
00660 if (sendline (socket_fd, request_string, 0, 30.0) < 0)
00661 {
00662 return (status = CMS_MISC_ERROR);
00663 }
00664 if (recvline (socket_fd, temp_buffer, temp_buffer_size, 0, 30.0, NULL) < 0)
00665 {
00666 rcs_print_error ("login: timed out.\n");
00667 return (0);
00668 }
00669 if (strncmp (temp_buffer, "login", 5))
00670 {
00671 rcs_print_error ("Bad reply from server on request for login: %s\n",
00672 temp_buffer);
00673 return 0;
00674 }
00675 return !strcmp (temp_buffer, "login succeeded");
00676 }