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

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

Ooops. Encoding boo boo.

File size: 35.2 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, 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 string sContext = this.AppContext;
1030 this.AppContext = "BMXRPC";
1031 Variable = Variable.Replace("^","~");
1032 string sRet = "0";
1033 bool bRet = false;
1034 string sParam = Variable + "^" + Increment + "^" + TimeOut;
1035 sRet = TransmitRPC("BMX LOCK", sParam);
1036 bRet = (sRet == "1")?true:false;
1037 this.AppContext = sContext;
1038 return bRet;
1039 }
1040 catch (Exception ex)
1041 {
1042 string sMsg = ex.Message;
1043 return false;
1044 }
1045 }
1046
1047 static ReaderWriterLock m_rwl = new ReaderWriterLock();
1048 private int m_nRWLTimeout = 30000; //30-second default timeout
1049
1050 /// <summary>
1051 /// Returns a reference to the internal ReaderWriterLock member.
1052 /// </summary>
1053 public ReaderWriterLock BMXRWL
1054 {
1055 get
1056 {
1057 return m_rwl;
1058 }
1059 }
1060
1061 /// <summary>
1062 /// Sets and returns the timeout in milliseconds for locking the transmit port.
1063 /// If the transmit port is unavailable an ApplicationException will be thrown.
1064 /// </summary>
1065 public int RWLTimeout
1066 {
1067 get
1068 {
1069 return m_nRWLTimeout;
1070 }
1071 set
1072 {
1073 m_nRWLTimeout = value;
1074 }
1075 }
1076
1077 public string TransmitRPC(string sRPC, string sParam, int nLockTimeOut)
1078 {
1079 try
1080 {
1081 try
1082 {
1083 if (m_bConnected == false)
1084 {
1085 throw new BMXNetException("BMXNetLib.TransmitRPC failed because BMXNetLib is not connected to RPMS.");
1086 }
1087 Debug.Assert(m_cDUZ != "");
1088 Debug.Assert(m_pCommSocket != null);
1089
1090 string sOldAppContext = "";
1091 if (sRPC.StartsWith("BMX")&&(this.m_cAppContext != "BMXRPC"))
1092 {
1093 sOldAppContext = this.m_cAppContext;
1094 this.AppContext = "BMXRPC";
1095 }
1096 string sMult = "";
1097 string sSend = ADEBLDMsg(m_cHDR, sRPC, sParam, ref sMult);
1098 SendString(m_pCommSocket, sSend, sMult);
1099#if TRACE
1100 DateTime sendTime = DateTime.Now;
1101 Debug.Write("TransmitRPC Sent: " + sSend.Replace((char) 30, (char) 10) + "\n");
1102#endif
1103 string strResult = ReceiveString(m_pCommSocket);
1104#if TRACE
1105 DateTime receiveTime = DateTime.Now;
1106 Debug.Write("TransmitRPC Received: " + strResult.Replace((char) 30, (char) 10) + "\n");
1107 TimeSpan executionTime = receiveTime - sendTime;
1108 Debug.Write("Execution Time: " + executionTime.Milliseconds + " ms.\n");
1109#endif
1110 if (sOldAppContext != "")
1111 {
1112 this.AppContext = sOldAppContext;
1113 }
1114 return strResult;
1115 }
1116 catch (Exception ex)
1117 {
1118 if (ex.Message == "Unable to write data to the transport connection.")
1119 {
1120 m_bConnected = false;
1121 }
1122 throw ex;
1123 }
1124 finally
1125 {
1126 }
1127 }
1128 catch (ApplicationException aex)
1129 {
1130 // The writer lock request timed out.
1131 Debug.Write("TransmitRPC writer lock request timed out.\n");
1132 throw aex;
1133 }
1134 catch (Exception OuterEx)
1135 {
1136 throw OuterEx;
1137 }
1138 }
1139
1140 public string TransmitRPC(string sRPC, string sParam)
1141 {
1142 try
1143 {
1144 return TransmitRPC(sRPC, sParam, m_nRWLTimeout);
1145 }
1146 catch (ApplicationException aex)
1147 {
1148 throw aex;
1149 }
1150 catch (Exception ex)
1151 {
1152 throw ex;
1153 }
1154 }
1155
1156 public string GetLoginFacility()
1157 {
1158 try
1159 {
1160 if (m_bConnected == false)
1161 {
1162 throw new BMXNetException("BMXNetLib is not connected to RPMS");
1163 }
1164
1165 if (m_cLoginFacility != "")
1166 {
1167 return m_cLoginFacility;
1168 }
1169
1170 Debug.Assert(m_pCommSocket != null);
1171 Debug.Assert(m_cDUZ != "");
1172 SendString(m_pCommSocket, ADEBLDMsg(m_cHDR, "BMXGetFac", m_cDUZ));
1173 string sFac = ReceiveString(m_pCommSocket);
1174 m_cLoginFacility = sFac;
1175 return sFac;
1176 }
1177 catch (BMXNetException bmxEx)
1178 {
1179 string sMessage = bmxEx.Message + bmxEx.StackTrace;
1180 throw new BMXNetException(sMessage);
1181 }
1182 catch (Exception ex)
1183 {
1184 throw ex;
1185 }
1186 }
1187
1188 #endregion RPX Functions
1189
1190 #region RPX Properties
1191
1192 /// <summary>
1193 /// Set and retrieve the timeout, in milliseconds, to receive a response from the RPMS server.
1194 /// If the retrieve time exceeds the timeout, an exception will be thrown and the connection will be closed.
1195 /// The default is 30 seconds.
1196 /// </summary>
1197 public int ReceiveTimeout
1198 {
1199 get { return m_nReceiveTimeout; }
1200 set { m_nReceiveTimeout = value; }
1201 }
1202
1203 public string WKID
1204 {
1205 get
1206 {
1207 return m_sWKID;
1208 }
1209 set
1210 {
1211 m_sWKID = value;
1212 }
1213 }
1214
1215 public string PRCH
1216 {
1217 get
1218 {
1219 return m_sPRCH;
1220 }
1221 set
1222 {
1223 m_sPRCH = value;
1224 }
1225 }
1226
1227 public string WINH
1228 {
1229 get
1230 {
1231 return m_sWINH;
1232 }
1233 set
1234 {
1235 m_sWINH = value;
1236 }
1237 }
1238
1239 public string WISH
1240 {
1241 get
1242 {
1243 return m_sWISH;
1244 }
1245 set
1246 {
1247 m_sWISH = value;
1248 }
1249 }
1250
1251 /// <summary>
1252 /// Gets/sets the Kernel Application context
1253 /// Throws an exception if unable to set the context.
1254 /// </summary>
1255 public string AppContext
1256 {
1257 get
1258 {
1259 return m_cAppContext;
1260 }
1261 set
1262 {
1263 //Send the changed context to RPMS
1264 if ((m_bConnected == true) && (value != ""))
1265 {
1266 try
1267 {
1268 string sRPC = ADEEncryp(value);
1269 string sAuthentication = TransmitRPC("XWB CREATE CONTEXT", sRPC);
1270
1271 if (BMXNetLib.FindSubString(sAuthentication, "does not have access to option") > -1)
1272 {
1273 throw new BMXNetException(sAuthentication);
1274 }
1275
1276 }
1277 catch (Exception ex)
1278 {
1279 Debug.Write(ex.Message);
1280 throw ex;
1281 }
1282 }
1283 m_cAppContext = value;
1284 }
1285 }
1286
1287 public bool Connected
1288 {
1289 get
1290 {
1291 return m_bConnected;
1292 }
1293 }
1294
1295 public string DUZ
1296 {
1297 get
1298 {
1299 return m_cDUZ;
1300 }
1301 }
1302
1303 public string MServerAddress
1304 {
1305 get
1306 {
1307 return m_cServerAddress;
1308 }
1309 }
1310
1311 public string MServerNamespace
1312 {
1313 get
1314 {
1315 return m_sNameSpace;
1316 }
1317 set
1318 {
1319 m_sNameSpace = value;
1320 }
1321 }
1322
1323 public int MServerPort
1324 {
1325 get
1326 {
1327 return m_nMServerPort;
1328 }
1329 set
1330 {
1331 m_nMServerPort = value;
1332 }
1333 }
1334
1335 public string NameSpace
1336 {
1337 get
1338 {
1339 return m_sNameSpace;
1340 }
1341 set
1342 {
1343 m_sNameSpace = value;
1344 }
1345 }
1346
1347 /// <summary>
1348 /// Gets or Sets the Default Encoder to use
1349 /// </summary>
1350 public Encoding Encoder
1351 {
1352 get
1353 {
1354 return this.m_Encoding;
1355 }
1356 set
1357 {
1358 this.m_Encoding = value;
1359 }
1360 }
1361
1362 #endregion RPX Properties
1363
1364 }
1365}
Note: See TracBrowser for help on using the repository browser.