public StateData(HTTPMessage req, IPEndPoint d, object Tag, HeaderHandler HeaderCB) { this.Dest = d; this.Request = req; this.Tag = Tag; this.HeaderCB = HeaderCB; }
/// <summary> /// This is used to complete an AsyncRequest in an AsyncFashion. /// <para> /// You must either assign all the Argument values, or return an exception with "e" /// </para> /// </summary> /// <param name="id">ID</param> /// <param name="RetArg">Return Argument</param> /// <param name="OutArgs">Out Arguments</param> /// <param name="e">Exception</param> public void DelayedInvokeResponse(long id, object RetArg, UPnPArgument[] OutArgs, UPnPCustomException e) { UPnPDevice.InvokerInfoStruct iis = (UPnPDevice.InvokerInfoStruct)DelayedResponseTable[id]; HTTPMessage resp = new HTTPMessage(); if (e != null) { resp.StatusCode = 500; resp.StatusData = "Internal"; resp.StringBuffer = ParentDevice.BuildErrorBody(e); } else { resp = ParentDevice.ParseInvokeResponse(iis.MethodName, iis.SOAPAction, this.ServiceURN, RetArg, OutArgs); } iis.WebSession.Send(resp); iis.WebSession.StartReading(); lock (DelayedResponseTable) { DelayedResponseTable.Remove(id); } }
/// <summary> /// Parses a Byte Array at a specific location, and builds a Packet. /// </summary> /// <param name="buffer">The Array of Bytes</param> /// <param name="indx">The Start Index</param> /// <param name="count">The number of Bytes to process</param> /// <returns></returns> public static HTTPMessage ParseByteArray(byte[] buffer, int indx, int count) { HTTPMessage TheMessage = new HTTPMessage(); UTF8Encoding UTF8 = new UTF8Encoding(); String TempData = UTF8.GetString(buffer,indx,count); DText parser = new DText(); String TempString; int idx = TempData.IndexOf("\r\n\r\n"); if (idx < 0) return null; TempData = TempData.Substring(0,idx); parser.ATTRMARK = "\r\n"; parser.MULTMARK = ":"; parser[0] = TempData; string CurrentLine = parser[1]; DText HdrParser = new DText(); HdrParser.ATTRMARK = " "; HdrParser.MULTMARK = "/"; HdrParser[0] = CurrentLine; if (CurrentLine.ToUpper().StartsWith("HTTP/")==true) { TheMessage.ResponseCode = int.Parse(HdrParser[2]); int s1 = CurrentLine.IndexOf(" "); s1 = CurrentLine.IndexOf(" ",s1+1); TheMessage.ResponseData = HTTPMessage.UnEscapeString(CurrentLine.Substring(s1)); try { TheMessage.Version = HdrParser[1,2]; } catch(Exception) { TheMessage.Version = "0.9"; } } else { TheMessage.Directive = HdrParser[1]; TempString = CurrentLine.Substring(CurrentLine.LastIndexOf(" ") + 1); if (TempString.ToUpper().StartsWith("HTTP/")==false) { TheMessage.Version = "0.9"; TheMessage.DirectiveObj = HTTPMessage.UnEscapeString(TempString); } else { TheMessage.Version = TempString.Substring(TempString.IndexOf("/")+1); int fs = CurrentLine.IndexOf(" ") + 1; TheMessage.DirectiveObj = HTTPMessage.UnEscapeString(CurrentLine.Substring( fs, CurrentLine.Length-fs-TempString.Length-1)); } } String Tag=""; String TagData=""; for(int line=2;line<=parser.DCOUNT();++line) { if (Tag!="" && parser[line,1].StartsWith(" ")) { TagData = parser[line,1].Substring(1); } else { Tag = parser[line,1]; TagData = ""; for(int i=2;i<=parser.DCOUNT(line);++i) { if (TagData=="") { TagData = parser[line,i]; } else { TagData = TagData + parser.MULTMARK + parser[line,i]; } } } TheMessage.AppendTag(Tag,TagData); } int cl=0; if (TheMessage.HasTag("Content-Length")) { try { cl = int.Parse(TheMessage.GetTag("Content-Length")); } catch(Exception) { cl = -1; } } else { cl = -1; } byte[] tbuffer; if (cl>0) { tbuffer = new byte[cl]; if ((idx+4+cl)>count) { // NOP } else { Array.Copy(buffer,idx+4,tbuffer,0,cl); TheMessage.DataBuffer = tbuffer; } } if (cl==-1) { tbuffer = new Byte[count-(idx+4)]; Array.Copy(buffer,idx+4,tbuffer,0,tbuffer.Length); TheMessage.DataBuffer = tbuffer; } if (cl==0) { TheMessage.DataBuffer = new byte[0]; } return(TheMessage); }
private void OnPacketTraceChangedSink(IUPnPTestGroup sender, HTTPMessage packet) { this.BeginInvoke(new UpdatePacketTraceForCurrentTestHandler(UpdatePacketTraceForCurrentTest), new object[] { sender, packet }); }
private void SniffPacketSink(HTTPSession sender, HTTPMessage MSG) { if (this.OnSniffPacket != null) { if (sender.StateObject == null) { OnSniffPacket(this, MSG, null); return; } StateData sd = (StateData)sender.StateObject; object Tag = sd.Tag; OnSniffPacket(this, MSG, Tag); } }
private void HeaderSink(HTTPSession sender, HTTPMessage header, Stream TheStream) { _Source = sender.Source; StateData sd = null; if (TheStream != null) { // This is the result of post-headers in a chunked document sd = (StateData)sender.StateObject; object Tag = sd.Tag; if (sd.HeaderCB != null) sd.HeaderCB(this, sender, header, TheStream, Tag); sender.StateObject = null; KeepAliveTimer.Add(this.GetHashCode(), 10); } else { lock (TagQueue) { sd = (StateData)TagQueue.Dequeue(); } sender.StateObject = sd; object Tag = sd.Tag; if (sd.HeaderCB != null) { sd.HeaderCB(this, sender, header, TheStream, Tag); if (sender.UserStream != null && !sender.IsChunked) { // If I don't set this to null, this holds a strong reference, resulting in // possible memory leaks sender.StateObject = null; } } } }
private void NonPipelinedSniffPacketSink(HTTPRequest sender, HTTPMessage Response, object Tag) { if (OnSniffPacket != null) OnSniffPacket(this, Response, Tag); }
/// <summary> /// Pipelines a request packet /// </summary> /// <param name="dest">Destination IPEndPoint</param> /// <param name="MSG">HTTPMessage Packet</param> /// <param name="Tag">State Data</param> public void PipelineRequest(IPEndPoint dest, HTTPMessage MSG, object Tag) { ContinueRequest(dest, "", Tag, MSG); }
private void HandleSendEvent(HTTPRequest R, HTTPMessage M, object Tag) { R.Dispose(); SendEventTable.Remove(R); }
private void HandleInvokeRequest(HTTPRequest sender, HTTPMessage response, object Tag) { AsyncInvokeInfo state = (AsyncInvokeInfo)Tag; if (response == null) { if (state.ErrorCB != null) { state.ErrorCB(this, state.MethodName, state.Args, new UPnPInvokeException(state.MethodName, state.Args, "Could not connect to device"), state.Tag); } else { if (OnInvokeError != null) { OnInvokeError(this, state.MethodName, state.Args, new UPnPInvokeException(state.MethodName, state.Args, "Could not connect to device"), state.Tag); } } return; } if (response.StatusCode == 100) { // Ignore return; } UPnPAction action = (UPnPAction)RemoteMethods[state.MethodName]; if (response.StatusCode != 200) { if ((OnInvokeError != null) || (state.ErrorCB != null)) { if ((response.StatusCode == 500) && (response.BodyBuffer.Length > 0)) { // Try to parse SOAP Encoded Error UPnPCustomException ce = null; try { ce = ParseErrorBody(response.StringBuffer); OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "UPnP Action <" + state.MethodName + "> Error [" + ce.ErrorCode.ToString() + "] " + ce.ErrorDescription); } catch { ce = null; OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "HTTP Fault invoking " + state.MethodName + " : " + response.StatusData); } if (state.ErrorCB != null) { state.ErrorCB(this, action.Name, state.Args, new UPnPInvokeException(state.MethodName, state.Args, response.StatusData, ce), state.Tag); } else { if (OnInvokeError != null) { OnInvokeError(this, action.Name, state.Args, new UPnPInvokeException(state.MethodName, state.Args, response.StatusData, ce), state.Tag); } } } else { if (state.ErrorCB != null) { state.ErrorCB(this, action.Name, state.Args, new UPnPInvokeException(state.MethodName, state.Args, response.StatusData), state.Tag); } else { if (OnInvokeError != null) { OnInvokeError(this, action.Name, state.Args, new UPnPInvokeException(state.MethodName, state.Args, response.StatusData), state.Tag); } } } } return; } //Lets Parse the data we got back //Now we can parse the XML Body StringReader MyString = new StringReader(response.StringBuffer.Trim()); XmlTextReader XMLDoc = new XmlTextReader(MyString); String MethodTag = ""; UPnPArgument VarArg; ArrayList VarList = new ArrayList(); XMLDoc.Read(); XMLDoc.MoveToContent(); if (XMLDoc.LocalName == "Envelope") { XMLDoc.Read(); XMLDoc.MoveToContent(); if (XMLDoc.LocalName == "Body") { XMLDoc.Read(); XMLDoc.MoveToContent(); MethodTag = XMLDoc.LocalName; XMLDoc.Read(); XMLDoc.MoveToContent(); if (XMLDoc.LocalName != "Body") { while ((XMLDoc.LocalName != MethodTag) && (XMLDoc.EOF == false)) { // VarArg = new UPnPArgument(XMLDoc.Name,UPnPStringFormatter.UnEscapeString(XMLDoc.ReadInnerXml())); VarArg = new UPnPArgument(XMLDoc.Name, XMLDoc.ReadString()); VarList.Add(VarArg); if ((!XMLDoc.IsStartElement() && XMLDoc.LocalName != MethodTag) || XMLDoc.IsEmptyElement) { XMLDoc.Read(); XMLDoc.MoveToContent(); } } } } } //Finished processing the SOAP, lets build the return list Object RetVal = null; UPnPArgument[] InVarArr = state.Args; UPnPArgument ThisArg; Object[] temp = new Object[1]; Type[] TypeParm = new Type[1]; TypeParm[0] = Type.GetType("System.String"); int StartIDX = 0; if (((UPnPAction)RemoteMethods[state.MethodName]).HasReturnValue == true) { UPnPArgument RetArg = action.GetArg(((UPnPArgument)VarList[0]).Name); Type RetType = RetArg.RelatedStateVar.GetNetType(); RetVal = CreateObjectInstance(RetType, (string)((UPnPArgument)VarList[0]).DataValue); StartIDX = 1; } for (int ID = StartIDX; ID < VarList.Count; ++ID) { for (int ix = 0; ix < InVarArr.Length; ++ix) { if (InVarArr[ix].Name == ((UPnPArgument)VarList[ID]).Name) { ThisArg = action.GetArg(InVarArr[ix].Name); if ((ThisArg.RelatedStateVar.GetNetType().FullName != "System.String") || (ThisArg.RelatedStateVar.GetNetType().FullName != "System.Object")) { InVarArr[ix].DataValue = CreateObjectInstance(ThisArg.RelatedStateVar.GetNetType(), (string)((UPnPArgument)VarList[ID]).DataValue); } else { InVarArr[ix].DataValue = ((UPnPArgument)VarList[ID]).DataValue; } InVarArr[ix].DataType = ThisArg.RelatedStateVar.GetNetType().FullName; break; } } } if (state.InvokeCB != null) { state.InvokeCB(this, state.MethodName, InVarArr, RetVal, state.Tag); } else { if (OnInvokeResponse != null) { OnInvokeResponse(this, state.MethodName, InVarArr, RetVal, state.Tag); } } }
internal HTTPMessage _SubscribeEvent(out String SID, String CallbackURL, String Timeout) { SubscriberInfo sinfo = new SubscriberInfo(); sinfo.SID = GetNewSID(); sinfo.CallbackURL = CallbackURL; sinfo.SEQ = 1; int to = int.Parse(Timeout); if (to == 0) { sinfo.Expires = -1; } else { sinfo.Expires = DateTime.Now.AddSeconds(to).Ticks; } SubscriberTable[sinfo.SID] = sinfo; // Send an inital Event //SSDP.ParseURL(CallbackURL,out WebIP, out WebPort, out Tag); HTTPMessage Packet = new HTTPMessage(); Packet.Directive = "NOTIFY"; Packet.AddTag("Content-Type", "text/xml"); Packet.AddTag("NT", "upnp:event"); Packet.AddTag("NTS", "upnp:propchange"); Packet.AddTag("SID", sinfo.SID); Packet.AddTag("SEQ", "0"); Packet.AddTag("CONNECTION", "close"); Packet.BodyBuffer = BuildEventXML(); SID = sinfo.SID; SubscriptionAddedEvent.Fire(this); // Trigger event saying that a subscription was added return (Packet); }
internal void SendEvents(UPnPStateVariable V) { //IDictionaryEnumerator en = SubscriberTable.GetEnumerator(); SubscriberInfo sinfo; HTTPMessage Packet; Uri[] EventURLS; ICollection en = SubscriberTable.Keys; String[] KEYS = new String[en.Count]; HTTPRequest R; en.CopyTo(KEYS, 0); for (int keyid = 0; keyid < KEYS.Length; ++keyid) { object _tobj = SubscriberTable[KEYS[keyid]]; if (_tobj != null) { sinfo = (SubscriberInfo)_tobj; if ((sinfo.Expires > DateTime.Now.Ticks) || (sinfo.Expires == -1)) { EventURLS = ParseEventURL(sinfo.CallbackURL); for (int x = 0; x < EventURLS.Length; ++x) { try { IPAddress dest = IPAddress.Parse(EventURLS[x].Host); Packet = new HTTPMessage(); Packet.Directive = "NOTIFY"; Packet.AddTag("Content-Type", "text/xml"); Packet.AddTag("NT", "upnp:event"); Packet.AddTag("NTS", "upnp:propchange"); Packet.BodyBuffer = BuildEventXML(new UPnPStateVariable[1] { V }); Packet.DirectiveObj = HTTPMessage.UnEscapeString(EventURLS[x].PathAndQuery); if (dest.AddressFamily == AddressFamily.InterNetwork) Packet.AddTag("Host", EventURLS[x].Host + ":" + EventURLS[x].Port.ToString()); if (dest.AddressFamily == AddressFamily.InterNetworkV6) Packet.AddTag("Host", "[" + RemoveIPv6Scope(EventURLS[x].Host) + "]:" + EventURLS[x].Port.ToString()); Packet.AddTag("SID", sinfo.SID); Packet.AddTag("SEQ", sinfo.SEQ.ToString()); Packet.AddTag("CONNECTION", "close"); ++sinfo.SEQ; SubscriberTable[KEYS[keyid]] = sinfo; //OpenSource.Utilities.EventLogger.Log(this,System.Diagnostics.EventLogEntryType.SuccessAudit,Packet.StringBuffer); R = new HTTPRequest(); SendEventTable[R] = R; R.OnResponse += new HTTPRequest.RequestHandler(HandleSendEvent); R.PipelineRequest(new IPEndPoint(IPAddress.Parse(EventURLS[x].Host), EventURLS[x].Port), Packet, null); } catch (Exception) { } } } else { SubscriberTable.Remove(sinfo.SID); } } } }
/// <summary> /// Unsubscribe to UPnPEvent /// </summary> /// <param name="cb"></param> public void UnSubscribe(UPnPEventHandler cb) { bool processUnSubscribe = false; lock (SubscribeLock) { --SubscribeCounter; if (SubscribeCounter <= 0) { SubscribeCounter = 0; processUnSubscribe = true; } if (cb == null) { processUnSubscribe = true; OnUPnPEvent = null; } else { OnUPnPEvent -= cb; } } if (processUnSubscribe == false) return; HTTPMessage request = new HTTPMessage(); String WebIP; int WebPort; String Tag; SSDP.ParseURL(this.__eventurl, out WebIP, out WebPort, out Tag); IPEndPoint dest = new IPEndPoint(IPAddress.Parse(WebIP), WebPort); request.Directive = "UNSUBSCRIBE"; request.DirectiveObj = Tag; request.AddTag("Host", WebIP + ":" + WebPort.ToString()); // WebIP is already formatted for IPv6 request.AddTag("SID", CurrentSID); HTTPRequest UR = new HTTPRequest(); SubscribeRequestTable[UR] = UR; UR.OnResponse += new HTTPRequest.RequestHandler(HandleUnsubscribeResponse); CurrentSID = ""; UR.PipelineRequest(dest, request, null); }
/// <summary> /// Subscribe to UPnPEvents /// </summary> /// <param name="Timeout">Subscription Cycle</param> public void Subscribe(int Timeout, UPnPEventSubscribeHandler CB) { bool processSubscribe = false; lock (SubscribeLock) { if (SubscribeCounter == 0) processSubscribe = true; ++SubscribeCounter; //OnUPnPEvent += UPnPEventCallback; } if (processSubscribe == false) { // Already subscribed... Just trigger Events foreach (UPnPStateVariable V in this.GetStateVariables()) V.InitialEvent(); if (CB != null) CB(this, true); return; } foreach (UPnPStateVariable V in this.GetStateVariables()) { if (V.SendEvent) V.CurrentValue = null; } CurrentTimeout = Timeout; HTTPMessage request = new HTTPMessage(); String WebIP; int WebPort; String Tag; String NT; if (Timeout == 0) { NT = "Second-infinite"; } else { NT = "Second-" + Timeout.ToString(); } SSDP.ParseURL(this.__eventurl, out WebIP, out WebPort, out Tag); IPEndPoint dest = new IPEndPoint(IPAddress.Parse(WebIP), WebPort); IPAddress addr = IPAddress.Parse(WebIP); request.Directive = "SUBSCRIBE"; request.DirectiveObj = Tag; if (addr.AddressFamily == AddressFamily.InterNetwork) { request.AddTag("Host", WebIP + ":" + WebPort.ToString()); } else if (addr.AddressFamily == AddressFamily.InterNetworkV6) { request.AddTag("Host", "[" + RemoveIPv6Scope(addr.ToString()) + "]:" + WebPort.ToString()); } request.AddTag("Callback", "<" + this.EventCallbackURL + ">"); request.AddTag("NT", "upnp:event"); request.AddTag("Timeout", NT); HTTPRequest SR = new HTTPRequest(); SubscribeRequestTable[SR] = SR; SR.OnResponse += new HTTPRequest.RequestHandler(HandleSubscribeResponse); SR.PipelineRequest(dest, request, CB); }
/// <summary> /// Invokes a method on this service with specific callbacks /// </summary> /// <param name="MethodName">Name of Method</param> /// <param name="InVarArr">Array of UPnPArguments</param> /// <param name="InvokeCallback">Callback for Success</param> /// <param name="ErrorCallback">Callback for Failed</param> /// <returns>Unique Handle identifier</returns> public void InvokeAsync(String MethodName, UPnPArgument[] InVarArr, object Tag, UPnPService.UPnPServiceInvokeHandler InvokeCallback, UPnPService.UPnPServiceInvokeErrorHandler ErrorCallback) { HTTPMessage request = new HTTPMessage(); if (InVarArr == null) { InVarArr = new UPnPArgument[0]; } UPnPAction action = (UPnPAction)RemoteMethods[MethodName]; if (action == null) { throw (new UPnPInvokeException(MethodName, InVarArr, MethodName + " is not currently defined in this object")); } else { action.ValidateArgs(InVarArr); } String WebIP; String sName; int WebPort; SSDP.ParseURL(__controlurl, out WebIP, out WebPort, out sName); IPEndPoint dest = new IPEndPoint(IPAddress.Parse(WebIP), WebPort); request.Directive = "POST"; request.DirectiveObj = sName; request.AddTag("Host", WebIP + ":" + WebPort); request.AddTag("Content-Type", "text/xml; charset=\"utf-8\""); request.AddTag("SoapAction", "\"" + ServiceURN + "#" + MethodName + "\""); MemoryStream mstream = new MemoryStream(4096); XmlTextWriter W = new XmlTextWriter(mstream, System.Text.Encoding.UTF8); W.Formatting = Formatting.Indented; W.Indentation = 3; W.WriteStartDocument(); String S = "http://schemas.xmlsoap.org/soap/envelope/"; W.WriteStartElement("s", "Envelope", S); W.WriteAttributeString("s", "encodingStyle", S, "http://schemas.xmlsoap.org/soap/encoding/"); W.WriteStartElement("s", "Body", S); W.WriteStartElement("u", MethodName, ServiceURN); for (int ID = 0; ID < InVarArr.Length; ++ID) { if (action.GetArg(InVarArr[ID].Name).Direction == "in") { W.WriteElementString(InVarArr[ID].Name, UPnPService.SerializeObjectInstance(InVarArr[ID].DataValue)); } } W.WriteEndElement(); W.WriteEndElement(); W.WriteEndElement(); W.WriteEndDocument(); W.Flush(); byte[] wbuf = new Byte[mstream.Length - 3]; mstream.Seek(3, SeekOrigin.Begin); mstream.Read(wbuf, 0, wbuf.Length); W.Close(); request.BodyBuffer = wbuf; AsyncInvokeInfo state = new AsyncInvokeInfo(); state.Args = InVarArr; state.MethodName = MethodName; state.Packet = request; state.Tag = Tag; state.InvokeCB = InvokeCallback; state.ErrorCB = ErrorCallback; InvocationPipeline.PipelineRequest(dest, request, state); }
private void OnReceiveSink2(byte[] buffer, IPEndPoint remote, IPEndPoint local) { HTTPMessage msg; try { msg = HTTPMessage.ParseByteArray(buffer, 0, buffer.Length); } catch (Exception ex) { OpenSource.Utilities.EventLogger.Log(ex); msg = new HTTPMessage(); msg.Directive = "---"; msg.DirectiveObj = "---"; msg.BodyBuffer = buffer; } msg.LocalEndPoint = local; msg.RemoteEndPoint = remote; DText parser = new DText(); String Location = msg.GetTag("Location"); int MaxAge = 0; String ma = msg.GetTag("Cache-Control").Trim(); if (ma != "") { parser.ATTRMARK = ","; parser.MULTMARK = "="; parser[0] = ma; for (int i = 1; i <= parser.DCOUNT(); ++i) { if (parser[i, 1].Trim().ToUpper() == "MAX-AGE") { MaxAge = int.Parse(parser[i, 2].Trim()); break; } } } ma = msg.GetTag("USN"); String USN = ma.Substring(ma.IndexOf(":") + 1); String ST = msg.GetTag("ST"); if (USN.IndexOf("::") != -1) USN = USN.Substring(0, USN.IndexOf("::")); OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.SuccessAudit, msg.RemoteEndPoint.ToString()); if (OnSearch != null) OnSearch(msg.RemoteEndPoint, msg.LocalEndPoint, new Uri(Location), USN, ST, MaxAge); }
private void SniffPacketSink(HTTPMessage Packet) { if (OnSniffPacket!=null) OnSniffPacket(Packet); }
private void HandleSubscribeResponse(HTTPRequest sender, HTTPMessage response, object Tag) { UPnPEventSubscribeHandler CB = (UPnPEventSubscribeHandler)Tag; SubscribeRequestTable.Remove(sender); sender.Dispose(); if (response != null) { if (response.StatusCode != 200) { if (CB != null) { CB(this, false); } else { if (OnSubscribe != null) OnSubscribe(this, false); } } else { CurrentSID = response.GetTag("SID"); if (CB != null) { CB(this, true); } else { if (OnSubscribe != null) OnSubscribe(this, true); } if (CurrentTimeout != 0) { EventLogger.Log(this, System.Diagnostics.EventLogEntryType.SuccessAudit, "SUBSCRIBE [" + this.CurrentSID + "] Duration: " + CurrentTimeout.ToString() + " <" + DateTime.Now.ToLongTimeString() + ">"); SubscribeCycle.Add(this.GetHashCode(), CurrentTimeout / 2); } } } else { if (CB != null) { CB(this, false); } else { if (OnSubscribe != null) OnSubscribe(this, false); } } }
private void ContinueRequest(IPEndPoint dest, string PQ, object Tag, HTTPMessage MSG) { HTTPMessage r = null; if (MSG == null) { r = new HTTPMessage(); r.Directive = "GET"; r.DirectiveObj = PQ; if (dest.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) r.AddTag("Host", dest.ToString()); if (dest.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) r.AddTag("Host", "[" + RemoveIPv6Scope(dest.ToString()) + "]"); } else { r = MSG; } lock (TagQueue) { this.IdleTimeout = false; KeepAliveTimer.Remove(this.GetHashCode()); LastMessage = r; if ((PIPELINE == false && _PIPELINE == false) || (_PIPELINE == false)) { HTTPRequest TR = new HTTPRequest(); TR.ProxySetting = ProxySetting; TR._PIPELINE = true; if (this.OnSniff != null) TR.OnSniff += new HTTPRequest.SniffHandler(NonPipelinedSniffSink); if (this.OnSniffPacket != null) TR.OnSniffPacket += new HTTPRequest.RequestHandler(NonPipelinedSniffPacketSink); TR.OnResponse += new HTTPRequest.RequestHandler(NonPipelinedResponseSink); this.NotPipelinedTable[TR] = TR; TR.PipelineRequest(dest, r, Tag); return; } bool NeedSend = (TagQueue.Count == 0); TagQueue.Enqueue(new StateData(r, dest, Tag, null)); IPAddress localif = IPAddress.Any; if (dest.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) localif = IPAddress.IPv6Any; if (s == null) { ReceivedFirstResponse = false; if (ProxySetting != null) { s = new HTTPSession(new IPEndPoint(localif, 0), ProxySetting, new HTTPSession.SessionHandler(CreateSink), new HTTPSession.SessionHandler(CreateFailedSink), null); } else { s = new HTTPSession(new IPEndPoint(localif, 0), dest, new HTTPSession.SessionHandler(CreateSink), new HTTPSession.SessionHandler(CreateFailedSink), null); } } else { if (s.IsConnected && this.ReceivedFirstResponse) { try { if (ProxySetting == null) { s.Send(r); } else { HTTPMessage pr = (HTTPMessage)r.Clone(); pr.DirectiveObj = "http://" + dest.ToString() + pr.DirectiveObj; pr.Version = "1.0"; s.Send(pr); } } catch (Exception ex) { OpenSource.Utilities.EventLogger.Log(ex); } } } } }
private void HandleUnsubscribeResponse(HTTPRequest sender, HTTPMessage response, object Tag) { SubscribeRequestTable.Remove(sender); sender.Dispose(); SubscribeCycle.Remove(this.GetHashCode()); }
private void NonPipelinedResponseSink(HTTPRequest sender, HTTPMessage Response, object Tag) { // OpenSource.Utilities.EventLogger.Log(sender.s,System.Diagnostics.EventLogEntryType.Information,"TryingToDispose"); _Source = sender.Source; this.NotPipelinedTable.Remove(sender); sender.Dispose(); if (this.OnResponse != null) OnResponse(this, Response, Tag); }
private void Renew() { HTTPMessage request = new HTTPMessage(); String WebIP; int WebPort; String Tag; String NT; NT = "Second-" + CurrentTimeout.ToString(); SSDP.ParseURL(this.__eventurl, out WebIP, out WebPort, out Tag); IPEndPoint dest = new IPEndPoint(IPAddress.Parse(WebIP), WebPort); request.Directive = "SUBSCRIBE"; request.DirectiveObj = Tag; request.AddTag("Host", WebIP + ":" + WebPort.ToString()); request.AddTag("SID", CurrentSID); request.AddTag("Timeout", NT); HTTPRequest R = new HTTPRequest(); R.OnResponse += new HTTPRequest.RequestHandler(RenewSink); this.SendEventTable[R] = R; R.PipelineRequest(dest, request, null); }
private void ReceiveSink(HTTPSession sender, HTTPMessage msg) { StateData sd = (StateData)sender.StateObject; object Tag = sd.Tag; if (msg.Version == "1.0" || msg.Version == "0.9") { sender.Close(); } else { if (msg.GetTag("Connection").ToUpper() == "CLOSE") { sender.Close(); } } if (OnResponse != null) OnResponse(this, msg, Tag); // If I don't set this to null, this holds a strong reference, resulting in // possible memory leaks sender.StateObject = null; lock (TagQueue) { if (TagQueue.Count == 0) { this.IdleTimeout = true; KeepAliveTimer.Add(this.GetHashCode(), 10); } } }
private void RenewSink(HTTPRequest sender, HTTPMessage M, object Tag) { if (M != null) { if (M.StatusCode != 200) { // Renew Failed EventLogger.Log(this, System.Diagnostics.EventLogEntryType.SuccessAudit, "Renewal [" + this.CurrentSID + "] Error:" + M.StatusCode.ToString() + " <" + DateTime.Now.ToLongTimeString() + ">"); SubscribeCycle.Remove(this.GetHashCode()); this.SubscribeCounter = 0; PeriodicRenewFailedEvent.Fire(this); } else { EventLogger.Log(this, System.Diagnostics.EventLogEntryType.SuccessAudit, "Renewal [" + this.CurrentSID + "] OK <" + DateTime.Now.ToLongTimeString() + ">"); SubscribeCycle.Add(this.GetHashCode(), CurrentTimeout / 2); } } else { // Renew Failed EventLogger.Log(this, System.Diagnostics.EventLogEntryType.SuccessAudit, "Renewal [" + this.CurrentSID + "] DeviceError <" + DateTime.Now.ToLongTimeString() + ">"); SubscribeCycle.Remove(this.GetHashCode()); this.SubscribeCounter = 0; PeriodicRenewFailedEvent.Fire(this); } this.SendEventTable.Remove(sender); sender.Dispose(); }
private void SniffPacketSink(HTTPRequest sender, HTTPMessage MSG, object Tag) { OnSniffPacketEvent.Fire(this, MSG); }
private void HandleNotify(IPEndPoint source, IPEndPoint local, Uri LocationURL, bool IsAlive, String USN, String ST, int MaxAge, HTTPMessage Packet) { if (IsAlive && LocationURL != null) OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.SuccessAudit, LocationURL.ToString()); if (OnNotify != null) OnNotify(source, local, LocationURL, IsAlive, USN, ST, MaxAge, Packet); }
private void UpdatePacketTraceForCurrentTest(IUPnPTestGroup sender, HTTPMessage msg) { if (sender != displaytestinfo) return; ListViewItem lv; if (msg.StatusCode == -1) { lv = new ListViewItem(new string[] { msg.RawPacket.Length.ToString() + " (" + msg.BodyBuffer.Length + ")", msg.Directive + " " + msg.DirectiveObj }, 5); } else { lv = new ListViewItem(new string[] { msg.RawPacket.Length.ToString() + " (" + msg.BodyBuffer.Length + ")", "(" + msg.StatusCode.ToString() + ") " + msg.StatusData }, 5); } lv.Tag = msg; packetListView.Items.Add(lv); }
/// <summary> /// Searches for a SearchTarget Asynchronously /// </summary> /// <param name="SearchTarget">The Target</param> public void FindDeviceAsync(String SearchTarget, IPEndPoint RemoteEP) { HTTPMessage request = new HTTPMessage(); request.Directive = "M-SEARCH"; request.DirectiveObj = "*"; request.AddTag("ST", SearchTarget); request.AddTag("MX", MX.ToString()); request.AddTag("MAN", "\"ssdp:discover\""); if (RemoteEP.AddressFamily == AddressFamily.InterNetwork) request.AddTag("HOST", RemoteEP.ToString()); // "239.255.255.250:1900" if (RemoteEP.AddressFamily == AddressFamily.InterNetworkV6) request.AddTag("HOST", string.Format("[{0}]:{1}", RemoteEP.Address.ToString(), RemoteEP.Port)); // "[FF05::C]:1900" byte[] buffer = UTF8Encoding.UTF8.GetBytes(request.StringPacket); IPAddress[] LocalAddresses = NetInfo.GetLocalAddresses(); foreach (IPAddress localaddr in LocalAddresses) { try { UdpClient session = (UdpClient)SSDPSessions[localaddr]; if (session == null) { session = new UdpClient(new IPEndPoint(localaddr, 0)); session.EnableBroadcast = true; session.BeginReceive(new AsyncCallback(OnReceiveSink), session); SSDPSessions[localaddr] = session; } if (RemoteEP.AddressFamily != session.Client.AddressFamily) continue; if ((RemoteEP.AddressFamily == AddressFamily.InterNetworkV6) && ((IPEndPoint)session.Client.LocalEndPoint).Address.IsIPv6LinkLocal == true && RemoteEP != Utils.UpnpMulticastV6EndPoint2) continue; if ((RemoteEP.AddressFamily == AddressFamily.InterNetworkV6) && ((IPEndPoint)session.Client.LocalEndPoint).Address.IsIPv6LinkLocal == false && RemoteEP != Utils.UpnpMulticastV6EndPoint1) continue; IPEndPoint lep = (IPEndPoint)session.Client.LocalEndPoint; if (session.Client.AddressFamily == AddressFamily.InterNetwork) { session.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, localaddr.GetAddressBytes()); } else if (session.Client.AddressFamily == AddressFamily.InterNetworkV6) { session.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastInterface, BitConverter.GetBytes((int)localaddr.ScopeId)); } session.Send(buffer, buffer.Length, RemoteEP); session.Send(buffer, buffer.Length, RemoteEP); } catch (Exception ex) { OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "CP Failure: " + localaddr.ToString()); OpenSource.Utilities.EventLogger.Log(ex); } } }
internal void SSDPNotifySink( IPEndPoint source, IPEndPoint local, Uri LocationURL, bool IsAlive, string USN, string SearchTarget, int MaxAge, HTTPMessage Packet ) { UPnPDevice device = null; if (SearchTarget == searchFilter) { if (!IsAlive) { lock (this.deviceTableLock) { device = this.UnprotectedRemoveMe(USN); } if (device != null) { //device.Removed(); } if (device != null) { this.OnRemovedDeviceEvent.Fire(this, device); } } else { lock (this.deviceTableLock) { if (!this.deviceTable.ContainsKey(USN)) { DeviceInfo info = new DeviceInfo(); info.Device = null; info.UDN = USN; info.NotifyTime = DateTime.Now; info.BaseURL = LocationURL; info.MaxAge = MaxAge; info.LocalEP = local; info.SourceEP = source; this.deviceTable[USN] = info; this.deviceFactory.CreateDevice(info.BaseURL, info.MaxAge, IPAddress.Any, info.UDN); } else { DeviceInfo info2 = (DeviceInfo)this.deviceTable[USN]; if (info2.Device != null) { if (info2.BaseURL.Equals(LocationURL)) { this.deviceUpdateClock.Remove(info2); info2.PendingBaseURL = null; info2.PendingMaxAge = 0; info2.PendingLocalEP = null; info2.PendingSourceEP = null; info2.NotifyTime = DateTime.Now; this.deviceTable[USN] = info2; this.deviceLifeTimeClock.Add(info2.UDN, MaxAge); } else if (info2.NotifyTime.AddSeconds(10.0).Ticks < DateTime.Now.Ticks) { info2.PendingBaseURL = LocationURL; info2.PendingMaxAge = MaxAge; info2.PendingLocalEP = local; info2.PendingSourceEP = source; this.deviceTable[USN] = info2; this.deviceUpdateClock.Add(info2.UDN, 3); } } } } } } }
private void PageHandler(OpenSource.UPnP.UPnPDevice sender, OpenSource.UPnP.HTTPMessage msg, OpenSource.UPnP.HTTPSession WebSession, string VirtualDir) { if (VirtualDir.Equals("/stream", StringComparison.InvariantCultureIgnoreCase) && msg.DirectiveObj.Equals("/swyh.mp3", StringComparison.InvariantCultureIgnoreCase)) { WebSession.OnStreamDone += (s, e) => { PipeStream value; while (!sessionMp3Streams.TryRemove(s.SessionID, out value)) ; ; App.CurrentInstance.wasapiProvider.UpdateClientsList(); }; PipeStream stream = sessionMp3Streams.GetOrAdd(WebSession.SessionID, new PipeStream()); App.CurrentInstance.wasapiProvider.UpdateClientsList(); WebSession.SendStreamObject(stream, "audio/mpeg"); } else if (VirtualDir.Equals("/stream", StringComparison.InvariantCultureIgnoreCase) && msg.DirectiveObj.Equals("/swyh.wav", StringComparison.InvariantCultureIgnoreCase)) { WebSession.OnStreamDone += (s, e) => { PipeStream value; while (!sessionPcmStreams.TryRemove(s.SessionID, out value)) ; ; App.CurrentInstance.wasapiProvider.UpdateClientsList(); }; PipeStream stream = sessionPcmStreams.GetOrAdd(WebSession.SessionID, new PipeStream()); App.CurrentInstance.wasapiProvider.UpdateClientsList(); var audioFormat = AudioSettings.GetAudioFormat(); WebSession.SendStreamObject(stream, "audio/L16;rate=" + audioFormat.SampleRate + ";channels=" + audioFormat.Channels); } else if (VirtualDir.Equals("/about", StringComparison.InvariantCultureIgnoreCase)) { OpenSource.UPnP.HTTPMessage response = new OpenSource.UPnP.HTTPMessage(); response.StatusCode = 200; response.StatusData = "OK"; response.AddTag("Content-Type", "text/html"); response.BodyBuffer = System.Text.Encoding.UTF8.GetBytes(Properties.Resources.About); WebSession.Send(response); } else { OpenSource.UPnP.HTTPMessage response = new OpenSource.UPnP.HTTPMessage(); response.StatusCode = 404; response.StatusData = "Not Found"; response.AddTag("Content-Type", "text/html"); response.BodyBuffer = System.Text.Encoding.UTF8.GetBytes(Properties.Resources.Error404); WebSession.Send(response); } }