diff --git a/OpenMetaverse.Http/CapsBase.cs b/OpenMetaverse.Http/CapsBase.cs
index 34b3fd30..cdf3f36c 100644
--- a/OpenMetaverse.Http/CapsBase.cs
+++ b/OpenMetaverse.Http/CapsBase.cs
@@ -134,17 +134,15 @@ namespace OpenMetaverse.Http
try
{
// Get the stream to write our upload to
- Stream uploadStream = state.Request.EndGetRequestStream(ar);
+ using (Stream uploadStream = state.Request.EndGetRequestStream(ar))
+ {
+ // Fire the callback for successfully opening the stream
+ if (state.OpenWriteCallback != null)
+ state.OpenWriteCallback(state.Request);
- // Fire the callback for successfully opening the stream
- if (state.OpenWriteCallback != null)
- state.OpenWriteCallback(state.Request);
-
- // Write our data to the upload stream
- uploadStream.Write(state.UploadData, 0, state.UploadData.Length);
- // We don't have to call Close with .NET, but Mono 2.4 will hang on
- // BeginGetResponse if we don't call it
- uploadStream.Close();
+ // Write our data to the upload stream
+ uploadStream.Write(state.UploadData, 0, state.UploadData.Length);
+ }
// Start the request for the remote server response
IAsyncResult result = state.Request.BeginGetResponse(GetResponse, state);
@@ -154,6 +152,7 @@ namespace OpenMetaverse.Http
}
catch (Exception ex)
{
+ Logger.Log.Debug("CapsBase.OpenWrite(): " + ex.Message);
if (state.CompletedCallback != null)
state.CompletedCallback(state.Request, null, null, ex);
}
@@ -168,49 +167,58 @@ namespace OpenMetaverse.Http
try
{
- response = (HttpWebResponse)state.Request.EndGetResponse(ar);
-
- // Get the stream for downloading the response
- Stream responseStream = response.GetResponseStream();
-
- #region Read the response
-
- // If Content-Length is set we create a buffer of the exact size, otherwise
- // a MemoryStream is used to receive the response
- bool nolength = (response.ContentLength <= 0);
- int size = (nolength) ? 8192 : (int)response.ContentLength;
- MemoryStream ms = (nolength) ? new MemoryStream() : null;
- byte[] buffer = new byte[size];
-
- int bytesRead = 0;
- int offset = 0;
-
- while ((bytesRead = responseStream.Read(buffer, offset, size)) != 0)
+ using (response = (HttpWebResponse)state.Request.EndGetResponse(ar))
{
+ // Get the stream for downloading the response
+ Stream responseStream = response.GetResponseStream();
+
+ #region Read the response
+
+ // If Content-Length is set we create a buffer of the exact size, otherwise
+ // a MemoryStream is used to receive the response
+ bool nolength = (response.ContentLength <= 0);
+ int size = (nolength) ? 8192 : (int)response.ContentLength;
+ MemoryStream ms = (nolength) ? new MemoryStream() : null;
+ byte[] buffer = new byte[size];
+
+ int bytesRead = 0;
+ int offset = 0;
+
+ while ((bytesRead = responseStream.Read(buffer, offset, size)) != 0)
+ {
+ if (nolength)
+ {
+ ms.Write(buffer, 0, bytesRead);
+ }
+ else
+ {
+ offset += bytesRead;
+ size -= bytesRead;
+ }
+
+ // Fire the download progress callback for each chunk of received data
+ if (state.DownloadProgressCallback != null)
+ state.DownloadProgressCallback(state.Request, response, bytesRead, size);
+ }
+
if (nolength)
{
- ms.Write(buffer, 0, bytesRead);
+ responseData = ms.ToArray();
+ ms.Close();
}
else
{
- offset += bytesRead;
- size -= bytesRead;
+ responseData = buffer;
}
- // Fire the download progress callback for each chunk of received data
- if (state.DownloadProgressCallback != null)
- state.DownloadProgressCallback(state.Request, response, bytesRead, size);
+ #endregion Read the response
+
+ responseStream.Close();
}
-
- if (nolength)
- responseData = ms.ToArray();
- else
- responseData = buffer;
-
- #endregion Read the response
}
catch (Exception ex)
{
+ Logger.Log.Debug("CapsBase.GetResponse(): " + ex.Message);
error = ex;
}
@@ -223,6 +231,8 @@ namespace OpenMetaverse.Http
if (timedOut)
{
RequestState requestState = state as RequestState;
+ Logger.Log.Warn("CapsBase.TimeoutCallback(): Request to " + requestState.Request.RequestUri +
+ " timed out after " + requestState.MillisecondsTimeout + " milliseconds");
if (requestState != null && requestState.Request != null)
requestState.Request.Abort();
}
diff --git a/OpenMetaverse.Http/CapsClient.cs b/OpenMetaverse.Http/CapsClient.cs
index 3684b4e7..d5ce74b6 100644
--- a/OpenMetaverse.Http/CapsClient.cs
+++ b/OpenMetaverse.Http/CapsClient.cs
@@ -105,14 +105,14 @@ namespace OpenMetaverse.Http
if (postData == null)
{
// GET
- Logger.Log.Debug("[CapsClient] GET " + _Address);
+ //Logger.Log.Debug("[CapsClient] GET " + _Address);
_Request = CapsBase.DownloadStringAsync(_Address, _ClientCert, millisecondsTimeout, DownloadProgressHandler,
RequestCompletedHandler);
}
else
{
// POST
- Logger.Log.Debug("[CapsClient] POST (" + postData.Length + " bytes) " + _Address);
+ //Logger.Log.Debug("[CapsClient] POST (" + postData.Length + " bytes) " + _Address);
_Request = CapsBase.UploadDataAsync(_Address, _ClientCert, contentType, postData, millisecondsTimeout, null,
DownloadProgressHandler, RequestCompletedHandler);
}
diff --git a/OpenMetaverse.Http/CapsServer.cs b/OpenMetaverse.Http/CapsServer.cs
index 1df5446d..183d4db2 100644
--- a/OpenMetaverse.Http/CapsServer.cs
+++ b/OpenMetaverse.Http/CapsServer.cs
@@ -43,8 +43,7 @@ namespace OpenMetaverse.Http
/// HTTP request
/// HTTP response
/// User-defined state object
- /// True to send the response and close the connection, false to leave the connection open
- public delegate bool CapsRequestCallback(IHttpClientContext context, IHttpRequest request, IHttpResponse response, object state);
+ public delegate void CapsRequestCallback(IHttpClientContext context, IHttpRequest request, IHttpResponse response, object state);
public class CapsServer
{
@@ -53,13 +52,15 @@ namespace OpenMetaverse.Http
public CapsRequestCallback LocalCallback;
public Uri RemoteHandler;
public bool ClientCertRequired;
+ public bool SendResponseAfterCallback;
public object State;
- public CapsRedirector(CapsRequestCallback localCallback, Uri remoteHandler, bool clientCertRequired, object state)
+ public CapsRedirector(CapsRequestCallback localCallback, Uri remoteHandler, bool clientCertRequired, bool sendResponseAfterCallback, object state)
{
LocalCallback = localCallback;
RemoteHandler = remoteHandler;
ClientCertRequired = clientCertRequired;
+ SendResponseAfterCallback = sendResponseAfterCallback;
State = state;
}
}
@@ -108,10 +109,21 @@ namespace OpenMetaverse.Http
server.RemoveHandler(capsHandler);
}
+ public UUID CreateCapability(CapsRequestCallback localHandler, bool clientCertRequired, bool sendResponseAfterCallback, object state)
+ {
+ UUID id = UUID.Random();
+ CapsRedirector redirector = new CapsRedirector(localHandler, null, clientCertRequired, sendResponseAfterCallback, state);
+
+ lock (syncRoot)
+ fixedCaps.Add(id, redirector);
+
+ return id;
+ }
+
public UUID CreateCapability(CapsRequestCallback localHandler, bool clientCertRequired, object state)
{
UUID id = UUID.Random();
- CapsRedirector redirector = new CapsRedirector(localHandler, null, clientCertRequired, state);
+ CapsRedirector redirector = new CapsRedirector(localHandler, null, clientCertRequired, true, state);
lock (syncRoot)
fixedCaps.Add(id, redirector);
@@ -119,10 +131,10 @@ namespace OpenMetaverse.Http
return id;
}
- public UUID CreateCapability(Uri remoteHandler, bool clientCertRequired)
+ public UUID CreateCapability(Uri remoteHandler, bool clientCertRequired, bool sendResponseAfterCallback)
{
UUID id = UUID.Random();
- CapsRedirector redirector = new CapsRedirector(null, remoteHandler, clientCertRequired, null);
+ CapsRedirector redirector = new CapsRedirector(null, remoteHandler, clientCertRequired, sendResponseAfterCallback, null);
lock (syncRoot)
fixedCaps.Add(id, redirector);
@@ -130,10 +142,10 @@ namespace OpenMetaverse.Http
return id;
}
- public UUID CreateCapability(CapsRequestCallback localHandler, bool clientCertRequired, object state, double ttlSeconds)
+ public UUID CreateCapability(CapsRequestCallback localHandler, bool clientCertRequired, bool sendResponseAfterCallback, object state, double ttlSeconds)
{
UUID id = UUID.Random();
- CapsRedirector redirector = new CapsRedirector(localHandler, null, clientCertRequired, state);
+ CapsRedirector redirector = new CapsRedirector(localHandler, null, clientCertRequired, sendResponseAfterCallback, state);
lock (syncRoot)
expiringCaps.Add(id, redirector, DateTime.Now + TimeSpan.FromSeconds(ttlSeconds));
@@ -141,10 +153,10 @@ namespace OpenMetaverse.Http
return id;
}
- public UUID CreateCapability(Uri remoteHandler, bool clientCertRequired, object state, double ttlSeconds)
+ public UUID CreateCapability(Uri remoteHandler, bool clientCertRequired, bool sendResponseAfterCallback, object state, double ttlSeconds)
{
UUID id = UUID.Random();
- CapsRedirector redirector = new CapsRedirector(null, remoteHandler, clientCertRequired, state);
+ CapsRedirector redirector = new CapsRedirector(null, remoteHandler, clientCertRequired, sendResponseAfterCallback, state);
lock (syncRoot)
expiringCaps.Add(id, redirector, DateTime.Now + TimeSpan.FromSeconds(ttlSeconds));
@@ -163,7 +175,7 @@ namespace OpenMetaverse.Http
}
}
- bool CapsCallback(IHttpClientContext client, IHttpRequest request, IHttpResponse response)
+ void CapsCallback(IHttpClientContext client, IHttpRequest request, IHttpResponse response)
{
UUID capsID;
CapsRedirector redirector;
@@ -192,14 +204,16 @@ namespace OpenMetaverse.Http
if (redirector.RemoteHandler != null)
ProxyCapCallback(client, request, response, redirector.RemoteHandler);
else
- return redirector.LocalCallback(client, request, response, redirector.State);
+ redirector.LocalCallback(client, request, response, redirector.State);
- return true;
+ if (redirector.SendResponseAfterCallback && !response.Sent)
+ response.Send();
+ return;
}
}
response.Status = HttpStatusCode.NotFound;
- return true;
+ response.Send();
}
void ProxyCapCallback(IHttpClientContext client, IHttpRequest request, IHttpResponse response, Uri remoteHandler)
@@ -223,8 +237,6 @@ namespace OpenMetaverse.Http
{
while ((numBytes = request.Body.Read(buffer, 0, BUFFER_SIZE)) > 0)
writeStream.Write(buffer, 0, numBytes);
-
- request.Body.Close();
}
}
@@ -242,16 +254,16 @@ namespace OpenMetaverse.Http
{
while ((numBytes = readStream.Read(buffer, 0, BUFFER_SIZE)) > 0)
response.Body.Write(buffer, 0, numBytes);
-
- response.Body.Close();
}
+
+ response.Send();
}
HttpRequestHandler BuildCapsHandler(string path)
{
- HttpRequestSignature signature = new HttpRequestSignature();
- signature.Path = path;
- return new HttpServer.HttpRequestHandler(signature, CapsCallback);
+ // All responses have to be send with response.Send() manually to allow proper handling of event queue
+ // capabilities
+ return new HttpServer.HttpRequestHandler(new HttpRequestSignature(null, null, path), CapsCallback, false);
}
}
}
diff --git a/OpenMetaverse.Http/EventQueueServer.cs b/OpenMetaverse.Http/EventQueueServer.cs
index 15f10cbf..4e363914 100644
--- a/OpenMetaverse.Http/EventQueueServer.cs
+++ b/OpenMetaverse.Http/EventQueueServer.cs
@@ -116,7 +116,7 @@ namespace OpenMetaverse.Http
eventQueue.Enqueue(events[i]);
}
- public bool EventQueueHandler(IHttpClientContext context, IHttpRequest request, IHttpResponse response)
+ public void EventQueueHandler(IHttpClientContext context, IHttpRequest request, IHttpResponse response)
{
// Decode the request
OSD osdRequest = null;
@@ -161,9 +161,6 @@ namespace OpenMetaverse.Http
Thread thread = new Thread(new ThreadStart(EventQueueThread));
thread.IsBackground = true;
thread.Start();
-
- // Tell HttpServer to leave the connection open
- return false;
}
else
{
@@ -172,7 +169,7 @@ namespace OpenMetaverse.Http
Stop();
response.Connection = request.Connection;
- return true;
+ response.Send();
}
}
else
@@ -182,7 +179,7 @@ namespace OpenMetaverse.Http
response.Connection = request.Connection;
response.Status = HttpStatusCode.BadRequest;
- return true;
+ response.Send();
}
}