예제 #1
0
        /// <summary>
        /// Handles an individual HTTP message
        /// Does the required action if it is a request, and sends the required response
        /// If the message is a response from the iOS device it does nothing
        /// </summary>
        /// <param name="clientStream">The stream that the message came from</param>
        /// <param name="message">The message text</param>
        private void handleMessageReceived(NetworkStream clientStream, string message, byte[] rawData)
        {
            message = message.Trim();
            if (message.StartsWith("POST /reverse HTTP/1.1")) //initial opening message, declares this connection to the the one that will be two-way
            {
                twoWayStream = clientStream;                  //this is the two way stream for comms use in future. Store it so we can use it for sending playback events later. If we try to use any other connection's stream, the iOS device will ignore it or refuse the connection.
                string response = "HTTP/1.1 101 Switching Protocols\r\n" +
                                  "Date: " + String.Format("{0:R}", DateTime.Now) + "\r\n" +
                                  "Upgrade: PTTH/1.0\r\n" +
                                  "Connection: Upgrade\r\n" +
                                  "\r\n";
                sendMessage(clientStream, response);
                return;
            }
            if (message.StartsWith("POST /scrub?position=")) //seek.
            {
                //regex to get position
                Regex regex = new Regex(@"POST /scrub\?position=([0-9\.]+) HTTP/1.1", RegexOptions.Multiline);
                Match match = regex.Match(message);

                if (match.Success)
                {
                    //scrub to position
                    string pos = match.Groups[1].ToString();
                    playbackEvent(this, "scrub", pos);
                }
                //reply with ok message
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("POST /play")) //play.
            {
                //get the url out of the message and play it here
                //URL is immediately after "Content-Location: "
                string   url;
                string[] array = Regex.Split(message, "Content-Location: ");
                if (array.Count() > 1)
                {
                    //split by URL and Start-location
                    array = Regex.Split(array[1], "Start-Position: ");
                    if (array.Count() > 1)
                    {
                        url = array[0].Trim();
                        Debug.WriteLine("Attempting to play URL" + url);

                        //get the start position
                        double start = 0;
                        Match  m     = Regex.Match(array[1].Trim(), @"(\d*\.?\d*)"); //sometimes some random stuff comes after the number, just want the number
                        if (m.Success)
                        {
                            try
                            {
                                start = Convert.ToDouble(m.Value);
                            }
                            catch (FormatException) { }
                        }


                        playURL(this, url, start);
                    }
                }
                //reply with postion message
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("GET /scrub HTTP/1.1")) //this is a request from the iOS device to ask the application how far along the playback is so it can update its progress bar
            {
                //get the current duration
                Publish theMainWindow = (Publish)Application.OpenForms["Publish"];
                int     duration      = theMainWindow.getPlayerDuration();
                int     position      = theMainWindow.getPlayerPosition();

                //get the response data string
                string responsedata = String.Format("duration: {0:0.000000}\nposition: {1:0.000000}", duration, position);

                //get the content length and add one for the newline at the end
                int contentLength = responsedata.Length + 1;

                //send the current playback position status
                string response = "HTTP/1.1 200 OK\r\n" +
                                  "Date: " + String.Format("{0:R}", DateTime.Now) + "\r\n" +
                                  "Content-Length: " + contentLength + "\r\n\r\n" +
                                  responsedata + "" +
                                  "\n";
                sendMessage(clientStream, response);
                return;
            }
            if (message.StartsWith("POST /rate?value=0.000000")) //this is how the iOS device requests the video should be paused
            {
                //pause
                playbackEvent(this, "pause", "");
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("POST /rate?value=1.000000")) //this is how the iOS device requests the video should be played
            {
                //play
                playbackEvent(this, "play", "");
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("POST /stop HTTP/1.1")) //stop
            {
                //stop the playback
                playbackEvent(this, "stop", "");
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("PUT /photo HTTP/1.1")) //photo
            {
                //get the position in the rawdata where the image starts
                int index = message.IndexOf("\r\n\r\n");
                index += 4; //the four \r\n\r\n characters
                MemoryStream ms          = new MemoryStream(rawData.Skip(index).ToArray());
                Image        returnImage = Image.FromStream(ms);
                playImage(this, returnImage);
            }
            if (message.StartsWith("POST /authorize HTTP/1.1")) //attempt to play a DRM track from the device (probably from ipod app, not youtube). Not currently supported as I don't know how to pass the key to quicktime! If anyone knows how to pass it to the quicktime control, LMK.
            {
                authorisationRequest();                         //notify the GUI that a DRM track was requested
                playbackEvent(this, "stop");                    //we can't deal with the video for now, for the above reason.
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("GET") || message.StartsWith("POST")) //unknown
            {
                //still a request of some sort (not a reply to a message sent to device), so reply with ok.
                sendHTTPOKMessage(clientStream);
                return;
            }
        }
