source: BMXNET_RPMS_dotNET_UTILITIES-BMX/branch/IHS BMX Framework/IndianHealthService.BMXNet/BMXNetBroker.cs@ 1146

Last change on this file since 1146 was 1146, checked in by Sam Habiel, 13 years ago

Initial Import of BMX4

File size: 23.4 KB
Line 
1using System;
2using System.Diagnostics;
3using System.Text;
4using System.IO;
5using System.Net.Sockets;
6using System.Net;
7using System.Security.Cryptography;
8using System.Security.Permissions;
9using System.Security.Principal;
10using System.Threading;
11using System.Timers;
12using IndianHealthService.BMXNet.Net;
13using IndianHealthService.BMXNet.Services;
14using IndianHealthService.BMXNet.Model;
15using System.Windows.Forms;
16
17namespace IndianHealthService.BMXNet
18{
19 /// <summary>
20 /// BMXNetBroker implements low-level socket connectivity to RPMS databases.
21 /// The VA RPC Broker must be running on the RPMS server in order for
22 /// BMXNetBroker to connect.
23 /// </summary>
24 [DnsPermission(SecurityAction.Assert, Unrestricted = true)]
25 internal abstract class BMXNetBroker:EncryptionProvider
26 {
27 public static BMXNetBroker CreateSocketBroker()
28 {
29 return (BMXNetBroker)new BMXNetSocketBroker();
30 }
31
32 private Log _log = new NullLog();
33
34 public Log Log
35 {
36 get { return _log; }
37 set { _log = value; }
38 }
39
40
41 public BMXNetBroker()
42 {
43 this.EncryptionProvider = new BMXAdeCrypto();
44 }
45
46 internal RemoteSessionPool CreateRemoteSessionPool(BMXNetSessionConnectionSource aSource, int maxConnectionCount)
47 {
48 BMXRemoteSessionPool pool = new BMXRemoteSessionPool();
49 pool.Log = this.Log;
50 pool.MaxSessions = maxConnectionCount;
51 pool.Begin(aSource);
52 return pool;
53 }
54
55 public abstract bool IsConnected { get; }
56
57 public abstract RemoteSession PrimaryRemoteSession { get; }
58
59
60 public virtual bool Open(string aServer, int aPort, string aNameSpace, string anAccessCode, string aVerifyCode, int sendTimeout, int receiveTimeout)
61 {
62 throw new NotSupportedException();
63 }
64
65 public virtual bool Open(string aServer, int aPort, string aNameSpace, WindowsIdentity windowsIdentity, int sendTimeout, int receiveTimeout)
66 {
67 throw new NotSupportedException();
68 }
69
70 private EncryptionProvider _encryptionProvider = null;
71
72 public EncryptionProvider EncryptionProvider
73 {
74 get
75 {
76 return _encryptionProvider;
77 }
78 set
79 {
80 _encryptionProvider = value;
81 }
82 }
83
84
85 public String Duz
86 {
87 get { return this.User.Duz; }
88 }
89
90 private User _user=null;
91
92 public User User
93 {
94 get { return _user; }
95 set { _user = value; }
96 }
97
98
99 public double ImHereServer()
100 {
101 try
102 {
103 DateTime past = DateTime.Now;
104 this.PrimaryRemoteSession.TransmitRPC("BMX IM HERE", "");
105 return (DateTime.Now - past).TotalMilliseconds;
106 }
107 catch
108 {
109 return -1;
110 }
111 }
112
113
114 public abstract void Close();
115
116 public abstract RemoteSessionPool RemoteSessionPool { get; }
117
118
119 #region Piece Functions
120
121 /// <summary>
122 /// Corresponds to M's $L(STRING,DELIMITER)
123 /// </summary>
124 /// <param name="sInput"></param>
125 /// <param name="sDelim"></param>
126 /// <returns></returns>
127 internal static int PieceLength(string sInput, string sDelim)
128 {
129 char[] cDelim = sDelim.ToCharArray();
130 string[] cSplit = sInput.Split(cDelim);
131 return cSplit.GetLength(0);
132 }
133
134 /// <summary>
135 /// Corresponds to M's $$Piece function
136 /// </summary>
137 /// <param name="sInput"></param>
138 /// <param name="sDelim"></param>
139 /// <param name="nNumber"></param>
140 /// <returns></returns>
141 internal static string Piece(string sInput, string sDelim, int nNumber)
142 {
143 try
144 {
145 char[] cDelim = sDelim.ToCharArray();
146 string[] cSplit = sInput.Split(cDelim);
147 int nLength = cSplit.GetLength(0);
148 if ((nLength < nNumber) || (nNumber < 1))
149 return "";
150 return cSplit[nNumber - 1];
151 }
152 catch (Exception bmxEx)
153 {
154 string sMessage = bmxEx.Message + bmxEx.StackTrace;
155 throw new BMXNetException(sMessage);
156 }
157
158 }
159
160 internal static string Piece(string sInput, string sDelim, int nNumber, int nEnd)
161 {
162 try
163 {
164 if (nNumber < 0)
165 nNumber = 1;
166
167 if (nEnd < nNumber)
168 return "";
169
170 if (nEnd == nNumber)
171 return Piece(sInput, sDelim, nNumber);
172
173 char[] cDelim = sDelim.ToCharArray();
174 string[] cSplit = sInput.Split(cDelim);
175 int nLength = cSplit.GetLength(0);
176 if ((nLength < nNumber) || (nNumber < 1))
177 return "";
178
179 //nNumber = 1-based index of the starting element to return
180 //nLength = count of elements
181 //nEnd = 1-based index of last element to return
182 //nCount = number of elements past nNumber to return
183
184 //convert nNumber to 0-based index:
185 nNumber--;
186
187 //convert nEnd to 0-based index;
188 nEnd--;
189
190 //Calculate nCount;
191 int nCount = nEnd - nNumber + 1;
192
193 //Adjust nCount for number of elements
194 if (nCount + nNumber >= nLength)
195 {
196 nCount = nLength - nNumber;
197 }
198
199 string sRet = string.Join(sDelim, cSplit, nNumber, nCount);
200 return sRet;
201 }
202 catch (Exception bmxEx)
203 {
204 string sMessage = bmxEx.Message + bmxEx.StackTrace;
205 throw new BMXNetException(sMessage);
206 }
207 }
208
209 #endregion Piece Functions
210
211
212
213 #region RPX Functions
214
215 /// <summary>
216 /// Given strInput = "13" builds "013" if nLength = 3. Default for nLength is 3.
217 /// </summary>
218 /// <param name="strInput"></param>
219 /// <returns></returns>
220 internal protected string ADEBLDPadString(string strInput)
221 {
222 return ADEBLDPadString(strInput, 3);
223 }
224
225 /// <summary>
226 /// Given strInput = "13" builds "013" if nLength = 3 Default for nLength is 3.
227 /// </summary>
228 /// <param name="strInput"></param>
229 /// <param name="nLength">Default = 3</param>
230 /// <returns></returns>
231
232
233
234 internal protected string ADEBLDPadString(string strInput, int nLength ) //=3
235 {
236 return strInput.PadLeft(nLength, '0');
237 }
238
239 /// <summary>
240 /// Concatenates zero-padded length of sInput to sInput
241 /// Given "Hello" returns "004Hello"
242 /// If nSize = 5, returns "00004Hello"
243 /// Default for nSize is 3.
244 /// </summary>
245 /// <param name="sInput"></param>
246 /// <returns></returns>
247 internal protected string ADEBLDB(string sInput)
248 {
249 return ADEBLDB(sInput, 3);
250 }
251
252 /// <summary>
253 /// Concatenates zero-padded length of sInput to sInput
254 /// Given "Hello" returns "004Hello"
255 /// If nSize = 5, returns "00004Hello"
256 /// Default for nSize is 3.
257 /// </summary>
258 /// <param name="sInput"></param>
259 /// <param name="nSize"></param>
260 /// <returns></returns>
261 internal protected string ADEBLDB(string sInput, int nSize) //=3
262 {
263 int nLen = sInput.Length;
264 string sLen = this.ADEBLDPadString(nLen.ToString(), nSize);
265 return sLen + sInput;
266 }
267
268 /// <summary>
269 /// Build protocol header
270 /// </summary>
271 /// <param name="sWKID"></param>
272 /// <param name="sWINH"></param>
273 /// <param name="sPRCH"></param>
274 /// <param name="sWISH"></param>
275 /// <returns></returns>
276 internal protected string ADEBHDR(string sWKID, string sWINH, string sPRCH, string sWISH)
277 {
278 string strResult;
279 strResult = sWKID + ";" + sWINH + ";" + sPRCH + ";" + sWISH + ";";
280 strResult = ADEBLDB(strResult);
281 return strResult;
282 }
283
284 internal protected string ADEBLDMsg(string cHDR, string cRPC, string cParam)
285 {
286 string sMult = "";
287 return ADEBLDMsg(cHDR, cRPC, cParam, ref sMult);
288 }
289
290 internal protected string ADEBLDMsg(string cHDR, string cRPC, string cParam, ref string cMult)
291 {
292 //Builds RPC message
293 //TODO: Verify that this is still needed. If this is needed, it should be
294 //handled exclusively on the RPMS-side and allow TCP/IP to optimize the
295 //transort
296 string cMSG;
297 string sBuild = "";
298 string sPiece = "";
299 int l;
300 int nLength;
301
302 if (cParam == "")
303 {
304 cMSG = "0" + cRPC;
305 }
306 else
307 {
308 l = PieceLength(cParam, "^");
309 for (int j = 1; j <= l; j++)
310 {
311 sPiece = Piece(cParam, "^", j);
312 nLength = sPiece.Length + 1;
313 sPiece = ADEBLDPadString(nLength.ToString()) + "0" + sPiece;
314 sBuild = sBuild + sPiece;
315 }
316 nLength = sBuild.Length;
317 string sTotLen = ADEBLDPadString(nLength.ToString(), 5);
318 if (cMult.Length > 0)
319 {
320 cMSG = "1" + cRPC + "^" + sTotLen + sBuild;
321 }
322 else
323 {
324 cMSG = "0" + cRPC + "^" + sTotLen + sBuild;
325 }
326 }
327 cMSG = ADEBLDB(cMSG, 5);
328 cMSG = cHDR + cMSG;
329 return cMSG;
330 }
331
332 internal static int FindChar(byte[] c, char y)
333 {
334 int n = 0;
335 int nRet = -1;
336 for (n = 0; n < c.Length; n++)
337 {
338 if (y == (char)c[n])
339 {
340 nRet = n;
341 break;
342 }
343 }
344
345 return nRet;
346 }
347
348 internal static int FindChar(string s, char y)
349 {
350 int n = 0;
351 int nRet = -1;
352 foreach (char c in s)
353 {
354 if (y == c)
355 {
356 nRet = n;
357 break;
358 }
359 n++;
360 }
361 return nRet;
362 }
363
364
365
366 /// <summary>
367 /// Returns index of first instance of sSubString in sString.
368 /// If sSubString not found, returns -1.
369 /// </summary>
370 /// <param name="sString"></param>
371 /// <param name="sSubString"></param>
372 /// <returns></returns>
373 internal static int FindSubString(string sString, string sSubString)
374 {
375 int nFound = -1;
376 int nLimit = sString.Length - sSubString.Length + 1;
377 if (nLimit < 0)
378 return -1;
379
380 int nSubLength = sSubString.Length;
381 for (int j = 0; j < nLimit; j++)
382 {
383 if (sString.Substring(j, nSubLength) == sSubString)
384 {
385 nFound = j;
386 break;
387 }
388 }
389 return nFound;
390 }
391 /*
392
393 StreamWriter m_LogWriter;
394 bool m_bLogging = false;
395
396 public void StartLog()
397 {
398 try
399 {
400 if (m_bLogging)
401 {
402 throw new Exception("Already logging.");
403 }
404 string sFile = "BMXLog " + DateTime.Now.DayOfYear.ToString() + " " +
405 DateTime.Now.Hour.ToString() + " " + DateTime.Now.Minute.ToString()
406 + " " + DateTime.Now.Second.ToString() + ".log";
407 StartLog(sFile);
408 return;
409 }
410 catch (Exception ex)
411 {
412 throw ex;
413 }
414 }
415
416 public void StartLog(string LogFileName)
417 {
418 try
419 {
420 if (m_bLogging)
421 {
422 throw new Exception("Already logging.");
423 }
424 m_LogWriter = File.AppendText(LogFileName);
425 m_bLogging = true;
426 return;
427 }
428 catch (Exception ex)
429 {
430 throw ex;
431 }
432 }
433
434 public void StopLog()
435 {
436 try
437 {
438 //Close the writer and underlying file.
439 if (m_bLogging == false)
440 {
441 return;
442 }
443 m_LogWriter.Close();
444 m_bLogging = false;
445 return;
446 }
447 catch (Exception ex)
448 {
449 throw ex;
450 }
451 }
452
453 private static void Log(String logMessage, TextWriter w)
454 {
455 w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
456 DateTime.Now.ToLongDateString());
457 w.WriteLine(" :");
458 w.WriteLine(" :{0}", logMessage);
459 w.WriteLine("-------------------------------");
460 // Update the underlying file.
461 w.Flush();
462 }
463
464
465
466 public bool Lock(string Variable)
467 {
468 return Lock(Variable, "", "");
469 }
470
471 public bool Lock(string Variable, string Increment)
472 {
473 return Lock(Variable, Increment, "");
474 }
475
476 /// <summary>
477 /// Lock a local or global M variable
478 /// Returns true if lock is obtained during TimeOut seconds
479 /// Use + to increment, - to decrement lock.
480 /// </summary>
481 /// <param name="Variable"></param>
482 /// <param name="Increment"></param>
483 /// <param name="TimeOut"></param>
484 /// <returns></returns>
485 public bool Lock(string Variable, string Increment, string TimeOut)
486 {
487 try
488 {
489 string sContext = this.AppContext;
490 this.AppContext = "BMXRPC";
491 Variable = Variable.Replace("^", "~");
492 string sRet = "0";
493 bool bRet = false;
494 string sParam = Variable + "^" + Increment + "^" + TimeOut;
495 sRet = TransmitRPC("BMX LOCK", sParam);
496 bRet = (sRet == "1") ? true : false;
497 this.AppContext = sContext;
498 return bRet;
499 }
500 catch (Exception ex)
501 {
502 string sMsg = ex.Message;
503 return false;
504 }
505 }
506
507 static ReaderWriterLock m_rwl = new ReaderWriterLock();
508 private int m_nRWLTimeout = 30000; //30-second default timeout
509
510 /// <summary>
511 /// Returns a reference to the internal ReaderWriterLock member.
512 /// </summary>
513 public ReaderWriterLock BMXRWL
514 {
515 get
516 {
517 return m_rwl;
518 }
519 }
520
521 /// <summary>
522 /// Sets and returns the timeout in milliseconds for locking the transmit port.
523 /// If the transmit port is unavailable an ApplicationException will be thrown.
524 /// </summary>
525 public int RWLTimeout
526 {
527 get
528 {
529 return m_nRWLTimeout;
530 }
531 set
532 {
533 m_nRWLTimeout = value;
534 }
535 }
536
537
538
539 protected string EncodeSendString(String cSendString, String cMulti)
540 {
541 String encoded = null;
542
543 int nLen = cSendString.Length;
544 string sLen = nLen.ToString();
545 sLen = sLen.PadLeft(5, '0');
546 encoded = sLen + cSendString;
547
548 nLen += 15;
549 sLen = nLen.ToString();
550 sLen = sLen.PadLeft(5, '0');
551
552 encoded = "{BMX}" + sLen + encoded;
553 encoded = encoded + cMulti;
554
555 return encoded;
556 }
557
558 protected string DecodeReceiveString(String aString)
559 {
560 return aString;
561 }
562
563
564 protected String SendReceiveString(String sendString)
565 {
566 return this.SendReceiveString(sendString, "");
567 }
568
569 protected abstract String SendReceiveString(String sendString, String multi);
570
571 public virtual string TransmitRPC(string sRPC, string sParam, int nLockTimeOut)
572 {
573 try
574 {
575 try
576 {
577 if (!this.IsConnected)
578 {
579 throw new BMXNetException("BMXNetBroker.TransmitRPC failed because BMXNetBroker is not connected to RPMS.");
580 }
581
582 string priorAppContext = this.AppContext;
583
584 if (sRPC.StartsWith("BMX") && (this.AppContext != "BMXRPC"))
585 {
586 this.AppContext = "BMXRPC";
587 }
588
589 string sMult = "";
590 string sSend = ADEBLDMsg(m_cHDR, sRPC, sParam, ref sMult);
591 string strResult = SendReceiveString(sSend, sMult);
592
593 this.AppContext = priorAppContext;
594
595 return strResult;
596 }
597 catch (Exception ex)
598 {
599 if (ex.Message == "Unable to write data to the transport connection.")
600 {
601 this.BeDisconnected();
602 }
603 throw ex;
604 }
605 finally
606 {
607 }
608 }
609 catch (ApplicationException aex)
610 {
611 // The writer lock request timed out.
612 Debug.Write("TransmitRPC writer lock request timed out.\n");
613 throw aex;
614 }
615 catch (Exception OuterEx)
616 {
617 throw OuterEx;
618 }
619 }
620
621 public virtual void BeDisconnected() {
622
623 //TAE
624 }
625
626 public string TransmitRPC(string sRPC, string sParam)
627 {
628 try
629 {
630 return TransmitRPC(sRPC, sParam, m_nRWLTimeout);
631 }
632 catch (ApplicationException aex)
633 {
634 throw aex;
635 }
636 catch (Exception ex)
637 {
638 throw ex;
639 }
640 }
641
642 public abstract string GetLoginFacility(String aDuz);
643
644
645 #endregion RPX Functions
646
647
648 /// <summary>
649 /// Gets/sets the Kernel Application context
650 /// Throws an exception if unable to set the context.
651 /// </summary>
652 public string AppContext
653 {
654 get
655 {
656 return m_cAppContext;
657 }
658 set
659 {
660
661 if (m_cAppContext == value)
662 return;
663
664 //Send the changed context to RPMS
665 if ((this.IsConnected) && (value != null) && (value != ""))
666 {
667 try
668 {
669 string sRPC = ADEEncryp(value);
670 string sAuthentication = TransmitRPC("XWB CREATE CONTEXT", sRPC);
671
672 if (BMXNetBroker.FindSubString(sAuthentication, "does not have access to option") > -1)
673 {
674 throw new BMXNetException(sAuthentication);
675 }
676
677 }
678 catch (Exception ex)
679 {
680 Debug.Write(ex.Message);
681 throw ex;
682 }
683 }
684 m_cAppContext = value;
685 }
686 }
687
688
689 public string DUZ
690 {
691 get
692 {
693 return m_cDUZ;
694 }
695 set { this.m_cDUZ = value; }
696 }
697 */
698
699 #region Encryption Keys
700
701 private string[] m_sKey = new string[]
702 {
703 @"wkEo-ZJt!dG)49K{nX1BS$vH<&:Myf*>Ae0jQW=;|#PsO`'%+rmb[gpqN,l6/hFC@DcUa ]z~R}""V\iIxu?872.(TYL5_3",
704 @"rKv`R;M/9BqAF%&tSs#Vh)dO1DZP> *fX'u[.4lY=-mg_ci802N7LTG<]!CWo:3?{+,5Q}(@jaExn$~p\IyHwzU""|k6Jeb",
705 @"\pV(ZJk""WQmCn!Y,y@1d+~8s?[lNMxgHEt=uw|X:qSLjAI*}6zoF{T3#;ca)/h5%`P4$r]G'9e2if_>UDKb7<v0&- RBO.",
706 @"depjt3g4W)qD0V~NJar\B ""?OYhcu[<Ms%Z`RIL_6:]AX-zG.#}$@vk7/5x&*m;(yb2Fn+l'PwUof1K{9,|EQi>H=CT8S!",
707 @"NZW:1}K$byP;jk)7'`x90B|cq@iSsEnu,(l-hf.&Y_?J#R]+voQXU8mrV[!p4tg~OMez CAaGFD6H53%L/dT2<*>""{\wI=",
708 @"vCiJ<oZ9|phXVNn)m K`t/SI%]A5qOWe\&?;jT~M!fz1l>[D_0xR32c*4.P""G{r7}E8wUgyudF+6-:B=$(sY,LkbHa#'@Q",
709 @"hvMX,'4Ty;[a8/{6l~F_V""}qLI\!@x(D7bRmUH]W15J%N0BYPkrs&9:$)Zj>u|zwQ=ieC-oGA.#?tfdcO3gp`S+En K2*<",
710 @"jd!W5[];4'<C$/&x|rZ(k{>?ghBzIFN}fAK""#`p_TqtD*1E37XGVs@0nmSe+Y6Qyo-aUu%i8c=H2vJ\) R:MLb.9,wlO~P",
711 @"2ThtjEM+!=xXb)7,ZV{*ci3""8@_l-HS69L>]\AUF/Q%:qD?1~m(yvO0e'<#o$p4dnIzKP|`NrkaGg.ufCRB[; sJYwW}5&",
712 @"vB\5/zl-9y:Pj|=(R'7QJI *&CTX""p0]_3.idcuOefVU#omwNZ`$Fs?L+1Sk<,b)hM4A6[Y%aDrg@~KqEW8t>H};n!2xG{",
713 @"sFz0Bo@_HfnK>LR}qWXV+D6`Y28=4Cm~G/7-5A\b9!a#rP.l&M$hc3ijQk;),TvUd<[:I""u1'NZSOw]*gxtE{eJp|y (?%",
714 @"M@,D}|LJyGO8`$*ZqH .j>c~h<d=fimszv[#-53F!+a;NC'6T91IV?(0x&/{B)w""]Q\YUWprk4:ol%g2nE7teRKbAPuS_X",
715 @".mjY#_0*H<B=Q+FML6]s;r2:e8R}[ic&KA 1w{)vV5d,$u""~xD/Pg?IyfthO@CzWp%!`N4Z'3-(o|J9XUE7k\TlqSb>anG",
716 @"xVa1']_GU<X`|\NgM?LS9{""jT%s$}y[nvtlefB2RKJW~(/cIDCPow4,>#zm+:5b@06O3Ap8=*7ZFY!H-uEQk; .q)i&rhd",
717 @"I]Jz7AG@QX.""%3Lq>METUo{Pp_ |a6<0dYVSv8:b)~W9NK`(r'4fs&wim\kReC2hg=HOj$1B*/nxt,;c#y+![?lFuZ-5D}",
718 @"Rr(Ge6F Hx>q$m&C%M~Tn,:""o'tX/*yP.{lZ!YkiVhuw_<KE5a[;}W0gjsz3]@7cI2\QN?f#4p|vb1OUBD9)=-LJA+d`S8",
719 @"I~k>y|m};d)-7DZ""Fe/Y<B:xwojR,Vh]O0Sc[`$sg8GXE!1&Qrzp._W%TNK(=J 3i*2abuHA4C'?Mv\Pq{n#56LftUl@9+",
720 @"~A*>9 WidFN,1KsmwQ)GJM{I4:C%}#Ep(?HB/r;t.&U8o|l['Lg""2hRDyZ5`nbf]qjc0!zS-TkYO<_=76a\X@$Pe3+xVvu",
721 @"yYgjf""5VdHc#uA,W1i+v'6|@pr{n;DJ!8(btPGaQM.LT3oe?NB/&9>Z`-}02*%x<7lsqz4OS ~E$\R]KI[:UwC_=h)kXmF",
722 @"5:iar.{YU7mBZR@-K|2 ""+~`M%8sq4JhPo<_X\Sg3WC;Tuxz,fvEQ1p9=w}FAI&j/keD0c?)LN6OHV]lGy'$*>nd[(tb!#",
723 };
724 #endregion Encryption Keys
725
726 #endregion
727
728 public virtual string RegisterWindowsIdentityForWindowsAuthenication(WindowsIdentity windowsIdentity)
729 {
730 throw new NotSupportedException();
731 }
732
733 #region IEncryptionProvider Members
734
735 public virtual string Encrypt(string aString)
736 {
737 throw new NotSupportedException();
738 }
739
740 public virtual string Decrypt(string aString)
741 {
742 throw new NotSupportedException();
743 }
744
745 #endregion
746 }
747
748}
Note: See TracBrowser for help on using the repository browser.