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

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

BMX version bumped to 2.3.
New dll
BMXNetConnectInfo: Event polling from RPMS/VISTA is now async. BMX Writer lock removed.
BMXNetLib:

  1. Application context changes are now suppressed. Developer must make sure that his/her application has all the needed BMX methods. This was done for performance enhancement as application context changes are very expensive in network time.
  2. Locks are implemented at the TransmitRPC with a very simple Lock(this) which works very well.

RPMSDb: See #1 for BMXNetLib. All context changes are now suppressed.

File size: 36.7 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 connector.Connect(m_cServerAddress, m_nMServerPort);
631 }
632 catch (SocketException exSocket)
633 {
634 string s = exSocket.Message + exSocket.StackTrace;
635 throw new BMXNetException(s);
636 }
637
638 //Prepare & send the connect message
639 string cSend = "TCPconnect^" + m_sNameSpace + "^^";
640 int nLen = cSend.Length;
641 string sLen = nLen.ToString();
642 sLen = sLen.PadLeft(5, '0');
643 cSend = "{BMX}" + sLen + cSend;
644
645 NetworkStream ns = connector.GetStream();
646 byte[] sendBytes = Encoding.ASCII.GetBytes(cSend);
647 ns.Write(sendBytes,0,sendBytes.Length);
648
649 m_pCommSocket = connector;
650 return;
651
652 }
653 catch (BMXNetException bmxEx)
654 {
655 throw bmxEx;
656 }
657 catch (Exception ex)
658 {
659 string s = ex.Message + ex.StackTrace;
660 throw new BMXNetException(s);
661 }
662 }//End OpenConnectionCommon
663
664 [SocketPermissionAttribute(SecurityAction.Assert,
665 Access="Connect",
666 Host="All",
667 Port="All",
668 Transport="All")]
669 public bool OpenConnection(string sServerAddress, WindowsIdentity winIdentity)
670 {
671 try
672 {
673 OpenConnectionCommon(sServerAddress);
674 bool bSecurity;
675 try
676 {
677 bSecurity = SendSecurityRequest(winIdentity);
678
679 }
680 catch (Exception ex)
681 {
682 //Close the connection
683 SendString(m_pCommSocket, "#BYE#");
684 m_pCommSocket.Close();
685 m_bConnected = false;
686 m_cServerAddress = "";
687 throw ex;
688 }
689
690 m_bConnected = bSecurity;
691 return m_bConnected;
692 }
693 catch (BMXNetException bmxEx)
694 {
695 throw bmxEx;
696 }
697 catch (Exception ex)
698 {
699 string s = ex.Message + ex.StackTrace;
700 throw new BMXNetException(s);
701 }
702 }
703
704 StreamWriter m_LogWriter;
705 bool m_bLogging = false;
706
707 public void StartLog()
708 {
709 try
710 {
711 if (m_bLogging)
712 {
713 throw new Exception("Already logging.");
714 }
715 string sFile = "BMXLog " + DateTime.Now.DayOfYear.ToString() + " " +
716 DateTime.Now.Hour.ToString() + " " + DateTime.Now.Minute.ToString()
717 + " " + DateTime.Now.Second.ToString() + ".log";
718 StartLog(sFile);
719 return;
720 }
721 catch (Exception ex)
722 {
723 throw ex;
724 }
725 }
726
727 public void StartLog(string LogFileName)
728 {
729 try
730 {
731 if (m_bLogging)
732 {
733 throw new Exception("Already logging.");
734 }
735 m_LogWriter = File.AppendText(LogFileName);
736 m_bLogging = true;
737 return;
738 }
739 catch (Exception ex)
740 {
741 throw ex;
742 }
743 }
744
745 public void StopLog()
746 {
747 try
748 {
749 //Close the writer and underlying file.
750 if (m_bLogging == false)
751 {
752 return;
753 }
754 m_LogWriter.Close();
755 m_bLogging = false;
756 return;
757 }
758 catch (Exception ex)
759 {
760 throw ex;
761 }
762 }
763
764 private static void Log(String logMessage, TextWriter w)
765 {
766 w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
767 DateTime.Now.ToLongDateString());
768 w.WriteLine(" :");
769 w.WriteLine(" :{0}", logMessage);
770 w.WriteLine("-------------------------------");
771 // Update the underlying file.
772 w.Flush();
773 }
774
775 [SocketPermissionAttribute(SecurityAction.Assert,
776 Access="Connect",
777 Host="All",
778 Port="All",
779 Transport="All")]
780 public bool OpenConnection(string sServerAddress, string sAccess, string sVerify)
781 {
782 try
783 {
784 this.OpenConnectionCommon(sServerAddress);
785
786 try
787 {
788 bool bSecurity = SendSecurityRequest(sAccess, sVerify);
789 }
790 catch (Exception ex)
791 {
792 //Close the connection
793 SendString(m_pCommSocket, "#BYE#");
794 m_pCommSocket.Close();
795 m_bConnected = false;
796 m_cServerAddress = "";
797 throw ex;
798 }
799
800 m_bConnected = true;
801 return m_bConnected;
802 }
803 catch (BMXNetException bmxEx)
804 {
805 throw bmxEx;
806 }
807 catch (Exception ex)
808 {
809 //string s = ex.Message + ex.StackTrace;
810 throw new BMXNetException(ex.Message, ex);
811 }
812 }
813
814 private void SendString(TcpClient tcpClient, string cSendString)
815 {
816 string sMult = "";
817 SendString(tcpClient, cSendString, sMult);
818 }
819
820 private void SendString(TcpClient tcpClient, string cSendString, string cMult)
821 {
822 int nLen = cSendString.Length;
823 string sLen = nLen.ToString();
824 sLen = sLen.PadLeft(5, '0');
825 cSendString = sLen + cSendString;
826
827 nLen += 15;
828 sLen = nLen.ToString();
829 sLen = sLen.PadLeft(5, '0');
830
831 cSendString = "{BMX}" + sLen + cSendString;
832 cSendString = cSendString + cMult;
833
834 NetworkStream ns = tcpClient.GetStream();
835 byte[] sendBytes = m_Encoding.GetBytes(cSendString);
836 ns.Write(sendBytes,0,sendBytes.Length);
837 if (this.m_bLogging == true)
838 {
839 Log("Sent: " + cSendString, this.m_LogWriter);
840 }
841 return;
842 }
843
844 private string ReceiveString(TcpClient tcpClient)
845 {
846 NetworkStream ns = tcpClient.GetStream();
847
848 int nTimeOut = this.m_nReceiveTimeout; //timeout
849 int nCnt = 0; //number of times trying to get a message from the client
850 int nTimeElapsed = 0; //compare with timeout; increment 50 ms everytime.
851 while (ns.DataAvailable == false)
852 {
853 if (nCnt > 9999)
854 break;
855 if (nTimeElapsed > nTimeOut)
856 break;
857 nCnt++;
858 nTimeElapsed += 50;
859 Thread.Sleep(50);
860 }
861
862 Debug.Assert(ns.DataAvailable == true);
863 if (ns.DataAvailable == false) //if still false, then we timed out.
864 {
865 this.CloseConnection();
866 throw new Exception("BMXNetLib.ReceiveString timeout. Connection Closed.");
867 //return "";
868 }
869
870 byte[] bReadBuffer = new byte[1024]; //byte buffer
871 string sReadBuffer = ""; //string buffer
872 StringBuilder sbAll = new StringBuilder("", 1024); //string builder
873 int numberOfBytesRead = 0;
874
875 // Incoming message may be larger than the buffer size.
876
877 bool bFinished = false; //finished reading?
878 int nFind = -1; //Position of $C(4) (End of Transmission)
879 bool bStarted = false; //Is the buffer started?
880 int lpBuf = 0; //?
881 string sError = ""; //?
882 string sAppError = ""; //?
883 do
884 {
885 numberOfBytesRead = ns.Read(bReadBuffer, 0, bReadBuffer.Length); // read 1024 characters
886 if ((numberOfBytesRead == 1)&&(bStarted == false)) // if only one byte read, try again in 15 ms
887 {
888 Thread.Sleep(15);
889 numberOfBytesRead += ns.Read(bReadBuffer,1, bReadBuffer.Length-1); //skip the first one of course
890 //Debug.Write("ReceiveString waiting for data...\n");
891 }
892 if (bStarted == false) //if this is the first transmission process error info
893 {
894 //Process error info at beginning of returned string
895 int nErrLen = bReadBuffer[0];
896 int nAppLen = bReadBuffer[bReadBuffer[0]+1];
897 if ((bReadBuffer[2] == 0)&&(bReadBuffer[3] == 0))
898 { //special case: M error trap invoked in SND^XWBTCPC
899 lpBuf += 2;
900 }
901 sError = m_Encoding.GetString(bReadBuffer, lpBuf + 1, nErrLen);
902 if (sError != "")
903 {
904 throw new BMXNetException(sError);
905 }
906 sAppError = m_Encoding.GetString(bReadBuffer, lpBuf+1+nErrLen+1, nAppLen);
907 lpBuf += (nErrLen + nAppLen + 2);
908 numberOfBytesRead -= (nErrLen + nAppLen + 2);
909 bStarted = true;
910 }
911
912 nFind = FindChar(bReadBuffer, (char) 4); //find end of transmission chracter
913 if (nFind > -1) // if found
914 bFinished = true; //then we are finished
915 Debug.Assert(numberOfBytesRead > -1); // this must be true
916 sReadBuffer = m_Encoding.GetString(bReadBuffer, lpBuf, numberOfBytesRead);
917 lpBuf = 0;
918 if (nFind > -1)
919 {
920 sbAll.Append(sReadBuffer, 0, sReadBuffer.Length - 1);
921 }
922 else
923 {
924 sbAll.Append(sReadBuffer);
925 }
926 }
927 while(bFinished == false);
928 if (this.m_bLogging == true)
929 {
930 Log("Received: " + sbAll.ToString(), this.m_LogWriter);
931 }
932 return sbAll.ToString();
933
934 }
935 private bool SendSecurityRequest(WindowsIdentity winIdentity)
936 {
937 string strReceive = "";
938 string cMSG;
939 string sTest;
940
941 //Build AV Call
942 cMSG = ADEBLDMsg(m_cHDR, "BMX AV CODE", winIdentity.Name);
943 SendString(m_pCommSocket, cMSG);
944
945 strReceive = ReceiveString(m_pCommSocket);
946 sTest = strReceive.Substring(0,3);
947
948
949 char[] cDelim = {(char) 13,(char) 10,(char) 0};
950 string sDelim = new string(cDelim);
951 int nPiece = 1;
952 m_cDUZ = Piece(strReceive, sDelim , nPiece);
953 if ((m_cDUZ == "0")||(m_cDUZ == ""))
954 {
955 nPiece = 7;
956 string sReason = Piece(strReceive, sDelim, nPiece);
957 throw new Exception(sReason);
958 }
959
960 return true;
961 }
962
963 private bool SendSecurityRequest(string sAccess, string sVerify)
964 {
965 string strReceive = "";
966 string cMSG;
967 sAccess = sAccess.ToUpper();
968 sVerify = sVerify.ToUpper();
969
970 //Build AV Call
971 string strAV = sAccess + ";" + sVerify;
972 strAV = ADEEncryp(strAV);
973 cMSG = ADEBLDMsg(m_cHDR, "XUS AV CODE", strAV);
974 SendString(m_pCommSocket, cMSG);
975
976 strReceive = ReceiveString(m_pCommSocket);
977
978 char[] cDelim = {(char) 13,(char) 10,(char) 0};
979 string sDelim = new string(cDelim);
980 int nPiece = 1;
981 m_cDUZ = Piece(strReceive, sDelim , nPiece);
982 if ((m_cDUZ == "0")||(m_cDUZ == ""))
983 {
984 nPiece = 7;
985 string sReason = Piece(strReceive, sDelim, nPiece);
986 throw new Exception(sReason);
987 }
988
989 return true;
990 }
991
992 public void CloseConnection()
993 {
994 if (!m_bConnected)
995 {
996 return;
997 }
998 SendString(m_pCommSocket, "#BYE#");
999 m_pCommSocket.Close();
1000 m_bConnected = false;
1001 m_cServerAddress = "";
1002 // m_cDUZ2 = "";
1003 m_cDUZ = "";
1004 }
1005
1006 public bool Lock(string Variable)
1007 {
1008 return Lock(Variable, "", "");
1009 }
1010
1011 public bool Lock(string Variable, string Increment)
1012 {
1013 return Lock(Variable, Increment, "");
1014 }
1015
1016 /// <summary>
1017 /// Lock a local or global M variable
1018 /// Returns true if lock is obtained during TimeOut seconds
1019 /// Use + to increment, - to decrement lock.
1020 /// </summary>
1021 /// <param name="Variable"></param>
1022 /// <param name="Increment"></param>
1023 /// <param name="TimeOut"></param>
1024 /// <returns></returns>
1025 public bool Lock(string Variable, string Increment, string TimeOut)
1026 {
1027 try
1028 {
1029 /* 3110109 -- smh Commented out for performance issues.
1030 /*string sContext = this.AppContext;
1031 this.AppContext = "BMXRPC";*/
1032 Variable = Variable.Replace("^","~");
1033 string sRet = "0";
1034 bool bRet = false;
1035 string sParam = Variable + "^" + Increment + "^" + TimeOut;
1036 sRet = TransmitRPC("BMX LOCK", sParam);
1037 bRet = (sRet == "1")?true:false;
1038 /* 3110109 -- smh Commented out for performance issues.
1039 /*this.AppContext = sContext;*/
1040 return bRet;
1041 }
1042 catch (Exception ex)
1043 {
1044 string sMsg = ex.Message;
1045 return false;
1046 }
1047 }
1048
1049 static ReaderWriterLock m_rwl = new ReaderWriterLock();
1050 private int m_nRWLTimeout = 30000; //30-second default timeout
1051
1052 /// <summary>
1053 /// Returns a reference to the internal ReaderWriterLock member.
1054 /// </summary>
1055 public ReaderWriterLock BMXRWL
1056 {
1057 get
1058 {
1059 return m_rwl;
1060 }
1061 }
1062
1063 /// <summary>
1064 /// Sets and returns the timeout in milliseconds for locking the transmit port.
1065 /// If the transmit port is unavailable an ApplicationException will be thrown.
1066 /// </summary>
1067 public int RWLTimeout
1068 {
1069 get
1070 {
1071 return m_nRWLTimeout;
1072 }
1073 set
1074 {
1075 m_nRWLTimeout = value;
1076 }
1077 }
1078
1079 public string TransmitRPC(string sRPC, string sParam, int nLockTimeOut)
1080 {
1081 lock (this) // This method CANNOT be executed simultaneously!
1082 {
1083 try
1084 {
1085 try
1086 {
1087 if (m_bConnected == false)
1088 {
1089 throw new BMXNetException("BMXNetLib.TransmitRPC failed because BMXNetLib is not connected to RPMS.");
1090 }
1091 Debug.Assert(m_cDUZ != "");
1092 Debug.Assert(m_pCommSocket != null);
1093
1094 string sOldAppContext = "";
1095 /* 3110109 -- smh Commented out for performance issues.
1096 if (sRPC.StartsWith("BMX")&&(this.m_cAppContext != "BMXRPC"))
1097 {
1098 sOldAppContext = this.m_cAppContext;
1099 this.AppContext = "BMXRPC";
1100 }
1101 */
1102 string sMult = "";
1103 string sSend = ADEBLDMsg(m_cHDR, sRPC, sParam, ref sMult);
1104 SendString(m_pCommSocket, sSend, sMult);
1105#if TRACE
1106 DateTime sendTime = DateTime.Now;
1107 int threadid = Thread.CurrentThread.ManagedThreadId;
1108 Debug.Write("TransmitRPC Sent: (T:" + threadid + ")" + sSend.Replace((char)30, (char)10) + "\n");
1109#endif
1110 string strResult = ReceiveString(m_pCommSocket);
1111#if TRACE
1112 DateTime receiveTime = DateTime.Now;
1113 Debug.Write("TransmitRPC Received: (T:" + threadid + ")" + strResult.Replace((char)30, (char)10) + "\n");
1114 TimeSpan executionTime = receiveTime - sendTime;
1115 Debug.Write("Execution Time: " + executionTime.TotalMilliseconds + " ms.\n");
1116 Debug.Write("-------------------------------------------------------\n");
1117#endif
1118 /* /* 3110109 -- smh Commented out for performance issues.
1119 * if (sOldAppContext != "")
1120 {
1121 this.AppContext = sOldAppContext;
1122 }
1123 */
1124 return strResult;
1125 }
1126 catch (Exception ex)
1127 {
1128 if (ex.Message == "Unable to write data to the transport connection.")
1129 {
1130 m_bConnected = false;
1131 }
1132 throw ex;
1133 }
1134 finally
1135 {
1136 }
1137 }
1138 catch (ApplicationException aex)
1139 {
1140 // The writer lock request timed out.
1141 Debug.Write("TransmitRPC writer lock request timed out.\n");
1142 throw aex;
1143 }
1144 catch (Exception OuterEx)
1145 {
1146 throw OuterEx;
1147 }
1148 }
1149 }
1150
1151 public string TransmitRPC(string sRPC, string sParam)
1152 {
1153 try
1154 {
1155 return TransmitRPC(sRPC, sParam, m_nRWLTimeout);
1156 }
1157 catch (ApplicationException aex)
1158 {
1159 throw aex;
1160 }
1161 catch (Exception ex)
1162 {
1163 throw ex;
1164 }
1165 }
1166
1167 public string GetLoginFacility()
1168 {
1169 try
1170 {
1171 if (m_bConnected == false)
1172 {
1173 throw new BMXNetException("BMXNetLib is not connected to RPMS");
1174 }
1175
1176 if (m_cLoginFacility != "")
1177 {
1178 return m_cLoginFacility;
1179 }
1180
1181 Debug.Assert(m_pCommSocket != null);
1182 Debug.Assert(m_cDUZ != "");
1183 SendString(m_pCommSocket, ADEBLDMsg(m_cHDR, "BMXGetFac", m_cDUZ));
1184 string sFac = ReceiveString(m_pCommSocket);
1185 m_cLoginFacility = sFac;
1186 return sFac;
1187 }
1188 catch (BMXNetException bmxEx)
1189 {
1190 string sMessage = bmxEx.Message + bmxEx.StackTrace;
1191 throw new BMXNetException(sMessage);
1192 }
1193 catch (Exception ex)
1194 {
1195 throw ex;
1196 }
1197 }
1198
1199 #endregion RPX Functions
1200
1201 #region RPX Properties
1202
1203 /// <summary>
1204 /// Set and retrieve the timeout, in milliseconds, to receive a response from the RPMS server.
1205 /// If the retrieve time exceeds the timeout, an exception will be thrown and the connection will be closed.
1206 /// The default is 30 seconds.
1207 /// </summary>
1208 public int ReceiveTimeout
1209 {
1210 get { return m_nReceiveTimeout; }
1211 set { m_nReceiveTimeout = value; }
1212 }
1213
1214 public string WKID
1215 {
1216 get
1217 {
1218 return m_sWKID;
1219 }
1220 set
1221 {
1222 m_sWKID = value;
1223 }
1224 }
1225
1226 public string PRCH
1227 {
1228 get
1229 {
1230 return m_sPRCH;
1231 }
1232 set
1233 {
1234 m_sPRCH = value;
1235 }
1236 }
1237
1238 public string WINH
1239 {
1240 get
1241 {
1242 return m_sWINH;
1243 }
1244 set
1245 {
1246 m_sWINH = value;
1247 }
1248 }
1249
1250 public string WISH
1251 {
1252 get
1253 {
1254 return m_sWISH;
1255 }
1256 set
1257 {
1258 m_sWISH = value;
1259 }
1260 }
1261
1262 /// <summary>
1263 /// Gets/sets the Kernel Application context
1264 /// Throws an exception if unable to set the context.
1265 /// </summary>
1266 public string AppContext
1267 {
1268 get
1269 {
1270 return m_cAppContext;
1271 }
1272 set
1273 {
1274 //Send the changed context to RPMS
1275 if ((m_bConnected == true) && (value != ""))
1276 {
1277 try
1278 {
1279 string sRPC = ADEEncryp(value);
1280 string sAuthentication = TransmitRPC("XWB CREATE CONTEXT", sRPC);
1281
1282 if (BMXNetLib.FindSubString(sAuthentication, "does not have access to option") > -1)
1283 {
1284 throw new BMXNetException(sAuthentication);
1285 }
1286
1287 }
1288 catch (Exception ex)
1289 {
1290 Debug.Write(ex.Message);
1291 throw ex;
1292 }
1293 }
1294 m_cAppContext = value;
1295 }
1296 }
1297
1298 public bool Connected
1299 {
1300 get
1301 {
1302 return m_bConnected;
1303 }
1304 }
1305
1306 public string DUZ
1307 {
1308 get
1309 {
1310 return m_cDUZ;
1311 }
1312 }
1313
1314 public string MServerAddress
1315 {
1316 get
1317 {
1318 return m_cServerAddress;
1319 }
1320 }
1321
1322 public string MServerNamespace
1323 {
1324 get
1325 {
1326 return m_sNameSpace;
1327 }
1328 set
1329 {
1330 m_sNameSpace = value;
1331 }
1332 }
1333
1334 public int MServerPort
1335 {
1336 get
1337 {
1338 return m_nMServerPort;
1339 }
1340 set
1341 {
1342 m_nMServerPort = value;
1343 }
1344 }
1345
1346 public string NameSpace
1347 {
1348 get
1349 {
1350 return m_sNameSpace;
1351 }
1352 set
1353 {
1354 m_sNameSpace = value;
1355 }
1356 }
1357
1358 /// <summary>
1359 /// Gets or Sets the Default Encoder to use
1360 /// </summary>
1361 public Encoding Encoder
1362 {
1363 get
1364 {
1365 return this.m_Encoding;
1366 }
1367 set
1368 {
1369 this.m_Encoding = value;
1370 }
1371 }
1372
1373 #endregion RPX Properties
1374
1375 }
1376}
Note: See TracBrowser for help on using the repository browser.