source: BMXNET_RPMS_dotNET_UTILITIES-BMX/branch/IHS BMX Framework/IndianHealthService.BMXNet/BMXNetSessionConnection.cs@ 1180

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

RemoteSession.cs Interface: Added:

  • Lock method to lock glvns on M db.
  • Encoding ConnectionEncoding to set the connection encoding on the DB

BMXNetSessionConnection: Added:

  • Abstract ConnectionEncoding property
  • Clarified error message that gets called. It now says that you don't have TransmitRPC writer lock??? When the error could be any BMXNetException.

BMXNetSessionSocketConnection:

  • Added ConnectionEncoding property
  • ReceiveString completely refactored: now we get much better performance
  • Timers and Debug Writes are all over the place now.

BMXNetRemoteSession:

  • Implemented the 2 new 'stuff' in Interface RemoteSesssion: -- Lock glvn -- Encoding Property
  • TableFromSQL with Dataset has an honest to god bug in it: The passed dataset and table name are not used even though they are passed.

BMXNetSessionConnectionOverAnotherSessionConnection:

  • Implemented the Encoding Property in Interface RemoteSession to have the project compile.

Updated dlls. Have fun.

File size: 24.6 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 /// BMXNetSessionConnection implements low-level connectivity to RPMS databases.
21 /// </summary>
22 [DnsPermission(SecurityAction.Assert, Unrestricted = true)]
23 internal abstract class BMXNetSessionConnection
24 {
25 public BMXNetSessionConnection(BMXNetBroker aBroker)
26 {
27 this.Broker = aBroker;
28 m_sWKID = "BMX";
29 m_sWINH = "";
30 m_sPRCH = "";
31 m_sWISH = "";
32 m_cHDR = ADEBHDR(m_sWKID, m_sWINH, m_sPRCH, m_sWISH);
33 }
34
35 protected BMXNetBroker _broker=null;
36
37 public BMXNetBroker Broker
38 {
39 get { return _broker; }
40 set { _broker=value;}
41 }
42
43 protected EncryptionProvider EncryptionProvider
44 {
45 get
46 {
47 return this.Broker.EncryptionProvider;
48 }
49 }
50
51
52 #region RPX Fields
53
54 private string m_sWKID;
55 private string m_sWISH;
56 private string m_sPRCH;
57 private string m_sWINH;
58 private string m_cHDR;
59 protected string m_cAppContext;
60 private string m_cDUZ;
61
62 #endregion RPX Fields
63
64 #region RPX Functions
65
66 /// <summary>
67 /// Given strInput = "13" builds "013" if nLength = 3. Default for nLength is 3.
68 /// </summary>
69 /// <param name="strInput"></param>
70 /// <returns></returns>
71 protected string ADEBLDPadString(string strInput)
72 {
73 return ADEBLDPadString(strInput, 3);
74 }
75
76 /// <summary>
77 /// Given strInput = "13" builds "013" if nLength = 3 Default for nLength is 3.
78 /// </summary>
79 /// <param name="strInput"></param>
80 /// <param name="nLength">Default = 3</param>
81 /// <returns></returns>
82 protected string ADEBLDPadString(string strInput, int nLength /*=3*/)
83 {
84 return strInput.PadLeft(nLength, '0');
85 }
86
87 /// <summary>
88 /// Concatenates zero-padded length of sInput to sInput
89 /// Given "Hello" returns "004Hello"
90 /// If nSize = 5, returns "00004Hello"
91 /// Default for nSize is 3.
92 /// </summary>
93 /// <param name="sInput"></param>
94 /// <returns></returns>
95 protected string ADEBLDB(string sInput)
96 {
97 return ADEBLDB(sInput, 3);
98 }
99
100 /// <summary>
101 /// Concatenates zero-padded length of sInput to sInput
102 /// Given "Hello" returns "004Hello"
103 /// If nSize = 5, returns "00004Hello"
104 /// Default for nSize is 3.
105 /// </summary>
106 /// <param name="sInput"></param>
107 /// <param name="nSize"></param>
108 /// <returns></returns>
109 protected string ADEBLDB(string sInput, int nSize /*=3*/)
110 {
111 int nLen = sInput.Length;
112 string sLen = this.ADEBLDPadString(nLen.ToString(), nSize);
113 return sLen + sInput;
114 }
115
116 /// <summary>
117 /// Build protocol header
118 /// </summary>
119 /// <param name="sWKID"></param>
120 /// <param name="sWINH"></param>
121 /// <param name="sPRCH"></param>
122 /// <param name="sWISH"></param>
123 /// <returns></returns>
124 protected string ADEBHDR(string sWKID, string sWINH, string sPRCH, string sWISH)
125 {
126 string strResult;
127 strResult = sWKID + ";" + sWINH + ";" + sPRCH + ";" + sWISH + ";";
128 strResult = ADEBLDB(strResult);
129 return strResult;
130 }
131 protected string ADEBLDMsg(string cHDR, string cRPC, string cParam)
132 {
133 string sMult = "";
134 return ADEBLDMsg(cHDR, cRPC, cParam, ref sMult);
135 }
136
137 protected string ADEBLDPadString(int anInteger)
138 {
139 return ADEBLDPadString(anInteger.ToString(), 3);
140 }
141
142 protected string ADEBLDPadString(int anInteger, int nLength /*=3*/)
143 {
144 return this.ADEBLDPadString(anInteger.ToString(), nLength);
145 }
146
147
148 protected string ADEBLDMsg(string cHDR, string cRPC, string cParam, ref string cMult)
149 {
150 //Builds RPC message
151 //Automatically splits parameters longer than 200 into subscripted array
152 String body;
153 cMult = "";
154
155 if (cParam == "")
156 {
157 body = "0" + cRPC;
158 }
159 else
160 {
161 StringBuilder parametersBuilder = new StringBuilder((int)(cParam.Length * 1.2));
162 int parameterCount = M.PieceLength(cParam, "^");
163 int maxChunkLength = 400;
164
165 for (int j = 1; j <= parameterCount; j++)
166 {
167 String piece = M.Piece(cParam, "^", j);
168
169 if (piece.Length > maxChunkLength)
170 {
171 if (j == parameterCount)
172 {
173 //Place holder for the long parameter
174 String prefix = ".x";
175 parametersBuilder.Append(ADEBLDPadString(prefix.Length + 1) + "2" + prefix);
176
177 StringBuilder encodedMultiPart = new StringBuilder((int)(piece.Length * 1.2));
178 int subscript = 1;
179 int startChunk = 0;
180 do
181 {
182 int chunkLength = Math.Min(piece.Length - startChunk, maxChunkLength);
183 String chunk = piece.Substring(startChunk, chunkLength);
184 String subscriptString = subscript.ToString();
185
186 encodedMultiPart.Append(ADEBLDPadString(subscriptString.Length));
187 encodedMultiPart.Append(subscriptString);
188 encodedMultiPart.Append(ADEBLDPadString(chunk.Length));
189 encodedMultiPart.Append(chunk);
190
191 subscript++;
192 startChunk += chunkLength;
193 } while (startChunk < piece.Length);
194 cMult = encodedMultiPart.ToString();
195 }
196 else
197 {
198 throw new BMXNetException("RPC parameter exceeds " + maxChunkLength.ToString() + ". Lone long parameter must be last.");
199 }
200 }
201 else
202 {
203 parametersBuilder.Append(ADEBLDPadString(piece.Length + 1) + "0" + piece);
204 }
205 }
206
207 String parameters = parametersBuilder.ToString();
208 body = (cMult.Length > 0 ? "1" : "0") + cRPC + "^" + ADEBLDPadString(parameters.Length, 5) + parameters;
209 }
210
211 return cHDR + ADEBLDB(body, 5);
212 }
213
214
215 public static int FindChar(byte[] c, char y)
216 {
217 int n = 0;
218 int nRet = -1;
219 for (n = 0; n < c.Length; n++)
220 {
221 if (y == (char)c[n])
222 {
223 nRet = n;
224 break;
225 }
226 }
227
228 return nRet;
229 }
230
231 public static int FindChar(string s, char y)
232 {
233 int n = 0;
234 int nRet = -1;
235 foreach (char c in s)
236 {
237 if (y == c)
238 {
239 nRet = n;
240 break;
241 }
242 n++;
243 }
244 return nRet;
245 }
246
247
248 /// <summary>
249 /// Returns index of first instance of sSubString in sString.
250 /// If sSubString not found, returns -1.
251 /// </summary>
252 /// <param name="sString"></param>
253 /// <param name="sSubString"></param>
254 /// <returns></returns>
255 public static int FindSubString(string sString, string sSubString)
256 {
257 int nFound = -1;
258 int nLimit = sString.Length - sSubString.Length + 1;
259 if (nLimit < 0)
260 return -1;
261
262 int nSubLength = sSubString.Length;
263 for (int j = 0; j < nLimit; j++)
264 {
265 if (sString.Substring(j, nSubLength) == sSubString)
266 {
267 nFound = j;
268 break;
269 }
270 }
271 return nFound;
272 }
273
274
275 protected StreamWriter m_LogWriter;
276 bool m_bLogging = false;
277
278 public void StartLog()
279 {
280 try
281 {
282 if (m_bLogging)
283 {
284 throw new Exception("Already logging.");
285 }
286 string sFile = "BMXLog " + DateTime.Now.DayOfYear.ToString() + " " +
287 DateTime.Now.Hour.ToString() + " " + DateTime.Now.Minute.ToString()
288 + " " + DateTime.Now.Second.ToString() + ".log";
289 StartLog(sFile);
290 return;
291 }
292 catch (Exception ex)
293 {
294 throw ex;
295 }
296 }
297
298 public void StartLog(string LogFileName)
299 {
300 try
301 {
302 if (m_bLogging)
303 {
304 throw new Exception("Already logging.");
305 }
306 m_LogWriter = File.AppendText(LogFileName);
307 m_bLogging = true;
308 return;
309 }
310 catch (Exception ex)
311 {
312 throw ex;
313 }
314 }
315
316 public void StopLog()
317 {
318 try
319 {
320 //Close the writer and underlying file.
321 if (m_bLogging == false)
322 {
323 return;
324 }
325 m_LogWriter.Close();
326 m_bLogging = false;
327 return;
328 }
329 catch (Exception ex)
330 {
331 throw ex;
332 }
333 }
334
335 private static void Log(String logMessage, TextWriter w)
336 {
337 w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
338 DateTime.Now.ToLongDateString());
339 w.WriteLine(" :");
340 w.WriteLine(" :{0}", logMessage);
341 w.WriteLine("-------------------------------");
342 // Update the underlying file.
343 w.Flush();
344 }
345
346
347
348 public bool Lock(string Variable)
349 {
350 return Lock(Variable, "", "");
351 }
352
353 public bool Lock(string Variable, string Increment)
354 {
355 return Lock(Variable, Increment, "");
356 }
357
358 /// <summary>
359 /// Lock a local or global M variable
360 /// Returns true if lock is obtained during TimeOut seconds
361 /// Use + to increment, - to decrement lock.
362 /// </summary>
363 /// <param name="Variable"></param>
364 /// <param name="Increment"></param>
365 /// <param name="TimeOut"></param>
366 /// <returns></returns>
367 public bool Lock(string Variable, string Increment, string TimeOut)
368 {
369 try
370 {
371 Variable = Variable.Replace("^", "~");
372 string sParam = Variable + "^" + Increment + "^" + TimeOut;
373 string sRet = TransmitRPC("BMX LOCK", sParam);
374 return (sRet == "1");
375 }
376 catch (Exception ex)
377 {
378
379 string sMsg = ex.Message;
380 return false;
381 }
382 }
383
384 static ReaderWriterLock m_rwl = new ReaderWriterLock();
385
386
387 /// <summary>
388 /// Returns a reference to the internal ReaderWriterLock member.
389 /// </summary>
390 public ReaderWriterLock BMXRWL
391 {
392 get
393 {
394 return m_rwl;
395 }
396 }
397
398 public abstract bool IsConnected { get; }
399
400 public abstract void Close();
401
402 protected string EncodeSendString(String cSendString, String cMulti)
403 {
404 String encoded = null;
405
406 int nLen = cSendString.Length;
407 string sLen = nLen.ToString();
408 sLen = sLen.PadLeft(5, '0');
409 encoded = sLen + cSendString;
410
411 nLen += 15;
412 sLen = nLen.ToString();
413 sLen = sLen.PadLeft(5, '0');
414
415 encoded = "{BMX}" + sLen + encoded;
416 encoded = encoded + cMulti;
417
418 return encoded;
419 }
420
421 protected string DecodeReceiveString(String aString)
422 {
423 return aString;
424 }
425
426 protected String SendReceiveString(String sendString)
427 {
428 return this.SendReceiveString(sendString, "");
429 }
430
431 private String _createContextRpc = "BMX CREATE CONTEXT";
432
433 protected String CreateContextRpc
434 {
435 get { return _createContextRpc; }
436 set { _createContextRpc = value; }
437 }
438
439 protected abstract String SendReceiveString(String sendString, String multi);
440
441 public abstract int ReceiveTimeout { get; set; }
442 public abstract int SendTimeout { get; set; }
443 public abstract Encoding ConnectionEncoding { get; set; }
444
445
446 /// <remarks>
447 /// AppContext is managed an client and server with c/s calls to change
448 /// appContext on the server. There is no use for AppContext on the client
449 /// so recommend integrated AppContext into BMX Protocol so always passing
450 /// it and managing switching it on the server.
451 /// </remarks>
452 public string TransmitRPC(string anRpc, string rpcParameter)
453 {
454 this.AssertConnected();
455
456
457 if (rpcParameter.Length > 32600)
458 {
459 throw new Exception("RPC parameter length exceeds maximum allowable size.");
460 }
461
462 try
463 {
464 string sMult = "";
465 string sSend = ADEBLDMsg(m_cHDR, anRpc, rpcParameter, ref sMult);
466 return this.SendReceiveString(sSend, sMult);
467 }
468 catch (ApplicationException exception)
469 {
470 // The writer lock request timed out.
471 //TODO: Remark: to writer lock for Transmit RPC
472 //SMH: Wrong error message. We do have an exception, but nothing to do with a lock.
473 //Debug.Write("TransmitRPC writer lock request timed out.\n");
474 Debug.Write("Exception: " + exception.Message);
475 throw exception;
476 }
477 catch (Exception problem)
478 {
479 throw problem;
480 }
481 }
482
483
484 public abstract string GetLoginFacility(String aDuz);
485
486
487 #endregion RPX Functions
488
489 protected void AssertConnected()
490 {
491 if (!this.IsConnected)
492 {
493 throw new BMXNetException("BMXNetBroker.TransmitRPC failed because BMXNetBroker is not connected to RPMS.");
494 }
495 }
496
497 private String _job = "";
498
499 public String Job
500 {
501 get { return _job; }
502 set { _job = value; }
503 }
504
505 /// <summary>
506 /// Gets/sets the Kernel Application context
507 /// Throws an exception if unable to set the context.
508 /// </summary>
509 public string AppContext
510 {
511 get
512 {
513 return m_cAppContext;
514 }
515 set
516 {
517 if (m_cAppContext == value)
518 return;
519
520 //Send the changed context to RPMS
521 if ((value != null) && (value != ""))
522 {
523 string encryptedContext = this.EncryptionProvider.Encrypt(value);
524 string sAuthentication = this.TransmitRPC("BMX CREATE CONTEXT", encryptedContext);
525
526 if (BMXNetBroker.FindSubString(sAuthentication, "does not have access to option") > -1)
527 {
528 throw new BMXNetException(sAuthentication);
529 }
530 if (BMXNetBroker.FindSubString(sAuthentication, "is not registered with port") > -1)
531 {
532 throw new BMXNetException(sAuthentication);
533 }
534 m_cAppContext = value;
535 }
536
537 }
538 }
539
540 public string DUZ
541 {
542 get
543 {
544 return m_cDUZ;
545 }
546 set { this.m_cDUZ = value; }
547 }
548
549 private EncryptionKeyProvider _keyProvider = null;
550
551 public EncryptionKeyProvider KeyProvider
552 {
553 get { return _keyProvider; }
554 set { _keyProvider = value; }
555 }
556
557
558 protected string RemoveADEEncryp(string sInput)
559 {
560 //Encrypt a string
561 string strResult = null;
562 string strPercent = null;
563 string strAssoc = null;
564 string strIdix = null;
565 int nPercent = 0;
566 int nAssocix = 0;
567 int nIdix = 0;
568 Debug.Assert(sInput != "");
569 System.Random rRand = new Random(DateTime.Now.Second);
570
571 nPercent = rRand.Next(0, 10000);
572 nPercent += 72439;
573 nAssocix = nPercent % 20;
574 nAssocix++;
575 Debug.Assert(nAssocix < 21);
576 strPercent = nPercent.ToString();
577 strPercent = strPercent.Substring(1, 2);
578 nIdix = Convert.ToInt32(strPercent);
579 nIdix = nIdix % 20;
580 nIdix++;
581 Debug.Assert(nIdix < 21);
582
583 Debug.Assert(strAssoc.Length == 94);
584 Debug.Assert(strIdix.Length == 94);
585 string sEncrypted = "";
586
587 foreach (char c in sInput)
588 {
589 string d = c.ToString();
590 int nFindChar = strIdix.IndexOf(c);
591 if (nFindChar > -1)
592 {
593 d = strAssoc.Substring(nFindChar, 1);
594 }
595 sEncrypted += d;
596 }
597
598 strResult = (char)(nIdix + 31) + sEncrypted + (char)(nAssocix + 31);
599
600 return strResult;
601 }
602
603
604 protected string RemoveLoadKey(int nID)
605 {
606 nID -= 102;
607 Debug.Assert(nID < 20);
608 return this.KeyProvider.Keys[nID];
609 }
610
611
612 internal string RemoveADEDecryp(string sInput)
613 {
614 //Encrypt a string
615 string strAssoc = null;
616 string strIdix = null;
617 int nAssocix;
618 int nIdix;
619 Debug.Assert(sInput != "");
620
621 //get associator string index
622 char cAssocix = sInput[sInput.Length - 1];
623 nAssocix = (int)cAssocix;
624 nAssocix -= 31;
625 Debug.Assert(nAssocix < 21);
626
627 //get identifier string index
628 char cIdix = sInput[0];
629 nIdix = (int)cIdix;
630 nIdix -= 31;
631 Debug.Assert(nIdix < 21);
632
633 //get associator string
634 Debug.Assert(strAssoc.Length == 94);
635 Debug.Assert(strIdix.Length == 94);
636
637 //translated result
638 string sDecrypted = "";
639 sInput = sInput.Substring(1, sInput.Length - 2);
640 foreach (char c in sInput)
641 {
642 string d = c.ToString();
643 int nFindChar = strAssoc.IndexOf(c);
644 if (nFindChar > -1)
645 {
646 d = strIdix.Substring(nFindChar, 1);
647 }
648 sDecrypted += d;
649 }
650
651 return sDecrypted;
652 }
653
654 internal string RemoveBMXEncrypt(string sInput)
655 {
656
657 ASCIIEncoding textConverter = new ASCIIEncoding();
658 RijndaelManaged myRijndael = new RijndaelManaged();
659 byte[] encrypted;
660 byte[] toEncrypt;
661 byte[] key;
662 byte[] IV;
663
664 string sKey = "pouphfoz sfdbqjuvmbwft qizmphfoz";
665 string sIV = "Gichin Funakoshi";
666 key = textConverter.GetBytes(sKey);
667 IV = textConverter.GetBytes(sIV);
668
669 //Get an encryptor.
670 ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, IV);
671
672 //Encrypt the data.
673 MemoryStream msEncrypt = new MemoryStream();
674 CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
675
676 //Convert the input data to a byte array.
677 toEncrypt = textConverter.GetBytes(sInput);
678
679 //Write all data to the crypto stream and flush it.
680 csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
681 csEncrypt.FlushFinalBlock();
682
683 //Get encrypted array of bytes.
684 encrypted = msEncrypt.ToArray();
685
686 //Convert to string to send to RPMS
687 string sEncrypted = "";
688 byte bTmp;
689 string sTmp;
690 for (int j = 0; j < encrypted.Length; j++)
691 {
692 bTmp = encrypted[j];
693 sTmp = bTmp.ToString();
694 sEncrypted += sTmp;
695 if (j < (encrypted.Length - 1))
696 sEncrypted += "~";
697 }
698 return sEncrypted;
699 }
700
701 internal string BMXDecrypt(string sInput)
702 {
703 try
704 {
705 byte[] fromEncrypt;
706 ASCIIEncoding textConverter = new ASCIIEncoding();
707 RijndaelManaged myRijndael = new RijndaelManaged();
708 string sRPMSEncrypted = sInput;
709 string sBar = "~";
710 char[] cBar = sBar.ToCharArray();
711 string[] sArray;
712 sArray = sRPMSEncrypted.Split(cBar);
713 byte[] bRPMSEncrypted = new byte[sArray.GetLength(0)];
714 byte[] key;
715 byte[] IV;
716
717 //Convert the RPMS-stored string to a byte array
718 for (int j = 0; j < sArray.GetLength(0); j++)
719 {
720 bRPMSEncrypted[j] = Byte.Parse(sArray[j]);
721 }
722
723 //Get a decryptor that uses the same key and IV as the encryptor.
724 string sKey = "pouphfoz sfdbqjuvmbwft qizmphfoz";
725 string sIV = "Gichin Funakoshi";
726 key = textConverter.GetBytes(sKey);
727 IV = textConverter.GetBytes(sIV);
728 ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, IV);
729
730 MemoryStream msDecrypt = new MemoryStream(bRPMSEncrypted);
731 CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
732
733 fromEncrypt = new byte[bRPMSEncrypted.Length - 2];
734
735 //Read the data out of the crypto stream.
736 csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
737
738 int nZ = FindChar(fromEncrypt, (char)0);
739
740 //Convert the byte array back into a string.
741 string sResult;
742 if (nZ < 0)
743 {
744 sResult = textConverter.GetString(fromEncrypt);
745 }
746 else
747 {
748 sResult = textConverter.GetString(fromEncrypt, 0, nZ);
749 }
750 return sResult;
751 }
752 catch (Exception ex)
753 {
754 Debug.Write(ex.Message);
755 return "";
756 }
757 }
758
759
760 private String _userName = null;
761
762 public String UserName
763 {
764 get {
765 if (_userName == null)
766 {
767 this._userName = this.TransmitRPC("BMX USER", this.DUZ);
768 }
769
770 return _userName; }
771 set { _userName = value; }
772 }
773 }
774}
Note: See TracBrowser for help on using the repository browser.