mirror of
https://github.com/opensim/opensim.git
synced 2026-08-05 08:55:56 +08:00
Merge branch 'opensim:master' into master
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
@@ -127,20 +128,19 @@ namespace OpenSim.Framework
|
||||
Console.WriteLine("--------------------");
|
||||
}
|
||||
|
||||
public static readonly byte[] ZeroCountBytesReply = osUTF8.GetASCIIBytes("version 1\ncount 0\n");
|
||||
public Byte[] ToBytes()
|
||||
{
|
||||
// If there was an error parsing the input, we give back an
|
||||
// empty set rather than the original data.
|
||||
if (m_parseError)
|
||||
{
|
||||
string dummy = "version 1\ncount 0\n";
|
||||
return System.Text.Encoding.ASCII.GetBytes(dummy);
|
||||
}
|
||||
if (m_parseError || m_animations.Count == 0)
|
||||
return ZeroCountBytesReply;
|
||||
|
||||
string assetData = String.Format("version 1\ncount {0}\n", m_animations.Count);
|
||||
osUTF8 sb = OSUTF8Cached.Acquire();
|
||||
sb.AppendASCII("$version 1\ncount {m_animations.Count}\n");
|
||||
foreach (KeyValuePair<string, KeyValuePair<string, UUID>> kvp in m_animations)
|
||||
assetData += String.Format("{0} {1} {2}\n", kvp.Key, kvp.Value.Value.ToString(), kvp.Value.Key);
|
||||
return System.Text.Encoding.ASCII.GetBytes(assetData);
|
||||
sb.AppendASCII($"{kvp.Key} {kvp.Value.Value} {kvp.Value.Key}\n");
|
||||
return OSUTF8Cached.GetArrayAndRelease(sb);
|
||||
}
|
||||
/*
|
||||
public bool Validate(AnimationSetValidator val)
|
||||
|
||||
@@ -32,6 +32,7 @@ using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using log4net;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenSim.Framework
|
||||
{
|
||||
@@ -541,16 +542,20 @@ namespace OpenSim.Framework
|
||||
|
||||
lock (m_attachments)
|
||||
{
|
||||
if (!m_attachments.ContainsKey(attach.AttachPoint))
|
||||
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
|
||||
ref List<AvatarAttachment> atlst = ref CollectionsMarshal.GetValueRefOrAddDefault(m_attachments, attach.AttachPoint, out bool ex);
|
||||
if(!ex)
|
||||
{
|
||||
atlst = new List<AvatarAttachment>() { attach };
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (AvatarAttachment prev in m_attachments[attach.AttachPoint])
|
||||
foreach (AvatarAttachment prev in atlst)
|
||||
{
|
||||
if (prev.ItemID.Equals(attach.ItemID))
|
||||
return;
|
||||
}
|
||||
|
||||
m_attachments[attach.AttachPoint].Add(attach);
|
||||
atlst.Add(attach);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,8 +567,7 @@ namespace OpenSim.Framework
|
||||
|
||||
lock (m_attachments)
|
||||
{
|
||||
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
|
||||
m_attachments[attach.AttachPoint].Add(attach);
|
||||
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>() { attach };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -185,11 +185,8 @@ namespace OpenSim.Framework
|
||||
|
||||
public void RemoveItem(UUID itemID)
|
||||
{
|
||||
if (m_items.ContainsKey(itemID))
|
||||
{
|
||||
m_ids.Remove(itemID);
|
||||
m_items.Remove(itemID);
|
||||
}
|
||||
m_ids.Remove(itemID);
|
||||
m_items.Remove(itemID);
|
||||
}
|
||||
|
||||
public void RemoveAsset(UUID assetID)
|
||||
@@ -225,9 +222,7 @@ namespace OpenSim.Framework
|
||||
|
||||
public UUID GetAsset(UUID itemID)
|
||||
{
|
||||
if (!m_items.ContainsKey(itemID))
|
||||
return UUID.Zero;
|
||||
return m_items[itemID];
|
||||
return m_items.TryGetValue(itemID, out UUID id) ? id : UUID.Zero;
|
||||
}
|
||||
|
||||
public static AvatarWearable[] DefaultWearables
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace OpenSim.Framework
|
||||
public bool IsBlocked(string key)
|
||||
{
|
||||
bool ret = false;
|
||||
_blockLockSlim.EnterReadLock();
|
||||
_blockLockSlim.EnterReadLock();
|
||||
ret = _tempBlocked.ContainsKey(key);
|
||||
_blockLockSlim.ExitReadLock();
|
||||
return ret;
|
||||
@@ -140,11 +140,8 @@ namespace OpenSim.Framework
|
||||
|
||||
if (_options.MaxConcurrentSessions > 0)
|
||||
{
|
||||
int sessionscount = 0;
|
||||
|
||||
_sessionLockSlim.EnterReadLock();
|
||||
if (_sessions.ContainsKey(key))
|
||||
sessionscount = _sessions[key];
|
||||
_sessions.TryGetValue(key, out int sessionscount);
|
||||
_sessionLockSlim.ExitReadLock();
|
||||
|
||||
if (sessionscount > _options.MaxConcurrentSessions)
|
||||
|
||||
@@ -344,26 +344,20 @@ namespace OpenSim.Framework
|
||||
//
|
||||
protected virtual CacheItemBase GetItem(string index)
|
||||
{
|
||||
CacheItemBase item = null;
|
||||
|
||||
lock (m_Index)
|
||||
{
|
||||
if (m_Lookup.ContainsKey(index))
|
||||
item = m_Lookup[index];
|
||||
|
||||
if (item == null)
|
||||
if(m_Lookup.TryGetValue(index, out CacheItemBase item))
|
||||
{
|
||||
item.hits++;
|
||||
item.lastUsed = DateTime.UtcNow;
|
||||
Expire(true);
|
||||
return null;
|
||||
return item;
|
||||
}
|
||||
|
||||
item.hits++;
|
||||
item.lastUsed = DateTime.UtcNow;
|
||||
|
||||
Expire(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
// Get an item from cache. Do not try to fetch from source if not
|
||||
@@ -566,12 +560,9 @@ namespace OpenSim.Framework
|
||||
{
|
||||
lock (m_Index)
|
||||
{
|
||||
if (!m_Lookup.ContainsKey(uuid))
|
||||
return;
|
||||
|
||||
CacheItemBase item = m_Lookup[uuid];
|
||||
if (m_Lookup.TryGetValue(uuid, out CacheItemBase item))
|
||||
m_Index.Remove(item);
|
||||
m_Lookup.Remove(uuid);
|
||||
m_Index.Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,39 +46,36 @@ namespace OpenSim.Framework.Monitoring
|
||||
public virtual string Report()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(Environment.NewLine);
|
||||
sb.Append("MEMORY STATISTICS");
|
||||
sb.Append(Environment.NewLine);
|
||||
sb.AppendFormat(
|
||||
"Heap allocated to OpenSim : {0} MB\n",
|
||||
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
|
||||
|
||||
sb.AppendFormat(
|
||||
"Heap allocation rate (last/avg): {0}/{1}MB/s\n",
|
||||
"Heap allocated: {0}MB \t allocation rate (last/avg): {1}/{2}MB/s\n",
|
||||
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0),
|
||||
Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1048576.0, 3),
|
||||
Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1048576.0, 3));
|
||||
|
||||
GCMemoryInfo gcmem = GC.GetGCMemoryInfo();
|
||||
sb.AppendFormat(
|
||||
"GCTotalCommited: {0}MB \t GCTotalAvaiable {1}MB \t GCHMthreshold {2}MB\n",
|
||||
Math.Round(gcmem.TotalCommittedBytes / 1024.0 / 1024.0),
|
||||
Math.Round(gcmem.TotalAvailableMemoryBytes / 1024.0 / 1024.0),
|
||||
Math.Round(gcmem.HighMemoryLoadThresholdBytes / 1024.0 / 1024.0));
|
||||
|
||||
try
|
||||
{
|
||||
using (Process myprocess = Process.GetCurrentProcess())
|
||||
{
|
||||
sb.AppendFormat(
|
||||
"Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
|
||||
"Process memory: Physical {0}MB \t Paged {1}MB\n",
|
||||
Math.Round(myprocess.WorkingSet64 / 1024.0 / 1024.0),
|
||||
Math.Round(myprocess.PagedMemorySize64 / 1024.0 / 1024.0),
|
||||
Math.Round(myprocess.VirtualMemorySize64 / 1024.0 / 1024.0));
|
||||
Math.Round(myprocess.PagedMemorySize64 / 1024.0 / 1024.0));
|
||||
sb.AppendFormat(
|
||||
"Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
|
||||
"Peak process memory: Physical {0}MB \t Paged {1}MB \t\n",
|
||||
Math.Round(myprocess.PeakWorkingSet64 / 1024.0 / 1024.0),
|
||||
Math.Round(myprocess.PeakPagedMemorySize64 / 1024.0 / 1024.0),
|
||||
Math.Round(myprocess.PeakVirtualMemorySize64 / 1024.0 / 1024.0));
|
||||
Math.Round(myprocess.PeakPagedMemorySize64 / 1024.0 / 1024.0));
|
||||
sb.AppendFormat("\nTotal process Threads {0}\n", myprocess.Threads.Count);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
// else
|
||||
// sb.Append("Process reported as Exited \n");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
@@ -188,6 +189,43 @@ namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
foreach (string report in GetAllStatsReports())
|
||||
con.Output(report);
|
||||
con.Output(MemoryReport());
|
||||
}
|
||||
|
||||
private static string MemoryReport()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(Environment.NewLine);
|
||||
sb.AppendFormat(
|
||||
"Heap allocated: {0}MB \t allocation rate (last/avg): {1}/{2}MB/s\n",
|
||||
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0),
|
||||
Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1048576.0, 3),
|
||||
Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1048576.0, 3));
|
||||
|
||||
GCMemoryInfo gcmem = GC.GetGCMemoryInfo();
|
||||
sb.AppendFormat(
|
||||
"GCTotalCommited: {0}MB \t GCTotalAvaiable {1}MB \t GCHMthreshold {2}MB\n",
|
||||
Math.Round(gcmem.TotalCommittedBytes / 1024.0 / 1024.0),
|
||||
Math.Round(gcmem.TotalAvailableMemoryBytes / 1024.0 / 1024.0),
|
||||
Math.Round(gcmem.HighMemoryLoadThresholdBytes / 1024.0 / 1024.0));
|
||||
|
||||
try
|
||||
{
|
||||
using (Process myprocess = Process.GetCurrentProcess())
|
||||
{
|
||||
sb.AppendFormat(
|
||||
"Process memory: Physical {0}MB \t Paged {1}MB\n",
|
||||
Math.Round(myprocess.WorkingSet64 / 1024.0 / 1024.0),
|
||||
Math.Round(myprocess.PagedMemorySize64 / 1024.0 / 1024.0));
|
||||
sb.AppendFormat(
|
||||
"Peak process memory: Physical {0}MB \t Paged {1}MB \t\n",
|
||||
Math.Round(myprocess.PeakWorkingSet64 / 1024.0 / 1024.0),
|
||||
Math.Round(myprocess.PeakPagedMemorySize64 / 1024.0 / 1024.0));
|
||||
sb.AppendFormat("\nTotal process Threads {0}\n", myprocess.Threads.Count);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static List<string> GetCategoryStatsReports(
|
||||
|
||||
@@ -269,18 +269,13 @@ namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
lock (m_threads)
|
||||
{
|
||||
if (m_threads.ContainsKey(threadID))
|
||||
if(RemoveThread(threadID))
|
||||
{
|
||||
//ThreadWatchdogInfo twi = m_threads[threadID];
|
||||
//twi.Thread.Abort();
|
||||
RemoveThread(threadID);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,11 +320,8 @@ namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
lock (m_threads)
|
||||
{
|
||||
if (m_threads.ContainsKey(Thread.CurrentThread.ManagedThreadId))
|
||||
return m_threads[Thread.CurrentThread.ManagedThreadId];
|
||||
return m_threads.TryGetValue(Thread.CurrentThread.ManagedThreadId, out ThreadWatchdogInfo twi) ? twi : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -159,17 +159,13 @@ namespace OpenSim.Framework
|
||||
{
|
||||
log.Info("[PLUGINS]: Loading extension point " + ext);
|
||||
|
||||
if (constraints.ContainsKey(ext))
|
||||
if (constraints.TryGetValue(ext , out IPluginConstraint cons))
|
||||
{
|
||||
IPluginConstraint cons = constraints[ext];
|
||||
if (cons.Apply(ext))
|
||||
log.Error("[PLUGINS]: " + ext + " failed constraint: " + cons.Message);
|
||||
}
|
||||
|
||||
IPluginFilter filter = null;
|
||||
|
||||
if (filters.ContainsKey(ext))
|
||||
filter = filters[ext];
|
||||
filters.TryGetValue(ext, out IPluginFilter filter);
|
||||
|
||||
List<T> loadedPlugins = new List<T>();
|
||||
foreach (PluginExtensionNode node in AddinManager.GetExtensionNodes(ext))
|
||||
|
||||
@@ -1139,12 +1139,13 @@ namespace OpenSim.Framework
|
||||
UInt32.TryParse(args["region_yloc"].AsString(), out locy);
|
||||
RegionLocY = locy;
|
||||
}
|
||||
if (args.ContainsKey("region_size_x"))
|
||||
RegionSizeX = (uint)args["region_size_x"].AsInteger();
|
||||
if (args.ContainsKey("region_size_y"))
|
||||
RegionSizeY = (uint)args["region_size_y"].AsInteger();
|
||||
if (args.ContainsKey("region_size_z"))
|
||||
RegionSizeZ = (uint)args["region_size_z"].AsInteger();
|
||||
OSD osdtmp;
|
||||
if (args.TryGetValue("region_size_x", out osdtmp))
|
||||
RegionSizeX = (uint)osdtmp.AsInteger();
|
||||
if (args.TryGetValue("region_size_y", out osdtmp))
|
||||
RegionSizeY = (uint)osdtmp.AsInteger();
|
||||
if (args.TryGetValue("region_size_z", out osdtmp))
|
||||
RegionSizeZ = (uint)osdtmp.AsInteger();
|
||||
|
||||
IPAddress ip_addr = null;
|
||||
if (args["internal_ep_address"] != null)
|
||||
|
||||
@@ -32,17 +32,18 @@ namespace OpenSim.Framework
|
||||
{
|
||||
public class RegionURI
|
||||
{
|
||||
private static byte[] schemaSep = osUTF8.GetASCIIBytes("://");
|
||||
private static byte[] altschemaSep = osUTF8.GetASCIIBytes("|!!");
|
||||
private static byte[] nameSep = osUTF8.GetASCIIBytes(":/ ");
|
||||
private static byte[] altnameSep = osUTF8.GetASCIIBytes(":/ +|");
|
||||
private static byte[] escapePref = osUTF8.GetASCIIBytes("+%");
|
||||
private static byte[] altPortSepPref = osUTF8.GetASCIIBytes(":|");
|
||||
private static readonly byte[] schemaSep = osUTF8.GetASCIIBytes("://");
|
||||
private static readonly byte[] altschemaSep = osUTF8.GetASCIIBytes("|!!");
|
||||
private static readonly byte[] nameSep = osUTF8.GetASCIIBytes(":/ ");
|
||||
private static readonly byte[] altnameSep = osUTF8.GetASCIIBytes(":/ +|");
|
||||
private static readonly byte[] escapePref = osUTF8.GetASCIIBytes("+%");
|
||||
private static readonly byte[] altPortSepPref = osUTF8.GetASCIIBytes(":|");
|
||||
private static readonly byte[] forbidonname = osUTF8.GetASCIIBytes(".,:;\\/");
|
||||
|
||||
public enum URIFlags : int
|
||||
{
|
||||
None = 0,
|
||||
Valid = 1 << 0,
|
||||
//Valid = 1 << 0,
|
||||
HasHost = 1 << 1,
|
||||
HasResolvedHost = 1 << 2,
|
||||
HasUserName = 1 << 3,
|
||||
@@ -70,7 +71,7 @@ namespace OpenSim.Framework
|
||||
{
|
||||
originalURI = _originalURI;
|
||||
Parse(_originalURI);
|
||||
if (!HasHost)
|
||||
if (!HasHost && HasRegionName)
|
||||
Flags |= URIFlags.IsLocalGrid;
|
||||
}
|
||||
|
||||
@@ -81,7 +82,10 @@ namespace OpenSim.Framework
|
||||
|
||||
if(!HasHost)
|
||||
{
|
||||
Flags |= URIFlags.IsLocalGrid;
|
||||
if(!HasRegionName)
|
||||
Flags = URIFlags.None;
|
||||
else
|
||||
Flags |= URIFlags.IsLocalGrid;
|
||||
return;
|
||||
}
|
||||
if(gi == null)
|
||||
@@ -290,6 +294,12 @@ namespace OpenSim.Framework
|
||||
if (tmpSlice.Length <= 0)
|
||||
return;
|
||||
|
||||
if(tmpSlice.IndexOfAny(forbidonname) > 0)
|
||||
{
|
||||
Flags = URIFlags.None;
|
||||
return;
|
||||
}
|
||||
|
||||
RegionName = tmpSlice.ToString();
|
||||
Flags |= URIFlags.HasRegionName;
|
||||
|
||||
|
||||
@@ -53,9 +53,9 @@ namespace OpenSim.Framework
|
||||
|
||||
public bool TryGet<T>(out T iface)
|
||||
{
|
||||
if (m_moduleInterfaces.ContainsKey(typeof(T)))
|
||||
if (m_moduleInterfaces.TryGetValue(typeof(T), out object o))
|
||||
{
|
||||
iface = (T)m_moduleInterfaces[typeof(T)];
|
||||
iface = (T)o;
|
||||
return true;
|
||||
}
|
||||
iface = default(T);
|
||||
|
||||
@@ -695,8 +695,8 @@ namespace OSHttpServer
|
||||
m_stream.EndWrite(res);
|
||||
|
||||
ContextTimeoutManager.ContextLeaveActiveSend();
|
||||
didleave = true;
|
||||
m_currentResponse.CheckSendNextAsyncContinue();
|
||||
didleave = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace OSHttpServer
|
||||
public int RawBufferLen { get; set; }
|
||||
public double RequestTS { get; private set; }
|
||||
|
||||
internal byte[] m_headerBytes = null;
|
||||
internal osUTF8 m_headerBytes = null;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IHttpResponse"/> class.
|
||||
@@ -228,55 +228,65 @@ namespace OSHttpServer
|
||||
m_headers[name] = value;
|
||||
}
|
||||
|
||||
public byte[] GetHeaders()
|
||||
public void GetHeaders()
|
||||
{
|
||||
HeadersSent = true;
|
||||
|
||||
var sb = osStringBuilderCache.Acquire();
|
||||
osUTF8 osu = OSUTF8Cached.Acquire(8 * 1024);
|
||||
|
||||
if(string.IsNullOrWhiteSpace(m_httpVersion))
|
||||
sb.AppendFormat("HTTP/1.1 {0} {1}\r\n", (int)Status,
|
||||
string.IsNullOrEmpty(Reason) ? Status.ToString() : Reason);
|
||||
if (string.IsNullOrWhiteSpace(m_httpVersion))
|
||||
{
|
||||
osu.AppendASCII($"HTTP/1.1 {(int)Status} ");
|
||||
if (string.IsNullOrEmpty(Reason))
|
||||
osu.AppendASCII($"{Status}");
|
||||
else
|
||||
osu.Append($"{Reason}");
|
||||
osu.AppendASCII("\r\n");
|
||||
}
|
||||
else
|
||||
sb.AppendFormat("{0} {1} {2}\r\n", m_httpVersion, (int)Status,
|
||||
string.IsNullOrEmpty(Reason) ? Status.ToString() : Reason);
|
||||
{
|
||||
osu.AppendASCII($"{m_httpVersion} {(int)Status} ");
|
||||
if (string.IsNullOrEmpty(Reason))
|
||||
osu.AppendASCII($"{Status}");
|
||||
else
|
||||
osu.Append($"{Reason}");
|
||||
osu.AppendASCII("\r\n");
|
||||
}
|
||||
|
||||
sb.AppendFormat("Date: {0}\r\n", DateTime.Now.ToString("r"));
|
||||
osu.AppendASCII($"Date: {DateTime.Now:r}\r\n");
|
||||
|
||||
long len = 0;
|
||||
if(m_body is not null)
|
||||
len = m_body.Length;
|
||||
if (RawBuffer is not null && RawBufferLen > 0)
|
||||
long len = m_body is null ? 0 : m_body.Length;
|
||||
if (RawBuffer is not null)
|
||||
len += RawBufferLen;
|
||||
sb.AppendFormat("Content-Length: {0}\r\n", len);
|
||||
osu.AppendASCII($"Content-Length: {len}\r\n");
|
||||
|
||||
if (m_headers["Content-Type"] is null)
|
||||
sb.AppendFormat("Content-Type: {0}\r\n", m_contentType ?? DefaultContentType);
|
||||
osu.AppendASCII($"Content-Type: {m_contentType ?? DefaultContentType}\r\n");
|
||||
|
||||
switch(Status)
|
||||
switch (Status)
|
||||
{
|
||||
case HttpStatusCode.OK:
|
||||
case HttpStatusCode.PartialContent:
|
||||
case HttpStatusCode.Accepted:
|
||||
case HttpStatusCode.Continue:
|
||||
case HttpStatusCode.Found:
|
||||
{
|
||||
int keepaliveS = m_context.TimeoutKeepAlive / 1000;
|
||||
if (Connection == ConnectionType.KeepAlive && keepaliveS > 0 && m_context.MaxRequests > 0)
|
||||
{
|
||||
sb.AppendFormat("Keep-Alive:timeout={0}, max={1}\r\n", keepaliveS, m_context.MaxRequests);
|
||||
sb.Append("Connection: Keep-Alive\r\n");
|
||||
int keepaliveS = m_context.TimeoutKeepAlive / 1000;
|
||||
if (Connection == ConnectionType.KeepAlive && keepaliveS > 0 && m_context.MaxRequests > 0)
|
||||
{
|
||||
osu.AppendASCII($"Keep-Alive:timeout={keepaliveS}, max={m_context.MaxRequests}\r\n");
|
||||
osu.AppendASCII("Connection: Keep-Alive\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
osu.AppendASCII("Connection: close\r\n");
|
||||
Connection = ConnectionType.Close;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append("Connection: close\r\n");
|
||||
Connection = ConnectionType.Close;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
sb.Append("Connection: close\r\n");
|
||||
osu.AppendASCII("Connection: close\r\n");
|
||||
Connection = ConnectionType.Close;
|
||||
break;
|
||||
}
|
||||
@@ -284,7 +294,7 @@ namespace OSHttpServer
|
||||
for (int i = 0; i < m_headers.Count; ++i)
|
||||
{
|
||||
string headerName = m_headers.AllKeys[i];
|
||||
switch(headerName)
|
||||
switch (headerName)
|
||||
{
|
||||
case "Connection":
|
||||
case "Content-Length":
|
||||
@@ -294,21 +304,27 @@ namespace OSHttpServer
|
||||
continue;
|
||||
}
|
||||
string[] values = m_headers.GetValues(i);
|
||||
if (values is null) continue;
|
||||
foreach (string value in values)
|
||||
sb.AppendFormat("{0}: {1}\r\n", headerName, value);
|
||||
if (values is not null)
|
||||
{
|
||||
foreach (string value in values)
|
||||
{
|
||||
osu.AppendASCII($"{headerName}: ");
|
||||
osu.Append($"{value}");
|
||||
osu.AppendASCII("\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append("Server: OSWebServer\r\n");
|
||||
osu.AppendASCII("Server: OSWebServer\r\n");
|
||||
|
||||
foreach (ResponseCookie cookie in Cookies)
|
||||
sb.AppendFormat("Set-Cookie: {0}\r\n", cookie);
|
||||
osu.Append($"Set-Cookie: {cookie}\r\n");
|
||||
|
||||
sb.Append("\r\n");
|
||||
osu.AppendASCII("\r\n");
|
||||
|
||||
m_headers.Clear();
|
||||
|
||||
return Encoding.GetBytes(osStringBuilderCache.GetStringAndRelease(sb));
|
||||
m_headerBytes = osu;
|
||||
}
|
||||
|
||||
public void Send()
|
||||
@@ -345,24 +361,20 @@ namespace OSHttpServer
|
||||
RawBufferLen = RawBuffer.Length - RawBufferStart;
|
||||
}
|
||||
|
||||
m_headerBytes = GetHeaders();
|
||||
if (RawBufferLen == 0)
|
||||
RawBuffer = null;
|
||||
|
||||
GetHeaders();
|
||||
|
||||
if (RawBuffer is not null && RawBufferLen > 0)
|
||||
{
|
||||
int tlen = m_headerBytes.Length + RawBufferLen;
|
||||
if(tlen < 8 * 1024)
|
||||
{
|
||||
byte[] tmp = new byte[tlen];
|
||||
Buffer.BlockCopy(m_headerBytes, 0, tmp, 0, m_headerBytes.Length);
|
||||
Buffer.BlockCopy(RawBuffer, RawBufferStart, tmp, m_headerBytes.Length, RawBufferLen);
|
||||
m_headerBytes = null;
|
||||
RawBuffer = tmp;
|
||||
RawBufferStart = 0;
|
||||
RawBufferLen = tlen;
|
||||
}
|
||||
|
||||
if (RawBufferLen == 0)
|
||||
m_headerBytes.Append(RawBuffer, RawBufferStart, RawBufferLen);
|
||||
RawBuffer = null;
|
||||
RawBufferLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_body is not null && m_body.Length == 0)
|
||||
@@ -384,11 +396,14 @@ namespace OSHttpServer
|
||||
{
|
||||
if (m_headerBytes is not null)
|
||||
{
|
||||
byte[] b = m_headerBytes;
|
||||
m_headerBytes = null;
|
||||
|
||||
if (!m_context.SendAsyncStart(b, 0, b.Length))
|
||||
if (!m_context.SendAsyncStart(m_headerBytes.GetArray(), 0, m_headerBytes.Length))
|
||||
{
|
||||
if(m_headerBytes is not null)
|
||||
{
|
||||
OSUTF8Cached.Release(m_headerBytes);
|
||||
m_headerBytes = null;
|
||||
}
|
||||
|
||||
if (m_body is not null)
|
||||
{
|
||||
m_body.Dispose();
|
||||
@@ -499,7 +514,13 @@ namespace OSHttpServer
|
||||
|
||||
public void CheckSendNextAsyncContinue()
|
||||
{
|
||||
if(m_headerBytes is null && RawBuffer is null && m_body is null)
|
||||
if (m_headerBytes is not null)
|
||||
{
|
||||
OSUTF8Cached.Release(m_headerBytes);
|
||||
m_headerBytes = null;
|
||||
}
|
||||
|
||||
if (m_headerBytes is null && RawBuffer is null && m_body is null)
|
||||
{
|
||||
Sent = true;
|
||||
m_context.EndSendResponse(requestID, Connection);
|
||||
@@ -512,6 +533,12 @@ namespace OSHttpServer
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if(m_headerBytes is not null)
|
||||
{
|
||||
OSUTF8Cached.Release(m_headerBytes);
|
||||
m_headerBytes = null;
|
||||
}
|
||||
|
||||
if(m_body is not null && m_body.CanRead)
|
||||
{
|
||||
m_body.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user