00001 using System;
00002 using System.Collections;
00003 using System.Collections.Specialized;
00004 using System.Threading;
00005 using Common;
00006 using ProtocolStack;
00007
00008 namespace Client {
00013 public class ServerStub {
00014 public delegate void ServerStubCallback(object o);
00015 public MessageQueue toServerMsgQ;
00016 public MessageQueue fromServerMsgQ;
00017 private StackInterface customProtocolStack;
00018 private Thread processingThread;
00019 private CallbackList callbackList;
00020 ClientControl clientControl;
00021
00022 public PendingRequestManager pendingRequestManager;
00023
00024
00025 public ServerStub(ClientControl clientControl) {
00026 try {
00027 this.clientControl = clientControl;
00028 customProtocolStack = new StackInterface(new ConnectionResetDelegate(clientControl.ResetConnection));
00029 pendingRequestManager = new PendingRequestManager(clientControl);
00030 toServerMsgQ = customProtocolStack.MessagesToSend;
00031 fromServerMsgQ = customProtocolStack.ReceivedMessages;
00032 callbackList = new CallbackList();
00033 } catch (ApplicationException appEx) {
00034 throw new ApplicationException("Unable to create Server Proxy interface in Client Library", appEx);
00035 }
00036 }
00037
00038 public void ResetConnection() {
00039 Console.WriteLine("### TODO: Server stub specific connection reset code ###");
00040 customProtocolStack.ResetConnection();
00041 }
00042
00046 public void ServiceReq(HTTPRequest req, Connection client) {
00047
00048 HTTPResponseHandler handler = new HTTPResponseHandler(req, client, clientControl);
00049 int callbackRcpt = callbackList.RegisterHandler(handler);
00050
00051
00052 EncodedHTTPRequest encodedReq = new EncodedHTTPRequest(req);
00053
00054 HTTPRequestMessage outgoingMessage = new HTTPRequestMessage(encodedReq, callbackRcpt, null);
00055 outgoingMessage.Destination = clientControl.settings.ServerID;
00056
00057 pendingRequestManager.ServiceRequest(req.URI, outgoingMessage, handler);
00058 toServerMsgQ.EnqueueBlocking(outgoingMessage);
00059 }
00060
00064 public void Freshen(byte[] CHK, HTTPRequest request, HTTPResponseHandler responseHandler) {
00065
00066 int callback = callbackList.RegisterHandler(responseHandler);
00067 HTTPRequestMessage reqMsg = new HTTPRequestMessage(new EncodedHTTPRequest(request), callback, CHK);
00068 reqMsg.Destination = clientControl.settings.ServerID;
00069
00070
00071 pendingRequestManager.ServiceRequest(request.URI, reqMsg, responseHandler);
00072 }
00073
00074 public void SendCacheIndexMessage(CacheIndexMessage msg) {
00075 toServerMsgQ.EnqueueBlocking(msg);
00076 clientControl.msgLog.LogSend("CLIENT CACHE INDEX MESSAGE Sent");
00077 }
00078
00082 public void Start() {
00083 customProtocolStack.Start();
00084 if (processingThread == null || !processingThread.IsAlive) {
00085 processingThread = new Thread(new ThreadStart(this.run));
00086 processingThread.Start();
00087 }
00088 }
00089
00093 public void Stop() {
00094 customProtocolStack.Stop();
00095 if (processingThread != null && processingThread.IsAlive) {
00096 processingThread.Abort();
00097 processingThread.Join();
00098 }
00099 }
00100
00104 public void run() {
00105 Message currentMsg;
00106 try {
00107 while(true) {
00108 try {
00109 currentMsg = fromServerMsgQ.DequeueBlocking();
00110
00111 ActionMessage(currentMsg);
00112 } catch (ApplicationException appEx) {
00113 Console.Error.WriteLine("*** Error processing incoming message ***\n{0}", appEx);
00114 }
00115 }
00116 } catch (ThreadAbortException) {
00117 Console.WriteLine("Shuting down 'from server' message queue processing");
00118 }
00119 }
00120
00121 public void ActionMessage(Message msg) {
00122
00123 switch(msg.Type) {
00124 case MessageType.NoChange:
00125 case MessageType.HTTPResponse: {
00126 IResponseHandler respHandler = (IResponseHandler)callbackList[((IContainsCallback)msg).CallbackReceipt];
00127 respHandler.Handle(msg);
00128 clientControl.serverStub.pendingRequestManager.HandleRemainingRequests(((HTTPResponseHandler)respHandler).RequestUri, msg, true);
00129 break;
00130 }
00131 case MessageType.CacheUpdateHTTPResponse: {
00132 clientControl.clientCacheManager.Handle(msg);
00133 clientControl.serverStub.pendingRequestManager.HandleRemainingRequests(((ICacheUpdateMessage)msg).RequestUri, msg, false);
00134 break;
00135 }
00136 case MessageType.CacheUpdateNoChange: {
00137 clientControl.clientCacheManager.Handle(msg);
00138 clientControl.serverStub.pendingRequestManager.HandleRemainingRequests(((ICacheUpdateMessage)msg).RequestUri, msg, false);
00139 break;
00140 }
00141 case MessageType.CacheIndexRequest: {
00142 clientControl.clientCacheManager.Handle(msg);
00143 break;
00144 }
00145 case MessageType.HTTPRequest: {
00146
00147 throw new Exception("Warning! HTTP Request received at client");
00148 }
00149 case MessageType.Retransmission: {
00150
00151 throw new Exception("Warning! Retransmission message made it past the protocol level");
00152 }
00153 case MessageType.Noop: {
00154 break;
00155 }
00156 default: {
00157 throw new ApplicationException(String.Format("Unrecognised message of type \"{0}\" in Server Stub receive queue processing", msg.Type));
00158 }
00159 }
00160 }
00161
00162 }
00163
00164
00165
00166
00167 class CallbackList : ListDictionary {
00171 Random rand;
00172
00173 public CallbackList() {
00174 rand = new Random();
00175 }
00176
00177 public int RegisterHandler(IResponseHandler responseHandler) {
00178 int receipt = rand.Next();
00179 while (this.Contains(receipt)) {
00180 receipt = rand.Next();
00181 }
00182 this.Add(receipt, responseHandler);
00183 return receipt;
00184 }
00185
00186 }
00187
00188
00189 }