clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using System;
29 using System.Collections.Generic;
30 using System.Net;
31 using System.Net.Sockets;
32 using System.Reflection;
33 using System.Text.RegularExpressions;
34 using System.Threading;
35 using System.Security.Cryptography.X509Certificates;
36 using log4net;
37 using HttpServer;
38  
39 using HttpListener = HttpServer.HttpListener;
40  
41 namespace OpenSim.Framework.Servers.HttpServer
42 {
43 /// <summary>
44 /// OSHttpServer provides an HTTP server bound to a specific
45 /// port. When instantiated with just address and port it uses
46 /// normal HTTP, when instantiated with address, port, and X509
47 /// certificate, it uses HTTPS.
48 /// </summary>
49 public class OSHttpServer
50 {
51 private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52  
53 private object _syncObject = new object();
54  
55 // underlying HttpServer.HttpListener
56 protected HttpListener _listener;
57 // underlying core/engine thread
58 protected Thread _engine;
59  
60 // Queue containing (OS)HttpRequests
61 protected OSHttpRequestQueue _queue;
62  
63 // OSHttpRequestPumps "pumping" incoming OSHttpRequests
64 // upwards
65 protected OSHttpRequestPump[] _pumps;
66  
67 // thread identifier
68 protected string _engineId;
69 public string EngineID
70 {
71 get { return _engineId; }
72 }
73  
74 /// <summary>
75 /// True if this is an HTTPS connection; false otherwise.
76 /// </summary>
77 protected bool _isSecure;
78 public bool IsSecure
79 {
80 get { return _isSecure; }
81 }
82  
83 public int QueueSize
84 {
85 get { return _pumps.Length; }
86 }
87  
88 /// <summary>
89 /// List of registered OSHttpHandlers for this OSHttpServer instance.
90 /// </summary>
91 protected List<OSHttpHandler> _httpHandlers = new List<OSHttpHandler>();
92 public List<OSHttpHandler> OSHttpHandlers
93 {
94 get
95 {
96 lock (_httpHandlers)
97 {
98 return new List<OSHttpHandler>(_httpHandlers);
99 }
100 }
101 }
102  
103  
104 /// <summary>
105 /// Instantiate an HTTP server.
106 /// </summary>
107 public OSHttpServer(IPAddress address, int port, int poolSize)
108 {
109 _engineId = String.Format("OSHttpServer (HTTP:{0})", port);
110 _isSecure = false;
111 _log.DebugFormat("[{0}] HTTP server instantiated", EngineID);
112  
113 _listener = new HttpListener(address, port);
114 _queue = new OSHttpRequestQueue();
115 _pumps = OSHttpRequestPump.Pumps(this, _queue, poolSize);
116 }
117  
118 /// <summary>
119 /// Instantiate an HTTPS server.
120 /// </summary>
121 public OSHttpServer(IPAddress address, int port, X509Certificate certificate, int poolSize)
122 {
123 _engineId = String.Format("OSHttpServer [HTTPS:{0}/ps:{1}]", port, poolSize);
124 _isSecure = true;
125 _log.DebugFormat("[{0}] HTTPS server instantiated", EngineID);
126  
127 _listener = new HttpListener(address, port, certificate);
128 _queue = new OSHttpRequestQueue();
129 _pumps = OSHttpRequestPump.Pumps(this, _queue, poolSize);
130 }
131  
132 /// <summary>
133 /// Turn an HttpRequest into an OSHttpRequestItem and place it
134 /// in the queue. The OSHttpRequestQueue object will pulse the
135 /// next available idle pump.
136 /// </summary>
137 protected void OnHttpRequest(HttpClientContext client, HttpRequest request)
138 {
139 // turn request into OSHttpRequest
140 OSHttpRequest req = new OSHttpRequest(client, request);
141  
142 // place OSHttpRequest into _httpRequestQueue, will
143 // trigger Pulse to idle waiting pumps
144 _queue.Enqueue(req);
145 }
146  
147 /// <summary>
148 /// Start the HTTP server engine.
149 /// </summary>
150 public void Start()
151 {
152 _engine = new Thread(new ThreadStart(Engine));
153 _engine.IsBackground = true;
154 _engine.Start();
155 _engine.Name = string.Format ("Engine:{0}",_engineId);
156  
157 ThreadTracker.Add(_engine);
158  
159 // start the pumps...
160 for (int i = 0; i < _pumps.Length; i++)
161 _pumps[i].Start();
162 }
163  
164 public void Stop()
165 {
166 lock (_syncObject) Monitor.Pulse(_syncObject);
167 }
168  
169 /// <summary>
170 /// Engine keeps the HTTP server running.
171 /// </summary>
172 private void Engine()
173 {
174 try {
175 _listener.RequestHandler += OnHttpRequest;
176 _listener.Start(QueueSize);
177 _log.InfoFormat("[{0}] HTTP server started", EngineID);
178  
179 lock (_syncObject) Monitor.Wait(_syncObject);
180 }
181 catch (Exception ex)
182 {
183 _log.DebugFormat("[{0}] HTTP server startup failed: {1}", EngineID, ex.ToString());
184 }
185  
186 _log.InfoFormat("[{0}] HTTP server terminated", EngineID);
187 }
188  
189  
190 /// <summary>
191 /// Add an HTTP request handler.
192 /// </summary>
193 /// <param name="handler">OSHttpHandler delegate</param>
194 /// <param name="path">regex object for path matching</parm>
195 /// <param name="headers">dictionary containing header names
196 /// and regular expressions to match against header values</param>
197 public void AddHandler(OSHttpHandler handler)
198 {
199 lock (_httpHandlers)
200 {
201 if (_httpHandlers.Contains(handler))
202 {
203 _log.DebugFormat("[OSHttpServer] attempt to add already existing handler ignored");
204 return;
205 }
206 _httpHandlers.Add(handler);
207 }
208 }
209 }
210 }