Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

stcpmem.cc

Go to the documentation of this file.
00001 
00002 // This is neccessary to avoid muliple definitions of fd_set, etc when both
00003 // RPC via PCNFS and Windows Sockets are to be available
00004 #ifdef USE_PCNFS
00005 #undef USE_PCNFS
00006 #endif
00007 
00008 #include "rcs_defs.hh"          /* EXTERN_C_STD_HEADERS */
00009 
00010 #ifdef EXTERN_C_STD_HEADERS
00011 extern "C"
00012 {
00013 #endif
00014 #include <stdio.h>              // sprintf()
00015 #include <ctype.h>              // isdigit()
00016 
00017 #ifndef irix6
00018 #include <math.h>               /* fmod() */
00019 #else
00020 // Work around for the conflict between the gcc includes and /usr/includes
00021 // on some of our SGI's regarding the definition of initstate()
00022   extern double fmod (double, double);
00023 #endif
00024 
00025 #include <string.h>             /* strerror() */
00026 #include <stdlib.h>             // malloc()
00027 #ifdef CenterLine
00028   char *strerror (int errnum);
00029 #endif
00030 #include <errno.h>              /* errno  */
00031 
00032 #ifdef EXTERN_C_STD_HEADERS
00033 }
00034 #endif
00035 
00036 #include "rem_msg.hh"           /* REMOTE_CMS_READ_REQUEST_TYPE, etc. */
00037 #include "rcs_prnt.hh"          /* rcs_print_error() */
00038 
00039 
00040 #define REQUEST_TIMEOUT (2.0)
00041 #include "timer.hh"             /* esleep() */
00042 
00043 #include "stcpmem.hh"
00044 
00045 #include "recvline.h"           /* recvline() */
00046 #include "sendline.h"           /* sendline() */
00047 #include "stcpopts.hh"          /* SET_TCP_NODELAY */
00048 #include "sokintrf.h"           /* dl_closesocket(), dl_gethostbyname(), dl_socket() */
00049 #include "crypt2.hh"            // crypt()
00050                                                                         /* dl_connect(), load_socket_interface(), unload_socket_interface() */
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   /* Set up the socket address stucture. */
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       /* Get the IP address of the server using it's BufferHost. */
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           // Timeout after 30 seconds on connect even if we
00200           // have no timeouts on other operations.
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   // FIXME: unimplemented function.
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 }

Generated on Sun Dec 2 15:56:52 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001