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

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

No changes. Just making my icon look green.

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