00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "rcs_defs.hh"
00013
00014 #ifdef EXTERN_C_STD_HEADERS
00015 extern "C"
00016 {
00017 #endif
00018
00019 #ifndef UNDER_CE
00020 #include <stdio.h>
00021
00022 #endif
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <ctype.h>
00026 #ifndef irix6
00027 #include <math.h>
00028 #else
00029
00030
00031 extern double fmod (double, double);
00032 #endif
00033
00034 #if defined(WIN32)
00035 #if defined(WIN32) && !defined(USE_OLD_WINSOCK)
00036
00037
00038 #include <winsock2.h>
00039 #endif
00040 #include <windows.h>
00041 #else
00042
00043 #ifdef VXWORKS
00044 #include <taskLib.h>
00045 #else
00046 #include <sys/types.h>
00047 #include <unistd.h>
00048 #include <sys/wait.h>
00049 #endif
00050 #endif
00051
00052 #ifndef UNDER_CE
00053 #include <signal.h>
00054
00055 #endif
00056
00057 #ifdef WIN32
00058 #ifdef MULTITHREADED
00059 #ifndef UNDER_CE
00060 #include <process.h>
00061 #else
00062 #include <Winbase.h>
00063 #endif
00064 #endif
00065 #endif
00066
00067
00068 #ifdef EXTERN_C_STD_HEADERS
00069 }
00070 #endif
00071
00072
00073 #include "cms.hh"
00074 #include "rem_msg.hh"
00075
00076 #include "cms_srv.hh"
00077 #include "cms_cfg.hh"
00078 #include "rcs_prnt.hh"
00079
00080
00081 #ifndef NO_DCE_RPC
00082 #define NO_DCE_RPC
00083 #endif
00084
00085 #ifndef NO_DCE_RPC
00086 #ifndef WIN32
00087 #include "rpc_srv.hh"
00088 #endif
00089 #endif
00090 #include "tcp_srv.hh"
00091 #ifndef UNDER_CE
00092 #include "stcpsvr.hh"
00093 #endif
00094
00095 #if !defined(VXWORKS) && (!defined(__MSDOS__) || defined(WIN32)) && !defined(UNDER_CE) && !defined(DARWIN) && !defined(qnx)
00096 #include "tty_srv.hh"
00097 #endif
00098
00099 #include "udp_srv.hh"
00100 #include "inetfile.hh"
00101 #include "timer.hh"
00102 #include "crypt2.hh"
00103
00104 #include "dbg_mem.h"
00105 #include "cmsdiag.hh"
00106
00107
00108 int cms_server_count = 0;
00109 int cms_server_task_priority = 100;
00110 int cms_server_task_stack_size = 32768;
00111
00112 void
00113 wait_for_servers (int count_to_waitfor)
00114 {
00115 do
00116 {
00117 esleep (0.1);
00118 }
00119 while (cms_server_count < count_to_waitfor);
00120
00121 }
00122
00123
00124
00125 class CMS_USER_INFO
00126 {
00127 public:
00128 CMS_USER_INFO ();
00129 private:
00130 char passwd[16];
00131 char epasswd[16];
00132 char name[16];
00133 char passwd_file_line[256];
00134 char key1[8];
00135 char key2[8];
00136 int has_passwd;
00137 int user_number;
00138 int allow_read;
00139 int allow_write;
00140 friend class CMS_SERVER;
00141 };
00142
00143
00144 CMS_USER_INFO::CMS_USER_INFO ()
00145 {
00146 memset (passwd, 0, 16);
00147 memset (epasswd, 0, 16);
00148 memset (name, 0, 16);
00149 memset (passwd_file_line, 0, 256);
00150 memset (key1, 0, 8);
00151 memset (key2, 0, 8);
00152 has_passwd = 0;
00153 user_number = 0;
00154 allow_read = 0;
00155 allow_write = 0;
00156 }
00157
00158 CMS_USER_CONNECT_STRUCT::CMS_USER_CONNECT_STRUCT ()
00159 {
00160 user_info = NULL;
00161 fd = -1;
00162 }
00163
00164
00165 RCS_LINKED_LIST *cms_server_list = NULL;
00166
00167 #ifdef VXWORKS
00168 SEM_ID cms_server_list_mutex = 0;
00169 #endif
00170
00171 CMS_SERVER_LOCAL_PORT::CMS_SERVER_LOCAL_PORT (CMS * _cms)
00172 {
00173 local_channel_reused = 1;
00174 security_enabled = 0;
00175 cms = _cms;
00176 orig_info = NULL;
00177 if (NULL != cms)
00178 {
00179 buffer_number = cms->buffer_number;
00180 }
00181 else
00182 {
00183 buffer_number = 0;
00184 }
00185 list_id = 0;
00186 };
00187
00188 CMS_SERVER_LOCAL_PORT::~CMS_SERVER_LOCAL_PORT ()
00189 {
00190 if (NULL != orig_info)
00191 {
00192 delete orig_info;
00193 orig_info = NULL;
00194 }
00195 }
00196
00197
00198 REMOTE_READ_REPLY *
00199 CMS_SERVER_LOCAL_PORT::reader (REMOTE_READ_REQUEST * _req)
00200 {
00201 return (NULL);
00202 }
00203
00204 REMOTE_READ_REPLY *
00205 CMS_SERVER_LOCAL_PORT::blocking_read (REMOTE_READ_REQUEST * _req)
00206 {
00207 return (NULL);
00208 }
00209
00210
00211 REMOTE_WRITE_REPLY *
00212 CMS_SERVER_LOCAL_PORT::writer (REMOTE_WRITE_REQUEST * _req)
00213 {
00214 return (NULL);
00215 }
00216
00217
00218 REMOTE_SET_DIAG_INFO_REPLY *
00219 CMS_SERVER_LOCAL_PORT::set_diag_info (REMOTE_SET_DIAG_INFO_REQUEST * _req)
00220 {
00221 return (NULL);
00222 }
00223
00224 REMOTE_GET_DIAG_INFO_REPLY *
00225 CMS_SERVER_LOCAL_PORT::get_diag_info (REMOTE_GET_DIAG_INFO_REQUEST * _req)
00226 {
00227 get_diag_info_reply.cdi = cms->get_diagnostics_info ();
00228 get_diag_info_reply.status = cms->status;
00229 return (&get_diag_info_reply);
00230 }
00231
00232 REMOTE_GET_MSG_COUNT_REPLY *
00233 CMS_SERVER_LOCAL_PORT::get_msg_count (REMOTE_GET_DIAG_INFO_REQUEST * _req)
00234 {
00235 return (NULL);
00236 }
00237
00238 void
00239 CMS_SERVER_LOCAL_PORT::reset_diag_info ()
00240 {
00241 }
00242
00243
00244 CMS_SERVER_REMOTE_PORT::CMS_SERVER_REMOTE_PORT (CMS_SERVER *
00245 _cms_server_parent)
00246 {
00247 current_clients = 0;
00248 max_clients = 0;
00249 port_registered = 0;
00250 cms_server_parent = _cms_server_parent;
00251 connected_users = NULL;
00252 security_enabled = 0;
00253 confirm_write = 0;
00254 min_compatible_version = 0.0;
00255 current_user_info = NULL;
00256 running = 0;
00257 max_total_subdivisions = _cms_server_parent->max_total_subdivisions;
00258 }
00259
00260 CMS_SERVER_REMOTE_PORT::~CMS_SERVER_REMOTE_PORT ()
00261 {
00262 if (NULL != connected_users)
00263 {
00264 CMS_USER_CONNECT_STRUCT *connected_user_struct =
00265 (CMS_USER_CONNECT_STRUCT *) connected_users->get_head ();
00266 while (NULL != connected_user_struct)
00267 {
00268 delete connected_user_struct;
00269 connected_user_struct = NULL;
00270 connected_users->delete_current_node ();
00271 connected_user_struct =
00272 (CMS_USER_CONNECT_STRUCT *) connected_users->get_next ();
00273 }
00274 delete connected_users;
00275 }
00276 current_connected_user_struct = NULL;
00277 }
00278
00279 void
00280 CMS_SERVER_REMOTE_PORT::add_connected_user (int _fd)
00281 {
00282 current_connected_user_struct = NULL;
00283 rcs_print_debug (PRINT_SOCKET_CONNECT, "Adding connected user %d\n", _fd);
00284 CMS_USER_CONNECT_STRUCT *connected_user_struct =
00285 new CMS_USER_CONNECT_STRUCT ();
00286 if (NULL == connected_user_struct)
00287 {
00288 return;
00289 }
00290 connected_user_struct->fd = _fd;
00291 if (NULL == connected_users)
00292 {
00293 connected_users = new RCS_LINKED_LIST ();
00294 }
00295 if (NULL == connected_users)
00296 {
00297 return;
00298 }
00299 connected_users->store_at_tail (connected_user_struct,
00300 sizeof (connected_user_struct), 0);
00301 current_connected_user_struct = connected_user_struct;
00302
00303 }
00304
00305 CMS_USER_INFO *
00306 CMS_SERVER_REMOTE_PORT::get_connected_user (int _fd)
00307 {
00308 current_connected_user_struct = NULL;
00309 if (NULL == connected_users)
00310 {
00311 connected_users = new RCS_LINKED_LIST ();
00312 }
00313 if (NULL == connected_users)
00314 {
00315 return NULL;
00316 }
00317 CMS_USER_CONNECT_STRUCT *connected_user_struct =
00318 (CMS_USER_CONNECT_STRUCT *) connected_users->get_head ();
00319 while (NULL != connected_user_struct)
00320 {
00321 if (connected_user_struct->fd == _fd)
00322 {
00323 current_connected_user_struct = connected_user_struct;
00324 return connected_user_struct->user_info;
00325 }
00326 connected_user_struct =
00327 (CMS_USER_CONNECT_STRUCT *) connected_users->get_next ();
00328 }
00329 add_connected_user (_fd);
00330 return NULL;
00331 }
00332
00333
00334 void
00335 CMS_SERVER_REMOTE_PORT::register_port ()
00336 {
00337 return;
00338 }
00339
00340 void
00341 CMS_SERVER_REMOTE_PORT::unregister_port ()
00342 {
00343 return;
00344 }
00345
00346 int
00347 CMS_SERVER_REMOTE_PORT::accept_local_port_cms (CMS * _cms)
00348 {
00349 if (NULL != _cms)
00350 {
00351 if (min_compatible_version < 1e-6 ||
00352 (min_compatible_version > _cms->min_compatible_version &&
00353 _cms->min_compatible_version > 1e-6))
00354 {
00355 min_compatible_version = _cms->min_compatible_version;
00356 }
00357 }
00358 if (_cms->total_subdivisions > max_total_subdivisions)
00359 {
00360 max_total_subdivisions = _cms->total_subdivisions;
00361 }
00362 return 1;
00363 }
00364
00365
00366 CMS_SERVER *
00367 CMS_SERVER_REMOTE_PORT::find_server (long _pid, long _tid )
00368 {
00369 CMS_SERVER *cms_server;
00370 #ifdef VXWORKS
00371 if (NULL != cms_server_list_mutex)
00372 {
00373 semTake (cms_server_list_mutex, WAIT_FOREVER);
00374 }
00375 else
00376 {
00377 taskLock ();
00378 }
00379 #endif
00380
00381 if (NULL == cms_server_list)
00382 {
00383 return NULL;
00384 }
00385
00386 cms_server = (CMS_SERVER *) cms_server_list->get_head ();
00387 while (NULL != cms_server)
00388 {
00389 #ifdef WIN32
00390 if (cms_server->server_pid == ((DWORD) _pid)
00391 && cms_server->server_tid == ((DWORD) _tid))
00392 #else
00393 if (cms_server->server_pid == _pid && cms_server->server_tid == _tid)
00394 #endif
00395 {
00396 break;
00397 }
00398 cms_server = (CMS_SERVER *) cms_server_list->get_next ();
00399 }
00400
00401 #ifdef VXWORKS
00402 if (NULL != cms_server_list_mutex)
00403 {
00404 semGive (cms_server_list_mutex);
00405 }
00406 else
00407 {
00408 taskUnlock ();
00409 }
00410 #endif
00411 return (cms_server);
00412 }
00413
00414 void
00415 CMS_SERVER_REMOTE_PORT::print_servers ()
00416 {
00417 CMS_SERVER *cms_server;
00418
00419 if (NULL == cms_server_list)
00420 {
00421 rcs_print ("cms_server_list is NULL.\n");
00422 return;
00423 }
00424
00425 cms_server = (CMS_SERVER *) cms_server_list->get_head ();
00426 rcs_print ("Server Tasks for this remote port.\n");
00427 while (NULL != cms_server)
00428 {
00429 rcs_print (" \t(%d (0x%X), %d (0x%X))\n",
00430 cms_server->server_pid, cms_server->server_pid,
00431 cms_server->server_tid, cms_server->server_tid);
00432
00433 cms_server = (CMS_SERVER *) cms_server_list->get_next ();
00434 }
00435 }
00436
00437 #ifndef UNDER_CE
00438
00439 void
00440 CMS_SERVER::read_passwd_file ()
00441 {
00442 using_passwd_file = 1;
00443 int user_name_length;
00444 int passwd_length;
00445 if (NULL == known_users)
00446 {
00447 known_users = new RCS_LINKED_LIST ();
00448 }
00449 srand ((int) ((2 ^ 32) * etime ()));
00450 char buf[256];
00451 INET_FILE *ifp = NULL;
00452 rcs_print ("Reading passwd file %s.\n", passwd_file);
00453 ifp = inet_file_open (passwd_file, "r");
00454 if (NULL == ifp)
00455 {
00456 rcs_print_error ("Can not open passwd file %s.\n", passwd_file);
00457 return;
00458 }
00459 CMS_USER_INFO *user_info = NULL;
00460
00461 while (!inet_file_eof (ifp))
00462 {
00463 memset (buf, 0, 256);
00464 inet_file_gets (buf, 256, ifp);
00465 user_name_length = strcspn (buf, "\n\r \t:");
00466 if (user_name_length > 16)
00467 {
00468 rcs_print_error ("CMS_SERVER: user name is too long.\n");
00469 continue;
00470 }
00471 if (user_name_length < 2)
00472 {
00473 continue;
00474 }
00475 user_info = new CMS_USER_INFO ();
00476 if (NULL == user_info)
00477 {
00478 break;
00479 }
00480 strcpy (user_info->passwd_file_line, buf);
00481 memcpy (user_info->name, buf, user_name_length);
00482 passwd_length = strcspn (buf + user_name_length + 1, "\n\r \t:");
00483 if (passwd_length > 16)
00484 {
00485 rcs_print_error ("CMS_SERVER: password is too long.\n");
00486 continue;
00487 }
00488 if (passwd_length > 16)
00489 {
00490 rcs_print_error ("CMS_SERVER: password is too long.\n");
00491 }
00492 if (passwd_length > 2)
00493 {
00494 memcpy (user_info->passwd, buf + user_name_length + 1,
00495 passwd_length);
00496 memcpy (user_info->key1, buf + user_name_length + 1, 2);
00497 user_info->has_passwd = 1;
00498 }
00499 else
00500 {
00501 user_info->has_passwd = 0;
00502 }
00503 gen_random_key (user_info->key2, 2);
00504 strcpy (user_info->epasswd,
00505 rcs_crypt (user_info->passwd, user_info->key2));
00506 user_info->allow_read = (NULL != strstr (buf, "read=true"));
00507 user_info->allow_write = (NULL != strstr (buf, "write=true"));
00508 user_info->user_number =
00509 known_users->store_at_tail (user_info, sizeof (user_info), 0);
00510 rcs_print ("Storing info for user (%s).\n", user_info->name);
00511
00512 if (!strcmp (user_info->name, "guest"))
00513 {
00514 guest_can_read = user_info->allow_read;
00515 guest_can_write = user_info->allow_write;
00516 }
00517 user_info = NULL;
00518 }
00519 }
00520
00521 void
00522 CMS_SERVER::gen_random_key (char key[], int len)
00523 {
00524 for (int i = 0; i < len; i++)
00525 {
00526 while (!isgraph (key[i]) || !key[i])
00527 {
00528 key[i] = (char) ((rand () % 128));
00529 }
00530 }
00531 }
00532
00533 CMS_USER_INFO *
00534 CMS_SERVER::find_user (const char *name)
00535 {
00536 if (NULL == known_users)
00537 {
00538 return NULL;
00539 }
00540 CMS_USER_INFO *user_info = (CMS_USER_INFO *) known_users->get_head ();
00541 while (NULL != user_info)
00542 {
00543 rcs_print ("CMS_SERVER::find_user: strcmp(%s,%s)\n", name,
00544 user_info->name);
00545 if (!strcmp (name, user_info->name))
00546 {
00547 return user_info;
00548 }
00549 user_info = (CMS_USER_INFO *) known_users->get_next ();
00550 }
00551 rcs_print_error ("CMS_SERVER: Can't find entry for user %s.\n", name);
00552 return NULL;
00553 }
00554
00555 int
00556 CMS_SERVER::get_user_keys (const char *name, char *key1, char *key2)
00557 {
00558 if (NULL == known_users)
00559 {
00560 gen_random_key (key1, 2);
00561 gen_random_key (key2, 2);
00562 return -1;
00563 }
00564 CMS_USER_INFO *user_info = find_user (name);
00565 if (NULL == user_info)
00566 {
00567 gen_random_key (key1, 2);
00568 gen_random_key (key2, 2);
00569 return -1;
00570 }
00571 strcpy (key1, user_info->key1);
00572 if (fabs (etime () - time_of_last_key_request) > 30.0)
00573 {
00574 memset (user_info->key2, 0, 8);
00575 memset (user_info->epasswd, 0, 16);
00576 gen_random_key (user_info->key2, 2);
00577 strcpy (user_info->epasswd,
00578 rcs_crypt (user_info->passwd, user_info->key2));
00579 }
00580 strcpy (key2, user_info->key2);
00581 time_of_last_key_request = etime ();
00582 return 0;
00583 }
00584
00585 CMS_USER_INFO *
00586 CMS_SERVER::get_user_info (const char *name, const char *epasswd)
00587 {
00588 if (NULL == known_users)
00589 {
00590 return NULL;
00591 }
00592 CMS_USER_INFO *user_info = find_user (name);
00593 if (NULL == user_info)
00594 {
00595 return NULL;
00596 }
00597 if (!strcmp (user_info->epasswd, epasswd) || !user_info->has_passwd)
00598 {
00599 return user_info;
00600 }
00601 rcs_print_error ("CMS_SERVER: %s gave the wrong passwd.\n", name);
00602 rcs_print_error ("CMS_SERVER: user_info->passwd = %s\n", user_info->passwd);
00603 rcs_print_error ("CMS_SERVER: user_info->epasswd = %s\n",
00604 user_info->epasswd);
00605 rcs_print_error ("CMS_SERVER: epasswd = %s\n", epasswd);
00606
00607 return NULL;
00608 }
00609
00610 #endif
00611
00612
00613 void
00614 CMS_SERVER::add_local_port (CMS_SERVER_LOCAL_PORT * _local_port)
00615 {
00616 if (NULL == _local_port)
00617 {
00618 rcs_print_error ("CMS_SERVER: Attempt to add NULL local port.\n");
00619 return;
00620 }
00621 if (NULL == _local_port->cms)
00622 {
00623 rcs_print_error
00624 ("CMS_SERVER: Attempt to add local port with NULL cms object.\n");
00625 return;
00626 }
00627 if (NULL == cms_local_ports)
00628 {
00629 rcs_print_error
00630 ("CMS_SERVER: Attempt to add local port when local ports list is NULL.\n");
00631 return;
00632 }
00633
00634 if (NULL == remote_port)
00635 {
00636 switch (_local_port->cms->remote_port_type)
00637 {
00638 #ifndef NO_DCE_RPC
00639 #ifndef WIN32
00640 case CMS_RPC_REMOTE_PORT_TYPE:
00641 remote_port = new CMS_SERVER_REMOTE_RPC_PORT (this);
00642 break;
00643 #endif
00644 #endif
00645 case CMS_TCP_REMOTE_PORT_TYPE:
00646 remote_port = new CMS_SERVER_REMOTE_TCP_PORT (this);
00647 break;
00648 #ifndef UNDER_CE
00649 case CMS_STCP_REMOTE_PORT_TYPE:
00650 remote_port = new CMS_SERVER_REMOTE_STCP_PORT (this);
00651 break;
00652 #endif
00653
00654
00655 #if !defined(VXWORKS) && (!defined(__MSDOS__) || defined(WIN32)) && !defined(UNDER_CE) && !defined(DARWIN) && !defined(qnx)
00656 case CMS_TTY_REMOTE_PORT_TYPE:
00657 remote_port = new CMS_SERVER_REMOTE_TTY_PORT (this);
00658 break;
00659 #endif
00660
00661 case CMS_UDP_REMOTE_PORT_TYPE:
00662 remote_port = new CMS_SERVER_REMOTE_UDP_PORT (this);
00663 break;
00664 default:
00665 rcs_print_error ("CMS_SERVER: Invalid remote port type. (%d)\n",
00666 _local_port->cms->remote_port_type);
00667 return;
00668 }
00669 }
00670 if (NULL == remote_port)
00671 {
00672 rcs_print_error ("CMS_SERVER: couldn't create remote port object.\n");
00673 return;
00674 }
00675 if (!accept_local_port_cms (_local_port->cms))
00676 {
00677 rcs_print_error
00678 ("CMS_SERVER: Attempt to add local port failed because the port was of an incompatible type.\n");
00679 }
00680 char *passwd_eq = strstr (_local_port->cms->BufferLine, "passwd=");
00681 if (NULL != passwd_eq)
00682 {
00683 #ifndef UNDER_CE
00684 if (!using_passwd_file)
00685 {
00686 memset (passwd_file, 0, 256);
00687 for (int i = 0; i < 256 && passwd_eq[i + 7]; i++)
00688 {
00689 if (passwd_eq[i + 7] == ' ' || passwd_eq[i + 7] == '\t'
00690 || passwd_eq[i + 7] == '\n' || passwd_eq[i + 7] == '\r')
00691 {
00692 break;
00693 }
00694 passwd_file[i] = passwd_eq[i + 7];
00695 }
00696 if (strlen (passwd_file) > 0)
00697 {
00698 read_passwd_file ();
00699 }
00700 }
00701 _local_port->security_enabled = 1;
00702 remote_port->security_enabled = 1;
00703 #else
00704 rcs_print_error
00705 ("CMS_SVR: Passwd control not supported under Windows CE.\n");
00706 #endif
00707 }
00708
00709
00710 _local_port->list_id =
00711 cms_local_ports->store_at_tail (_local_port,
00712 sizeof (CMS_SERVER_LOCAL_PORT), 0);
00713 if (-1 == _local_port->list_id)
00714 {
00715 rcs_print_error
00716 ("CMS_SERVER: Can not store local port on linked list.\n");
00717 }
00718 }
00719
00720 int
00721 CMS_SERVER::accept_local_port_cms (CMS * _cms)
00722 {
00723 if (NULL == remote_port || NULL == _cms)
00724 {
00725 return (0);
00726 }
00727
00728 return (remote_port->accept_local_port_cms (_cms));
00729 }
00730
00731 CMS_SERVER_LOCAL_PORT *
00732 CMS_SERVER::find_local_port (long _buffer_number)
00733 {
00734 CMS_SERVER_LOCAL_PORT *cms_local_port;
00735 cms_local_port = (CMS_SERVER_LOCAL_PORT *) cms_local_ports->get_head ();
00736 while (NULL != cms_local_port)
00737 {
00738 if (cms_local_port->buffer_number == _buffer_number)
00739 {
00740 break;
00741 }
00742 cms_local_port = (CMS_SERVER_LOCAL_PORT *) cms_local_ports->get_next ();
00743 }
00744 return (cms_local_port);
00745 }
00746
00747
00748 int
00749 CMS_SERVER::get_total_subdivisions (long _buffer_number)
00750 {
00751 CMS_SERVER_LOCAL_PORT *cms_local_port = find_local_port (_buffer_number);
00752 if (NULL == cms_local_port)
00753 {
00754 return 1;
00755 }
00756 if (NULL == cms_local_port->cms)
00757 {
00758 return 1;
00759 }
00760 return cms_local_port->cms->total_subdivisions;
00761 }
00762
00763
00764 void
00765 CMS_SERVER::set_diag_info (REMOTE_SET_DIAG_INFO_REQUEST * _diag_info)
00766 {
00767 diag_enabled = 1;
00768 CMS_SERVER_LOCAL_PORT *local_port =
00769 find_local_port (_diag_info->buffer_number);
00770 if (NULL == local_port)
00771 {
00772 rcs_print_error
00773 ("CMS_SERVER: Cannot find local port for buffer number %ld\n",
00774 _diag_info->buffer_number);
00775 return;
00776 }
00777 local_port->set_diag_info (_diag_info);
00778 last_local_port_used = local_port;
00779 }
00780
00781 void
00782 CMS_SERVER::reset_diag_info (int buffer_number)
00783 {
00784 diag_enabled = 0;
00785 CMS_SERVER_LOCAL_PORT *local_port = find_local_port (buffer_number);
00786 if (NULL == local_port)
00787 {
00788 rcs_print_error
00789 ("CMS_SERVER: Cannot find local port for buffer number %ld\n",
00790 buffer_number);
00791 return;
00792 }
00793 local_port->reset_diag_info ();
00794 last_local_port_used = NULL;
00795 }
00796
00797
00798 REMOTE_CMS_REPLY *
00799 CMS_SERVER::process_request (REMOTE_CMS_REQUEST * _request)
00800 {
00801 CMS_SERVER_LOCAL_PORT *local_port;
00802
00803 requests_processed++;
00804
00805 request = _request;
00806 if (NULL == request)
00807 {
00808 rcs_print_error ("CMS_SERVER: Request is NULL.\n");
00809 return NULL;
00810 }
00811
00812 local_port = find_local_port (request->buffer_number);
00813 last_local_port_used = local_port;
00814 if (NULL == local_port)
00815 {
00816 rcs_print_error
00817 ("CMS_SERVER: Cannot find local port for buffer number %ld\n",
00818 request->buffer_number);
00819 return (NULL);
00820 }
00821
00822 #ifndef UNDER_CE
00823 if (!security_check
00824 (remote_port->current_user_info, request->buffer_number))
00825 {
00826 return NULL;
00827 }
00828 #endif
00829
00830 local_port->cms->set_subdivision (_request->subdiv);
00831 _request->subdiv = 0;
00832
00833 switch (request->type)
00834 {
00835 case REMOTE_CMS_GET_BUF_NAME_REQUEST_TYPE:
00836 {
00837 REMOTE_GET_BUF_NAME_REPLY *namereply = &local_port->namereply;
00838 const char *name = get_buffer_name (request->buffer_number);
00839 if (0 == name)
00840 {
00841 return NULL;
00842 }
00843 strncpy (namereply->name, name, 31);
00844 return namereply;
00845 }
00846
00847 case REMOTE_CMS_READ_REQUEST_TYPE:
00848 return (local_port->reader ((REMOTE_READ_REQUEST *) request));
00849 case REMOTE_CMS_GET_DIAG_INFO_REQUEST_TYPE:
00850 return (local_port->get_diag_info
00851 ((REMOTE_GET_DIAG_INFO_REQUEST *) request));
00852 case REMOTE_CMS_BLOCKING_READ_REQUEST_TYPE:
00853 return (local_port->blocking_read ((REMOTE_READ_REQUEST *) request));
00854 case REMOTE_CMS_WRITE_REQUEST_TYPE:
00855 return (local_port->writer ((REMOTE_WRITE_REQUEST *) request));
00856 case REMOTE_CMS_CHECK_IF_READ_REQUEST_TYPE:
00857 if (NULL == local_port->cms)
00858 {
00859 rcs_print_error
00860 ("CMS_SERVER: cms object associated with local port is NULL.\n");
00861 return (NULL);
00862 }
00863 cir_reply.was_read = local_port->cms->check_if_read ();
00864 cir_reply.status = local_port->cms->status;
00865 return (&cir_reply);
00866
00867 case REMOTE_CMS_CLEAR_REQUEST_TYPE:
00868 if (NULL == local_port->cms)
00869 {
00870 rcs_print_error
00871 ("CMS_SERVER: cms object associated with local port is NULL.\n");
00872 return (NULL);
00873 }
00874 local_port->cms->clear ();
00875 clear_reply_struct.status = local_port->cms->status;
00876 return (&clear_reply_struct);
00877
00878 #ifndef UNDER_CE
00879 case REMOTE_CMS_GET_KEYS_REQUEST_TYPE:
00880 get_keys_reply = &perm_get_keys_reply;
00881 get_user_keys (
00882 ((REMOTE_GET_KEYS_REQUEST *) request)->name,
00883 get_keys_reply->key1, get_keys_reply->key2);
00884 return (&perm_get_keys_reply);
00885
00886 case REMOTE_CMS_LOGIN_REQUEST_TYPE:
00887 login_reply = &perm_login_reply;
00888 if (NULL == remote_port->current_connected_user_struct)
00889 {
00890 login_reply->success = 0;
00891 return (&perm_login_reply);
00892 }
00893 remote_port->current_connected_user_struct->user_info =
00894 get_user_info (
00895 ((REMOTE_LOGIN_REQUEST *) request)->name,
00896 ((REMOTE_LOGIN_REQUEST *) request)->passwd);
00897 login_reply->success =
00898 (NULL != remote_port->current_connected_user_struct->user_info);
00899 if (login_reply->success)
00900 {
00901 rcs_print ("%s logged in.\n",
00902 remote_port->current_connected_user_struct->user_info->
00903 name);
00904 }
00905 return (&perm_login_reply);
00906 #endif
00907
00908 case REMOTE_CMS_SET_SUBSCRIPTION_REQUEST_TYPE:
00909 set_subscription_reply = &perm_set_subscription_reply;
00910 set_subscription_reply->success = 1;
00911 return (&perm_set_subscription_reply);
00912
00913 default:
00914 rcs_print_error ("CMS_SERVER: Invalid request type (%d)\n",
00915 request->type);
00916 return (NULL);
00917 }
00918 }
00919
00920 #if defined(WIN32) && !defined(gnuwin32)
00921 DWORD
00922 CMS_ServerRun (LPVOID svr)
00923 {
00924 if (NULL == svr)
00925 {
00926 return FALSE;
00927 }
00928 ((CMS_SERVER *) svr)->run ();
00929 return FALSE;
00930 }
00931 #endif
00932
00933
00934 int
00935 CMS_SERVER::spawn ()
00936 {
00937 if (0 == server_spawned)
00938 {
00939 if (NULL != remote_port)
00940 {
00941 remote_port->running = 0;
00942 }
00943 server_spawned = 1;
00944 #if defined(WIN32) && !defined(gnuwin32) && defined(MULTITHREADED)
00945 server_pid = current_pid = spawner_pid = GetCurrentProcessId ();
00946 current_tid = spawner_tid = GetCurrentThreadId ();
00947 server_thread_handle = (HANDLE) _beginthread (
00948 (void (__cdecl *)
00949 (void *)) CMS_ServerRun,
00950 0, (LPVOID) this);
00951 if (((int) server_thread_handle) < 0)
00952 {
00953 rcs_print_sys_error (ERRNO_ERROR_SOURCE, "CreateThread failed.");
00954 return -1;
00955 }
00956 #else
00957 #ifndef VXWORKS
00958 current_pid = spawner_pid = getpid ();
00959 if (0 == (server_pid = fork ()))
00960 {
00961
00962 run ();
00963 clean (2);
00964 exit (-1);
00965 }
00966 else
00967 {
00968
00969 }
00970 #else
00971 spawner_pid = taskIdSelf ();
00972 if (spawner_pid == creator_pid)
00973 {
00974 server_pid =
00975 taskSpawn (NULL, cms_server_task_priority, VX_FP_TASK,
00976 cms_server_task_stack_size,
00977 (FUNCPTR) (&CMS_SERVER::run), (int) this, 0, 0, 0, 0,
00978 0, 0, 0, 0, 0);
00979 }
00980 else
00981 {
00982 spawner_pid = 0;
00983 return 0;
00984 }
00985 #endif
00986 #endif
00987 int waits = 0;
00988 while (waits < 20)
00989 {
00990 esleep (0.01);
00991 if (NULL == remote_port)
00992 {
00993 break;
00994 }
00995 if (remote_port->running)
00996 {
00997 break;
00998 }
00999 waits++;
01000 }
01001 return 1;
01002 }
01003 return 0;
01004 }
01005
01006 void
01007 CMS_SERVER::kill_server ()
01008 {
01009 #ifdef VXWORKS
01010 current_pid = taskIdSelf ();
01011 if (current_pid != spawner_pid)
01012 {
01013 return;
01014 }
01015 #endif
01016 if (0 != server_pid)
01017 {
01018 #if defined(WIN32) && !defined(gnuwin32)
01019 #ifndef UNDER_CE
01020 if (server_pid != current_pid)
01021 {
01022 GenerateConsoleCtrlEvent (CTRL_C_EVENT, server_pid);
01023 }
01024 #else
01025 TerminateProcess ((HANDLE) server_pid, 0);
01026 #endif
01027 #else
01028 signal (SIGINT, SIG_DFL);
01029 cms_server_count--;
01030 kill (server_pid, SIGINT);
01031 #ifdef VXWORKS
01032 int count = 0;
01033 while (OK == taskIdVerify (server_pid) && count < 100)
01034 {
01035 taskDelay (1);
01036 count++;
01037 }
01038 if (OK == taskIdVerify (server_pid))
01039 {
01040 taskDelete (server_pid);
01041 }
01042 #else
01043 waitpid (server_pid, NULL, 0);
01044 #endif
01045 #endif
01046 server_pid = 0;
01047 }
01048 }
01049
01050
01051
01052
01053 void
01054 CMS_SERVER::register_server (int setup_CC_signal_local_port)
01055 {
01056 last_local_port_used = NULL;
01057 server_registered = 1;
01058 #ifdef VXWORKS
01059 taskLock ();
01060 if (NULL == cms_server_list_mutex)
01061 {
01062 cms_server_list_mutex =
01063 semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
01064 }
01065
01066 if (NULL == cms_server_list_mutex)
01067 {
01068 taskUnlock ();
01069 return;
01070 }
01071 int sem_take_succeeded = 0;
01072 if (OK == semTake (cms_server_list_mutex, NO_WAIT))
01073 {
01074 sem_take_succeeded = 1;
01075 taskUnlock ();
01076 }
01077
01078 #endif
01079
01080 if (NULL == cms_server_list)
01081 {
01082 cms_server_list = new RCS_LINKED_LIST;
01083 }
01084 list_id = cms_server_list->store_at_tail (this, sizeof (CMS_SERVER), 0);
01085
01086 #ifdef VXWORKS
01087 if (sem_take_succeeded)
01088 {
01089 semGive (cms_server_list_mutex);
01090 }
01091 else
01092 {
01093 taskUnlock ();
01094 }
01095 #endif
01096
01097
01098
01099 if (setup_CC_signal_local_port)
01100 {
01101 #ifndef UNDER_CE
01102 #if defined(WIN32) && !defined(gnuwin32)
01103 SetConsoleCtrlHandler ((PHANDLER_ROUTINE) clean, TRUE);
01104 #else
01105 #ifdef sparcworks_sun4
01106 signal (SIGINT, (void (*)(int,...)) clean);
01107 #else
01108 signal (SIGINT, clean);
01109 #endif
01110 #endif
01111 #endif
01112 }
01113
01114 if (NULL == remote_port)
01115 {
01116 rcs_print_error ("CMS_SERVER: Can't register with NULL remote port.\n");
01117 return;
01118 }
01119 remote_port->register_port ();
01120
01121 }
01122
01123
01124 void
01125 CMS_SERVER::run (int setup_CC_signal_local_port)
01126 {
01127 #if defined(WIN32) && !defined(gnuwin32)
01128 server_pid = current_pid = GetCurrentProcessId ();
01129 server_tid = current_tid = GetCurrentThreadId ();
01130 #else
01131 server_tid = current_tid = 0;
01132 #ifdef VXWORKS
01133 server_pid = taskIdSelf ();
01134 #else
01135 current_pid = server_pid = getpid ();
01136 #endif
01137 #endif
01138 if (!server_registered)
01139 {
01140 register_server (setup_CC_signal_local_port);
01141 }
01142 initialize_write_request_space ();
01143 if (NULL == remote_port)
01144 {
01145 rcs_print_error
01146 ("CMS_SERVER: Cannot run with remote port equal to NULL.\n");
01147 return;
01148 }
01149 remote_port->running = 1;
01150 if (remote_port->port_registered)
01151 {
01152 remote_port->run ();
01153 }
01154 }
01155
01156 void
01157 CMS_SERVER::initialize_write_request_space ()
01158 {
01159 max_total_subdivisions = 1;
01160 maximum_cms_size = 0;
01161 CMS_SERVER_LOCAL_PORT *local_port;
01162 if (NULL == cms_local_ports)
01163 {
01164 rcs_print_error
01165 ("CMS_SERVER: Can not search list of local ports to determine the size of space needed for the write request\n"
01166 "because the list is NULL.\n");
01167 return;
01168 }
01169 local_port = (CMS_SERVER_LOCAL_PORT *) cms_local_ports->get_head ();
01170 while (NULL != local_port)
01171 {
01172 if (NULL != local_port->cms)
01173 {
01174 if (local_port->cms->size > maximum_cms_size)
01175 {
01176 maximum_cms_size = local_port->cms->size;
01177 }
01178 if (local_port->cms->total_subdivisions > max_total_subdivisions)
01179 {
01180 max_total_subdivisions = local_port->cms->total_subdivisions;
01181 }
01182 if (NULL != remote_port)
01183 {
01184 if (local_port->cms->total_subdivisions >
01185 remote_port->max_total_subdivisions)
01186 {
01187 remote_port->max_total_subdivisions =
01188 local_port->cms->total_subdivisions;
01189 }
01190 }
01191 if (local_port->cms->max_encoded_message_size > maximum_cms_size)
01192 {
01193 maximum_cms_size = local_port->cms->max_encoded_message_size;
01194 }
01195 }
01196 local_port = (CMS_SERVER_LOCAL_PORT *) cms_local_ports->get_next ();
01197 }
01198 if (NULL != write_req.data)
01199 {
01200 #ifdef sparcworks_sun4
01201
01202
01203 DEBUG_FREE ((char *) write_req.data);
01204 #else
01205 DEBUG_FREE (write_req.data);
01206 #endif
01207 write_req.data = NULL;
01208 }
01209 write_req.data = DEBUG_MALLOC (maximum_cms_size);
01210 if (NULL == write_req.data)
01211 {
01212 rcs_print_error ("malloc(%d) failed.\n", maximum_cms_size);
01213 }
01214 local_port = (CMS_SERVER_LOCAL_PORT *) cms_local_ports->get_head ();
01215 while (NULL != local_port)
01216 {
01217 if (NULL != local_port->cms)
01218 {
01219 local_port->cms->set_encoded_data (write_req.data,
01220 maximum_cms_size);
01221 }
01222 local_port = (CMS_SERVER_LOCAL_PORT *) cms_local_ports->get_next ();
01223 }
01224 }
01225
01226 CMS_SERVER::CMS_SERVER ()
01227 {
01228 last_local_port_used = NULL;
01229 diag_enabled = 0;
01230 using_passwd_file = 0;
01231 current_pid = 0;
01232 server_pid = 0;
01233 spawner_pid = 0;
01234 server_registered = 0;
01235 guest_can_read = 0;
01236 guest_can_write = 0;
01237 server_spawned = 0;
01238 list_id = 0;
01239 requests_processed = 0;
01240 read_reply = NULL;
01241 write_reply = NULL;
01242 check_if_read_reply = NULL;
01243 clear_reply = NULL;
01244 remote_port = NULL;
01245 request = NULL;
01246 write_req.data = NULL;
01247 cms_local_ports = new RCS_LINKED_LIST;
01248 known_users = NULL;
01249 max_total_subdivisions = 1;
01250 memset (passwd_file, 0, 256);
01251 #if defined(WIN32) && !defined(gnuwin32)
01252 creator_pid = GetCurrentProcessId ();
01253 creator_tid = GetCurrentThreadId ();
01254 #else
01255 #ifndef VXWORKS
01256 creator_pid = getpid ();
01257 #else
01258 creator_pid = taskIdSelf ();
01259 #endif
01260 #endif
01261
01262 }
01263
01264 CMS_SERVER::~CMS_SERVER ()
01265 {
01266 last_local_port_used = NULL;
01267 #ifdef VXWORKS
01268 current_pid = taskIdSelf ();
01269 #endif
01270 if (server_registered && (!server_spawned || current_pid == server_pid))
01271 {
01272 unregister_server ();
01273 }
01274 else if (server_spawned && current_pid == spawner_pid)
01275 {
01276 kill_server ();
01277 }
01278 delete_all_local_ports ();
01279 if (NULL != remote_port)
01280 {
01281 delete remote_port;
01282 remote_port = NULL;
01283 }
01284 if (NULL != cms_local_ports)
01285 {
01286 delete cms_local_ports;
01287 cms_local_ports = NULL;
01288 }
01289
01290
01291
01292
01293 if (NULL != write_req.data)
01294 {
01295 #ifdef sparcworks_sun4
01296
01297
01298 DEBUG_FREE ((char *) write_req.data);
01299 #else
01300 DEBUG_FREE (write_req.data);
01301 #endif
01302 write_req.data = NULL;
01303 }
01304 }
01305
01306 void
01307 CMS_SERVER::delete_all_local_ports ()
01308 {
01309 if (NULL != cms_local_ports)
01310 {
01311 CMS_SERVER_LOCAL_PORT *local_port;
01312 local_port = (CMS_SERVER_LOCAL_PORT *) cms_local_ports->get_head ();
01313 while (NULL != local_port)
01314 {
01315 delete local_port;
01316 cms_local_ports->delete_current_node ();
01317 local_port = (CMS_SERVER_LOCAL_PORT *) cms_local_ports->get_next ();
01318 }
01319 }
01320 }
01321
01322 static int last_cms_server_signum = 0;
01323
01324 void
01325 CMS_SERVER::clean (int signum)
01326 {
01327 last_cms_server_signum = signum;
01328 #if defined(WIN32) && !defined(gnuwin32)
01329 DWORD current_pid = GetCurrentProcessId ();
01330 DWORD current_tid = GetCurrentThreadId ();
01331 #else
01332 #ifdef VXWORKS
01333 int current_pid;
01334 int current_tid = 0;
01335 current_pid = taskIdSelf ();
01336 #else
01337 pid_t current_pid;
01338 pid_t current_tid = 0;
01339 current_pid = getpid ();
01340 #endif
01341 #endif
01342 CMS_SERVER *cms_server = NULL;
01343
01344
01345 #ifdef VXWORKS
01346 if (NULL != cms_server_list_mutex)
01347 {
01348 semTake (cms_server_list_mutex, WAIT_FOREVER);
01349 }
01350 else
01351 {
01352 taskLock ();
01353 }
01354 #endif
01355 cms_server = (CMS_SERVER *) cms_server_list->get_head ();
01356 while (NULL != cms_server)
01357 {
01358 if (cms_server->server_pid == current_pid
01359 && cms_server->server_tid == current_tid)
01360 {
01361 cms_server->unregister_server ();
01362 delete cms_server;
01363 cms_server = NULL;
01364 }
01365 cms_server = (CMS_SERVER *) cms_server_list->get_next ();
01366 }
01367
01368 #ifdef VXWORKS
01369 if (NULL != cms_server_list_mutex)
01370 {
01371 semGive (cms_server_list_mutex);
01372 }
01373 else
01374 {
01375 taskUnlock ();
01376 }
01377 #endif
01378 #ifndef UNDER_CE
01379 exit (0);
01380 #else
01381 ExitThread (0);
01382 #endif
01383 }
01384
01385 void
01386 CMS_SERVER::unregister_server ()
01387 {
01388 if (server_registered)
01389 {
01390 server_registered = 0;
01391 if (NULL != remote_port)
01392 {
01393 remote_port->unregister_port ();
01394 }
01395 }
01396 }
01397
01398 void
01399 CMS_SERVER::delete_from_list ()
01400 {
01401 #ifdef VXWORKS
01402 if (NULL != cms_server_list_mutex)
01403 {
01404 semTake (cms_server_list_mutex, WAIT_FOREVER);
01405 }
01406 else
01407 {
01408 taskLock ();
01409 }
01410 #endif
01411
01412 #if defined(WIN32) && !defined(gnuwin32)
01413 current_pid = GetCurrentProcessId ();
01414 current_tid = GetCurrentThreadId ();
01415 #else
01416 #ifndef VXWORKS
01417 current_pid = getpid ();
01418 current_tid = 0;
01419 #else
01420 current_pid = taskIdSelf ();
01421 current_tid = 0;
01422 #endif
01423 #endif
01424
01425 if (current_pid == server_pid && current_tid == server_tid)
01426 {
01427 if (NULL != cms_server_list && list_id > 0)
01428 {
01429 cms_server_list->delete_node (list_id);
01430 list_id = -1;
01431 }
01432 }
01433
01434 #ifdef VXWORKS
01435 if (NULL != cms_server_list_mutex)
01436 {
01437 semGive (cms_server_list_mutex);
01438 }
01439 else
01440 {
01441 taskUnlock ();
01442 }
01443 #endif
01444 }
01445
01446 const char *
01447 CMS_SERVER::get_buffer_name (int buffer_number)
01448 {
01449 CMS_SERVER_LOCAL_PORT *local_port;
01450 local_port = find_local_port (buffer_number);
01451 if (NULL == local_port)
01452 {
01453 return NULL;
01454 }
01455 return (const char *) local_port->cms->BufferName;
01456 }
01457
01458 long
01459 CMS_SERVER::get_message_type ()
01460 {
01461 return -1;
01462
01463 }
01464
01465 int
01466 CMS_SERVER::get_access_type ()
01467 {
01468 if (NULL == request)
01469 {
01470 return -1;
01471 }
01472 return request->type;
01473 }
01474
01475
01476 #ifndef UNDER_CE
01477 int
01478 CMS_SERVER::security_check (CMS_USER_INFO * user_info, int buffer_number)
01479 {
01480 CMS_SERVER_LOCAL_PORT *local_port;
01481 local_port = find_local_port (buffer_number);
01482 if (!using_passwd_file)
01483 {
01484 return 1;
01485 }
01486 if (!local_port->security_enabled)
01487 {
01488 return 1;
01489 }
01490 if (request->type == REMOTE_CMS_GET_KEYS_REQUEST_TYPE ||
01491 request->type == REMOTE_CMS_LOGIN_REQUEST_TYPE)
01492 {
01493 return 1;
01494 }
01495
01496
01497 if (NULL == user_info)
01498 {
01499
01500 if (guest_can_read && (request->type == REMOTE_CMS_READ_REQUEST_TYPE ||
01501 request->type ==
01502 REMOTE_CMS_SET_SUBSCRIPTION_REQUEST_TYPE))
01503 {
01504 return 1;
01505 }
01506
01507 if (guest_can_write && request->type == REMOTE_CMS_WRITE_REQUEST_TYPE)
01508 {
01509 return 1;
01510 }
01511 rcs_print_error
01512 ("CMS_SERVER: Refusing to process request of unknown user.\n");
01513 return 0;
01514 }
01515
01516 if (user_info->allow_read
01517 && (request->type == REMOTE_CMS_READ_REQUEST_TYPE
01518 || request->type == REMOTE_CMS_SET_SUBSCRIPTION_REQUEST_TYPE))
01519 {
01520 return 1;
01521 }
01522
01523 if (user_info->allow_write
01524 && request->type == REMOTE_CMS_WRITE_REQUEST_TYPE)
01525 {
01526 return 1;
01527 }
01528
01529 if (NULL != detailed_security_check)
01530 {
01531 return detailed_security_check (user_info->name,
01532 get_buffer_name (buffer_number),
01533 get_message_type (),
01534 get_access_type ());
01535 }
01536
01537 if (!user_info->allow_read && request->type == REMOTE_CMS_READ_REQUEST_TYPE)
01538 {
01539 rcs_print_error ("CMS_SERVER:: %s does not have read permission.");
01540 return 0;
01541 }
01542
01543 if (!user_info->allow_write
01544 && request->type == REMOTE_CMS_WRITE_REQUEST_TYPE)
01545 {
01546 rcs_print_error ("CMS_SERVER:: %s does not have write permission.");
01547 return 0;
01548 }
01549 return 1;
01550
01551 }
01552
01553
01554 int (*detailed_security_check) (const char *user_name,
01555 const char *buffer_name,
01556 long msg_type, int access_type) = NULL;
01557
01558 #endif