Main Page | Class Hierarchy | Class List | File List | Class Members

HTTPObject.cs

00001 using System;
00002 using System.Threading;
00003 using System.Collections;
00004 using System.Collections.Specialized;
00005 using System.Text;
00006 using System.IO;
00007 using System.Net;
00008 using System.Net.Sockets;
00009 using System.Security.Cryptography;
00010 
00011 namespace Common
00012 {
00016         public abstract class HTTPObject
00017         {
00018                 protected HTTPHeader headers;
00019                 protected HTTPBody body;
00020 
00021                 public HTTPObject() {}
00022 
00023                 public byte[] Serialise() {
00024                         /* produces byte array in the following format:
00025                          * 0..3: Header Length (int bytes, -1 if no header);
00026                          * 4..7: Body Length (int bytes, -1 if no body)
00027                          * [8..n: Header Data]
00028                          * [n..m; Body Data]
00029                          */ 
00030                         byte[] result;
00031                         byte[] headerBuffer = null;
00032                         byte[] intSizeByteBuffer;
00033                         int resultLength = 0;
00034                         int headerLength = 0;
00035                         int bodyLength = 0;
00036                         if (headers != null) { 
00037                                 headerBuffer = Encoding.ASCII.GetBytes(headers.rawString);
00038                                 headerLength = headerBuffer.Length;
00039                                 resultLength += headerLength;
00040                         } else {
00041                                 headerLength = -1;
00042                         }
00043                         if (body != null) { 
00044                                 bodyLength = body.data.Length;
00045                                 resultLength += bodyLength; 
00046                         } else {
00047                                 bodyLength = -1;
00048                         }
00049                         result = new byte[resultLength + 8]; // add 8 for header length, body length at start
00050                         intSizeByteBuffer = BitConverter.GetBytes(headerLength);
00051                         Array.Copy(intSizeByteBuffer, 0, result, 0, intSizeByteBuffer.Length);
00052                         intSizeByteBuffer = BitConverter.GetBytes(bodyLength);
00053                         Array.Copy(intSizeByteBuffer, 0, result, 4, intSizeByteBuffer.Length);
00054                         if (headers != null) { Array.Copy(headerBuffer, 0, result, 8, headerBuffer.Length); }
00055                         if (body != null) { Array.Copy(body.data, 0, result, 8 + headerBuffer.Length, body.data.Length); }
00056                         return result;
00057                 }
00058 
00059                 public byte[] ToHTTPByteArray() {
00060                         /* produces byte array in the following format:
00061                          * 0..3: Header Length (int bytes, -1 if no header);
00062                          * 4..7: Body Length (int bytes, -1 if no body)
00063                          * [8..n: Header Data]
00064                          * [n..m; Body Data]
00065                          */ 
00066                         byte[] result;
00067                         byte[] headerBuffer = null;
00068                         int resultLength = 0;
00069                         if (headers != null) { 
00070                                 headerBuffer = Encoding.ASCII.GetBytes(headers.rawString);
00071                                 resultLength += headerBuffer.Length;
00072                         }
00073                         if (body != null) { 
00074                                 resultLength += body.data.Length; 
00075                         } 
00076                         result = new byte[resultLength];
00077                         if (headers != null) { Array.Copy(headerBuffer, 0, result, 0, headerBuffer.Length); }
00078                         if (body != null) { Array.Copy(body.data, 0, result, headerBuffer.Length, body.data.Length); }
00079                         return result;
00080                 }
00081 
00082 
00087                 public HTTPObject(byte[] src) {
00088                         int headerLength = BitConverter.ToInt32(src, 0);
00089                         int bodyLength = BitConverter.ToInt32(src, 4);
00090                         if (headerLength != -1 ) {
00091                                 headerBytes = new byte[headerLength];
00092                                 Array.Copy(src, 8, headerBytes, 0, headerLength);
00093                         } else { 
00094                                 headerBytes = null;
00095                         }
00096                         if (bodyLength != -1) {
00097                                 bodyBytes = new byte[bodyLength];
00098                                 Array.Copy(src, 8 + headerLength, bodyBytes, 0, bodyLength);
00099                         } else {
00100                                 bodyBytes = null;
00101                         }
00102                 }
00103 
00104 
00105                 // Used in creation of object from byte array. 
00106                 protected byte[] headerBytes;
00107                 protected byte[] bodyBytes;
00108 
00109                 public void AppendBody(HTTPBody newBody) {
00110                         body = newBody;
00111                 }
00112 
00113                 public byte[] GetCHK() {
00114                         return body.GetCHK();
00115                 }
00116         }
00117 
00118         /*****************************************************************************************/
00119         public class HTTPBody {
00120                 public byte[] data;
00121 
00122                 public HTTPBody(byte[] data) {
00123                         this.data = data;
00124                 }
00125 
00126                 public byte[] GetCHK() {
00127                         SHA1Managed sha1 = new SHA1Managed();
00128                         return sha1.ComputeHash(data);
00129                 }
00130         }
00131 
00132         /*****************************************************************************************/
00133         public abstract class HTTPHeader {
00134                 public string rawString;
00135                 protected int rawStringPos = -1; // at proc exit, points to next readable char (or last)
00136 //              protected string VersionInfo;
00137                 public WebHeaderCollection headerCollection;
00138 
00139                 /*** Constructors ***/
00140 
00141                 public HTTPHeader(string source) {
00142                         rawString = source;
00143                         parseRaw();
00144                 }
00145 
00146                 /*** Methods ***/
00147 
00148                 // Parses the raw data string
00149                 public void parseRaw() {
00150                         rawStringPos = 0;
00151                         this.parseHTTP();
00152                         this.populateRawHeaders();
00153                 }
00154 
00158                 protected abstract void parseHTTP();
00159 //
00160 //              protected void parseVersionInfo(string src) {
00161 //              }
00162 
00163 //              protected void parseResponseText(string src) {
00164 //              }
00165 
00166                 public void populateRawHeaders() {
00167                         string CRLF = "\r\n";
00168                         headerCollection = new WebHeaderCollection();
00169                         // keep on looping until we hit a blank line.
00170                         int i1 = rawStringPos;
00171                         int i2 = rawString.IndexOf(CRLF, i1);
00172                         string s = rawString.Substring(i1, i2-i1);
00173                         while (s != "") {
00174                                 headerCollection.Add(s);
00175                                 i1 = i2 + CRLF.Length;
00176                                 i2 = rawString.IndexOf(CRLF, i1);
00177                                 s = rawString.Substring(i1, i2-i1);
00178                         }
00179                         rawStringPos = i1;
00180                 }
00181         }
00182 
00183 
00184         /**************************************************************************************************/
00185         public class HTTPObjectQueue: Queue {
00186                 //TODO: Comment
00187                 //TODO: Search Client for calls to Enqueue and Dequeue
00188 
00189                 public void EnqueueBlocking(HTTPObject obj) {
00190                         lock(this) {
00191                                 Enqueue(obj);
00192                                 Monitor.Pulse(this);
00193                         }
00194                 }
00195 
00196                 public HTTPObject DequeueBlocking() {
00197                         HTTPObject result;
00198                         lock(this) {
00199                                 while (Count == 0) { Monitor.Wait(this); }
00200                                 result = (HTTPObject)Dequeue();
00201                                 Monitor.Pulse(this);
00202                         }
00203                         return result;
00204                 }
00205 
00206                 
00207         }
00208 
00209         public class StreamUtil {
00210                 public static string ReadLine(ref Stream ns) {
00211                         const byte CR = 13;
00212                         const byte LF = 10;
00213                         byte[] bBuffer = new byte[8 * 1024]; // 8kB Buffer
00214                         int elementCount = 0;
00215                         bool endOfStream = false;
00216                         bool endOfLine = false;
00217 
00218                         string sBuffer;
00219                         int readByteResult;
00220                         byte currentByte;
00221 
00222                         while (!endOfStream && !endOfLine) {
00223                                 readByteResult = ns.ReadByte();
00224                                 if (readByteResult == -1) {
00225                                         endOfStream = true;
00226                                 } else {
00227                                         currentByte = (byte)readByteResult;
00228                                         if (currentByte == CR) {
00229                                                 readByteResult = ns.ReadByte();
00230                                                 if (readByteResult == -1) {
00231                                                         endOfStream = true;
00232                                                 } else { // if CR & 2nd char is not end of stream
00233                                                         currentByte = (byte)readByteResult;
00234                                                         if (currentByte == LF) { // if second char is LF
00235                                                                 endOfLine = true; // exit search loop
00236                                                         } else { // second char was not LF
00237                                                                 append(ref bBuffer, ref elementCount, CR);
00238                                                                 append(ref bBuffer, ref elementCount, currentByte);
00239                                                         }
00240                                                 } // end 2nd char switch
00241                                         } else if (currentByte == LF) { // else if 1st char was LF
00242                                                 endOfLine = true; // exit the search loop
00243                                         } else { // 1st char was not CR or LF
00244                                                 append(ref bBuffer, ref elementCount, currentByte);
00245                                         }
00246                                 }
00247                         }
00248                         if (endOfStream) {
00249                                 // do fancy end of stream processing
00250                                 sBuffer = null;
00251                         } else {
00252                                 // convert bBuffer into sBuffer
00253                                 sBuffer = Encoding.ASCII.GetString(bBuffer, 0, elementCount);
00254                         }
00255                         return sBuffer; 
00256                 }
00257 
00258                 private static byte[] ReadBody(ref Stream ns, bool haveTarget, int targetBytes) {
00259                         // init variables
00260                         byte[] readBuffer = new byte[8*1024];
00261                         byte[] bBuffer = new byte[8*1024];
00262                         bool endOfStream = false;
00263                         int readByteResult;
00264                         byte currentByte;
00265 
00266                         int totalBytesRead = 0;
00267 
00268                         // read the stream
00269                         while (!endOfStream && (haveTarget ? totalBytesRead < targetBytes : true)) {
00270                                 readByteResult = ns.ReadByte();
00271                                 if (readByteResult != -1) {
00272                                         currentByte = (byte)readByteResult;
00273                                         append(ref bBuffer, ref totalBytesRead, currentByte);
00274                                         //append(ref bBuffer, ref totalBytesRead, readBuffer);
00275                                 } else { // end of stream?
00276                                         endOfStream = true;
00277                                 }
00278                         }
00279                         
00280                         // return the trimmed result
00281                         byte[] result = new byte[totalBytesRead];
00282                         Array.Copy(bBuffer, result, totalBytesRead);
00283                         return result;
00284                 }
00285 
00286                 public static byte[] ReadBody(ref Stream ns, int targetBytes) {
00287                         return ReadBody(ref ns, true, targetBytes);
00288                 }
00289                 public static byte[] ReadBody(ref Stream ns) {
00290                         return ReadBody(ref ns, false, 0);
00291                 }
00292 
00293                 private static void append(ref byte[] buffer, ref int elementCount,  byte data) {
00294                         if (elementCount + 1 > buffer.Length) {
00295                                 byte[] newBuffer = new byte[buffer.Length * 2];
00296                                 Array.Copy(buffer, 0, newBuffer, 0, buffer.Length);
00297                                 buffer = newBuffer;
00298                         }
00299                         buffer[elementCount] = data;
00300                         elementCount++;
00301                 }
00302 
00303         }
00304 }

Generated on Mon May 8 22:07:27 2006 by  doxygen 1.3.9.1