예제 #2
0
        /// <summary>
        /// Handles an individual HTTP message
        /// Does the required action if it is a request, and sends the required response
        /// If the message is a response from the iOS device it does nothing
        /// </summary>
        /// <param name="clientStream">The stream that the message came from</param>
        /// <param name="message">The message text</param>
        ///

        //从这里开始处理实际请求 nick

        private void handleMessageReceived(NetworkStream clientStream, string message, byte[] rawData)
        {
            //message = message.Trim();              //Nick ban

            string[] messageparse = message.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);              //Nick parse

            string cseq       = "kong";
            string contentlen = "kong";
            int    type       = 0;
            int    seq        = 0;

            foreach (string trystr in messageparse)
            {
                if (trystr.Contains("CSeq"))
                {
                    cseq = parseHeader(trystr, "CSeq: ");
                }
                if (trystr.Contains("Content-Length"))
                {
                    contentlen = parseHeader(trystr, "Content-Length: ");
                }
            }
            Debug.WriteLine("Cseq: " + cseq);
            Debug.WriteLine("contentlen: " + contentlen);

            if (message.StartsWith("POST /fp-"))
            {
                int httpcontentstart = 0;
                for (int a = 0; a < 1023; a++)
                {
                    if (rawData[a] == 0x46 && rawData[a + 1] == 0x50 && rawData[a + 2] == 0x4c && rawData[a + 3] == 0x59)
                    {
                        //Debug.WriteLine(a);
                        type             = rawData[a + 5];
                        seq              = rawData[a + 6];
                        httpcontentstart = a;
                        break;
                    }
                }

                int    httpcontentlenth = Convert.ToInt32(contentlen);
                byte[] httpcontent      = new byte[httpcontentlenth];

                for (int hc = 0; hc < httpcontentlenth; hc++)
                {
                    httpcontent[hc] = rawData[httpcontentstart + hc];
                }

                Debug.WriteLine("type: " + type);
                Debug.WriteLine("seq: " + seq);

                if (type == 1)
                {
                    if (seq == 1)
                    {
                        string header = "RTSP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\nServer: AirTunes/220.68\r\nContent-Length: 142\r\nCSeq:" + cseq + "\r\n\r\n";
                        sendMessage(clientStream, header);

                        int    sb1 = (int)fairplay_setup(httpcontent, httpcontentlenth);
                        byte[] vb1 = new byte[142];
                        for (int i = 0; i < 142; i++)
                        {
                            vb1[i] = (byte)Marshal.PtrToStructure((IntPtr)(sb1++), typeof(byte));
                            //Console.Write((char)vb1[i]);
                        }

                        clientStream.Write(vb1, 0, vb1.Length);
                        clientStream.Flush();
                    }
                    else if (seq == 3)
                    {
                        string header = "RTSP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\nServer: AirTunes/220.68\r\nContent-Length: 32\r\nCSeq:" + cseq + "\r\n\r\n";
                        sendMessage(clientStream, header);

                        int    sb1 = (int)fairplay_setup(httpcontent, httpcontentlenth);
                        byte[] vb1 = new byte[142];
                        for (int i = 0; i < 142; i++)
                        {
                            vb1[i] = (byte)Marshal.PtrToStructure((IntPtr)(sb1++), typeof(byte));
                            //Console.Write((char)vb1[i]);
                        }

                        clientStream.Write(vb1, 0, 32);
                        clientStream.Flush();
                    }
                }
            }


            if (message.StartsWith("SETUP"))
            {
                if (cseq == "2")
                {
                    string setup1 = "RTSP/1.0 200 OK\r\nContent-Type: application/x-apple-binary-plist\r\nServer: AirTunes/220.68\r\nContent-Length: 0\r\nCseq: " + "2" + "\r\n\r\n";
                    sendMessage(clientStream, setup1);
                }
            }

            if (message.StartsWith("GET /info"))
            {
                string getinfocontentlen = "nick";


                Dictionary <string, object> getinforespdict = new Dictionary <string, object>
                {
                    { "macAddress", "3F:5D:62:2C:41:36" },                                                 //mac地址,需要修改
                    { "statusFlags", 68 },                                                                 //需要修改,原版为0x4
                    { "pi", "fffffd2d-fe60-42ab-8877-d3ac6084459a" },
                    { "deviceID", "3F:5D:62:2C:41:36" },
                    { "keepAliveSendStatsAsBody", true },
                    { "vv", 2 },                                                                           //这个应该不用改,和原始的mdns一样
                    { "audioLatencies", new Dictionary <string, object>[] {
                          new Dictionary <string, object>
                          {
                              { "type", 100 },
                              { "inputLatencyMicros", 0 },
                              { "audioType", "default" },
                              { "outputLatencyMicros", 0 }
                          },

                          new Dictionary <string, object> {
                              { "type", 101 },
                              { "inputLatencyMicros", 0 },
                              { "audioType", "default" },
                              { "outputLatencyMicros", 0 }
                          }
                      } },
                    { "audioFormats", new Dictionary <string, object>[] {
                          new Dictionary <string, object>
                          {
                              { "audioOutputFormats", 67108860 },
                              { "type", 100 },
                              { "audioInputFormats", 67108860 }
                          },
                          new Dictionary <string, object>
                          {
                              { "audioOutputFormats", 67108860 },
                              { "type", 101 },
                              { "audioInputFormats", 67108860 }
                          }
                      } },
                    { "displays", new Dictionary <string, object>[] {
                          new Dictionary <string, object>
                          {
                              { "widthPhysical", 0 },
                              { "heightPhysical", 0 },
                              { "uuid", "e5f7a68d-7b0f-4305-984b-974f677a150b" },
                              { "widthPixels", 1280 },
                              { "edid", new byte[] { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
                                                     , 0x5a, 0x63, 0x22, 0x38, 0x00, 0x00, 0x00, 0x00, 0x31, 0x12, 0x01, 0x03, 0x80, 0x34, 0x1d, 0x78
                                                     , 0x2e, 0xee, 0xd5, 0xa5, 0x55, 0x48, 0x9b, 0x26, 0x12, 0x50, 0x54, 0xbf, 0xef, 0x80, 0xd1, 0xc0
                                                     , 0xb3, 0x00, 0xa9, 0x40, 0x95, 0x00, 0x90, 0x40, 0x81, 0x80, 0x81, 0x40, 0x71, 0x4f, 0x02, 0x3a
                                                     , 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x08, 0x22, 0x21, 0x00, 0x00, 0x1e
                                                     , 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                                                     , 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, 0x4b, 0x0f, 0x52, 0x12, 0x00, 0x0a, 0x20, 0x20
                                                     , 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x56, 0x58, 0x32, 0x34, 0x33, 0x33, 0x77
                                                     , 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x01, 0xf6, 0x02, 0x03, 0x25, 0xf1, 0x52, 0x90, 0x05, 0x04
                                                     , 0x03, 0x02, 0x07, 0x06, 0x0f, 0x0e, 0x1f, 0x14, 0x1e, 0x1d, 0x13, 0x12, 0x11, 0x16, 0x01, 0x23
                                                     , 0x09, 0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x02, 0x3a, 0x80
                                                     , 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x08, 0x22, 0x21, 0x00, 0x00, 0x1e, 0x01
                                                     , 0x1d, 0x80, 0x18, 0x71, 0x1c, 0x16, 0x20, 0x58, 0x2c, 0x25, 0x00, 0x08, 0x22, 0x21, 0x00, 0x00
                                                     , 0x9e, 0x01, 0x1d, 0x00, 0x72, 0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0x08, 0x22, 0x21
                                                     , 0x00, 0x00, 0x1e, 0x02, 0x3a, 0x80, 0xd0, 0x72, 0x38, 0x2d, 0x40, 0x10, 0x2c, 0x45, 0x80, 0x08
                                                     , 0x22, 0x21, 0x00, 0x00, 0x1e, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10, 0x3e, 0x96
                                                     , 0x00, 0x08, 0x22, 0x21, 0x00, 0x00, 0x18, 0xe3 } },
                              { "height", 720 },
                              { "features", 14 },
                              { "rotation", true },
                              { "overscanned", true },
                              { "refreshRate", 0.016667 },
                              { "width", 1280 },
                              { "heightPixels", 720 }
                          }
                      } },
                    { "pk", new byte[] { 0x23, 0xf3, 0x1f, 0x8f, 0xd4, 0xe5, 0x02, 0xfa, 0xf0, 0xf0, 0x51, 0x89, 0x0b, 0x89, 0x23
                                         , 0xa1, 0xe0, 0xe2, 0x9d, 0xdf, 0xca, 0x1d, 0x46, 0x6b, 0x4d, 0xd0, 0x01, 0xd2, 0xf5, 0xc3, 0x35, 0xe0 } }, //这里的pk目前看来跟mdns的对不上,想不明白
                    { "model", "AppleTV3,2" },
                    { "features", 1518338039 },                                                                                                      //这个feature是需要pair-verify的,需要修改
                    { "name", "Apple TV" },
                    { "keepAliveLowPower", true },
                    { "sourceVersion", "220.68" }
                };

                //int[] x = { 2, 3, { 4 } }; //CS0623



                string getinfoheader = "RTSP/1.0 200 OK\r\nContent-Type: application/x-apple-binary-plist\r\nServer: AirTunes/220.68\r\nCSeq: " + cseq + "\r\nContent-Length: " + getinfocontentlen + "\r\n\r\n";
            }


            if (message.StartsWith("POST /reverse HTTP/1.1")) //initial opening message, declares this connection to the the one that will be two-way
            {
                twoWayStream = clientStream;                  //this is the two way stream for comms use in future. Store it so we can use it for sending playback events later. If we try to use any other connection's stream, the iOS device will ignore it or refuse the connection.
                string response = "HTTP/1.1 101 Switching Protocols\r\n" +
                                  "Date: " + String.Format("{0:R}", DateTime.Now) + "\r\n" +
                                  "Upgrade: PTTH/1.0\r\n" +
                                  "Connection: Upgrade\r\n" +
                                  "\r\n";
                sendMessage(clientStream, response);
                return;
            }
            if (message.StartsWith("POST /scrub?position=")) //seek.
            {
                //regex to get position
                Regex regex = new Regex(@"POST /scrub\?position=([0-9\.]+) HTTP/1.1", RegexOptions.Multiline);
                Match match = regex.Match(message);

                if (match.Success)
                {
                    //scrub to position
                    string pos = match.Groups[1].ToString();
                    playbackEvent(this, "scrub", pos);
                }
                //reply with ok message
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("POST /play")) //play.
            {
                //get the url out of the message and play it here
                //URL is immediately after "Content-Location: "
                string   url;
                string[] array = Regex.Split(message, "Content-Location: ");
                if (array.Count() > 1)
                {
                    //split by URL and Start-location
                    array = Regex.Split(array[1], "Start-Position: ");
                    if (array.Count() > 1)
                    {
                        url = array[0].Trim();
                        Debug.WriteLine("Attempting to play URL" + url);

                        //get the start position
                        double start = 0;
                        Match  m     = Regex.Match(array[1].Trim(), @"(\d*\.?\d*)"); //sometimes some random stuff comes after the number, just want the number
                        if (m.Success)
                        {
                            try
                            {
                                start = Convert.ToDouble(m.Value);
                            }
                            catch (FormatException) { }
                        }


                        playURL(this, url, start);
                    }
                }
                //reply with postion message
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("GET /scrub HTTP/1.1")) //this is a request from the iOS device to ask the application how far along the playback is so it can update its progress bar
            {
                //get the current duration
                Publish theMainWindow = (Publish)Application.OpenForms["Publish"];
                int     duration      = theMainWindow.getPlayerDuration();
                int     position      = theMainWindow.getPlayerPosition();

                //get the response data string
                string responsedata = String.Format("duration: {0:0.000000}\nposition: {1:0.000000}", duration, position);

                //get the content length and add one for the newline at the end
                int contentLength = responsedata.Length + 1;

                //send the current playback position status
                string response = "HTTP/1.1 200 OK\r\n" +
                                  "Date: " + String.Format("{0:R}", DateTime.Now) + "\r\n" +
                                  "Content-Length: " + contentLength + "\r\n\r\n" +
                                  responsedata + "" +
                                  "\n";
                sendMessage(clientStream, response);
                return;
            }
            if (message.StartsWith("POST /rate?value=0.000000")) //this is how the iOS device requests the video should be paused
            {
                //pause
                playbackEvent(this, "pause", "");
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("POST /rate?value=1.000000")) //this is how the iOS device requests the video should be played
            {
                //play
                playbackEvent(this, "play", "");
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("POST /stop HTTP/1.1")) //stop
            {
                //stop the playback
                playbackEvent(this, "stop", "");
                sendHTTPOKMessage(clientStream);
                return;
            }
            if (message.StartsWith("PUT /photo HTTP/1.1")) //photo
            {
                //get the position in the rawdata where the image starts
                int index = message.IndexOf("\r\n\r\n");
                index += 4; //the four \r\n\r\n characters
                MemoryStream ms          = new MemoryStream(rawData.Skip(index).ToArray());
                Image        returnImage = Image.FromStream(ms);
                playImage(this, returnImage);
            }
            if (message.StartsWith("POST /authorize HTTP/1.1")) //attempt to play a DRM track from the device (probably from ipod app, not youtube). Not currently supported as I don't know how to pass the key to quicktime! If anyone knows how to pass it to the quicktime control, LMK.
            {
                authorisationRequest();                         //notify the GUI that a DRM track was requested
                playbackEvent(this, "stop");                    //we can't deal with the video for now, for the above reason.
                sendHTTPOKMessage(clientStream);
                return;
            }

            /*
             * if (message.StartsWith("GET") || message.StartsWith("POST")) //unknown
             * {
             *  //still a request of some sort (not a reply to a message sent to device), so reply with ok.
             *  sendHTTPOKMessage(clientStream);
             *  return;
             * }
             */
        }