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

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

Support for UTF-8 encoding.

File size: 35.3 KB
Line 
1using System;
2using System.Diagnostics;
3using System.Text;
4using System.IO;
5using System.Net.Sockets;
6using System.Net;
7using System.Security.Cryptography;
8using System.Security.Permissions;
9using System.Security.Principal;
10using System.Threading;
11using System.Timers;
12
13namespace IndianHealthService.BMXNet
14{
15 /// <summary>
16 /// BMXNetLib implements low-level socket connectivity to RPMS databases.
17 /// The VA RPC Broker must be running on the RPMS server in order for
18 /// BMXNetLib to connect.
19 /// </summary>
20 [DnsPermission(SecurityAction.Assert, Unrestricted = true)]
21 public class BMXNetLib
22 {
23 /// <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(s);
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, numberOfBytesRead -1); //utf8
921 sbAll.Append(sReadBuffer, 0, sReadBuffer.Length - 1);
922 }
923 else
924 {
925 sbAll.Append(sReadBuffer);
926 }
927 }
928 while(bFinished == false);
929 if (this.m_bLogging == true)
930 {
931 Log("Received: " + sbAll.ToString(), this.m_LogWriter);
932 }
933 return sbAll.ToString();
934
935 }
936 private bool SendSecurityRequest(WindowsIdentity winIdentity)
937 {
938 string strReceive = "";
939 string cMSG;
940 string sTest;
941
942 //Build AV Call
943 cMSG = ADEBLDMsg(m_cHDR, "BMX AV CODE", winIdentity.Name);
944 SendString(m_pCommSocket, cMSG);
945
946 strReceive = ReceiveString(m_pCommSocket);
947 sTest = strReceive.Substring(0,3);
948
949
950 char[] cDelim = {(char) 13,(char) 10,(char) 0};
951 string sDelim = new string(cDelim);
952 int nPiece = 1;
953 m_cDUZ = Piece(strReceive, sDelim , nPiece);
954 if ((m_cDUZ == "0")||(m_cDUZ == ""))
955 {
956 nPiece = 7;
957 string sReason = Piece(strReceive, sDelim, nPiece);
958 throw new Exception(sReason);
959 }
960
961 return true;
962 }
963
964 private bool SendSecurityRequest(string sAccess, string sVerify)
965 {
966 string strReceive = "";
967 string cMSG;
968 sAccess = sAccess.ToUpper();
969 sVerify = sVerify.ToUpper();
970
971 //Build AV Call
972 string strAV = sAccess + ";" + sVerify;
973 strAV = ADEEncryp(strAV);
974 cMSG = ADEBLDMsg(m_cHDR, "XUS AV CODE", strAV);
975 SendString(m_pCommSocket, cMSG);
976
977 strReceive = ReceiveString(m_pCommSocket);
978
979 char[] cDelim = {(char) 13,(char) 10,(char) 0};
980 string sDelim = new string(cDelim);
981 int nPiece = 1;
982 m_cDUZ = Piece(strReceive, sDelim , nPiece);
983 if ((m_cDUZ == "0")||(m_cDUZ == ""))
984 {
985 nPiece = 7;
986 string sReason = Piece(strReceive, sDelim, nPiece);
987 throw new Exception(sReason);
988 }
989
990 return true;
991 }
992
993 public void CloseConnection()
994 {
995 if (!m_bConnected)
996 {
997 return;
998 }
999 SendString(m_pCommSocket, "#BYE#");
1000 m_pCommSocket.Close();
1001 m_bConnected = false;
1002 m_cServerAddress = "";
1003 // m_cDUZ2 = "";
1004 m_cDUZ = "";
1005 }
1006
1007 public bool Lock(string Variable)
1008 {
1009 return Lock(Variable, "", "");
1010 }
1011
1012 public bool Lock(string Variable, string Increment)
1013 {
1014 return Lock(Variable, Increment, "");
1015 }
1016
1017 /// <summary>
1018 /// Lock a local or global M variable
1019 /// Returns true if lock is obtained during TimeOut seconds
1020 /// Use + to increment, - to decrement lock.
1021 /// </summary>
1022 /// <param name="Variable"></param>
1023 /// <param name="Increment"></param>
1024 /// <param name="TimeOut"></param>
1025 /// <returns></returns>
1026 public bool Lock(string Variable, string Increment, string TimeOut)
1027 {
1028 try
1029 {
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 this.AppContext = sContext;
1039 return bRet;
1040 }
1041 catch (Exception ex)
1042 {
1043 string sMsg = ex.Message;
1044 return false;
1045 }
1046 }
1047
1048 static ReaderWriterLock m_rwl = new ReaderWriterLock();
1049 private int m_nRWLTimeout = 30000; //30-second default timeout
1050
1051 /// <summary>
1052 /// Returns a reference to the internal ReaderWriterLock member.
1053 /// </summary>
1054 public ReaderWriterLock BMXRWL
1055 {
1056 get
1057 {
1058 return m_rwl;
1059 }
1060 }
1061
1062 /// <summary>
1063 /// Sets and returns the timeout in milliseconds for locking the transmit port.
1064 /// If the transmit port is unavailable an ApplicationException will be thrown.
1065 /// </summary>
1066 public int RWLTimeout
1067 {
1068 get
1069 {
1070 return m_nRWLTimeout;
1071 }
1072 set
1073 {
1074 m_nRWLTimeout = value;
1075 }
1076 }
1077
1078 public string TransmitRPC(string sRPC, string sParam, int nLockTimeOut)
1079 {
1080 try
1081 {
1082 try
1083 {
1084 if (m_bConnected == false)
1085 {
1086 throw new BMXNetException("BMXNetLib.TransmitRPC failed because BMXNetLib is not connected to RPMS.");
1087 }
1088 Debug.Assert(m_cDUZ != "");
1089 Debug.Assert(m_pCommSocket != null);
1090
1091 string sOldAppContext = "";
1092 if (sRPC.StartsWith("BMX")&&(this.m_cAppContext != "BMXRPC"))
1093 {
1094 sOldAppContext = this.m_cAppContext;
1095 this.AppContext = "BMXRPC";
1096 }
1097 string sMult = "";
1098 string sSend = ADEBLDMsg(m_cHDR, sRPC, sParam, ref sMult);
1099 SendString(m_pCommSocket, sSend, sMult);
1100#if TRACE
1101 DateTime sendTime = DateTime.Now;
1102 Debug.Write("TransmitRPC Sent: " + sSend.Replace((char) 30, (char) 10) + "\n");
1103#endif
1104 string strResult = ReceiveString(m_pCommSocket);
1105#if TRACE
1106 DateTime receiveTime = DateTime.Now;
1107 Debug.Write("TransmitRPC Received: " + strResult.Replace((char) 30, (char) 10) + "\n");
1108 TimeSpan executionTime = receiveTime - sendTime;
1109 Debug.Write("Execution Time: " + executionTime.Milliseconds + " ms.\n");
1110#endif
1111 if (sOldAppContext != "")
1112 {
1113 this.AppContext = sOldAppContext;
1114 }
1115 return strResult;
1116 }
1117 catch (Exception ex)
1118 {
1119 if (ex.Message == "Unable to write data to the transport connection.")
1120 {
1121 m_bConnected = false;
1122 }
1123 throw ex;
1124 }
1125 finally
1126 {
1127 }
1128 }
1129 catch (ApplicationException aex)
1130 {
1131 // The writer lock request timed out.
1132 Debug.Write("TransmitRPC writer lock request timed out.\n");
1133 throw aex;
1134 }
1135 catch (Exception OuterEx)
1136 {
1137 throw OuterEx;
1138 }
1139 }
1140
1141 public string TransmitRPC(string sRPC, string sParam)
1142 {
1143 try
1144 {
1145 return TransmitRPC(sRPC, sParam, m_nRWLTimeout);
1146 }
1147 catch (ApplicationException aex)
1148 {
1149 throw aex;
1150 }
1151 catch (Exception ex)
1152 {
1153 throw ex;
1154 }
1155 }
1156
1157 public string GetLoginFacility()
1158 {
1159 try
1160 {
1161 if (m_bConnected == false)
1162 {
1163 throw new BMXNetException("BMXNetLib is not connected to RPMS");
1164 }
1165
1166 if (m_cLoginFacility != "")
1167 {
1168 return m_cLoginFacility;
1169 }
1170
1171 Debug.Assert(m_pCommSocket != null);
1172 Debug.Assert(m_cDUZ != "");
1173 SendString(m_pCommSocket, ADEBLDMsg(m_cHDR, "BMXGetFac", m_cDUZ));
1174 string sFac = ReceiveString(m_pCommSocket);
1175 m_cLoginFacility = sFac;
1176 return sFac;
1177 }
1178 catch (BMXNetException bmxEx)
1179 {
1180 string sMessage = bmxEx.Message + bmxEx.StackTrace;
1181 throw new BMXNetException(sMessage);
1182 }
1183 catch (Exception ex)
1184 {
1185 throw ex;
1186 }
1187 }
1188
1189 #endregion RPX Functions
1190
1191 #region RPX Properties
1192
1193 /// <summary>
1194 /// Set and retrieve the timeout, in milliseconds, to receive a response from the RPMS server.
1195 /// If the retrieve time exceeds the timeout, an exception will be thrown and the connection will be closed.
1196 /// The default is 30 seconds.
1197 /// </summary>
1198 public int ReceiveTimeout
1199 {
1200 get { return m_nReceiveTimeout; }
1201 set { m_nReceiveTimeout = value; }
1202 }
1203
1204 public string WKID
1205 {
1206 get
1207 {
1208 return m_sWKID;
1209 }
1210 set
1211 {
1212 m_sWKID = value;
1213 }
1214 }
1215
1216 public string PRCH
1217 {
1218 get
1219 {
1220 return m_sPRCH;
1221 }
1222 set
1223 {
1224 m_sPRCH = value;
1225 }
1226 }
1227
1228 public string WINH
1229 {
1230 get
1231 {
1232 return m_sWINH;
1233 }
1234 set
1235 {
1236 m_sWINH = value;
1237 }
1238 }
1239
1240 public string WISH
1241 {
1242 get
1243 {
1244 return m_sWISH;
1245 }
1246 set
1247 {
1248 m_sWISH = value;
1249 }
1250 }
1251
1252 /// <summary>
1253 /// Gets/sets the Kernel Application context
1254 /// Throws an exception if unable to set the context.
1255 /// </summary>
1256 public string AppContext
1257 {
1258 get
1259 {
1260 return m_cAppContext;
1261 }
1262 set
1263 {
1264 //Send the changed context to RPMS
1265 if ((m_bConnected == true) && (value != ""))
1266 {
1267 try
1268 {
1269 string sRPC = ADEEncryp(value);
1270 string sAuthentication = TransmitRPC("XWB CREATE CONTEXT", sRPC);
1271
1272 if (BMXNetLib.FindSubString(sAuthentication, "does not have access to option") > -1)
1273 {
1274 throw new BMXNetException(sAuthentication);
1275 }
1276
1277 }
1278 catch (Exception ex)
1279 {
1280 Debug.Write(ex.Message);
1281 throw ex;
1282 }
1283 }
1284 m_cAppContext = value;
1285 }
1286 }
1287
1288 public bool Connected
1289 {
1290 get
1291 {
1292 return m_bConnected;
1293 }
1294 }
1295
1296 public string DUZ
1297 {
1298 get
1299 {
1300 return m_cDUZ;
1301 }
1302 }
1303
1304 public string MServerAddress
1305 {
1306 get
1307 {
1308 return m_cServerAddress;
1309 }
1310 }
1311
1312 public string MServerNamespace
1313 {
1314 get
1315 {
1316 return m_sNameSpace;
1317 }
1318 set
1319 {
1320 m_sNameSpace = value;
1321 }
1322 }
1323
1324 public int MServerPort
1325 {
1326 get
1327 {
1328 return m_nMServerPort;
1329 }
1330 set
1331 {
1332 m_nMServerPort = value;
1333 }
1334 }
1335
1336 public string NameSpace
1337 {
1338 get
1339 {
1340 return m_sNameSpace;
1341 }
1342 set
1343 {
1344 m_sNameSpace = value;
1345 }
1346 }
1347
1348 /// <summary>
1349 /// Gets or Sets the Default Encoder to use
1350 /// </summary>
1351 public Encoding Encoder
1352 {
1353 get
1354 {
1355 return this.m_Encoding;
1356 }
1357 set
1358 {
1359 this.m_Encoding = Encoder;
1360 }
1361 }
1362
1363 #endregion RPX Properties
1364
1365 }
1366}
Note: See TracBrowser for help on using the repository browser.