source: BMXNET_RPMS_dotNET_UTILITIES-BMX/trunk/cs/bmx_0200scr/BMXNetLib.cs@ 815

Last change on this file since 815 was 815, checked in by Sam Habiel, 14 years ago

Initial commit of C# Source Code. Now to try to get it to compile.

File size: 31.3 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;
12
13namespace IndianHealthService.BMXNet
14{
15 /// <summary>
16 /// BMXNetLib implements low-level socket connectivity to RPMS databases.
17 /// The VA RPC Broker must be running on the RPMS server in order for
18 /// BMXNetLib to connect.
19 /// </summary>
20 [DnsPermission(SecurityAction.Assert, Unrestricted = true)]
21 public class BMXNetLib
22 {
23 public BMXNetLib()
24 {
25 m_sWKID = "BMX";
26 m_sWINH = "";
27 m_sPRCH = "";
28 m_sWISH = "";
29 m_cHDR = ADEBHDR(m_sWKID,m_sWINH,m_sPRCH,m_sWISH);
30
31 }
32
33 #region Piece Functions
34
35 /// <summary>
36 /// Corresponds to M's $L(STRING,DELIMITER)
37 /// </summary>
38 /// <param name="sInput"></param>
39 /// <param name="sDelim"></param>
40 /// <returns></returns>
41 public static int PieceLength(string sInput, string sDelim)
42 {
43 char[] cDelim = sDelim.ToCharArray();
44 string [] cSplit = sInput.Split(cDelim);
45 return cSplit.GetLength(0);
46 }
47
48 /// <summary>
49 /// Corresponds to M's $$Piece function
50 /// </summary>
51 /// <param name="sInput"></param>
52 /// <param name="sDelim"></param>
53 /// <param name="nNumber"></param>
54 /// <returns></returns>
55 public static string Piece(string sInput, string sDelim, int nNumber)
56 {
57 try
58 {
59 char[] cDelim = sDelim.ToCharArray();
60 string [] cSplit = sInput.Split(cDelim);
61 int nLength = cSplit.GetLength(0);
62 if ((nLength < nNumber)||(nNumber < 1))
63 return "";
64 return cSplit[nNumber-1];
65 }
66 catch (Exception bmxEx)
67 {
68 string sMessage = bmxEx.Message + bmxEx.StackTrace;
69 throw new BMXNetException(sMessage);
70 }
71
72 }
73
74 public static string Piece(string sInput, string sDelim, int nNumber, int nEnd)
75 {
76 try
77 {
78 if (nNumber < 0)
79 nNumber = 1;
80
81 if (nEnd < nNumber)
82 return "";
83
84 if (nEnd == nNumber)
85 return Piece(sInput, sDelim, nNumber);
86
87 char[] cDelim = sDelim.ToCharArray();
88 string [] cSplit = sInput.Split(cDelim);
89 int nLength = cSplit.GetLength(0);
90 if ((nLength < nNumber)||(nNumber < 1))
91 return "";
92
93 //nNumber = 1-based index of the starting element to return
94 //nLength = count of elements
95 //nEnd = 1-based index of last element to return
96 //nCount = number of elements past nNumber to return
97
98 //convert nNumber to 0-based index:
99 nNumber--;
100
101 //convert nEnd to 0-based index;
102 nEnd--;
103
104 //Calculate nCount;
105 int nCount = nEnd - nNumber + 1;
106
107 //Adjust nCount for number of elements
108 if (nCount + nNumber >= nLength)
109 {
110 nCount = nLength - nNumber;
111 }
112
113 string sRet = string.Join(sDelim, cSplit, nNumber, nCount );
114 return sRet;
115 }
116 catch (Exception bmxEx)
117 {
118 string sMessage = bmxEx.Message + bmxEx.StackTrace;
119 throw new BMXNetException(sMessage);
120 }
121 }
122
123 #endregion Piece Functions
124
125 #region RPX Fields
126
127 private string m_sWKID;
128 private string m_sWISH;
129 private string m_sPRCH;
130 private string m_sWINH;
131 private string m_cHDR;
132 private string m_cAppContext;
133 private bool m_bConnected;
134 private int m_nMServerPort;
135 private string m_cServerAddress;
136 private string m_cDUZ;
137 private string m_cLoginFacility;
138 private TcpClient m_pCommSocket;
139 private string m_sNameSpace = "";
140 private int m_nReceiveTimeout = 30000;
141
142 #endregion RPX Fields
143
144 #region Encryption Keys
145 private string[] m_sKey = new string[]
146 {
147 @"MUST PROVIDE A VALID KEY",
148 @"MUST PROVIDE A VALID KEY",
149 @"MUST PROVIDE A VALID KEY",
150 @"MUST PROVIDE A VALID KEY",
151 @"MUST PROVIDE A VALID KEY",
152 @"MUST PROVIDE A VALID KEY",
153 @"MUST PROVIDE A VALID KEY",
154 @"MUST PROVIDE A VALID KEY",
155 @"MUST PROVIDE A VALID KEY",
156 @"MUST PROVIDE A VALID KEY",
157 @"MUST PROVIDE A VALID KEY",
158 @"MUST PROVIDE A VALID KEY",
159 @"MUST PROVIDE A VALID KEY",
160 @"MUST PROVIDE A VALID KEY",
161 @"MUST PROVIDE A VALID KEY",
162 @"MUST PROVIDE A VALID KEY",
163 @"MUST PROVIDE A VALID KEY",
164 @"MUST PROVIDE A VALID KEY",
165 @"MUST PROVIDE A VALID KEY",
166 @"MUST PROVIDE A VALID KEY",
167 };
168 #endregion Encryption Keys
169
170 #region RPX Functions
171
172 /// <summary>
173 /// Given strInput = "13" builds "013" if nLength = 3. Default for nLength is 3.
174 /// </summary>
175 /// <param name="strInput"></param>
176 /// <returns></returns>
177 private string ADEBLDPadString(string strInput)
178 {
179 return ADEBLDPadString(strInput, 3);
180 }
181
182 /// <summary>
183 /// Given strInput = "13" builds "013" if nLength = 3 Default for nLength is 3.
184 /// </summary>
185 /// <param name="strInput"></param>
186 /// <param name="nLength">Default = 3</param>
187 /// <returns></returns>
188 private string ADEBLDPadString(string strInput, int nLength /*=3*/)
189 {
190 return strInput.PadLeft(nLength, '0');
191 }
192
193 /// <summary>
194 /// Concatenates zero-padded length of sInput to sInput
195 /// Given "Hello" returns "004Hello"
196 /// If nSize = 5, returns "00004Hello"
197 /// Default for nSize is 3.
198 /// </summary>
199 /// <param name="sInput"></param>
200 /// <returns></returns>
201 private string ADEBLDB(string sInput)
202 {
203 return ADEBLDB(sInput, 3);
204 }
205
206 /// <summary>
207 /// Concatenates zero-padded length of sInput to sInput
208 /// Given "Hello" returns "004Hello"
209 /// If nSize = 5, returns "00004Hello"
210 /// Default for nSize is 3.
211 /// </summary>
212 /// <param name="sInput"></param>
213 /// <param name="nSize"></param>
214 /// <returns></returns>
215 private string ADEBLDB(string sInput, int nSize /*=3*/)
216 {
217 int nLen = sInput.Length;
218 string sLen = this.ADEBLDPadString(nLen.ToString(), nSize);
219 return sLen + sInput;
220 }
221
222 /// <summary>
223 /// Build protocol header
224 /// </summary>
225 /// <param name="sWKID"></param>
226 /// <param name="sWINH"></param>
227 /// <param name="sPRCH"></param>
228 /// <param name="sWISH"></param>
229 /// <returns></returns>
230 private string ADEBHDR(string sWKID, string sWINH, string sPRCH, string sWISH)
231 {
232 string strResult;
233 strResult = sWKID+";"+sWINH+";"+sPRCH+";"+sWISH+";";
234 strResult = ADEBLDB(strResult);
235 return strResult;
236 }
237 private string ADEBLDMsg(string cHDR, string cRPC, string cParam)
238 {
239 string sMult = "";
240 return ADEBLDMsg(cHDR, cRPC, cParam, ref sMult);
241 }
242 private string ADEBLDMsg(string cHDR, string cRPC, string cParam, ref string cMult)
243 {
244 //Builds RPC message
245 //Automatically splits parameters longer than 200 into subscripted array
246 string cMSG;
247 string sBuild = "";
248 string sPiece = "";
249 string sBig = "";
250 int l;
251 int nLength;
252
253 if (cParam == "")
254 {
255 cMSG = "0" + cRPC ;
256 }
257 else
258 {
259 l = PieceLength(cParam, "^");
260 for (int j=1; j <= l; j++)
261 {
262 sPiece = Piece(cParam, "^", j);
263 if ((j == l) && (sPiece.Length > 200))
264 {
265 //Split up long param into array pieces
266 sBig = sPiece;
267 sPiece = ".x";
268 nLength = sPiece.Length + 1;
269 sPiece = ADEBLDPadString(nLength.ToString()) + "2" + sPiece;
270 sBuild = sBuild + sPiece;
271 int nSubscript = 1;
272 string sSubscript ="";
273 int nSubLen = 0;
274 string sSubLen ="";
275 int nBigLen = sBig.Length;
276 string sHunk ="";
277 int nHunkLen = 0;
278 string sHunkLen ="";
279 int nChunk = 0;
280 do
281 {
282 nChunk = (sBig.Length > 200)?200:sBig.Length ;
283 sHunk = sBig.Substring(0, nChunk);
284 sBig = sBig.Remove(0, nChunk);
285 nBigLen = sBig.Length;
286 sSubscript = nSubscript.ToString();
287 nSubLen = sSubscript.Length;
288 sSubLen = nSubLen.ToString();
289 sSubLen = ADEBLDPadString(sSubLen);
290 nHunkLen = sHunk.Length;
291 sHunkLen = nHunkLen.ToString();
292 sHunkLen = ADEBLDPadString(sHunkLen);
293 cMult = cMult + sSubLen + sSubscript + sHunkLen + sHunk;
294 nSubscript++;
295 } while (nBigLen > 0);
296 }
297 else
298 {
299 nLength = sPiece.Length +1;
300 sPiece = ADEBLDPadString(nLength.ToString()) + "0" + sPiece;
301 sBuild = sBuild + sPiece;
302 }
303 }
304 nLength = sBuild.Length;
305 string sTotLen = ADEBLDPadString(nLength.ToString(),5);
306 if (cMult.Length > 0)
307 {
308 cMSG = "1"+ cRPC + "^" +sTotLen + sBuild;
309 }
310 else
311 {
312 cMSG = "0"+ cRPC + "^" +sTotLen + sBuild;
313 }
314 }
315 cMSG = ADEBLDB(cMSG, 5);
316 cMSG = cHDR + cMSG;
317 return cMSG;
318 }
319
320 internal string ADEEncryp(string sInput)
321 {
322 //Encrypt a string
323 string strResult;
324 string strPercent;
325 string strAssoc;
326 string strIdix;
327 int nPercent;
328 int nAssocix;
329 int nIdix;
330 Debug.Assert(sInput != "");
331 System.Random rRand = new Random(DateTime.Now.Second);
332
333 nPercent = rRand.Next(0,10000);
334 nPercent += 72439;
335 nAssocix = nPercent % 20;
336 nAssocix++;
337 Debug.Assert(nAssocix < 21);
338 strPercent = nPercent.ToString();
339 strPercent = strPercent.Substring(1,2);
340 nIdix = Convert.ToInt32(strPercent);
341 nIdix = nIdix % 20;
342 nIdix++;
343 Debug.Assert(nIdix < 21);
344
345 const int nEncryptBase = 101;
346 strAssoc = LoadKey(nEncryptBase + nAssocix);
347 Debug.Assert(strAssoc.Length == 94);
348 strIdix = LoadKey(nEncryptBase + nIdix);
349 Debug.Assert(strIdix.Length == 94);
350 string sEncrypted = "";
351
352 foreach (char c in sInput)
353 {
354 string d = c.ToString();
355 int nFindChar = strIdix.IndexOf(c);
356 if (nFindChar > -1)
357 {
358 d = strAssoc.Substring(nFindChar,1);
359 }
360 sEncrypted += d;
361 }
362
363 strResult = (char) (nIdix + 31) + sEncrypted + (char) (nAssocix + 31);
364
365 return strResult;
366 }
367
368 internal string ADEDecryp(string sInput)
369 {
370 //Encrypt a string
371 string strAssoc;
372 string strIdix;
373 int nAssocix;
374 int nIdix;
375 Debug.Assert(sInput != "");
376
377 //get associator string index
378 char cAssocix = sInput[sInput.Length-1];
379 nAssocix =(int) cAssocix;
380 nAssocix -= 31;
381 Debug.Assert(nAssocix < 21);
382
383 //get identifier string index
384 char cIdix = sInput[0];
385 nIdix = (int) cIdix;
386 nIdix -= 31;
387 Debug.Assert(nIdix < 21);
388
389 //get associator string
390 const int nEncryptBase = 101;
391 strAssoc = LoadKey(nEncryptBase + nAssocix);
392 Debug.Assert(strAssoc.Length == 94);
393
394 //get identifier string
395 strIdix = LoadKey(nEncryptBase + nIdix);
396 Debug.Assert(strIdix.Length == 94);
397
398 //translated result
399 string sDecrypted = "";
400 sInput = sInput.Substring(1, sInput.Length - 2);
401 foreach (char c in sInput)
402 {
403 string d = c.ToString();
404 int nFindChar = strAssoc.IndexOf(c);
405 if (nFindChar > -1)
406 {
407 d = strIdix.Substring(nFindChar,1);
408 }
409 sDecrypted += d;
410 }
411
412 return sDecrypted;
413 }
414
415 internal string BMXEncrypt(string sInput)
416 {
417
418 ASCIIEncoding textConverter = new ASCIIEncoding();
419 RijndaelManaged myRijndael = new RijndaelManaged();
420 byte[] encrypted;
421 byte[] toEncrypt;
422 byte[] key;
423 byte[] IV;
424
425 string sKey="pouphfoz sfdbqjuvmbwft qizmphfoz";
426 string sIV = "Gichin Funakoshi";
427 key = textConverter.GetBytes(sKey);
428 IV = textConverter.GetBytes(sIV);
429
430 //Get an encryptor.
431 ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, IV);
432
433 //Encrypt the data.
434 MemoryStream msEncrypt = new MemoryStream();
435 CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
436
437 //Convert the input data to a byte array.
438 toEncrypt = textConverter.GetBytes(sInput);
439
440 //Write all data to the crypto stream and flush it.
441 csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
442 csEncrypt.FlushFinalBlock();
443
444 //Get encrypted array of bytes.
445 encrypted = msEncrypt.ToArray();
446
447 //Convert to string to send to RPMS
448 string sEncrypted = "" ;
449 byte bTmp;
450 string sTmp;
451 for (int j =0; j < encrypted.Length; j++)
452 {
453 bTmp = encrypted[j];
454 sTmp = bTmp.ToString();
455 sEncrypted += sTmp;
456 if (j < (encrypted.Length -1))
457 sEncrypted += "~";
458 }
459 return sEncrypted;
460 }
461
462 internal string BMXDecrypt(string sInput)
463 {
464 try
465 {
466 byte[] fromEncrypt;
467 ASCIIEncoding textConverter = new ASCIIEncoding();
468 RijndaelManaged myRijndael = new RijndaelManaged();
469 string sRPMSEncrypted = sInput;
470 string sBar = "~";
471 char[] cBar = sBar.ToCharArray();
472 string[] sArray;
473 sArray = sRPMSEncrypted.Split(cBar);
474 byte[] bRPMSEncrypted = new byte[sArray.GetLength(0)];
475 byte[] key;
476 byte[] IV;
477
478 //Convert the RPMS-stored string to a byte array
479 for (int j = 0; j < sArray.GetLength(0); j++)
480 {
481 bRPMSEncrypted[j] = Byte.Parse(sArray[j]);
482 }
483
484 //Get a decryptor that uses the same key and IV as the encryptor.
485 string sKey="pouphfoz sfdbqjuvmbwft qizmphfoz";
486 string sIV = "Gichin Funakoshi";
487 key = textConverter.GetBytes(sKey);
488 IV = textConverter.GetBytes(sIV);
489 ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, IV);
490
491 MemoryStream msDecrypt = new MemoryStream(bRPMSEncrypted);
492 CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
493
494 fromEncrypt = new byte[bRPMSEncrypted.Length - 2];
495
496 //Read the data out of the crypto stream.
497 csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
498
499 int nZ = FindChar(fromEncrypt, (char) 0);
500
501 //Convert the byte array back into a string.
502 string sResult;
503 if (nZ < 0)
504 {
505 sResult = textConverter.GetString(fromEncrypt);
506 }
507 else
508 {
509 sResult = textConverter.GetString(fromEncrypt, 0, nZ);
510 }
511 return sResult;
512 }
513 catch (Exception ex)
514 {
515 Debug.Write(ex.Message);
516 return "";
517 }
518 }
519
520 public static int FindChar(byte[] c, char y)
521 {
522 int n = 0;
523 int nRet = -1;
524 for (n=0; n < c.Length; n++)
525 {
526 if (y == (char) c[n])
527 {
528 nRet = n;
529 break;
530 }
531 }
532
533 return nRet;
534 }
535
536 public static int FindChar(string s, char y)
537 {
538 int n = 0;
539 int nRet = -1;
540 foreach (char c in s)
541 {
542 if (y == c)
543 {
544 nRet = n;
545 break;
546 }
547 n++;
548 }
549 return nRet;
550 }
551
552
553 /// <summary>
554 /// Returns index of first instance of sSubString in sString.
555 /// If sSubString not found, returns -1.
556 /// </summary>
557 /// <param name="sString"></param>
558 /// <param name="sSubString"></param>
559 /// <returns></returns>
560 public static int FindSubString(string sString, string sSubString)
561 {
562 int nFound = -1;
563 int nLimit = sString.Length - sSubString.Length + 1;
564 if (nLimit < 0)
565 return -1;
566
567 int nSubLength = sSubString.Length;
568 for (int j=0; j < nLimit; j++)
569 {
570 if (sString.Substring(j, nSubLength) == sSubString)
571 {
572 nFound = j;
573 break;
574 }
575 }
576 return nFound;
577 }
578
579 private string LoadKey(int nID)
580 {
581 nID -= 102;
582 Debug.Assert( nID < 20);
583 return m_sKey[nID];
584 }
585
586 private void OpenConnectionCommon(string sServerAddress)
587 {
588 try
589 {
590 m_cServerAddress = sServerAddress;
591
592 //Connect with the server
593 TcpClient connector = new TcpClient();
594
595 try
596 {
597 connector = new TcpClient();
598 connector.Connect(m_cServerAddress, m_nMServerPort);
599 }
600 catch (SocketException exSocket)
601 {
602 string s = exSocket.Message + exSocket.StackTrace;
603 throw new BMXNetException(s);
604 }
605
606 //Prepare & send the connect message
607 string cSend = "TCPconnect^" + m_sNameSpace + "^^";
608 int nLen = cSend.Length;
609 string sLen = nLen.ToString();
610 sLen = sLen.PadLeft(5, '0');
611 cSend = "{BMX}" + sLen + cSend;
612
613 NetworkStream ns = connector.GetStream();
614 byte[] sendBytes = Encoding.ASCII.GetBytes(cSend);
615 ns.Write(sendBytes,0,sendBytes.Length);
616
617 m_pCommSocket = connector;
618 return;
619
620 }
621 catch (BMXNetException bmxEx)
622 {
623 throw bmxEx;
624 }
625 catch (Exception ex)
626 {
627 string s = ex.Message + ex.StackTrace;
628 throw new BMXNetException(s);
629 }
630 }//End OpenConnectionCommon
631
632 [SocketPermissionAttribute(SecurityAction.Assert,
633 Access="Connect",
634 Host="All",
635 Port="All",
636 Transport="All")]
637 public bool OpenConnection(string sServerAddress, WindowsIdentity winIdentity)
638 {
639 try
640 {
641 OpenConnectionCommon(sServerAddress);
642 bool bSecurity;
643 try
644 {
645 bSecurity = SendSecurityRequest(winIdentity);
646
647 }
648 catch (Exception ex)
649 {
650 //Close the connection
651 SendString(m_pCommSocket, "#BYE#");
652 m_pCommSocket.Close();
653 m_bConnected = false;
654 m_cServerAddress = "";
655 throw ex;
656 }
657
658 m_bConnected = bSecurity;
659 return m_bConnected;
660 }
661 catch (BMXNetException bmxEx)
662 {
663 throw bmxEx;
664 }
665 catch (Exception ex)
666 {
667 string s = ex.Message + ex.StackTrace;
668 throw new BMXNetException(s);
669 }
670 }
671
672 StreamWriter m_LogWriter;
673 bool m_bLogging = false;
674
675 public void StartLog()
676 {
677 try
678 {
679 if (m_bLogging)
680 {
681 throw new Exception("Already logging.");
682 }
683 string sFile = "BMXLog " + DateTime.Now.DayOfYear.ToString() + " " +
684 DateTime.Now.Hour.ToString() + " " + DateTime.Now.Minute.ToString()
685 + " " + DateTime.Now.Second.ToString() + ".log";
686 StartLog(sFile);
687 return;
688 }
689 catch (Exception ex)
690 {
691 throw ex;
692 }
693 }
694
695 public void StartLog(string LogFileName)
696 {
697 try
698 {
699 if (m_bLogging)
700 {
701 throw new Exception("Already logging.");
702 }
703 m_LogWriter = File.AppendText(LogFileName);
704 m_bLogging = true;
705 return;
706 }
707 catch (Exception ex)
708 {
709 throw ex;
710 }
711 }
712
713 public void StopLog()
714 {
715 try
716 {
717 //Close the writer and underlying file.
718 if (m_bLogging == false)
719 {
720 return;
721 }
722 m_LogWriter.Close();
723 m_bLogging = false;
724 return;
725 }
726 catch (Exception ex)
727 {
728 throw ex;
729 }
730 }
731
732 private static void Log(String logMessage, TextWriter w)
733 {
734 w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
735 DateTime.Now.ToLongDateString());
736 w.WriteLine(" :");
737 w.WriteLine(" :{0}", logMessage);
738 w.WriteLine("-------------------------------");
739 // Update the underlying file.
740 w.Flush();
741 }
742
743 [SocketPermissionAttribute(SecurityAction.Assert,
744 Access="Connect",
745 Host="All",
746 Port="All",
747 Transport="All")]
748 public bool OpenConnection(string sServerAddress, string sAccess, string sVerify)
749 {
750 try
751 {
752 this.OpenConnectionCommon(sServerAddress);
753
754 try
755 {
756 bool bSecurity = SendSecurityRequest(sAccess, sVerify);
757 }
758 catch (Exception ex)
759 {
760 //Close the connection
761 SendString(m_pCommSocket, "#BYE#");
762 m_pCommSocket.Close();
763 m_bConnected = false;
764 m_cServerAddress = "";
765 throw ex;
766 }
767
768 m_bConnected = true;
769 return m_bConnected;
770 }
771 catch (BMXNetException bmxEx)
772 {
773 throw bmxEx;
774 }
775 catch (Exception ex)
776 {
777 string s = ex.Message + ex.StackTrace;
778 throw new BMXNetException(s);
779 }
780 }
781
782 private void SendString(TcpClient tcpClient, string cSendString)
783 {
784 string sMult = "";
785 SendString(tcpClient, cSendString, sMult);
786 }
787
788 private void SendString(TcpClient tcpClient, string cSendString, string cMult)
789 {
790 int nLen = cSendString.Length;
791 string sLen = nLen.ToString();
792 sLen = sLen.PadLeft(5, '0');
793 cSendString = sLen + cSendString;
794
795 nLen += 15;
796 sLen = nLen.ToString();
797 sLen = sLen.PadLeft(5, '0');
798
799 cSendString = "{BMX}" + sLen + cSendString;
800 cSendString = cSendString + cMult;
801
802 NetworkStream ns = tcpClient.GetStream();
803 byte[] sendBytes = Encoding.ASCII.GetBytes(cSendString);
804 ns.Write(sendBytes,0,sendBytes.Length);
805 if (this.m_bLogging == true)
806 {
807 Log("Sent: " + cSendString, this.m_LogWriter);
808 }
809 return;
810 }
811
812 private string ReceiveString(TcpClient tcpClient)
813 {
814 NetworkStream ns = tcpClient.GetStream();
815
816 int nTimeOut = this.m_nReceiveTimeout;
817 int nCnt = 0;
818 int nTimeElapsed = 0;
819 while (ns.DataAvailable == false)
820 {
821 if (nCnt > 9999)
822 break;
823 if (nTimeElapsed > nTimeOut)
824 break;
825 nCnt++;
826 nTimeElapsed += 50;
827 Thread.Sleep(50);
828 }
829
830 Debug.Assert(ns.DataAvailable == true);
831 if (ns.DataAvailable == false)
832 {
833 this.CloseConnection();
834 throw new Exception("BMXNetLib.ReceiveString timeout. Connection Closed.");
835 //return "";
836 }
837
838 byte[] bReadBuffer = new byte[1024];
839 string sReadBuffer = "";
840 StringBuilder sbAll = new StringBuilder("", 1024);
841 int numberOfBytesRead = 0;
842
843 // Incoming message may be larger than the buffer size.
844
845 bool bFinished = false;
846 int nFind = -1;
847 bool bStarted = false;
848 int lpBuf = 0;
849 string sError = "";
850 string sAppError = "";
851 do
852 {
853
854 numberOfBytesRead = ns.Read(bReadBuffer, 0, bReadBuffer.Length);
855 if ((numberOfBytesRead == 1)&&(bStarted == false))
856 {
857 Thread.Sleep(15);
858 numberOfBytesRead += ns.Read(bReadBuffer,1, bReadBuffer.Length-1);
859 //Debug.Write("ReceiveString waiting for data...\n");
860 }
861 if (bStarted == false)
862 {
863 //Process error info at beginning of returned string
864 int nErrLen = bReadBuffer[0];
865 int nAppLen = bReadBuffer[bReadBuffer[0]+1];
866 if ((bReadBuffer[2] == 0)&&(bReadBuffer[3] == 0))
867 { //special case: M error trap invoked in SND^XWBTCPC
868 lpBuf += 2;
869 }
870 sError = Encoding.ASCII.GetString(bReadBuffer, lpBuf + 1, nErrLen);
871 if (sError != "")
872 {
873 throw new BMXNetException(sError);
874 }
875 sAppError = Encoding.ASCII.GetString(bReadBuffer, lpBuf+1+nErrLen+1, nAppLen);
876 lpBuf += (nErrLen + nAppLen + 2);
877 numberOfBytesRead -= (nErrLen + nAppLen + 2);
878 bStarted = true;
879 }
880
881 nFind = FindChar(bReadBuffer, (char) 4);
882 if (nFind > -1)
883 bFinished = true;
884 Debug.Assert(numberOfBytesRead > -1);
885 sReadBuffer = Encoding.ASCII.GetString(bReadBuffer, lpBuf, numberOfBytesRead);
886 lpBuf = 0;
887 if (nFind > -1)
888 {
889 sbAll.Append(sReadBuffer, 0, numberOfBytesRead -1);
890 }
891 else
892 {
893 sbAll.Append(sReadBuffer);
894 }
895 }
896 while(bFinished == false);
897 if (this.m_bLogging == true)
898 {
899 Log("Received: " + sbAll.ToString(), this.m_LogWriter);
900 }
901 return sbAll.ToString();
902
903 }
904 private bool SendSecurityRequest(WindowsIdentity winIdentity)
905 {
906 string strReceive = "";
907 string cMSG;
908 string sTest;
909
910 //Build AV Call
911 cMSG = ADEBLDMsg(m_cHDR, "BMX AV CODE", winIdentity.Name);
912 SendString(m_pCommSocket, cMSG);
913
914 strReceive = ReceiveString(m_pCommSocket);
915 sTest = strReceive.Substring(0,3);
916
917
918 char[] cDelim = {(char) 13,(char) 10,(char) 0};
919 string sDelim = new string(cDelim);
920 int nPiece = 1;
921 m_cDUZ = Piece(strReceive, sDelim , nPiece);
922 if ((m_cDUZ == "0")||(m_cDUZ == ""))
923 {
924 nPiece = 7;
925 string sReason = Piece(strReceive, sDelim, nPiece);
926 throw new Exception(sReason);
927 }
928
929 return true;
930 }
931
932 private bool SendSecurityRequest(string sAccess, string sVerify)
933 {
934 string strReceive = "";
935 string cMSG;
936 sAccess = sAccess.ToUpper();
937 sVerify = sVerify.ToUpper();
938
939 //Build AV Call
940 string strAV = sAccess + ";" + sVerify;
941 strAV = ADEEncryp(strAV);
942 cMSG = ADEBLDMsg(m_cHDR, "XUS AV CODE", strAV);
943 SendString(m_pCommSocket, cMSG);
944
945 strReceive = ReceiveString(m_pCommSocket);
946
947 char[] cDelim = {(char) 13,(char) 10,(char) 0};
948 string sDelim = new string(cDelim);
949 int nPiece = 1;
950 m_cDUZ = Piece(strReceive, sDelim , nPiece);
951 if ((m_cDUZ == "0")||(m_cDUZ == ""))
952 {
953 nPiece = 7;
954 string sReason = Piece(strReceive, sDelim, nPiece);
955 throw new Exception(sReason);
956 }
957
958 return true;
959 }
960
961 public void CloseConnection()
962 {
963 if (!m_bConnected)
964 {
965 return;
966 }
967 SendString(m_pCommSocket, "#BYE#");
968 m_pCommSocket.Close();
969 m_bConnected = false;
970 m_cServerAddress = "";
971 // m_cDUZ2 = "";
972 m_cDUZ = "";
973 }
974
975 public bool Lock(string Variable)
976 {
977 return Lock(Variable, "", "");
978 }
979
980 public bool Lock(string Variable, string Increment)
981 {
982 return Lock(Variable, Increment, "");
983 }
984
985 /// <summary>
986 /// Lock a local or global M variable
987 /// Returns true if lock is obtained during TimeOut seconds
988 /// Use + to increment, - to decrement lock.
989 /// </summary>
990 /// <param name="Variable"></param>
991 /// <param name="Increment"></param>
992 /// <param name="TimeOut"></param>
993 /// <returns></returns>
994 public bool Lock(string Variable, string Increment, string TimeOut)
995 {
996 try
997 {
998 string sContext = this.AppContext;
999 this.AppContext = "BMXRPC";
1000 Variable = Variable.Replace("^","~");
1001 string sRet = "0";
1002 bool bRet = false;
1003 string sParam = Variable + "^" + Increment + "^" + TimeOut;
1004 sRet = TransmitRPC("BMX LOCK", sParam);
1005 bRet = (sRet == "1")?true:false;
1006 this.AppContext = sContext;
1007 return bRet;
1008 }
1009 catch (Exception ex)
1010 {
1011 string sMsg = ex.Message;
1012 return false;
1013 }
1014 }
1015
1016 static ReaderWriterLock m_rwl = new ReaderWriterLock();
1017 private int m_nRWLTimeout = 30000; //30-second default timeout
1018
1019 /// <summary>
1020 /// Returns a reference to the internal ReaderWriterLock member.
1021 /// </summary>
1022 public ReaderWriterLock BMXRWL
1023 {
1024 get
1025 {
1026 return m_rwl;
1027 }
1028 }
1029
1030 /// <summary>
1031 /// Sets and returns the timeout in milliseconds for locking the transmit port.
1032 /// If the transmit port is unavailable an ApplicationException will be thrown.
1033 /// </summary>
1034 public int RWLTimeout
1035 {
1036 get
1037 {
1038 return m_nRWLTimeout;
1039 }
1040 set
1041 {
1042 m_nRWLTimeout = value;
1043 }
1044 }
1045
1046 public string TransmitRPC(string sRPC, string sParam, int nLockTimeOut)
1047 {
1048 try
1049 {
1050 try
1051 {
1052 if (m_bConnected == false)
1053 {
1054 throw new BMXNetException("BMXNetLib.TransmitRPC failed because BMXNetLib is not connected to RPMS.");
1055 }
1056 Debug.Assert(m_cDUZ != "");
1057 Debug.Assert(m_pCommSocket != null);
1058
1059 string sOldAppContext = "";
1060 if (sRPC.StartsWith("BMX")&&(this.m_cAppContext != "BMXRPC"))
1061 {
1062 sOldAppContext = this.m_cAppContext;
1063 this.AppContext = "BMXRPC";
1064 }
1065 string sMult = "";
1066 string sSend = ADEBLDMsg(m_cHDR, sRPC, sParam, ref sMult);
1067 SendString(m_pCommSocket, sSend, sMult);
1068 // Debug.Write("TransmitRPC Sent: " + sSend + "\n");
1069 string strResult = ReceiveString(m_pCommSocket);
1070 // Debug.Write("TransmitRPC Received: " + strResult + "\n");
1071
1072 if (sOldAppContext != "")
1073 {
1074 this.AppContext = sOldAppContext;
1075 }
1076 return strResult;
1077 }
1078 catch (Exception ex)
1079 {
1080 if (ex.Message == "Unable to write data to the transport connection.")
1081 {
1082 m_bConnected = false;
1083 }
1084 throw ex;
1085 }
1086 finally
1087 {
1088 }
1089 }
1090 catch (ApplicationException aex)
1091 {
1092 // The writer lock request timed out.
1093 Debug.Write("TransmitRPC writer lock request timed out.\n");
1094 throw aex;
1095 }
1096 catch (Exception OuterEx)
1097 {
1098 throw OuterEx;
1099 }
1100 }
1101
1102 public string TransmitRPC(string sRPC, string sParam)
1103 {
1104 try
1105 {
1106 return TransmitRPC(sRPC, sParam, m_nRWLTimeout);
1107 }
1108 catch (ApplicationException aex)
1109 {
1110 throw aex;
1111 }
1112 catch (Exception ex)
1113 {
1114 throw ex;
1115 }
1116 }
1117
1118 public string GetLoginFacility()
1119 {
1120 try
1121 {
1122 if (m_bConnected == false)
1123 {
1124 throw new BMXNetException("BMXNetLib is not connected to RPMS");
1125 }
1126
1127 if (m_cLoginFacility != "")
1128 {
1129 return m_cLoginFacility;
1130 }
1131
1132 Debug.Assert(m_pCommSocket != null);
1133 Debug.Assert(m_cDUZ != "");
1134 SendString(m_pCommSocket, ADEBLDMsg(m_cHDR, "BMXGetFac", m_cDUZ));
1135 string sFac = ReceiveString(m_pCommSocket);
1136 m_cLoginFacility = sFac;
1137 return sFac;
1138 }
1139 catch (BMXNetException bmxEx)
1140 {
1141 string sMessage = bmxEx.Message + bmxEx.StackTrace;
1142 throw new BMXNetException(sMessage);
1143 }
1144 catch (Exception ex)
1145 {
1146 throw ex;
1147 }
1148 }
1149
1150 #endregion RPX Functions
1151
1152 #region RPX Properties
1153
1154 /// <summary>
1155 /// Set and retrieve the timeout, in milliseconds, to receive a response from the RPMS server.
1156 /// If the retrieve time exceeds the timeout, an exception will be thrown and the connection will be closed.
1157 /// The default is 30 seconds.
1158 /// </summary>
1159 public int ReceiveTimeout
1160 {
1161 get { return m_nReceiveTimeout; }
1162 set { m_nReceiveTimeout = value; }
1163 }
1164
1165 public string WKID
1166 {
1167 get
1168 {
1169 return m_sWKID;
1170 }
1171 set
1172 {
1173 m_sWKID = value;
1174 }
1175 }
1176
1177 public string PRCH
1178 {
1179 get
1180 {
1181 return m_sPRCH;
1182 }
1183 set
1184 {
1185 m_sPRCH = value;
1186 }
1187 }
1188
1189 public string WINH
1190 {
1191 get
1192 {
1193 return m_sWINH;
1194 }
1195 set
1196 {
1197 m_sWINH = value;
1198 }
1199 }
1200
1201 public string WISH
1202 {
1203 get
1204 {
1205 return m_sWISH;
1206 }
1207 set
1208 {
1209 m_sWISH = value;
1210 }
1211 }
1212
1213 /// <summary>
1214 /// Gets/sets the Kernel Application context
1215 /// Throws an exception if unable to set the context.
1216 /// </summary>
1217 public string AppContext
1218 {
1219 get
1220 {
1221 return m_cAppContext;
1222 }
1223 set
1224 {
1225 //Send the changed context to RPMS
1226 if ((m_bConnected == true) && (value != ""))
1227 {
1228 try
1229 {
1230 string sRPC = ADEEncryp(value);
1231 string sAuthentication = TransmitRPC("XWB CREATE CONTEXT", sRPC);
1232
1233 if (BMXNetLib.FindSubString(sAuthentication, "does not have access to option") > -1)
1234 {
1235 throw new BMXNetException(sAuthentication);
1236 }
1237
1238 }
1239 catch (Exception ex)
1240 {
1241 Debug.Write(ex.Message);
1242 throw ex;
1243 }
1244 }
1245 m_cAppContext = value;
1246 }
1247 }
1248
1249 public bool Connected
1250 {
1251 get
1252 {
1253 return m_bConnected;
1254 }
1255 }
1256
1257 public string DUZ
1258 {
1259 get
1260 {
1261 return m_cDUZ;
1262 }
1263 }
1264
1265 public string MServerAddress
1266 {
1267 get
1268 {
1269 return m_cServerAddress;
1270 }
1271 }
1272
1273 public string MServerNamespace
1274 {
1275 get
1276 {
1277 return m_sNameSpace;
1278 }
1279 set
1280 {
1281 m_sNameSpace = value;
1282 }
1283 }
1284
1285 public int MServerPort
1286 {
1287 get
1288 {
1289 return m_nMServerPort;
1290 }
1291 set
1292 {
1293 m_nMServerPort = value;
1294 }
1295 }
1296
1297 public string NameSpace
1298 {
1299 get
1300 {
1301 return m_sNameSpace;
1302 }
1303 set
1304 {
1305 m_sNameSpace = value;
1306 }
1307 }
1308
1309 #endregion RPX Properties
1310
1311 }
1312}
Note: See TracBrowser for help on using the repository browser.