public void Search(string SearchString, IPEndPoint ep) { HTTPMessage request = new HTTPMessage(); request.Directive = "M-SEARCH"; request.DirectiveObj = "*"; if (ep.AddressFamily == AddressFamily.InterNetwork) { request.AddTag("HOST", ep.ToString()); // "239.255.255.250:1900" } if (ep.AddressFamily == AddressFamily.InterNetworkV6) { request.AddTag("HOST", string.Format("[{0}]:{1}", ep.Address.ToString(), ep.Port)); // "[FF05::C]:1900" or "[FF02::C]:1900" } request.AddTag("MAN", "\"ssdp:discover\""); request.AddTag("MX", "10"); request.AddTag("ST", SearchString); SearchEx(UTF8Encoding.UTF8.GetBytes(request.StringPacket), ep); }
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) => { if (sessionMp3Streams.ContainsKey(s.SessionID)) { PipeStream value; 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) => { if (sessionPcmStreams.ContainsKey(s.SessionID)) { PipeStream value; 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); } }
/// <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 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); }
/// <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> /// 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 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); } }
private void Validate_MSEARCH_RESPONSETIME() { AddMessage(0, "Testing Notifications"); HTTPMessage r = new HTTPMessage(); r.Directive = "M-SEARCH"; r.DirectiveObj = "*"; r.AddTag("MX", "10"); r.AddTag("ST", "uuid:" + TestDevice.UniqueDeviceName); r.AddTag("Host", "239.255.255.250:1900"); r.AddTag("MAN", "\"ssdp:discover\""); byte[] buf = r.RawPacket; IPEndPoint dest = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900); Cache = -1; MRE.Reset(); StartTime = DateTime.Now; ASocket.Send(buf, 0, buf.Length, dest); StartCountDown(0, 90); MRE.WaitOne(15000, false); AbortCountDown(); MRE.Reset(); StartTime = DateTime.Now; ASocket.Send(buf, 0, buf.Length, dest); StartCountDown(15, 90); MRE.WaitOne(15000, false); AbortCountDown(); MRE.Reset(); StartTime = DateTime.Now; ASocket.Send(buf, 0, buf.Length, dest); StartCountDown(30, 90); MRE.WaitOne(15000, false); AbortCountDown(); MRE.Reset(); StartTime = DateTime.Now; ASocket.Send(buf, 0, buf.Length, dest); StartCountDown(45, 90); MRE.WaitOne(15000, false); AbortCountDown(); MRE.Reset(); StartTime = DateTime.Now; ASocket.Send(buf, 0, buf.Length, dest); StartCountDown(60, 90); MRE.WaitOne(15000, false); AbortCountDown(); MRE.Reset(); StartTime = DateTime.Now; ASocket.Send(buf, 0, buf.Length, dest); StartCountDown(75, 90); MRE.WaitOne(15000, false); AbortCountDown(); double s = 0; try { s = DPA.StandardDeviation.TotalSeconds; } catch (DivideByZeroException) {} if (s < (double)1.50) { AddEvent(LogImportance.Medium, "M-SEARCH, MX Value", "WARNING: Device not choosing Random interval based on MX value <<Standard Deviation: " + s.ToString() + ">>"); Results.Add("M-SEARCH Response time not choosing Random interval based on MX value"); MX = UPnPTestStates.Warn; SetState("MX Value", UPnPTestStates.Warn); } else { MX = UPnPTestStates.Pass; AddEvent(LogImportance.Remark, "M-SEARCH, MX Value", "Random MX interval: <<Standard Deviation: " + s.ToString() + ">> OK"); Results.Add("M-SEARCH Response time OK"); SetState("MX Value", UPnPTestStates.Pass); } }
private HTTPMessage[] BuildByePacket(IPAddress local) { HTTPMessage msg; ArrayList ByeList = new ArrayList(); msg = new HTTPMessage(); msg.Directive = "NOTIFY"; msg.DirectiveObj = "*"; msg.AddTag("Host", Utils.GetMulticastAddrBraketPort(local)); msg.AddTag("NT", "upnp:rootdevice"); msg.AddTag("NTS", "ssdp:byebye"); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::upnp:rootdevice"); ByeList.Add(msg); BuildByePacket2(ByeList, local); foreach (UPnPDevice d in this.EmbeddedDevices) { d.BuildByePacket2(ByeList, local); } return ((HTTPMessage[])ByeList.ToArray(typeof(HTTPMessage))); }
internal HTTPMessage ParseInvokeResponse(string MethodTag, string SOAPACTION, string urn, object RetVal, UPnPArgument[] OutArgs) { HTTPMessage response = new HTTPMessage(); 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); if (SOAPACTION.EndsWith("#QueryStateVariable\"") == false) { W.WriteStartElement("u", MethodTag + "Response", urn); if (RetVal != null) { W.WriteElementString(((UPnPArgument)RetVal).Name, UPnPService.SerializeObjectInstance(((UPnPArgument)RetVal).DataValue)); } foreach (UPnPArgument arg in OutArgs) { W.WriteElementString(arg.Name, UPnPService.SerializeObjectInstance(arg.DataValue)); } } else { //QueryStateVariableResponse String QSV = "urn:schemas-upnp-org:control-1-0"; W.WriteStartElement("u", MethodTag + "Response", QSV); W.WriteElementString("return", UPnPStringFormatter.EscapeString(UPnPService.SerializeObjectInstance(RetVal))); } 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(); response.StatusCode = 200; response.StatusData = "OK"; response.AddTag("Content-Type", "text/xml; charset=\"utf-8\""); response.AddTag("EXT", ""); response.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); response.BodyBuffer = wbuf; return (response); }
private void HeaderHandler(OpenSource.UPnP.UPnPDevice sender, OpenSource.UPnP.HTTPMessage msg, OpenSource.UPnP.HTTPSession WebSession, string VirtualDir) { msg.AddTag("transferMode.dlna.org", "Streaming"); msg.AddTag("contentFeatures.dlna.org", "DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000"); }
public override void Start(UPnPDevice device) { if(!Enabled) return; UPnPDevice dv = device; while(dv.ParentDevice!=null) { dv = dv.ParentDevice; } state = UPnPTestStates.Running; UPnPService[] _S = device.GetServices("urn:"); foreach(UPnPService s in _S) { bool ok = false; foreach(UPnPStateVariable v in s.GetStateVariables()) { if(v.SendEvent) { ok = true; break; } } if(ok) { UPnPDebugObject d = new UPnPDebugObject(s); Uri EventUri = new Uri((string)d.GetField("__eventurl")); IPEndPoint dest = new IPEndPoint(IPAddress.Parse(EventUri.Host),EventUri.Port); HTTPMessage R = new HTTPMessage(); R.Directive = "SUBSCRIBE"; R.DirectiveObj = HTTPMessage.UnEscapeString(EventUri.PathAndQuery); R.AddTag("Host",dest.ToString()); R.AddTag("Callback","<http://" + dv.InterfaceToHost.ToString()+ ":" + NetworkInfo.GetFreePort(10000,50000,dv.InterfaceToHost).ToString() + ">"); //R.AddTag("Callback","<http://127.0.0.1:55555>"); R.AddTag("NT","upnp:event"); R.AddTag("Timeout","Second-15"); System.Console.WriteLine(R.GetTag("Callback")); MRE.Reset(); SID = ""; StartCountDown(30); HTTPRequest rq = new HTTPRequest(); rq.OnResponse += new HTTPRequest.RequestHandler(SubscribeSink); AddHTTPMessage(R); rq.PipelineRequest(dest,R,s); MRE.WaitOne(30000,false); AbortCountDown(); if (SID=="") { AddEvent(LogImportance.Critical,"Subscribe","SUBSCRIBE: " + s.ServiceURN + " << FAILED >>"); AddEvent(LogImportance.Remark,"Subscribe","Aborting tests"); result = "Subscription test failed."; // TODO state = UPnPTestStates.Failed; return; } else { AddEvent(LogImportance.Remark,"Subscribe","SUBSCRIBE: " + s.ServiceURN + " << OK >>"); // Renew Test R = new HTTPMessage(); R.Directive = "SUBSCRIBE"; R.DirectiveObj = HTTPMessage.UnEscapeString(EventUri.PathAndQuery); R.AddTag("Host",dest.ToString()); R.AddTag("SID",SID); R.AddTag("Timeout","Second-15"); StartCountDown(30); SID = ""; MRE.Reset(); AddHTTPMessage(R); rq = new HTTPRequest(); rq.OnResponse += new HTTPRequest.RequestHandler(SubscribeSink); rq.PipelineRequest(dest,R,s); MRE.WaitOne(30000,false); AbortCountDown(); if (SID=="") { AddEvent(LogImportance.Critical,"Subscribe","SUBSCRIBE (Renew): " + s.ServiceURN + " << FAILED >>"); AddEvent(LogImportance.Remark,"Subscribe","Aborting tests"); result = "Subscription test failed."; // TODO state = UPnPTestStates.Failed; return; } else { AddEvent(LogImportance.Remark,"Subscribe","SUBSCRIBE (Renew): " + s.ServiceURN + " << OK >>"); // Cancel R = new HTTPMessage(); R.Directive = "UNSUBSCRIBE"; R.DirectiveObj = HTTPMessage.UnEscapeString(EventUri.PathAndQuery); R.AddTag("Host",dest.ToString()); R.AddTag("SID",SID); StartCountDown(30); SID = ""; MRE.Reset(); rq = new HTTPRequest(); rq.OnResponse += new HTTPRequest.RequestHandler(CancelSink); AddHTTPMessage(R); rq.PipelineRequest(dest,R,s); MRE.WaitOne(30000,false); AbortCountDown(); if (SID=="") { AddEvent(LogImportance.Critical,"Subscribe","UNSUBSCRIBE: " + s.ServiceURN + " << FAILED >>"); AddEvent(LogImportance.Remark,"Subscribe","Aborting tests"); result = "Subscription test failed."; state = UPnPTestStates.Failed; return; } else { AddEvent(LogImportance.Remark,"Subscribe","UNSUBSCRIBE: " + s.ServiceURN + " << OK >>"); } /* Test for duplicate SID * as well as initial events */ EventTable.Clear(); NumEvents = 0; foreach(UPnPStateVariable V in s.GetStateVariables()) { if(V.SendEvent) { ++ NumEvents; EventTable[V.Name] = false; V.OnModified -= new UPnPStateVariable.ModifiedHandler(StateVarModifiedSink); V.OnModified += new UPnPStateVariable.ModifiedHandler(StateVarModifiedSink); } } if(EventTable.Count>0) { MRE.Reset(); s.OnSubscribe -= new UPnPService.UPnPEventSubscribeHandler(OnSubscribeSink); s.OnSubscribe += new UPnPService.UPnPEventSubscribeHandler(OnSubscribeSink); s.UnSubscribe(null); foreach(UPnPStateVariable V in s.GetStateVariables()) { V.Clear(); } s.Subscribe(120,null); MRE.WaitOne(30000,false); if(SID=="") { // Subscribe Failed AddEvent(LogImportance.Critical,"Subscribe","SUBSCRIBE(2): " + s.ServiceURN + " << FAILED >>"); AddEvent(LogImportance.Remark,"Subscribe","Aborting tests"); result = "Subscription test failed."; state = UPnPTestStates.Failed; return; } else { if(SID==null) { // Duplicate SID // Subscribe Failed AddEvent(LogImportance.Critical,"Subscribe","SUBSCRIBE(2): " + s.ServiceURN + " << FAILED, duplicate SID >>"); AddEvent(LogImportance.Remark,"Subscribe","Aborting tests"); result = "Subscription test failed."; state = UPnPTestStates.Failed; return; } else { // Check Hashtable IDictionaryEnumerator de = EventTable.GetEnumerator(); bool OK = true; while(de.MoveNext()) { if((bool)de.Value==false) { // No Event Received OK = false; AddEvent(LogImportance.Critical,"Subscribe"," StateVariable: " + (string)de.Key + " >> Event NOT received"); } else { // OK AddEvent(LogImportance.Remark,"Subscribe"," StateVariable: " + (string)de.Key + " >> Event OK"); } } if(OK==false) { AddEvent(LogImportance.Critical,"Subscribe","SUBSCRIBE(2): " + s.ServiceURN + " << FAILED, Did not receive all events >>"); AddEvent(LogImportance.Remark,"Subscribe","Aborting tests"); result = "Subscription test failed."; state = UPnPTestStates.Failed; return; } } } } } } } } result = "Subscribe Tests OK"; state = UPnPTestStates.Pass; }
/// <summary> /// Method executes when a control point invokes the ContentDirectory.ImportResource action. /// The method first checks to see if the local URI actually maps to an automapped file /// and that the remote URI is an HTTP resource. /// The method then asks upper software layers to accept or reject the request to /// import a resource from a remote URI to a local URI. Upper software layers reject the request by throwing an exception, /// preferably a UPnPCustomException. If the request was approved by upper layers, /// then we do a bunch of stuff that results in the file getting transferred over HTTP. /// </summary> /// <param name="SourceURI">the URI where the binary should be obtained</param> /// <param name="DestinationURI">the URI (that can map to a local file) where the binary should be stored</param> /// <param name="TransferID">Returns ID for the file transfer.</param> private void SinkCd_ImportResource(System.Uri SourceURI, System.Uri DestinationURI, out System.UInt32 TransferID) { string objectID, resourceID; // Parse the media and resource IDs from the destination uri. this.GetObjectResourceIDS(DestinationURI, out objectID, out resourceID); if ((objectID == "") || (resourceID == "")) { throw new Error_NoSuchResource(DestinationURI.ToString()); } else { // TODO: Might consider throwing ane xception in the // rare case that stupid ass control point says to // download to a different media server. } // ensure that we're doing http if (SourceURI.Scheme.ToLower().StartsWith("http") == false) { throw new Error_NonHttpImport(DestinationURI.ToString()); } // get the resource object associated with the destination uri IDvResource res = this.GetResource(objectID, resourceID); // request application logic to approve the binary transfer; // Application logic should throw an exception to rject the request. if (this.OnRequestSaveBinary != null) { this.OnRequestSaveBinary(this, res); } else { throw new Error_InvalidServerConfiguration("ImportResource() cannot be supported until the vendor configures the server correctly."); } // // Grab the file through http-get // IPAddress addr = null; IPHostEntry ihe = null; IPEndPoint dest = null; // Attempt to get a routeable IP address for the request try { if(SourceURI.HostNameType == UriHostNameType.Dns) { ihe = Dns.GetHostByName(SourceURI.Host); addr = new IPAddress(ihe.AddressList[0].Address); } else { addr = IPAddress.Parse(SourceURI.Host); } } catch { throw new Error_ConnectionProblem("Could parse or resolve the SourceURI IP address represented by" +SourceURI.ToString()); } dest = new IPEndPoint(addr, SourceURI.Port); // Open a socket and connect to the remote IP address and port System.Net.Sockets.Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { s.Connect(dest); } catch { throw new Error_ConnectionProblem("Could not connect to the remote URI " + DestinationURI.ToString()); } // Do a check to make sure we're not dumping to a directory. string filename = res.ContentUri.Substring(MediaResource.AUTOMAPFILE.Length); if (Directory.Exists(filename)) { throw new Error_ImportError("System error. Resource has been mapped incorrectly. Cannot overwrite a directory with a binary."); } // Create an HTTP session for this socket. // Set things up so that the HTTP-GET will automatically dump // the body of the message into a binary file that has // been automatically mapped. HTTPSession session = new HTTPSession(s, null, null); this.SetupSessionForTransfer(session); session.OnHeader += new HTTPSession.ReceiveHeaderHandler(this.GetRequest_OnHeaderReceiveSink); try { session.UserStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None); } catch { throw new Error_ImportError("System busy. Could not open file from local system for writing."); } if (session.UserStream == null) { throw new Error_ImportError("System error. Cannot write to a null stream."); } SessionData sd = (SessionData) session.StateObject; sd.HttpVer1_1 = false; // Create the HTTP message that will request the binary. HTTPMessage msg = new HTTPMessage(); msg.Directive = "GET"; msg.DirectiveObj = HTTPMessage.UnEscapeString(SourceURI.PathAndQuery); msg.AddTag("HOST", dest.ToString()); msg.Version = "1.0"; // Create an HttpTransfer object that will represent the progress // of this file transfer and add it to the media server's current // transfers list. long expectedLength = 0; HttpTransfer transferInfo = new HttpTransfer(true, true, session, res, session.UserStream, expectedLength); this.AddTransfer(session, transferInfo); TransferID = transferInfo.m_TransferId; // Go make the request for the file. session.Send(msg); this.m_Stats.ImportResource++; this.FireStatsChange(); }
/// <summary> /// This method is called by <see cref="MediaServerDevice.WebServer_OnPacketReceiveSink"/> /// and handles the HTTP-GET or HTTP-GET message requests and provides /// the appropriate response. In either case, the handler is intended /// to handle requests for resource URIs that have been mapped to local /// files using the <see cref="MediaResource.AUTOMAPFILE"/> convention. /// <para> /// If a resource cannot be mapped to a local file, /// then the method will ask upper-layer application logic /// for a stream object to send in response to the request. /// This is used primarily in scenarios where the application intentionally /// specified a contentUri value for a resource that uses the /// <see cref="MediaResource.AUTOMAPFILE"/> convention but doesn't /// actually map to a local file. This gives the upper application layer /// to provide transcoded stream objects or some specialized file stream /// that is not stored on the local file system. /// </para> /// <para> /// Upper application layers can always opt to leave the stream object /// blank, effectively indicating that the HTTP-GET or head request /// cannot be handled because such a file does not exist. /// </para> /// </summary> /// <param name="msg"></param> /// <param name="session"></param> private void HandleGetOrHeadRequest(HTTPMessage msg, HTTPSession session) { // Format of DirectiveObj will be // "/[res.m_ResourceID]/[item.ID]/[item.Title].[ext]" // We want the bool is404 = true; Exception problem = null; string resourceID = null; string objectID = null; try { DText DirectiveParser = new DText(); DirectiveParser.ATTRMARK = "/"; DirectiveParser[0] = msg.DirectiveObj; resourceID = DirectiveParser[2]; objectID = DirectiveParser[3]; IDvResource res = this.GetResource(objectID, resourceID); if (res == null) { throw new Error_GetRequestError(msg.DirectiveObj, null); } else { // attempt to figure otu the local file path and the mime type string f = MediaResource.AUTOMAPFILE; string fileName = res.ContentUri.Substring(f.Length); string type = res.ProtocolInfo.MimeType; if ((type == null) || (type == "") || (type == "*")) { //content-type not known, programmer //that built content-hierarchy didn't provide one throw new Error_GetRequestError(msg.DirectiveObj, res); } else { // must be a get or head request // check if the file actually exists if (Directory.Exists(fileName)) { throw new Error_GetRequestError(msg.DirectiveObj, res); } FileNotMapped mapping = new FileNotMapped(); mapping.RequestedResource = res; mapping.LocalInterface = session.Source.ToString(); mapping.RedirectedStream = null; if (File.Exists(fileName)) { // the file exists, so go ahead and send it mapping.RedirectedStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); } else { try { // the file doesn't exist but the owner of this // server specified some kind of locally mapped file // so perhaps they may want to route a stream object themselves if (this.OnFileNotMapped != null) { this.OnFileNotMapped (this, mapping); } } catch (Exception ofnm) { mapping.RedirectedStream = null; } } // if the RedirectedStream is blank, then it means // no stream can be sent in response to the request if (mapping.RedirectedStream != null) { lock (session) { // get the intended length, if known long expectedLength = -1; if (mapping.OverrideRedirectedStreamLength) { expectedLength = mapping.ExpectedStreamLength; } else { expectedLength = mapping.RedirectedStream.Length; } if (String.Compare(msg.Directive, "HEAD", true) == 0) { // must be a head request - reply with 200/OK, content type, content length HTTPMessage head = new HTTPMessage(); head.StatusCode = 200; head.StatusData = "OK"; head.ContentType = type; if (expectedLength >= 0) { // if we can calculate the length, // then we provide a content-length and // also indicate that range requests can be // handled. head.OverrideContentLength = true; string rangeStr = msg.GetTag("RANGE"); if ((rangeStr == null) || (rangeStr == "")) { head.AddTag("CONTENT-LENGTH", expectedLength.ToString()); head.AddTag("ACCEPT-RANGES", "bytes"); } else { ArrayList rangeSets = new ArrayList(); head.StatusCode = 206; AddRangeSets(rangeSets, rangeStr.Trim().ToLower(), expectedLength); if (rangeSets.Count == 1) { head.AddTag("Content-Range", "bytes " + ((HTTPSession.Range)(rangeSets[0])).Position.ToString() + "-" + ((int)(((HTTPSession.Range)(rangeSets[0])).Position+((HTTPSession.Range)(rangeSets[0])).Length-1)).ToString() + "/" + expectedLength.ToString()); head.AddTag("Content-Length", ((HTTPSession.Range)(rangeSets[0])).Length.ToString()); } } } else { // can't calculate length => can't do range head.AddTag("ACCEPT-RANGES", "none"); } session.Send(head); is404 = false; } else { ArrayList rangeSets = new ArrayList(); string rangeStr = msg.GetTag("RANGE"); // Only allow range requests for content where we have the // entire length and also only for requests that have // also provided an allowed range. if ((rangeStr == null) || (rangeStr != "")) { if (expectedLength >= 0) { // validate the requested ranges; if invalid range // found, send the entire document... AddRangeSets(rangeSets, rangeStr.Trim().ToLower(), expectedLength); } } // must be a get request // create an outgoing transfer that is not visible to UPNP // GetTransferProgress method, and add the transfer HttpTransfer transferInfo = new HttpTransfer(false, false, session, res, mapping.RedirectedStream, expectedLength); this.AddTransfer(session, transferInfo); if (rangeSets.Count > 0) { session.SendStreamObject(mapping.RedirectedStream, (HTTPSession.Range[])rangeSets.ToArray(typeof(HTTPSession.Range)), type); } else { //start from the beginning mapping.RedirectedStream.Seek(0, SeekOrigin.Begin); if (expectedLength >= 0) { session.SendStreamObject(mapping.RedirectedStream, expectedLength, type); } else { session.SendStreamObject(mapping.RedirectedStream, type); } } is404 = false; } } } } } } catch (Exception error) { problem = error; } if (is404) { StringBuilder sb = new StringBuilder(); sb.Append("File not found."); sb.AppendFormat("\r\n\tRequested: \"{0}\"", msg.DirectiveObj); if (objectID != null) { sb.AppendFormat("\r\n\tObjectID=\"{0}\"", objectID); } if (resourceID != null) { sb.AppendFormat("\r\n\tResourceID=\"{0}\"", resourceID); } Error_GetRequestError getHeadError = problem as Error_GetRequestError; if (getHeadError != null) { sb.Append("\r\n"); IUPnPMedia mobj = this._GetEntry(objectID); if (mobj == null) { sb.AppendFormat("\r\n\tCould not find object with ID=\"{0}\"", objectID); } else { sb.AppendFormat("\r\n\tFound object with ID=\"{0}\"", objectID); sb.Append("\r\n---Metadata---\r\n"); sb.Append(mobj.ToDidl()); } sb.Append("\r\n"); if (getHeadError.Resource == null) { sb.Append("\r\n\tResource is null."); } else { sb.Append("\r\n\tResource is not null."); string uri = getHeadError.Resource.ContentUri; if (uri== null) { sb.Append("\r\n\t\tContentUri of resource is null."); } else if (uri == "") { sb.Append("\r\n\t\tContentUri of resource is empty."); } else { sb.AppendFormat("\r\n\t\tContentUri of resource is \"{0}\"", uri); } } } if (problem != null) { sb.Append("\r\n"); Exception e = problem; sb.Append("\r\n!!! Exception information !!!"); while (e != null) { sb.AppendFormat("\r\nMessage=\"{0}\".\r\nStackTrace=\"{1}\"", e.Message, e.StackTrace); e = e.InnerException; if (e != null) { sb.Append("\r\n---InnerException---"); } } } // file has not been found so return a valid HTTP 404 error message HTTPMessage error = new HTTPMessage(); error.StatusCode = 404; error.StatusData = "File not found"; error.StringBuffer = sb.ToString(); session.Send(error); } }
private HTTPMessage[] MSEARCH(UPnPDevice device) { ArrayList PacketList = new ArrayList(); foreach (UPnPDevice d in device.EmbeddedDevices) { foreach (HTTPMessage m in MSEARCH(d)) { PacketList.Add(m); } } HTTPMessage rq; rq = new HTTPMessage(); rq.Directive = "M-SEARCH"; rq.DirectiveObj = "*"; rq.AddTag("MX", "5"); rq.AddTag("ST", "uuid:" + device.UniqueDeviceName); rq.AddTag("Host", "239.255.255.250:1900"); rq.AddTag("MAN", "\"ssdp:discover\""); PacketList.Add(rq); rq = new HTTPMessage(); rq.Directive = "M-SEARCH"; rq.DirectiveObj = "*"; rq.AddTag("MX", "5"); rq.AddTag("ST", device.DeviceURN); rq.AddTag("Host", "239.255.255.250:1900"); rq.AddTag("MAN", "\"ssdp:discover\""); PacketList.Add(rq); foreach (UPnPService s in device.Services) { rq = new HTTPMessage(); rq.Directive = "M-SEARCH"; rq.DirectiveObj = "*"; rq.AddTag("MX", "5"); rq.AddTag("ST", s.ServiceURN); rq.AddTag("Host", "239.255.255.250:1900"); rq.AddTag("MAN", "\"ssdp:discover\""); PacketList.Add(rq); } return ((HTTPMessage[])PacketList.ToArray(typeof(HTTPMessage))); }
private void BuildByePacket2(ArrayList ByeList, IPAddress local) { HTTPMessage msg; for (int id = 0; id < Services.Length; ++id) { msg = new HTTPMessage(); msg.Directive = "NOTIFY"; msg.DirectiveObj = "*"; msg.AddTag("Host", Utils.GetMulticastAddrBraketPort(local)); msg.AddTag("NT", Services[id].ServiceURN); msg.AddTag("NTS", "ssdp:byebye"); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::" + Services[id].ServiceURN); ByeList.Add(msg); } msg = new HTTPMessage(); msg.Directive = "NOTIFY"; msg.DirectiveObj = "*"; msg.AddTag("Host", Utils.GetMulticastAddrBraketPort(local)); msg.AddTag("NT", DeviceURN); msg.AddTag("NTS", "ssdp:byebye"); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::" + DeviceURN); ByeList.Add(msg); msg = new HTTPMessage(); msg.Directive = "NOTIFY"; msg.DirectiveObj = "*"; msg.AddTag("Host", Utils.GetMulticastAddrBraketPort(local)); msg.AddTag("NT", "uuid:" + UniqueDeviceName); msg.AddTag("NTS", "ssdp:byebye"); msg.AddTag("USN", "uuid:" + UniqueDeviceName); ByeList.Add(msg); }
private void Validate_DISCOVERY() { //Test all types of M-SEARCH, both valid and invalid MSEARCHTable.Clear(); ASocket.OnReceive -= new AsyncSocket.OnReceiveHandler(ReceiveSink); ASocket.OnReceive += new AsyncSocket.OnReceiveHandler(MSEARCHSink); HTTPMessage rq = new HTTPMessage(); byte[] rbuf; IPEndPoint d = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900); rq.Directive = "M-SEARCH"; rq.DirectiveObj = "*"; rq.AddTag("MX", "5"); rq.AddTag("Host", "239.255.255.250:1900"); rq.AddTag("MAN", "\"ssdp:discover\""); rq.AddTag("ST", "ssdp:all"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(0, 91); MRE.WaitOne(8000, false); AbortCountDown(); if (MSEARCHTable.ContainsKey("upnp:rootdevice")) { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<ssdp:all / upnp:rootdevice>> OK"); } else { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.Critical, "Discovery", "MSEARCH <<ssdp:all / upnp:rootdevice>> MISSING"); } foreach (HTTPMessage m in MSEARCH(TestDevice)) { if (MSEARCHTable.ContainsKey(m.GetTag("ST").Trim())) { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<ssdp:all / " + m.GetTag("ST").Trim() + ">> OK"); } else { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.Critical, "Discovery", "MSEARCH <<ssdp:all / " + m.GetTag("ST").Trim() + ">> MISSING"); } } // Test MSEARCH upnp:rootdevice, and others MSEARCHTable.Clear(); rq.AddTag("ST", "upnp:rootdevice"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); foreach (HTTPMessage m in MSEARCH(TestDevice)) { this.sample2 += "\r\n\r\n" + m.StringPacket; ASocket.Send(m.RawPacket, 0, m.RawPacket.Length, d); } MRE.Reset(); StartCountDown(8, 91); MRE.WaitOne(8000, false); AbortCountDown(); ASocket.OnReceive -= new AsyncSocket.OnReceiveHandler(MSEARCHSink); if (MSEARCHTable.ContainsKey("upnp:rootdevice")) { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<upnp:rootdevice>> OK"); } else { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.Critical, "Discovery", "MSEARCH <<upnp:rootdevice>> MISSING"); } foreach (HTTPMessage m in MSEARCH(TestDevice)) { if (MSEARCHTable.ContainsKey(m.GetTag("ST").Trim())) { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<" + m.GetTag("ST").Trim() + ">> OK"); } else { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.Critical, "Discovery", "MSEARCH <<" + m.GetTag("ST").Trim() + ">> MISSING"); } } // Test Invalid MSEARCHes string ST = ""; MSEARCHTable.Clear(); ASocket.OnReceive += new AsyncSocket.OnReceiveHandler(BadMSEARCHSink); rq = new HTTPMessage(); rq.Directive = "M-SEARCH"; rq.DirectiveObj = "*"; rq.AddTag("MX", "2"); rq.AddTag("Host", "239.255.255.250:1900"); rq.AddTag("MAN", "\"ssdp:discover\""); rq.AddTag("ST", "uuid:___" + TestDevice.UniqueDeviceName + "___"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(16, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<NonExistent UDN>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<NonExistent UDN>> OK"); } MSEARCHTable.Clear(); ST = TestDevice.DeviceURN; int i = ST.LastIndexOf(":"); if (i == -1) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "Can't parse DeviceURN"); return; } ST = ST.Substring(0, i); ST = ST + ":" + ((int)(int.Parse(TestDevice.Version) + 5)).ToString(); rq.AddTag("ST", ST); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(21, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<Existing Device Type, Bad Version>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<Existing Device Type, Bad Version>> OK"); } MSEARCHTable.Clear(); UPnPService _S = FetchAService(TestDevice); ST = _S.ServiceURN; ST = ST.Substring(0, ST.LastIndexOf(":")); ST = ST + ":" + ((int)(int.Parse(_S.Version) + 5)).ToString(); rq.AddTag("ST", ST); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(26, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<Existing Service Type, Bad Version>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<Existing Service Type, Bad Version>> OK"); } // Test MSEARCH No * MSEARCHTable.Clear(); rq = new HTTPMessage(); rq.Directive = "M-SEARCH"; rq.DirectiveObj = ""; rq.AddTag("MX", "2"); rq.AddTag("Host", "239.255.255.250:1900"); rq.AddTag("MAN", "\"ssdp:discover\""); rq.AddTag("ST", "upnp:rootdevice"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(31, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<No *>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<No *>> OK"); } MSEARCHTable.Clear(); rq.DirectiveObj = "/"; rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(36, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<Not *>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<Not *>> OK"); } MSEARCHTable.Clear(); rq = new HTTPMessage(); rq.Directive = "M-SEARCH"; rq.DirectiveObj = ""; rq.AddTag("MX", "2"); rq.AddTag("Host", "239.255.255.250:1900"); rq.AddTag("MAN", "\"ssdp:discover\""); rq.AddTag("ST", "upnp:rootdevice"); rq.Version = "1.0"; rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(41, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<Version = 1.0>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<Version = 1.0>> OK"); } MSEARCHTable.Clear(); rq.DirectiveObj = "*"; rq.Version = ""; rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(46, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<No Version>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<No Version>> OK"); } MSEARCHTable.Clear(); rq.Version = "1.1"; rq.RemoveTag("MAN"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(51, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<No MAN>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<No MAN>> OK"); } MSEARCHTable.Clear(); rq.AddTag("MAN", "\"ssdp:discover\""); rq.RemoveTag("MX"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(56, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<No MX>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<No MX>> OK"); } MSEARCHTable.Clear(); rq.AddTag("MX", ""); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(61, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<MX Empty>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<MX Empty>> OK"); } MSEARCHTable.Clear(); rq.AddTag("MX", "Z"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(66, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<MX Not Integer>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<MX Not Integer>> OK"); } MSEARCHTable.Clear(); rq.AddTag("MX", "-1"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(71, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<MX Negative>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<MX Negative>> OK"); } MSEARCHTable.Clear(); rq.AddTag("MX", "2"); rq.RemoveTag("ST"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(76, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<No ST>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<No ST>> OK"); } MSEARCHTable.Clear(); rq.AddTag("ST", ""); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(81, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<ST Empty>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<ST Empty>> OK"); } MSEARCHTable.Clear(); rq.AddTag("ST", "ABCDEFG"); rbuf = rq.RawPacket; ASocket.Send(rbuf, 0, rbuf.Length, d); MRE.Reset(); StartCountDown(86, 91); MRE.WaitOne(5000, false); AbortCountDown(); if (MSEARCHTable.Count != 0) { DISCOVERY = UPnPTestStates.Failed; AddEvent(LogImportance.High, "Discovery", "MSEARCH <<ST Invalid>> Unexpected Response"); } else { AddEvent(LogImportance.Remark, "Discovery", "MSEARCH <<ST Invalid>> OK"); } SetState("Discovery", DISCOVERY); if (DISCOVERY == UPnPTestStates.Pass) { Results.Add("Discovery mechanism OK"); } else { Results.Add("Discovery mechanism is not behaving correctly"); } }
private HTTPMessage[] BuildNotifyPacket(IPAddress local) { ArrayList NotifyList = new ArrayList(); IPEndPoint localep = null; HTTPMessage msg; try { localep = ((MiniWebServer)WebServerTable[local.ToString()]).LocalIPEndPoint; } catch (Exception ex) { OpenSource.Utilities.EventLogger.Log(ex); return (new HTTPMessage[0]); } String BaseURL; if (localep.AddressFamily == AddressFamily.InterNetworkV6) { string ipaddr = localep.Address.ToString(); int i = ipaddr.IndexOf("%"); if (i > 0) ipaddr = ipaddr.Substring(0, i); BaseURL = "http://[" + ipaddr + "]:" + localep.Port.ToString() + "/"; } else { BaseURL = "http://" + localep.Address.ToString() + ":" + localep.Port.ToString() + "/"; } msg = new HTTPMessage(); msg.Directive = "NOTIFY"; msg.DirectiveObj = "*"; msg.AddTag("Host", Utils.GetMulticastAddrBraketPort(local)); msg.AddTag("NT", "upnp:rootdevice"); msg.AddTag("NTS", "ssdp:alive"); msg.AddTag("Location", BaseURL); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::upnp:rootdevice"); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); NotifyList.Add(msg); BuildNotifyPacket2(BaseURL, NotifyList, local); foreach (UPnPDevice d in this.EmbeddedDevices) { d.BuildNotifyPacket2(BaseURL, NotifyList, local); } return ((HTTPMessage[])NotifyList.ToArray(typeof(HTTPMessage))); }
/// <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); } } }
private void BuildNotifyPacket2(string BaseURL, ArrayList NotifyList, IPAddress local) { HTTPMessage msg; for (int id = 0; id < Services.Length; ++id) { msg = new HTTPMessage(); msg.Directive = "NOTIFY"; msg.DirectiveObj = "*"; msg.AddTag("Host", Utils.GetMulticastAddrBraketPort(local)); msg.AddTag("NT", Services[id].ServiceURN); msg.AddTag("NTS", "ssdp:alive"); msg.AddTag("Location", BaseURL); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::" + Services[id].ServiceURN); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); NotifyList.Add(msg); } msg = new HTTPMessage(); msg.Directive = "NOTIFY"; msg.DirectiveObj = "*"; msg.AddTag("Host", Utils.GetMulticastAddrBraketPort(local)); msg.AddTag("NT", DeviceURN); msg.AddTag("NTS", "ssdp:alive"); msg.AddTag("Location", BaseURL); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::" + DeviceURN); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); NotifyList.Add(msg); msg = new HTTPMessage(); msg.Directive = "NOTIFY"; msg.DirectiveObj = "*"; msg.AddTag("Host", Utils.GetMulticastAddrBraketPort(local)); msg.AddTag("NT", "uuid:" + UniqueDeviceName); msg.AddTag("NTS", "ssdp:alive"); msg.AddTag("Location", BaseURL); msg.AddTag("USN", "uuid:" + UniqueDeviceName); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); NotifyList.Add(msg); }
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 HTTPMessage Get(String GetWhat, IPEndPoint local) { HTTPMessage msg = new HTTPMessage(); if (GetWhat == "/") { msg.StatusCode = 200; msg.StatusData = "OK"; msg.AddTag("Content-Type", "text/xml"); msg.BodyBuffer = GetRootDeviceXML(local); return (msg); } else { GetWhat = GetWhat.Substring(1); } /* if ((GetWhat == "icon.png") && (_icon != null)) { lock (_icon) { MemoryStream mstm = new MemoryStream(); _icon.Save(mstm, System.Drawing.Imaging.ImageFormat.Png); msg.StatusCode = 200; msg.StatusData = "OK"; msg.ContentType = "image/png"; msg.BodyBuffer = mstm.ToArray(); mstm.Close(); } return (msg); } if ((GetWhat == "favicon.ico") && (_favicon != null)) { lock (_favicon) { MemoryStream mstm = new MemoryStream(); _favicon.Save(mstm); msg.StatusCode = 200; msg.StatusData = "OK"; msg.ContentType = "image/x-icon"; msg.BodyBuffer = mstm.ToArray(); mstm.Close(); } return (msg); } */ bool SCPDok = false; for (int id = 0; id < Services.Length; ++id) { if (GetWhat == Services[id].SCPDFile) { SCPDok = true; msg.StatusCode = 200; msg.StatusData = "OK"; msg.AddTag("Content-Type", "text/xml"); msg.BodyBuffer = Services[id].GetSCPDXml(); break; } } if (SCPDok == true) { return (msg); } try { FileStream fs = new FileStream(RootPath + GetWhat, FileMode.Open, FileAccess.Read, FileShare.Read); byte[] buffer = new byte[(int)fs.Length]; fs.Read(buffer, 0, (int)fs.Length); fs.Close(); msg.StatusCode = 200; msg.StatusData = "OK"; String ct = "application/octet-stream"; if ((GetWhat.EndsWith(".html")) || (GetWhat.EndsWith(".htm")) == true) { ct = "text/html"; } else { if (GetWhat.EndsWith(".xml") == true) { ct = "text/xml"; } } msg.AddTag("Content-Type", ct); msg.BodyBuffer = buffer; return (msg); } catch (Exception ex) { OpenSource.Utilities.EventLogger.Log(ex); throw (new UPnPCustomException(404, "File Not Found")); } }
/// <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); }
private void HandleSearch(String ST, IPEndPoint src, IPEndPoint local) { if (WebServerTable == null) return; //if (local == null) local = new IPEndPoint(IPAddress.Loopback, 1234); // DEBUG ********************** string x = src.Address.ToString(); ArrayList ResponseList = new ArrayList(); HTTPMessage msg; string Location = null; if (local.AddressFamily == AddressFamily.InterNetwork) { Location = "http://" + local.Address.ToString() + ":" + ((MiniWebServer)WebServerTable[local.Address.ToString()]).LocalIPEndPoint.Port.ToString() + "/"; } if (local.AddressFamily == AddressFamily.InterNetworkV6) { string xx = local.Address.ToString(); xx = xx.Substring(0, xx.IndexOf("%")); Location = "http://[" + xx + "]:" + ((MiniWebServer)WebServerTable[local.Address.ToString()]).LocalIPEndPoint.Port.ToString() + "/"; } if ((ST == "upnp:rootdevice") || (ST == "ssdp:all")) { msg = new HTTPMessage(); msg.StatusCode = 200; msg.StatusData = "OK"; msg.AddTag("ST", "upnp:rootdevice"); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::upnp:rootdevice"); msg.AddTag("Location", Location); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("EXT", ""); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); ResponseList.Add(msg); } ContainsSearchTarget(ST, Location, ResponseList); foreach (HTTPMessage SR in ResponseList) { try { SR.LocalEndPoint = local; SR.RemoteEndPoint = src; SSDPServer.UnicastData(SR); } catch (SocketException ex) { OpenSource.Utilities.EventLogger.Log(ex); } } }
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); } } } }
private void HandleWebRequest(HTTPMessage msg, HTTPSession WebSession) { DText parser = new DText(); HTTPMessage Response = new HTTPMessage(); HTTPMessage Response2 = null; String Method = msg.Directive; String MethodData = msg.DirectiveObj; if (WebSession.InternalStateObject != null) { HTTPMessage _msg = (HTTPMessage)msg.Clone(); object[] state = (object[])WebSession.InternalStateObject; _msg.DirectiveObj = (string)state[1]; VirtualDirectoryHandler t = (VirtualDirectoryHandler)state[2]; WebSession.InternalStateObject = null; t(this, _msg, WebSession, (string)state[0]); return; } if ((Method != "GET") && (Method != "HEAD") && (Method != "POST") && (Method != "SUBSCRIBE") && (Method != "UNSUBSCRIBE") && (Method != "NOTIFY")) { Response.StatusCode = 405; Response.StatusData = Method + " not supported"; WebSession.Send(Response); return; // Other methods are unknown to us } // Process Headers if (Method == "GET" || Method == "HEAD") { try { Response = Get(MethodData, WebSession.Source); } catch (UPnPCustomException ce) { OpenSource.Utilities.EventLogger.Log(ce); Response.StatusCode = ce.ErrorCode; Response.StatusData = ce.ErrorDescription; WebSession.Send(Response); return; } catch (Exception e) { OpenSource.Utilities.EventLogger.Log(e); Response.StatusCode = 500; Response.StatusData = "Internal"; Response.StringBuffer = e.ToString(); } if (Method == "HEAD") { Response.BodyBuffer = null; } WebSession.Send(Response); } if (Method == "POST") { //InvokerInfo[Thread.CurrentThread.GetHashCode()] = WebSession; try { Response = Post(MethodData, msg.StringBuffer, msg.GetTag("SOAPACTION"), WebSession); } catch (DelayedResponseException ex) { OpenSource.Utilities.EventLogger.Log(ex); InvokerInfo.Remove(Thread.CurrentThread.GetHashCode()); WebSession.StopReading(); return; } catch (UPnPCustomException ce) { OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "UPnP Error [" + ce.ErrorCode.ToString() + "] " + ce.ErrorDescription); Response.StatusCode = 500; Response.StatusData = "Internal"; Response.StringBuffer = BuildErrorBody(ce); WebSession.Send(Response); InvokerInfo.Remove(Thread.CurrentThread.GetHashCode()); return; } catch (UPnPInvokeException ie) { Response.StatusCode = 500; Response.StatusData = "Internal"; if (ie.UPNP != null) { OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "UPnP Error [" + ie.UPNP.ErrorCode.ToString() + "] " + ie.UPNP.ErrorDescription); Response.StringBuffer = BuildErrorBody(ie.UPNP); } else { OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "UPnP Invocation Error [" + ie.MethodName + "] " + ie.Message); Response.StringBuffer = BuildErrorBody(new UPnPCustomException(500, ie.Message)); } WebSession.Send(Response); InvokerInfo.Remove(Thread.CurrentThread.GetHashCode()); return; } catch (UPnPTypeMismatchException tme) { OpenSource.Utilities.EventLogger.Log(tme); Response.StatusCode = 500; Response.StatusData = "Internal"; Response.StringBuffer = BuildErrorBody(new UPnPCustomException(402, tme.Message)); WebSession.Send(Response); InvokerInfo.Remove(Thread.CurrentThread.GetHashCode()); return; } catch (UPnPStateVariable.OutOfRangeException oor) { OpenSource.Utilities.EventLogger.Log(oor); Response.StatusCode = 500; Response.StatusData = "Internal"; Response.StringBuffer = BuildErrorBody(new UPnPCustomException(402, oor.Message)); WebSession.Send(Response); InvokerInfo.Remove(Thread.CurrentThread.GetHashCode()); return; } catch (System.Reflection.TargetInvocationException tie) { Exception inner = tie.InnerException; OpenSource.Utilities.EventLogger.Log(tie); while (inner.InnerException != null && (typeof(UPnPCustomException).IsInstanceOfType(inner) == false)) { inner = inner.InnerException; } if (typeof(UPnPCustomException).IsInstanceOfType(inner)) { UPnPCustomException ce = (UPnPCustomException)inner; OpenSource.Utilities.EventLogger.Log(this, System.Diagnostics.EventLogEntryType.Error, "UPnP Error [" + ce.ErrorCode.ToString() + "] " + ce.ErrorDescription); Response.StatusCode = 500; Response.StatusData = "Internal"; Response.StringBuffer = BuildErrorBody(ce); WebSession.Send(Response); InvokerInfo.Remove(Thread.CurrentThread.GetHashCode()); return; } else { Response.StatusCode = 500; Response.StatusData = "Internal"; Response.StringBuffer = BuildErrorBody(new UPnPCustomException(500, inner.ToString())); WebSession.Send(Response); OpenSource.Utilities.EventLogger.Log(inner); return; } } catch (Exception e) { Response.StatusCode = 500; Response.StatusData = "Internal"; Response.StringBuffer = BuildErrorBody(new UPnPCustomException(500, e.ToString())); WebSession.Send(Response); OpenSource.Utilities.EventLogger.Log(e); return; } WebSession.Send(Response); InvokerInfo.Remove(Thread.CurrentThread.GetHashCode()); return; } if (Method == "SUBSCRIBE") { String SID = msg.GetTag("SID"); String NT = msg.GetTag("NT"); String Timeout = msg.GetTag("Timeout"); String CallbackURL = msg.GetTag("Callback"); if (Timeout == "") { Timeout = "7200"; // Default = 2 Hours } else { Timeout = Timeout.Substring(Timeout.IndexOf("-") + 1).Trim().ToUpper(); if (Timeout == "INFINITE") { Timeout = "0"; } } if (SID != "") { // Renew RenewEvents(MethodData.Substring(1), SID, Timeout); } else { // Subscribe try { Response2 = SubscribeEvents(ref SID, MethodData.Substring(1), CallbackURL, Timeout); } catch (Exception s_exception) { OpenSource.Utilities.EventLogger.Log(s_exception); HTTPMessage err = new HTTPMessage(); err.StatusCode = 500; err.StatusData = s_exception.Message; WebSession.Send(err); return; } } if (Timeout == "0") { Timeout = "Second-infinite"; } else { Timeout = "Second-" + Timeout; } Response.StatusCode = 200; Response.StatusData = "OK"; Response.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); Response.AddTag("SID", SID); Response.AddTag("Timeout", Timeout); WebSession.Send(Response); if (Response2 != null) { Uri[] cbURL = ParseEventURL(CallbackURL); for (int x = 0; x < cbURL.Length; ++x) { Response2.DirectiveObj = HTTPMessage.UnEscapeString(cbURL[x].PathAndQuery); Response2.AddTag("Host", cbURL[x].Host + ":" + cbURL[x].Port.ToString()); IPEndPoint d = new IPEndPoint(IPAddress.Parse(cbURL[x].Host), cbURL[x].Port); HTTPRequest R = new HTTPRequest(); R.OnResponse += new HTTPRequest.RequestHandler(HandleInitialEvent); this.InitialEventTable[R] = R; R.PipelineRequest(d, Response2, null); } } } if (Method == "UNSUBSCRIBE") { CancelEvent(MethodData.Substring(1), msg.GetTag("SID")); Response.StatusCode = 200; Response.StatusData = "OK"; WebSession.Send(Response); } }
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 static void ParseIconXML(UPnPDevice d, int startLine, String XML) { StringReader MyString = new StringReader(XML); XmlTextReader XMLDoc = new XmlTextReader(MyString); String iurl = null; try { XMLDoc.Read(); XMLDoc.MoveToContent(); if (XMLDoc.LocalName == "icon") { XMLDoc.Read(); XMLDoc.MoveToContent(); while (XMLDoc.LocalName != "icon") { if (XMLDoc.LocalName == "url") { iurl = XMLDoc.ReadString(); } else { XMLDoc.Skip(); } XMLDoc.Read(); XMLDoc.MoveToContent(); } } if (iurl != null && d.BaseURL != null) { if (iurl.ToUpper().StartsWith("HTTP://") == false) { if (iurl.StartsWith("/") == true) { iurl = "http://" + d.BaseURL.Host + ":" + d.BaseURL.Port.ToString() + iurl; } else { iurl = HTTPMessage.UnEscapeString(d.BaseURL.AbsoluteUri + iurl); } } d.FetchIcon(new Uri(iurl)); } } catch (Exception ex) { throw new Exception("Invalid icon XML near line " + (startLine + XMLDoc.LineNumber).ToString() + ", Position " + XMLDoc.LinePosition.ToString(), ex); } } internal void FetchIcon(Uri IconUri) { HttpRequestor httprequestor = new HttpRequestor(); httprequestor.OnRequestCompleted += new HttpRequestor.RequestCompletedHandler(HandleIcon); httprequestor.LaunchRequest(IconUri.ToString(), null, null, null, null); InitialEventTable[httprequestor] = httprequestor; } */ /* void HandleIcon(HttpRequestor sender, bool success, object tag, string url, byte[] data) { InitialEventTable.Remove(sender); if (success) { System.Drawing.Image i = System.Drawing.Image.FromStream(new MemoryStream(data)); if (i != null) _icon = i; } } */ /// <summary> /// Adds response packets for matches in a search request /// </summary> /// <param name="ST">SearchTarget</param> /// <param name="Location">Location</param> /// <param name="ResponseList">ArrayList</param> public void ContainsSearchTarget(String ST, string Location, ArrayList ResponseList) { HTTPMessage msg; if (ST == "ssdp:all") { msg = new HTTPMessage(); msg.StatusCode = 200; msg.StatusData = "OK"; msg.AddTag("ST", "uuid:" + UniqueDeviceName); msg.AddTag("USN", "uuid:" + UniqueDeviceName); msg.AddTag("Location", Location); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("EXT", ""); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); ResponseList.Add(msg); msg = new HTTPMessage(); msg.StatusCode = 200; msg.StatusData = "OK"; msg.AddTag("ST", DeviceURN); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::" + DeviceURN); msg.AddTag("Location", Location); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("EXT", ""); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); ResponseList.Add(msg); } if (("uuid:" + UniqueDeviceName) == ST) { msg = new HTTPMessage(); msg.StatusCode = 200; msg.StatusData = "OK"; msg.AddTag("ST", ST); msg.AddTag("USN", "uuid:" + UniqueDeviceName); msg.AddTag("Location", Location); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("EXT", ""); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); ResponseList.Add(msg); } if (DeviceURN == ST) { msg = new HTTPMessage(); msg.StatusCode = 200; msg.StatusData = "OK"; msg.AddTag("ST", DeviceURN); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::" + DeviceURN); msg.AddTag("Location", Location); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("EXT", ""); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); ResponseList.Add(msg); } foreach (UPnPService s in Services) { if (ST == "ssdp:all") { msg = new HTTPMessage(); msg.StatusCode = 200; msg.StatusData = "OK"; msg.AddTag("ST", s.ServiceURN); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::" + s.ServiceURN); msg.AddTag("Location", Location); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("EXT", ""); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); ResponseList.Add(msg); } if (s.ServiceURN == ST) { msg = new HTTPMessage(); msg.StatusCode = 200; msg.StatusData = "OK"; msg.AddTag("ST", s.ServiceURN); msg.AddTag("USN", "uuid:" + UniqueDeviceName + "::" + s.ServiceURN); msg.AddTag("Location", Location); msg.AddTag("Server", "Windows NT/5.0, UPnP/1.0"); msg.AddTag("EXT", ""); msg.AddTag("Cache-Control", "max-age=" + ExpirationTimeout.ToString()); ResponseList.Add(msg); } } foreach (UPnPDevice d in this.EmbeddedDevices) { d.ContainsSearchTarget(ST, Location, ResponseList); } }
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); } } } } }
public void Search(string SearchString, IPEndPoint ep) { HTTPMessage request = new HTTPMessage(); request.Directive = "M-SEARCH"; request.DirectiveObj = "*"; if (ep.AddressFamily == AddressFamily.InterNetwork) request.AddTag("HOST", ep.ToString()); // "239.255.255.250:1900" if (ep.AddressFamily == AddressFamily.InterNetworkV6) request.AddTag("HOST", string.Format("[{0}]:{1}", ep.Address.ToString(), ep.Port)); // "[FF05::C]:1900" or "[FF02::C]:1900" request.AddTag("MAN", "\"ssdp:discover\""); request.AddTag("MX", "10"); request.AddTag("ST", SearchString); SearchEx(System.Text.UTF8Encoding.UTF8.GetBytes(request.StringPacket), ep); }