source: BMXNET_RPMS_dotNET_UTILITIES-BMX/trunk/cs/bmx_0200scr/BMX2/BMXNet/BMXNetLib.cs@ 818

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

Some profiling code in BMXNetLib.cs conditional on #DEBUG.

File size: 33.0 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 @"wkEo-ZJt!dG)49K{nX1BS$vH<&:Myf*>Ae0jQW=;|#PsO`'%+rmb[gpqN,l6/hFC@DcUa ]z~R}""V\iIxu?872.(TYL5_3",
148 @"rKv`R;M/9BqAF%&tSs#Vh)dO1DZP> *fX'u[.4lY=-mg_ci802N7LTG<]!CWo:3?{+,5Q}(@jaExn$~p\IyHwzU""|k6Jeb",
149 @"\pV(ZJk""WQmCn!Y,y@1d+~8s?[lNMxgHEt=uw|X:qSLjAI*}6zoF{T3#;ca)/h5%`P4$r]G'9e2if_>UDKb7<v0&- RBO.",
150 @"depjt3g4W)qD0V~NJar\B ""?OYhcu[<Ms%Z`RIL_6:]AX-zG.#}$@vk7/5x&*m;(yb2Fn+l'PwUof1K{9,|EQi>H=CT8S!",
151 @"NZW:1}K$byP;jk)7'`x90B|cq@iSsEnu,(l-hf.&Y_?J#R]+voQXU8mrV[!p4tg~OMez CAaGFD6H53%L/dT2<*>""{\wI=",
152 @"vCiJ<oZ9|phXVNn)m K`t/SI%]A5qOWe\&?;jT~M!fz1l>[D_0xR32c*4.P""G{r7}E8wUgyudF+6-:B=$(sY,LkbHa#'@Q",
153 @"hvMX,'4Ty;[a8/{6l~F_V""}qLI\!@x(D7bRmUH]W15J%N0BYPkrs&9:$)Zj>u|zwQ=ieC-oGA.#?tfdcO3gp`S+En K2*<",
154 @"jd!W5[];4'<C$/&x|rZ(k{>?ghBzIFN}fAK""#`p_TqtD*1E37XGVs@0nmSe+Y6Qyo-aUu%i8c=H2vJ\) R:MLb.9,wlO~P",
155 @"2ThtjEM+!=xXb)7,ZV{*ci3""8@_l-HS69L>]\AUF/Q%:qD?1~m(yvO0e'<#o$p4dnIzKP|`NrkaGg.ufCRB[; sJYwW}5&",
156 @"vB\5/zl-9y:Pj|=(R'7QJI *&CTX""p0]_3.idcuOefVU#omwNZ`$Fs?L+1Sk<,b)hM4A6[Y%aDrg@~KqEW8t>H};n!2xG{",
157 @"sFz0Bo@_HfnK>LR}qWXV+D6`Y28=4Cm~G/7-5A\b9!a#rP.l&M$hc3ijQk;),TvUd<[:I""u1'NZSOw]*gxtE{eJp|y (?%",
158 @"M@,D}|LJyGO8`$*ZqH .j>c~h<d=fimszv[#-53F!+a;NC'6T91IV?(0x&/{B)w""]Q\YUWprk4:ol%g2nE7teRKbAPuS_X",
159 @".mjY#_0*H<B=Q+FML6]s;r2:e8R}[ic&KA 1w{)vV5d,$u""~xD/Pg?IyfthO@CzWp%!`N4Z'3-(o|J9XUE7k\TlqSb>anG",
160 @"xVa1']_GU<X`|\NgM?LS9{""jT%s$}y[nvtlefB2RKJW~(/cIDCPow4,>#zm+:5b@06O3Ap8=*7ZFY!H-uEQk; .q)i&rhd",
161 @"I]Jz7AG@QX.""%3Lq>METUo{Pp_ |a6<0dYVSv8:b)~W9NK`(r'4fs&wim\kReC2hg=HOj$1B*/nxt,;c#y+![?lFuZ-5D}",
162 @"Rr(Ge6F Hx>q$m&C%M~Tn,:""o'tX/*yP.{lZ!YkiVhuw_<KE5a[;}W0gjsz3]@7cI2\QN?f#4p|vb1OUBD9)=-LJA+d`S8",
163 @"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+",
164 @"~A*>9 WidFN,1KsmwQ)GJM{I4:C%}#Ep(?HB/r;t.&U8o|l['Lg""2hRDyZ5`nbf]qjc0!zS-TkYO<_=76a\X@$Pe3+xVvu",
165 @"yYgjf""5VdHc#uA,W1i+v'6|@pr{n;DJ!8(btPGaQM.LT3oe?NB/&9>Z`-}02*%x<7lsqz4OS ~E$\R]KI[:UwC_=h)kXmF",
166 @"5:iar.{YU7mBZR@-K|2 ""+~`M%8sq4JhPo<_X\Sg3WC;Tuxz,fvEQ1p9=w}FAI&j/keD0c?)LN6OHV]lGy'$*>nd[(tb!#",
167 };
168
169 #endregion Encryption Keys
170
171 #region RPX Functions
172
173 /// <summary>
174 /// Given strInput = "13" builds "013" if nLength = 3. Default for nLength is 3.
175 /// </summary>
176 /// <param name="strInput"></param>
177 /// <returns></returns>
178 private string ADEBLDPadString(string strInput)
179 {
180 return ADEBLDPadString(strInput, 3);
181 }
182
183 /// <summary>
184 /// Given strInput = "13" builds "013" if nLength = 3 Default for nLength is 3.
185 /// </summary>
186 /// <param name="strInput"></param>
187 /// <param name="nLength">Default = 3</param>
188 /// <returns></returns>
189 private string ADEBLDPadString(string strInput, int nLength /*=3*/)
190 {
191 return strInput.PadLeft(nLength, '0');
192 }
193
194 /// <summary>
195 /// Concatenates zero-padded length of sInput to sInput
196 /// Given "Hello" returns "004Hello"
197 /// If nSize = 5, returns "00004Hello"
198 /// Default for nSize is 3.
199 /// </summary>
200 /// <param name="sInput"></param>
201 /// <returns></returns>
202 private string ADEBLDB(string sInput)
203 {
204 return ADEBLDB(sInput, 3);
205 }
206
207 /// <summary>
208 /// Concatenates zero-padded length of sInput to sInput
209 /// Given "Hello" returns "004Hello"
210 /// If nSize = 5, returns "00004Hello"
211 /// Default for nSize is 3.
212 /// </summary>
213 /// <param name="sInput"></param>
214 /// <param name="nSize"></param>
215 /// <returns></returns>
216 private string ADEBLDB(string sInput, int nSize /*=3*/)
217 {
218 int nLen = sInput.Length;
219 string sLen = this.ADEBLDPadString(nLen.ToString(), nSize);
220 return sLen + sInput;
221 }
222
223 /// <summary>
224 /// Build protocol header
225 /// </summary>
226 /// <param name="sWKID"></param>
227 /// <param name="sWINH"></param>
228 /// <param name="sPRCH"></param>
229 /// <param name="sWISH"></param>
230 /// <returns></returns>
231 private string ADEBHDR(string sWKID, string sWINH, string sPRCH, string sWISH)
232 {
233 string strResult;
234 strResult = sWKID+";"+sWINH+";"+sPRCH+";"+sWISH+";";
235 strResult = ADEBLDB(strResult);
236 return strResult;
237 }
238 private string ADEBLDMsg(string cHDR, string cRPC, string cParam)
239 {
240 string sMult = "";
241 return ADEBLDMsg(cHDR, cRPC, cParam, ref sMult);
242 }
243 private string ADEBLDMsg(string cHDR, string cRPC, string cParam, ref string cMult)
244 {
245 //Builds RPC message
246 //Automatically splits parameters longer than 200 into subscripted array
247 string cMSG;
248 string sBuild = "";
249 string sPiece = "";
250 string sBig = "";
251 int l;
252 int nLength;
253
254 if (cParam == "")
255 {
256 cMSG = "0" + cRPC ;
257 }
258 else
259 {
260 l = PieceLength(cParam, "^");
261 for (int j=1; j <= l; j++)
262 {
263 sPiece = Piece(cParam, "^", j);
264 if ((j == l) && (sPiece.Length > 200))
265 {
266 //Split up long param into array pieces
267 sBig = sPiece;
268 sPiece = ".x";
269 nLength = sPiece.Length + 1;
270 sPiece = ADEBLDPadString(nLength.ToString()) + "2" + sPiece;
271 sBuild = sBuild + sPiece;
272 int nSubscript = 1;
273 string sSubscript ="";
274 int nSubLen = 0;
275 string sSubLen ="";
276 int nBigLen = sBig.Length;
277 string sHunk ="";
278 int nHunkLen = 0;
279 string sHunkLen ="";
280 int nChunk = 0;
281 do
282 {
283 nChunk = (sBig.Length > 200)?200:sBig.Length ;
284 sHunk = sBig.Substring(0, nChunk);
285 sBig = sBig.Remove(0, nChunk);
286 nBigLen = sBig.Length;
287 sSubscript = nSubscript.ToString();
288 nSubLen = sSubscript.Length;
289 sSubLen = nSubLen.ToString();
290 sSubLen = ADEBLDPadString(sSubLen);
291 nHunkLen = sHunk.Length;
292 sHunkLen = nHunkLen.ToString();
293 sHunkLen = ADEBLDPadString(sHunkLen);
294 cMult = cMult + sSubLen + sSubscript + sHunkLen + sHunk;
295 nSubscript++;
296 } while (nBigLen > 0);
297 }
298 else
299 {
300 nLength = sPiece.Length +1;
301 sPiece = ADEBLDPadString(nLength.ToString()) + "0" + sPiece;
302 sBuild = sBuild + sPiece;
303 }
304 }
305 nLength = sBuild.Length;
306 string sTotLen = ADEBLDPadString(nLength.ToString(),5);
307 if (cMult.Length > 0)
308 {
309 cMSG = "1"+ cRPC + "^" +sTotLen + sBuild;
310 }
311 else
312 {
313 cMSG = "0"+ cRPC + "^" +sTotLen + sBuild;
314 }
315 }
316 cMSG = ADEBLDB(cMSG, 5);
317 cMSG = cHDR + cMSG;
318 return cMSG;
319 }
320
321 internal string ADEEncryp(string sInput)
322 {
323 //Encrypt a string
324 string strResult;
325 string strPercent;
326 string strAssoc;
327 string strIdix;
328 int nPercent;
329 int nAssocix;
330 int nIdix;
331 Debug.Assert(sInput != "");
332 System.Random rRand = new Random(DateTime.Now.Second);
333
334 nPercent = rRand.Next(0,10000);
335 nPercent += 72439;
336 nAssocix = nPercent % 20;
337 nAssocix++;
338 Debug.Assert(nAssocix < 21);
339 strPercent = nPercent.ToString();
340 strPercent = strPercent.Substring(1,2);
341 nIdix = Convert.ToInt32(strPercent);
342 nIdix = nIdix % 20;
343 nIdix++;
344 Debug.Assert(nIdix < 21);
345
346 const int nEncryptBase = 101;
347 strAssoc = LoadKey(nEncryptBase + nAssocix);
348 Debug.Assert(strAssoc.Length == 94);
349 strIdix = LoadKey(nEncryptBase + nIdix);
350 Debug.Assert(strIdix.Length == 94);
351 string sEncrypted = "";
352
353 foreach (char c in sInput)
354 {
355 string d = c.ToString();
356 int nFindChar = strIdix.IndexOf(c);
357 if (nFindChar > -1)
358 {
359 d = strAssoc.Substring(nFindChar,1);
360 }
361 sEncrypted += d;
362 }
363
364 strResult = (char) (nIdix + 31) + sEncrypted + (char) (nAssocix + 31);
365
366 return strResult;
367 }
368
369 internal string ADEDecryp(string sInput)
370 {
371 //Encrypt a string
372 string strAssoc;
373 string strIdix;
374 int nAssocix;
375 int nIdix;
376 Debug.Assert(sInput != "");
377
378 //get associator string index
379 char cAssocix = sInput[sInput.Length-1];
380 nAssocix =(int) cAssocix;
381 nAssocix -= 31;
382 Debug.Assert(nAssocix < 21);
383
384 //get identifier string index
385 char cIdix = sInput[0];
386 nIdix = (int) cIdix;
387 nIdix -= 31;
388 Debug.Assert(nIdix < 21);
389
390 //get associator string
391 const int nEncryptBase = 101;
392 strAssoc = LoadKey(nEncryptBase + nAssocix);
393 Debug.Assert(strAssoc.Length == 94);
394
395 //get identifier string
396 strIdix = LoadKey(nEncryptBase + nIdix);
397 Debug.Assert(strIdix.Length == 94);
398
399 //translated result
400 string sDecrypted = "";
401 sInput = sInput.Substring(1, sInput.Length - 2);
402 foreach (char c in sInput)
403 {
404 string d = c.ToString();
405 int nFindChar = strAssoc.IndexOf(c);
406 if (nFindChar > -1)
407 {
408 d = strIdix.Substring(nFindChar,1);
409 }
410 sDecrypted += d;
411 }
412
413 return sDecrypted;
414 }
415
416 internal string BMXEncrypt(string sInput)
417 {
418
419 ASCIIEncoding textConverter = new ASCIIEncoding();
420 RijndaelManaged myRijndael = new RijndaelManaged();
421 byte[] encrypted;
422 byte[] toEncrypt;
423 byte[] key;
424 byte[] IV;
425
426 string sKey="pouphfoz sfdbqjuvmbwft qizmphfoz";
427 string sIV = "Gichin Funakoshi";
428 key = textConverter.GetBytes(sKey);
429 IV = textConverter.GetBytes(sIV);
430
431 //Get an encryptor.
432 ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, IV);
433
434 //Encrypt the data.
435 MemoryStream msEncrypt = new MemoryStream();
436 CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
437
438 //Convert the input data to a byte array.
439 toEncrypt = textConverter.GetBytes(sInput);
440
441 //Write all data to the crypto stream and flush it.
442 csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
443 csEncrypt.FlushFinalBlock();
444
445 //Get encrypted array of bytes.
446 encrypted = msEncrypt.ToArray();
447
448 //Convert to string to send to RPMS
449 string sEncrypted = "" ;
450 byte bTmp;
451 string sTmp;
452 for (int j =0; j < encrypted.Length; j++)
453 {
454 bTmp = encrypted[j];
455 sTmp = bTmp.ToString();
456 sEncrypted += sTmp;
457 if (j < (encrypted.Length -1))
458 sEncrypted += "~";
459 }
460 return sEncrypted;
461 }
462
463 internal string BMXDecrypt(string sInput)
464 {
465 try
466 {
467 byte[] fromEncrypt;
468 ASCIIEncoding textConverter = new ASCIIEncoding();
469 RijndaelManaged myRijndael = new RijndaelManaged();
470 string sRPMSEncrypted = sInput;
471 string sBar = "~";
472 char[] cBar = sBar.ToCharArray();
473 string[] sArray;
474 sArray = sRPMSEncrypted.Split(cBar);
475 byte[] bRPMSEncrypted = new byte[sArray.GetLength(0)];
476 byte[] key;
477 byte[] IV;
478
479 //Convert the RPMS-stored string to a byte array
480 for (int j = 0; j < sArray.GetLength(0); j++)
481 {
482 bRPMSEncrypted[j] = Byte.Parse(sArray[j]);
483 }
484
485 //Get a decryptor that uses the same key and IV as the encryptor.
486 string sKey="pouphfoz sfdbqjuvmbwft qizmphfoz";
487 string sIV = "Gichin Funakoshi";
488 key = textConverter.GetBytes(sKey);
489 IV = textConverter.GetBytes(sIV);
490 ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, IV);
491
492 MemoryStream msDecrypt = new MemoryStream(bRPMSEncrypted);
493 CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
494
495 fromEncrypt = new byte[bRPMSEncrypted.Length - 2];
496
497 //Read the data out of the crypto stream.
498 csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
499
500 int nZ = FindChar(fromEncrypt, (char) 0);
501
502 //Convert the byte array back into a string.
503 string sResult;
504 if (nZ < 0)
505 {
506 sResult = textConverter.GetString(fromEncrypt);
507 }
508 else
509 {
510 sResult = textConverter.GetString(fromEncrypt, 0, nZ);
511 }
512 return sResult;
513 }
514 catch (Exception ex)
515 {
516 Debug.Write(ex.Message);
517 return "";
518 }
519 }
520
521 public static int FindChar(byte[] c, char y)
522 {
523 int n = 0;
524 int nRet = -1;
525 for (n=0; n < c.Length; n++)
526 {
527 if (y == (char) c[n])
528 {
529 nRet = n;
530 break;
531 }
532 }
533
534 return nRet;
535 }
536
537 public static int FindChar(string s, char y)
538 {
539 int n = 0;
540 int nRet = -1;
541 foreach (char c in s)
542 {
543 if (y == c)
544 {
545 nRet = n;
546 break;
547 }
548 n++;
549 }
550 return nRet;
551 }
552
553
554 /// <summary>
555 /// Returns index of first instance of sSubString in sString.
556 /// If sSubString not found, returns -1.
557 /// </summary>
558 /// <param name="sString"></param>
559 /// <param name="sSubString"></param>
560 /// <returns></returns>
561 public static int FindSubString(string sString, string sSubString)
562 {
563 int nFound = -1;
564 int nLimit = sString.Length - sSubString.Length + 1;
565 if (nLimit < 0)
566 return -1;
567
568 int nSubLength = sSubString.Length;
569 for (int j=0; j < nLimit; j++)
570 {
571 if (sString.Substring(j, nSubLength) == sSubString)
572 {
573 nFound = j;
574 break;
575 }
576 }
577 return nFound;
578 }
579
580 private string LoadKey(int nID)
581 {
582 nID -= 102;
583 Debug.Assert( nID < 20);
584 return m_sKey[nID];
585 }
586
587 private void OpenConnectionCommon(string sServerAddress)
588 {
589 try
590 {
591 m_cServerAddress = sServerAddress;
592
593 //Connect with the server
594 TcpClient connector = new TcpClient();
595
596 try
597 {
598 connector = new TcpClient();
599 connector.Connect(m_cServerAddress, m_nMServerPort);
600 }
601 catch (SocketException exSocket)
602 {
603 string s = exSocket.Message + exSocket.StackTrace;
604 throw new BMXNetException(s);
605 }
606
607 //Prepare & send the connect message
608 string cSend = "TCPconnect^" + m_sNameSpace + "^^";
609 int nLen = cSend.Length;
610 string sLen = nLen.ToString();
611 sLen = sLen.PadLeft(5, '0');
612 cSend = "{BMX}" + sLen + cSend;
613
614 NetworkStream ns = connector.GetStream();
615 byte[] sendBytes = Encoding.ASCII.GetBytes(cSend);
616 ns.Write(sendBytes,0,sendBytes.Length);
617
618 m_pCommSocket = connector;
619 return;
620
621 }
622 catch (BMXNetException bmxEx)
623 {
624 throw bmxEx;
625 }
626 catch (Exception ex)
627 {
628 string s = ex.Message + ex.StackTrace;
629 throw new BMXNetException(s);
630 }
631 }//End OpenConnectionCommon
632
633 [SocketPermissionAttribute(SecurityAction.Assert,
634 Access="Connect",
635 Host="All",
636 Port="All",
637 Transport="All")]
638 public bool OpenConnection(string sServerAddress, WindowsIdentity winIdentity)
639 {
640 try
641 {
642 OpenConnectionCommon(sServerAddress);
643 bool bSecurity;
644 try
645 {
646 bSecurity = SendSecurityRequest(winIdentity);
647
648 }
649 catch (Exception ex)
650 {
651 //Close the connection
652 SendString(m_pCommSocket, "#BYE#");
653 m_pCommSocket.Close();
654 m_bConnected = false;
655 m_cServerAddress = "";
656 throw ex;
657 }
658
659 m_bConnected = bSecurity;
660 return m_bConnected;
661 }
662 catch (BMXNetException bmxEx)
663 {
664 throw bmxEx;
665 }
666 catch (Exception ex)
667 {
668 string s = ex.Message + ex.StackTrace;
669 throw new BMXNetException(s);
670 }
671 }
672
673 StreamWriter m_LogWriter;
674 bool m_bLogging = false;
675
676 public void StartLog()
677 {
678 try
679 {
680 if (m_bLogging)
681 {
682 throw new Exception("Already logging.");
683 }
684 string sFile = "BMXLog " + DateTime.Now.DayOfYear.ToString() + " " +
685 DateTime.Now.Hour.ToString() + " " + DateTime.Now.Minute.ToString()
686 + " " + DateTime.Now.Second.ToString() + ".log";
687 StartLog(sFile);
688 return;
689 }
690 catch (Exception ex)
691 {
692 throw ex;
693 }
694 }
695
696 public void StartLog(string LogFileName)
697 {
698 try
699 {
700 if (m_bLogging)
701 {
702 throw new Exception("Already logging.");
703 }
704 m_LogWriter = File.AppendText(LogFileName);
705 m_bLogging = true;
706 return;
707 }
708 catch (Exception ex)
709 {
710 throw ex;
711 }
712 }
713
714 public void StopLog()
715 {
716 try
717 {
718 //Close the writer and underlying file.
719 if (m_bLogging == false)
720 {
721 return;
722 }
723 m_LogWriter.Close();
724 m_bLogging = false;
725 return;
726 }
727 catch (Exception ex)
728 {
729 throw ex;
730 }
731 }
732
733 private static void Log(String logMessage, TextWriter w)
734 {
735 w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
736 DateTime.Now.ToLongDateString());
737 w.WriteLine(" :");
738 w.WriteLine(" :{0}", logMessage);
739 w.WriteLine("-------------------------------");
740 // Update the underlying file.
741 w.Flush();
742 }
743
744 [SocketPermissionAttribute(SecurityAction.Assert,
745 Access="Connect",
746 Host="All",
747 Port="All",
748 Transport="All")]
749 public bool OpenConnection(string sServerAddress, string sAccess, string sVerify)
750 {
751 try
752 {
753 this.OpenConnectionCommon(sServerAddress);
754
755 try
756 {
757 bool bSecurity = SendSecurityRequest(sAccess, sVerify);
758 }
759 catch (Exception ex)
760 {
761 //Close the connection
762 SendString(m_pCommSocket, "#BYE#");
763 m_pCommSocket.Close();
764 m_bConnected = false;
765 m_cServerAddress = "";
766 throw ex;
767 }
768
769 m_bConnected = true;
770 return m_bConnected;
771 }
772 catch (BMXNetException bmxEx)
773 {
774 throw bmxEx;
775 }
776 catch (Exception ex)
777 {
778 string s = ex.Message + ex.StackTrace;
779 throw new BMXNetException(s);
780 }
781 }
782
783 private void SendString(TcpClient tcpClient, string cSendString)
784 {
785 string sMult = "";
786 SendString(tcpClient, cSendString, sMult);
787 }
788
789 private void SendString(TcpClient tcpClient, string cSendString, string cMult)
790 {
791 int nLen = cSendString.Length;
792 string sLen = nLen.ToString();
793 sLen = sLen.PadLeft(5, '0');
794 cSendString = sLen + cSendString;
795
796 nLen += 15;
797 sLen = nLen.ToString();
798 sLen = sLen.PadLeft(5, '0');
799
800 cSendString = "{BMX}" + sLen + cSendString;
801 cSendString = cSendString + cMult;
802
803 NetworkStream ns = tcpClient.GetStream();
804 byte[] sendBytes = Encoding.ASCII.GetBytes(cSendString);
805 ns.Write(sendBytes,0,sendBytes.Length);
806 if (this.m_bLogging == true)
807 {
808 Log("Sent: " + cSendString, this.m_LogWriter);
809 }
810 return;
811 }
812
813 private string ReceiveString(TcpClient tcpClient)
814 {
815 NetworkStream ns = tcpClient.GetStream();
816
817 int nTimeOut = this.m_nReceiveTimeout;
818 int nCnt = 0;
819 int nTimeElapsed = 0;
820 while (ns.DataAvailable == false)
821 {
822 if (nCnt > 9999)
823 break;
824 if (nTimeElapsed > nTimeOut)
825 break;
826 nCnt++;
827 nTimeElapsed += 50;
828 Thread.Sleep(50);
829 }
830
831 Debug.Assert(ns.DataAvailable == true);
832 if (ns.DataAvailable == false)
833 {
834 this.CloseConnection();
835 throw new Exception("BMXNetLib.ReceiveString timeout. Connection Closed.");
836 //return "";
837 }
838
839 byte[] bReadBuffer = new byte[1024];
840 string sReadBuffer = "";
841 StringBuilder sbAll = new StringBuilder("", 1024);
842 int numberOfBytesRead = 0;
843
844 // Incoming message may be larger than the buffer size.
845
846 bool bFinished = false;
847 int nFind = -1;
848 bool bStarted = false;
849 int lpBuf = 0;
850 string sError = "";
851 string sAppError = "";
852 do
853 {
854
855 numberOfBytesRead = ns.Read(bReadBuffer, 0, bReadBuffer.Length);
856 if ((numberOfBytesRead == 1)&&(bStarted == false))
857 {
858 Thread.Sleep(15);
859 numberOfBytesRead += ns.Read(bReadBuffer,1, bReadBuffer.Length-1);
860 //Debug.Write("ReceiveString waiting for data...\n");
861 }
862 if (bStarted == false)
863 {
864 //Process error info at beginning of returned string
865 int nErrLen = bReadBuffer[0];
866 int nAppLen = bReadBuffer[bReadBuffer[0]+1];
867 if ((bReadBuffer[2] == 0)&&(bReadBuffer[3] == 0))
868 { //special case: M error trap invoked in SND^XWBTCPC
869 lpBuf += 2;
870 }
871 sError = Encoding.ASCII.GetString(bReadBuffer, lpBuf + 1, nErrLen);
872 if (sError != "")
873 {
874 throw new BMXNetException(sError);
875 }
876 sAppError = Encoding.ASCII.GetString(bReadBuffer, lpBuf+1+nErrLen+1, nAppLen);
877 lpBuf += (nErrLen + nAppLen + 2);
878 numberOfBytesRead -= (nErrLen + nAppLen + 2);
879 bStarted = true;
880 }
881
882 nFind = FindChar(bReadBuffer, (char) 4);
883 if (nFind > -1)
884 bFinished = true;
885 Debug.Assert(numberOfBytesRead > -1);
886 sReadBuffer = Encoding.ASCII.GetString(bReadBuffer, lpBuf, numberOfBytesRead);
887 lpBuf = 0;
888 if (nFind > -1)
889 {
890 sbAll.Append(sReadBuffer, 0, numberOfBytesRead -1);
891 }
892 else
893 {
894 sbAll.Append(sReadBuffer);
895 }
896 }
897 while(bFinished == false);
898 if (this.m_bLogging == true)
899 {
900 Log("Received: " + sbAll.ToString(), this.m_LogWriter);
901 }
902 return sbAll.ToString();
903
904 }
905 private bool SendSecurityRequest(WindowsIdentity winIdentity)
906 {
907 string strReceive = "";
908 string cMSG;
909 string sTest;
910
911 //Build AV Call
912 cMSG = ADEBLDMsg(m_cHDR, "BMX AV CODE", winIdentity.Name);
913 SendString(m_pCommSocket, cMSG);
914
915 strReceive = ReceiveString(m_pCommSocket);
916 sTest = strReceive.Substring(0,3);
917
918
919 char[] cDelim = {(char) 13,(char) 10,(char) 0};
920 string sDelim = new string(cDelim);
921 int nPiece = 1;
922 m_cDUZ = Piece(strReceive, sDelim , nPiece);
923 if ((m_cDUZ == "0")||(m_cDUZ == ""))
924 {
925 nPiece = 7;
926 string sReason = Piece(strReceive, sDelim, nPiece);
927 throw new Exception(sReason);
928 }
929
930 return true;
931 }
932
933 private bool SendSecurityRequest(string sAccess, string sVerify)
934 {
935 string strReceive = "";
936 string cMSG;
937 sAccess = sAccess.ToUpper();
938 sVerify = sVerify.ToUpper();
939
940 //Build AV Call
941 string strAV = sAccess + ";" + sVerify;
942 strAV = ADEEncryp(strAV);
943 cMSG = ADEBLDMsg(m_cHDR, "XUS AV CODE", strAV);
944 SendString(m_pCommSocket, cMSG);
945
946 strReceive = ReceiveString(m_pCommSocket);
947
948 char[] cDelim = {(char) 13,(char) 10,(char) 0};
949 string sDelim = new string(cDelim);
950 int nPiece = 1;
951 m_cDUZ = Piece(strReceive, sDelim , nPiece);
952 if ((m_cDUZ == "0")||(m_cDUZ == ""))
953 {
954 nPiece = 7;
955 string sReason = Piece(strReceive, sDelim, nPiece);
956 throw new Exception(sReason);
957 }
958
959 return true;
960 }
961
962 public void CloseConnection()
963 {
964 if (!m_bConnected)
965 {
966 return;
967 }
968 SendString(m_pCommSocket, "#BYE#");
969 m_pCommSocket.Close();
970 m_bConnected = false;
971 m_cServerAddress = "";
972 // m_cDUZ2 = "";
973 m_cDUZ = "";
974 }
975
976 public bool Lock(string Variable)
977 {
978 return Lock(Variable, "", "");
979 }
980
981 public bool Lock(string Variable, string Increment)
982 {
983 return Lock(Variable, Increment, "");
984 }
985
986 /// <summary>
987 /// Lock a local or global M variable
988 /// Returns true if lock is obtained during TimeOut seconds
989 /// Use + to increment, - to decrement lock.
990 /// </summary>
991 /// <param name="Variable"></param>
992 /// <param name="Increment"></param>
993 /// <param name="TimeOut"></param>
994 /// <returns></returns>
995 public bool Lock(string Variable, string Increment, string TimeOut)
996 {
997 try
998 {
999 string sContext = this.AppContext;
1000 this.AppContext = "BMXRPC";
1001 Variable = Variable.Replace("^","~");
1002 string sRet = "0";
1003 bool bRet = false;
1004 string sParam = Variable + "^" + Increment + "^" + TimeOut;
1005 sRet = TransmitRPC("BMX LOCK", sParam);
1006 bRet = (sRet == "1")?true:false;
1007 this.AppContext = sContext;
1008 return bRet;
1009 }
1010 catch (Exception ex)
1011 {
1012 string sMsg = ex.Message;
1013 return false;
1014 }
1015 }
1016
1017 static ReaderWriterLock m_rwl = new ReaderWriterLock();
1018 private int m_nRWLTimeout = 30000; //30-second default timeout
1019
1020 /// <summary>
1021 /// Returns a reference to the internal ReaderWriterLock member.
1022 /// </summary>
1023 public ReaderWriterLock BMXRWL
1024 {
1025 get
1026 {
1027 return m_rwl;
1028 }
1029 }
1030
1031 /// <summary>
1032 /// Sets and returns the timeout in milliseconds for locking the transmit port.
1033 /// If the transmit port is unavailable an ApplicationException will be thrown.
1034 /// </summary>
1035 public int RWLTimeout
1036 {
1037 get
1038 {
1039 return m_nRWLTimeout;
1040 }
1041 set
1042 {
1043 m_nRWLTimeout = value;
1044 }
1045 }
1046
1047 public string TransmitRPC(string sRPC, string sParam, int nLockTimeOut)
1048 {
1049 try
1050 {
1051 try
1052 {
1053 if (m_bConnected == false)
1054 {
1055 throw new BMXNetException("BMXNetLib.TransmitRPC failed because BMXNetLib is not connected to RPMS.");
1056 }
1057 Debug.Assert(m_cDUZ != "");
1058 Debug.Assert(m_pCommSocket != null);
1059
1060 string sOldAppContext = "";
1061 if (sRPC.StartsWith("BMX")&&(this.m_cAppContext != "BMXRPC"))
1062 {
1063 sOldAppContext = this.m_cAppContext;
1064 this.AppContext = "BMXRPC";
1065 }
1066 string sMult = "";
1067 string sSend = ADEBLDMsg(m_cHDR, sRPC, sParam, ref sMult);
1068 SendString(m_pCommSocket, sSend, sMult);
1069#if DEBUG
1070 DateTime sendTime = DateTime.Now;
1071 Debug.Write("TransmitRPC Sent: " + sSend + "\n");
1072#endif
1073 string strResult = ReceiveString(m_pCommSocket);
1074#if DEBUG
1075 DateTime receiveTime = DateTime.Now;
1076 Debug.Write("TransmitRPC Received: " + strResult + "\n");
1077 TimeSpan executionTime = receiveTime - sendTime;
1078 Debug.Write("Execution Time: " + executionTime.Milliseconds + " ms.\n");
1079#endif
1080 if (sOldAppContext != "")
1081 {
1082 this.AppContext = sOldAppContext;
1083 }
1084 return strResult;
1085 }
1086 catch (Exception ex)
1087 {
1088 if (ex.Message == "Unable to write data to the transport connection.")
1089 {
1090 m_bConnected = false;
1091 }
1092 throw ex;
1093 }
1094 finally
1095 {
1096 }
1097 }
1098 catch (ApplicationException aex)
1099 {
1100 // The writer lock request timed out.
1101 Debug.Write("TransmitRPC writer lock request timed out.\n");
1102 throw aex;
1103 }
1104 catch (Exception OuterEx)
1105 {
1106 throw OuterEx;
1107 }
1108 }
1109
1110 public string TransmitRPC(string sRPC, string sParam)
1111 {
1112 try
1113 {
1114 return TransmitRPC(sRPC, sParam, m_nRWLTimeout);
1115 }
1116 catch (ApplicationException aex)
1117 {
1118 throw aex;
1119 }
1120 catch (Exception ex)
1121 {
1122 throw ex;
1123 }
1124 }
1125
1126 public string GetLoginFacility()
1127 {
1128 try
1129 {
1130 if (m_bConnected == false)
1131 {
1132 throw new BMXNetException("BMXNetLib is not connected to RPMS");
1133 }
1134
1135 if (m_cLoginFacility != "")
1136 {
1137 return m_cLoginFacility;
1138 }
1139
1140 Debug.Assert(m_pCommSocket != null);
1141 Debug.Assert(m_cDUZ != "");
1142 SendString(m_pCommSocket, ADEBLDMsg(m_cHDR, "BMXGetFac", m_cDUZ));
1143 string sFac = ReceiveString(m_pCommSocket);
1144 m_cLoginFacility = sFac;
1145 return sFac;
1146 }
1147 catch (BMXNetException bmxEx)
1148 {
1149 string sMessage = bmxEx.Message + bmxEx.StackTrace;
1150 throw new BMXNetException(sMessage);
1151 }
1152 catch (Exception ex)
1153 {
1154 throw ex;
1155 }
1156 }
1157
1158 #endregion RPX Functions
1159
1160 #region RPX Properties
1161
1162 /// <summary>
1163 /// Set and retrieve the timeout, in milliseconds, to receive a response from the RPMS server.
1164 /// If the retrieve time exceeds the timeout, an exception will be thrown and the connection will be closed.
1165 /// The default is 30 seconds.
1166 /// </summary>
1167 public int ReceiveTimeout
1168 {
1169 get { return m_nReceiveTimeout; }
1170 set { m_nReceiveTimeout = value; }
1171 }
1172
1173 public string WKID
1174 {
1175 get
1176 {
1177 return m_sWKID;
1178 }
1179 set
1180 {
1181 m_sWKID = value;
1182 }
1183 }
1184
1185 public string PRCH
1186 {
1187 get
1188 {
1189 return m_sPRCH;
1190 }
1191 set
1192 {
1193 m_sPRCH = value;
1194 }
1195 }
1196
1197 public string WINH
1198 {
1199 get
1200 {
1201 return m_sWINH;
1202 }
1203 set
1204 {
1205 m_sWINH = value;
1206 }
1207 }
1208
1209 public string WISH
1210 {
1211 get
1212 {
1213 return m_sWISH;
1214 }
1215 set
1216 {
1217 m_sWISH = value;
1218 }
1219 }
1220
1221 /// <summary>
1222 /// Gets/sets the Kernel Application context
1223 /// Throws an exception if unable to set the context.
1224 /// </summary>
1225 public string AppContext
1226 {
1227 get
1228 {
1229 return m_cAppContext;
1230 }
1231 set
1232 {
1233 //Send the changed context to RPMS
1234 if ((m_bConnected == true) && (value != ""))
1235 {
1236 try
1237 {
1238 string sRPC = ADEEncryp(value);
1239 string sAuthentication = TransmitRPC("XWB CREATE CONTEXT", sRPC);
1240
1241 if (BMXNetLib.FindSubString(sAuthentication, "does not have access to option") > -1)
1242 {
1243 throw new BMXNetException(sAuthentication);
1244 }
1245
1246 }
1247 catch (Exception ex)
1248 {
1249 Debug.Write(ex.Message);
1250 throw ex;
1251 }
1252 }
1253 m_cAppContext = value;
1254 }
1255 }
1256
1257 public bool Connected
1258 {
1259 get
1260 {
1261 return m_bConnected;
1262 }
1263 }
1264
1265 public string DUZ
1266 {
1267 get
1268 {
1269 return m_cDUZ;
1270 }
1271 }
1272
1273 public string MServerAddress
1274 {
1275 get
1276 {
1277 return m_cServerAddress;
1278 }
1279 }
1280
1281 public string MServerNamespace
1282 {
1283 get
1284 {
1285 return m_sNameSpace;
1286 }
1287 set
1288 {
1289 m_sNameSpace = value;
1290 }
1291 }
1292
1293 public int MServerPort
1294 {
1295 get
1296 {
1297 return m_nMServerPort;
1298 }
1299 set
1300 {
1301 m_nMServerPort = value;
1302 }
1303 }
1304
1305 public string NameSpace
1306 {
1307 get
1308 {
1309 return m_sNameSpace;
1310 }
1311 set
1312 {
1313 m_sNameSpace = value;
1314 }
1315 }
1316
1317 #endregion RPX Properties
1318
1319 }
1320}
Note: See TracBrowser for help on using the repository browser.