public EventQueue Run(CapsRequest eqReq) { Running = true; byte[] response = Encoding.UTF8.GetBytes("HTTP/1.0 200 OK\r\n"); ; return EventQueueHandler(eqReq); //byte[] wr = Encoding.UTF8.GetBytes("HTTP/1.0 200 OK\r\n"); //Console.WriteLine("[EventQueue]: Writing " + response.Length + " back into socket"); //_sock.Write(response, 0, response.Length); }
//private Dictionary<string, bool> SubHack = new Dictionary<string, bool>(); private void ProxyCaps(NetworkStream netStream, string meth, string uri, Dictionary<string, string> headers, byte[] content, int reqNo) { Match match = new Regex(@"^(https?)://([^:/]+)(:\d+)?(/.*)$").Match(uri); if (!match.Success) { Console.WriteLine("[" + reqNo + "] Malformed proxy URI: " + uri); byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 404 Not Found\r\nContent-Length: 0\r\n\r\n"); netStream.Write(wr, 0, wr.Length); return; } //Console.WriteLine("[" + reqNo + "]: " + meth + "; " + uri + "; "); CapInfo cap = null; lock (this) { if (KnownCaps.ContainsKey(uri)) { cap = KnownCaps[uri]; } } CapsRequest capReq = null; bool shortCircuit = false; bool requestFailed = false; if (cap != null) { Console.WriteLine("[ProxyCaps]: " + cap.CapType + "; format: " + cap.ReqFmt + "; content-type: " + headers["content-type"]); capReq = new CapsRequest(cap); if (cap.ReqFmt == CapsDataFormat.SD) { capReq.Request = OSDParser.DeserializeLLSDXml(content); } else { capReq.Request = OSDParser.DeserializeLLSDBinary(content); } foreach (CapsDelegate d in cap.GetDelegates()) { if (d(capReq, CapsStage.Request)) { shortCircuit = true; break; } } if (cap.ReqFmt == CapsDataFormat.SD) { content = OSDParser.SerializeLLSDXmlBytes((OSD)capReq.Request); } else { content = OSDParser.SerializeLLSDXmlBytes(capReq.Request); } } else { Console.WriteLine("[GRID PROXY]: Unknown Cap " + uri); return; } byte[] respBuf = null; string consoleMsg = String.Empty; if (shortCircuit) { // //if (eq == null) // //{ // // Console.WriteLine("[GRID SURFER]: Creating new EventQueue"); // // eq = new EventQueue(netStream); // //} // //else // //{ // // Console.WriteLine("[GRID SURFER]: Event Queue already exists???"); // // eq.SetSock(netStream); // //} // //eq = eq.Run(capReq); // ////eq = null; // return; //byte[] wr = Encoding.UTF8.GetBytes("HTTP/1.0 200 OK\r\n"); //netStream.Write(wr, 0, wr.Length); } else { HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri); req.KeepAlive = false; foreach (string header in headers.Keys) { if (header == "accept" || header == "connection" || header == "content-length" || header == "date" || header == "expect" || header == "host" || header == "if-modified-since" || header == "referer" || header == "transfer-encoding" || header == "user-agent" || header == "proxy-connection") { // can't touch these! } else if (header == "content-type") { req.ContentType = headers["content-type"]; } else { req.Headers[header] = headers[header]; } } req.Method = meth; req.ContentLength = content.Length; HttpWebResponse resp; try { Stream reqStream = req.GetRequestStream(); reqStream.Write(content, 0, content.Length); reqStream.Close(); resp = (HttpWebResponse)req.GetResponse(); } catch (WebException e) { if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.SendFailure) { Console.WriteLine("Request timeout"); byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 504 Proxy Request Timeout\r\nContent-Length: 0\r\n\r\n"); netStream.Write(wr, 0, wr.Length); return; } else if (e.Status == WebExceptionStatus.ProtocolError && e.Response != null) { resp = (HttpWebResponse)e.Response; requestFailed = true; } else { Console.WriteLine("Request error: " + e.ToString()); byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 502 Gateway Error\r\nContent-Length: 0\r\n\r\n"); // FIXME netStream.Write(wr, 0, wr.Length); return; } } try { Stream respStream = resp.GetResponseStream(); int read; int length = 0; respBuf = new byte[256]; do { read = respStream.Read(respBuf, length, 256); if (read > 0) { length += read; Array.Resize(ref respBuf, length + 256); } } while (read > 0); Array.Resize(ref respBuf, length); if (capReq != null && !requestFailed) { if (cap.RespFmt == CapsDataFormat.SD) { capReq.Response = OSDParser.DeserializeLLSDXml(respBuf); } else { capReq.Response = OSDParser.DeserializeLLSDXml(respBuf); } } consoleMsg += "[" + reqNo + "] Response from " + uri + "\nStatus: " + (int)resp.StatusCode + " " + resp.StatusDescription + "\n"; { byte[] wr = Encoding.UTF8.GetBytes("HTTP/1.0 " + (int)resp.StatusCode + " " + resp.StatusDescription + "\r\n"); netStream.Write(wr, 0, wr.Length); } for (int i = 0; i < resp.Headers.Count; i++) { string key = resp.Headers.Keys[i]; string val = resp.Headers[i]; string lkey = key.ToLower(); if (lkey != "content-length" && lkey != "transfer-encoding" && lkey != "connection") { consoleMsg += key + ": " + val + "\n"; byte[] wr = Encoding.UTF8.GetBytes(key + ": " + val + "\r\n"); netStream.Write(wr, 0, wr.Length); } } } catch (Exception) { // TODO: Should we handle this somehow? } } if (cap != null && !requestFailed) { foreach (CapsDelegate d in cap.GetDelegates()) { try { if (d(capReq, CapsStage.Response)) { break; } } catch (Exception e) { Console.WriteLine(e.ToString()); break; } } if (capReq.Response != null) { if (cap.RespFmt == CapsDataFormat.SD) { respBuf = OSDParser.SerializeLLSDXmlBytes((OSD)capReq.Response); } else { respBuf = OSDParser.SerializeLLSDXmlBytes(capReq.Response); } } } if (respBuf != null) consoleMsg += "\n" + Encoding.UTF8.GetString(respBuf) + "\n--------"; #if DEBUG_CAPS Console.WriteLine(consoleMsg); #endif /* try { if(resp.StatusCode == HttpStatusCode.OK) respBuf = CapsFixup(uri,respBuf); } catch(Exception e) { Console.WriteLine("["+reqNo+"] Couldn't fixup response: "+e.ToString()); } */ #if DEBUG_CAPS Console.WriteLine("[" + reqNo + "] Fixed-up response:\n" + Encoding.UTF8.GetString(respBuf) + "\n--------"); #endif try { if (capReq.Response != null) { if (shortCircuit) { byte[] wr = Encoding.UTF8.GetBytes("HTTP/1.0 200 OK\r\n"); netStream.Write(wr, 0, wr.Length); } byte[] wr2 = Encoding.UTF8.GetBytes("Content-Length: " + respBuf.Length + "\r\n\r\n"); netStream.Write(wr2, 0, wr2.Length); netStream.Write(respBuf, 0, respBuf.Length); } else { byte[] wr = Encoding.UTF8.GetBytes("HTTP/1.0 404 Not Found\r\n"); netStream.Write(wr, 0, wr.Length); } } catch (Exception e) { Console.WriteLine(e.ToString()); } return; }
private bool KnownCapDelegate(CapsRequest capReq, CapsStage stage) { lock (this) { if (!KnownCapsDelegates.ContainsKey(capReq.Info.CapType)) return false; List<CapsDelegate> delegates = KnownCapsDelegates[capReq.Info.CapType]; foreach (CapsDelegate d in delegates) { if (d(capReq, stage)) { return true; } } } return false; }
private bool FixupEventQueueGet(CapsRequest capReq, CapsStage stage) { //if (stage == CapsStage.Request) // return ReifyEventQueueGetRequest(capReq); if (stage != CapsStage.Response) return false; Console.WriteLine("HERE : " + stage.ToString()); OSDMap map = (OSDMap)capReq.Response; OSDArray array = (OSDArray)map["events"]; for (int i = 0; i < array.Count; i++) { OSDMap evt = (OSDMap)array[i]; string message = evt["message"].AsString(); OSDMap body = (OSDMap)evt["body"]; if (message == "TeleportFinish" || message == "CrossedRegion") { OSDMap info = null; if (message == "TeleportFinish") info = (OSDMap)(((OSDArray)body["Info"])[0]); else info = (OSDMap)(((OSDArray)body["RegionData"])[0]); byte[] bytes = info["SimIP"].AsBinary(); uint simIP = Utils.BytesToUInt(bytes); ushort simPort = (ushort)info["SimPort"].AsInteger(); string capsURL = info["SeedCapability"].AsString(); GenericCheck(ref simIP, ref simPort, ref capsURL, capReq.Info.Sim == activeCircuit); info["SeedCapability"] = OSD.FromString(capsURL); bytes[0] = (byte)(simIP % 256); bytes[1] = (byte)((simIP >> 8) % 256); bytes[2] = (byte)((simIP >> 16) % 256); bytes[3] = (byte)((simIP >> 24) % 256); info["SimIP"] = OSD.FromBinary(bytes); info["SimPort"] = OSD.FromInteger(simPort); } else if (message == "EnableSimulator") { OSDMap info = null; info = (OSDMap)(((OSDArray)body["SimulatorInfo"])[0]); byte[] bytes = info["IP"].AsBinary(); uint IP = Utils.BytesToUInt(bytes); ushort Port = (ushort)info["Port"].AsInteger(); string capsURL = null; GenericCheck(ref IP, ref Port, ref capsURL, capReq.Info.Sim == activeCircuit); bytes[0] = (byte)(IP % 256); bytes[1] = (byte)((IP >> 8) % 256); bytes[2] = (byte)((IP >> 16) % 256); bytes[3] = (byte)((IP >> 24) % 256); info["IP"] = OSD.FromBinary(bytes); info["Port"] = OSD.FromInteger(Port); } else if (message == "EstablishAgentCommunication") { string ipAndPort = body["sim-ip-and-port"].AsString(); string[] pieces = ipAndPort.Split(':'); byte[] bytes = IPAddress.Parse(pieces[0]).GetAddressBytes(); uint simIP = Utils.BytesToUInt(bytes); ushort simPort = (ushort)Convert.ToInt32(pieces[1]); string capsURL = body["seed-capability"].AsString(); #if DEBUG_CAPS Console.WriteLine("DEBUG: Got EstablishAgentCommunication for " + ipAndPort + " with seed cap " + capsURL); #endif GenericCheck(ref simIP, ref simPort, ref capsURL, false); body["seed-capability"] = OSD.FromString(capsURL); string ipport = String.Format("{0}:{1}", new IPAddress(simIP), simPort); body["sim-ip-and-port"] = OSD.FromString(ipport); #if DEBUG_CAPS Console.WriteLine("DEBUG: Modified EstablishAgentCommunication to " + body["sim-ip-and-port"].AsString() + " with seed cap " + capsURL); #endif } } return false; }
public void ForwardCaps(string uri, CapsRequest capReq) { bool requestFailed = false; HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri); req.KeepAlive = false; req.ContentType = "application/llsd+xml"; req.Method = "POST"; byte[] content = OSDParser.SerializeLLSDXmlBytes(capReq.Request); req.ContentLength = content.Length; Console.WriteLine(" >> content-length: " + req.ContentLength); HttpWebResponse resp = null; try { Stream reqStream = req.GetRequestStream(); reqStream.Write(content, 0, content.Length); reqStream.Close(); } catch (WebException e) { if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.SendFailure) { Console.WriteLine("Request timeout"); //byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 504 Proxy Request Timeout\r\nContent-Length: 0\r\n\r\n"); //netStream.Write(wr, 0, wr.Length); return; } else if (e.Status == WebExceptionStatus.ProtocolError && e.Response != null) { //resp = (HttpWebResponse)e.Response; requestFailed = true; } else { Console.WriteLine("Request error: " + e.ToString()); //byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 502 Gateway Error\r\nContent-Length: 0\r\n\r\n"); // FIXME //netStream.Write(wr, 0, wr.Length); return; } } try { resp = (HttpWebResponse)req.GetResponse(); } catch (WebException e) { if (e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.SendFailure) { Console.WriteLine("Request timeout"); //byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 504 Proxy Request Timeout\r\nContent-Length: 0\r\n\r\n"); //netStream.Write(wr, 0, wr.Length); return; } else if (e.Status == WebExceptionStatus.ProtocolError && e.Response != null) { //resp = (HttpWebResponse)e.Response; requestFailed = true; } else { Console.WriteLine("Request error: " + e.ToString()); //byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 502 Gateway Error\r\nContent-Length: 0\r\n\r\n"); // FIXME //netStream.Write(wr, 0, wr.Length); return; } } byte[] respBuf = null; try { Stream respStream = resp.GetResponseStream(); int read; int length = 0; respBuf = new byte[256]; do { read = respStream.Read(respBuf, length, 256); if (read > 0) { length += read; Array.Resize(ref respBuf, length + 256); } } while (read > 0); Array.Resize(ref respBuf, length); if (capReq != null && !requestFailed) { if (capReq.Info.RespFmt == CapsDataFormat.SD) { capReq.Response = OSDParser.DeserializeLLSDXml(respBuf); } else { capReq.Response = OSDParser.DeserializeLLSDXml(respBuf); } } //consoleMsg += "[" + reqNo + "] Response from " + uri + "\nStatus: " + (int)resp.StatusCode + " " + resp.StatusDescription + "\n"; //{ // byte[] wr = Encoding.UTF8.GetBytes("HTTP/1.0 " + (int)resp.StatusCode + " " + resp.StatusDescription + "\r\n"); // netStream.Write(wr, 0, wr.Length); //} //for (int i = 0; i < resp.Headers.Count; i++) //{ // string key = resp.Headers.Keys[i]; // string val = resp.Headers[i]; // string lkey = key.ToLower(); // if (lkey != "content-length" && lkey != "transfer-encoding" && lkey != "connection") // { // consoleMsg += key + ": " + val + "\n"; // byte[] wr = Encoding.UTF8.GetBytes(key + ": " + val + "\r\n"); // netStream.Write(wr, 0, wr.Length); // } //} } catch (Exception) { // TODO: Should we handle this somehow? } }
public bool FixupSeedCapsResponse(CapsRequest capReq, CapsStage stage) { if (stage != CapsStage.Response) return false; OSDMap nm = new OSDMap(); if (capReq.Response.Type == OSDType.Map) { OSDMap m = (OSDMap)capReq.Response; foreach (string key in m.Keys) { string val = m[key].AsString(); if (!String.IsNullOrEmpty(val)) { if (!KnownCaps.ContainsKey(val)) { CapInfo newCap = new CapInfo(val, capReq.Info.Sim, key); newCap.AddDelegate(new CapsDelegate(KnownCapDelegate)); lock (this) { KnownCaps[val] = newCap; } //Console.WriteLine(" >> Adding KnownCap " + val + " = " + newCap); } nm[key] = OSD.FromString(loginURI + val); //Console.WriteLine(" >> Sending transformed Cap " + loginURI + val); } else { nm[key] = OSD.FromString(val); } } } //Console.WriteLine("---------------"); //lock (this) //{ // foreach (KeyValuePair<string, CapInfo> kvp in KnownCaps) // { // Console.WriteLine(" >> Key: " + kvp.Key + "; Value: " + kvp.Value.CapType); // } //} //Console.WriteLine("---------------"); capReq.Response = nm; return false; }
private bool ReifyEventQueueGetRequest(CapsRequest capReq) { return false; }
void StartEventQueue(CapsRequest eqRequest) { EventQueueEvent eventQueueEvent = null; int totalMsPassed = 0; Console.WriteLine("[EventQueue] Starting..." + id); while (Running) { if (eventQueue.Dequeue(BATCH_WAIT_INTERVAL, ref eventQueueEvent)) { Console.WriteLine("[EventQueue]: Dequeued event " + eventQueueEvent.Name); // An event was dequeued totalMsPassed = 0; List<EventQueueEvent> eventsToSend = new List<EventQueueEvent>(); eventsToSend.Add(eventQueueEvent); DateTime start = DateTime.Now; int batchMsPassed = 0; // Wait BATCH_WAIT_INTERVAL milliseconds looking for more events, // or until the size of the current batch equals MAX_EVENTS_PER_RESPONSE while (batchMsPassed < BATCH_WAIT_INTERVAL && eventsToSend.Count < MAX_EVENTS_PER_RESPONSE) { if (eventQueue.Dequeue(BATCH_WAIT_INTERVAL - batchMsPassed, ref eventQueueEvent)) { Console.WriteLine("[EventQueue]: Dequeued event " + eventQueueEvent.Name); eventsToSend.Add(eventQueueEvent); } batchMsPassed = (int)(DateTime.Now - start).TotalMilliseconds; } SendResponse(eqRequest, eventsToSend); return; } else { // BATCH_WAIT_INTERVAL milliseconds passed with no event. Check if the connection // has timed out yet. totalMsPassed += BATCH_WAIT_INTERVAL; if (totalMsPassed >= CONNECTION_TIMEOUT) { Console.WriteLine("[EventQueue] Timeout without an event, " + totalMsPassed); List<EventQueueEvent> evl = new List<EventQueueEvent>(); evl.Add(FakeEvent); SendResponse(eqRequest, evl); return; } } } Console.WriteLine("[EventQueue] Handler thread is no longer Running"); }
void SendResponse(CapsRequest eqRequest, List<EventQueueEvent> eventsToSend) { if (eventsToSend != null) { OSDArray responseArray = new OSDArray(eventsToSend.Count); // Put all of the events in an array for (int i = 0; i < eventsToSend.Count; i++) { EventQueueEvent currentEvent = eventsToSend[i]; OSDMap eventMap = new OSDMap(2); eventMap.Add("message", OSD.FromString(currentEvent.Name)); eventMap.Add("body", currentEvent.Body); responseArray.Add(eventMap); } // Create a map containing the events array and the id of this response OSDMap responseMap = new OSDMap(2); responseMap.Add("events", responseArray); responseMap.Add("id", OSD.FromInteger(currentID++)); eqRequest.Response = responseMap; //string respstr = "HTTP/1.0 200 OK\r\n"; //respstr += "Content-Type: application/llsd+xml\r\n"; //// Serialize the events and send the response //byte[] buffer = OSDParser.SerializeLLSDXmlBytes(responseMap); //respstr += "Content-Length: " + buffer.Length + "\r\n\r\n"; //Console.WriteLine("----- Sending ----"); //Console.WriteLine(respstr); //byte[] top = Encoding.UTF8.GetBytes(respstr); //_sock.Write(top, 0, top.Length); //_sock.Write(buffer, 0, buffer.Length); ////response = new byte[top.Length + buffer.Length]; ////top.CopyTo(response, 0); ////buffer.CopyTo(response, top.Length); ////response.Body.Flush(); } else { //// The 502 response started as a bug in the LL event queue server implementation, //// but is now hardcoded into the protocol as the code to use for a timeout //response = Encoding.UTF8.GetBytes("HTTP/1.0 502 Bad Gateway\r\n"); //response = Encoding.UTF8.GetBytes("HTTP/1.0 200 OK\r\n"); //_sock.Write(response, 0, response.Length); } }
private EventQueue EventQueueHandler(CapsRequest eqRequest) { // Decode the request OSD osdRequest = eqRequest.Request; if (eqRequest != null && osdRequest.Type == OSDType.Map) { OSDMap requestMap = (OSDMap)osdRequest; int ack = requestMap["ack"].AsInteger(); bool done = requestMap["done"].AsBoolean(); if (ack != currentID - 1 && ack != 0) { Console.WriteLine("[EventQueue] Received an ack for id " + ack + ", last id sent was " + (currentID - 1)); } if (!done) { StartEventQueue(eqRequest); eventQueue.Close(); eventQueue = new BlockingQueue<EventQueueEvent>(); return this; } else { Console.WriteLine("[EventQueue] Shutting down the event queue at the client's request " + id); Stop(); //response = Encoding.UTF8.GetBytes("HTTP/1.0 404 Not Found\r\n"); return null; } } else { Console.WriteLine("[EventQueue] Received a request with invalid or missing LLSD at, closing the connection"); //response = Encoding.UTF8.GetBytes("HTTP/1.0 400 Bad Request\r\n"); return null; } }