'How to extract a file from a large Stream and broadcast it?

Im trying to get with the result from 2 days ago and nothing till today.

  • First in the same stream i need to connect to the server via TCP after I sent a XML format with the credentials to the server.

  • Read the response from the server to know if the connection was made successfully and if its authenticated.

  • Send the XML to get the camera video in a multipart imag format. The response is in HTTP format and there is the file that I want.

I tried getting the image partially like frame per frame and writing each frame in a Stream and using a PushStreamContent to response but only show the first frame when i GET from a <img src="/api/sample"/> in a Chrome Browser.

Really I tried a lot of way to do it and every are wrong... I'm in a point where I don't know what to do. This is not my enviroment and obviosly need help.

    public HttpResponseMessage Get([FromUri] string serverHost, string cameraId, string username, string password)
    {
        SystemAccess _sysInfo = new SystemAccess();
        _sysInfo.Connect(serverHost, username, password);

        LoginInfo loginInfo = _sysInfo.LoginInfo;
        _sysInfo._basicConnection.GetConfiguration(loginInfo.Token);

        Uri webServer = new Uri("http://localhost/");
        foreach (ServerCommandService.RecorderInfo recorder in _sysInfo._basicConnection.ConfigurationInfo.Recorders)
        {
            foreach (ServerCommandService.CameraInfo cameraInfo in recorder.Cameras.Where(x => x.DeviceId == Guid.Parse(cameraId)))
            {
                webServer = new Uri(recorder.WebServerUri);
            }
        }
        //The top code is to get camera information
        ImageServerConnection imgSvr = new ImageServerConnection(webServer, cameraId, 75);
        imgSvr.SetCredentials(_sysInfo, username, password); //Auth
        imgSvr.PlaybackStartTime = 1648587605015;
        imgSvr.PlaybackEndTime = 1648587614925;

        var response = new HttpResponseMessage();
        response.Content = new PushStreamContent((stream, content, context) => imgSvr.Playback(stream));
        response.StatusCode = HttpStatusCode.OK;

        return response;
    }

    public void Playback(Stream imageContent)
    {
        Stream networkStream = null;
        try
        {
            networkStream = ConnectToImageServer();
            if (networkStream == null) return;

            _playback = true;
            int maxbuf = 1024 * 64;

            string sendBuffer = FormatConnect();
            Byte[] bytesSent = Encoding.Default.GetBytes(sendBuffer);
            networkStream.Write(bytesSent, 0, bytesSent.Length);

            Byte[] bytesReceived = new Byte[maxbuf];

            int bytes = RecvUntil(networkStream, bytesReceived, 0, maxbuf);
            string page = Encoding.UTF8.GetString(bytesReceived, 0, bytes);

            bool authenticated = false;
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(page);
            XmlNodeList nodes = doc.GetElementsByTagName("connected");
            foreach (XmlNode node in nodes)
            {
                if (node.InnerText.ToLower() == "yes")
                {
                    authenticated = true;
                }
            }

            if (!authenticated)
            {
                return;
            }

            int count = 1;
            _playbackTime = PlaybackStartTime;

            int curBufSize = maxbuf;

            int qual = _quality;
            if (_quality < 1 || _quality > 104)
            {
                qual = 100;
            }

            //Request to get the video
            sendBuffer = string.Format( 
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<methodcall>" +
                    "<requestid>{0}</requestid>" +
                    "<methodname>goto</methodname>" +
                    "<time>{1}</time>" +
                    "<compressionrate>{2}</compressionrate>" +
                    "<keyframesonly>no</keyframesonly>" +
                "</methodcall>\r\n\r\n",
                ++count, _playbackTime, qual);


            bytesSent = Encoding.UTF8.GetBytes(sendBuffer);
            networkStream.Write(bytesSent, 0, bytesSent.Length);

            page = Encoding.UTF8.GetString(bytesReceived, 0, bytes); //The headers from the page
        }
        catch (Exception e)
        {
            //...
        }
        finally
        {
            networkStream?.Dispose();
        }
    }

    private static int RecvUntil(Stream stream, byte[] buf, int offset, int size)
    {
        int miss = size;
        int got = 0;
        int bytes = 0;
        int ended = 4;
        int i = 0;

        while (got < size && ended > 0)
        {
            i = offset + got;
            bytes = stream.Read(buf, i, 1);
            if (buf[i] == '\r' || buf[i] == '\n')
            {
                ended--;
            }
            else
            {
                ended = 4;
            }

            got += bytes;
            miss -= bytes;
        }

        if (got > size)
        {
            throw new Exception("Buffer overflow");
        }

        if (ended == 0)
        {
            return got;
        }

        return -got;
    }

    private string XmlEscapeGt127(string raw)
    {
        string str = "";

        foreach (char c in raw)
        {
            if (c < 128)
            {
                str += c;
            }
            else
            {
                str += string.Format("&#{0};", Convert.ToUInt32(c));
            }
        }

        return str;
    }

    private string FormatConnect()
    {
        string sendBuffer;

        if (_token == "BASIC")
        {
            sendBuffer = string.Format(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<methodcall>" +
                    "<requestid>0</requestid>" +
                    "<methodname>connect</methodname>" +
                    "<username>{0}</username>" +
                    "<password>{1}</password>" +
                    "<cameraid>{2}</cameraid>" +
                    "<clientcapabilities>" +
                        "<multipartdata>yes</multipartdata>" +
                    "</clientcapabilities>" +
                "</methodcall>\r\n\r\n",
                XmlEscapeGt127(_user), XmlEscapeGt127(_pwd), _cameraGuid);
        }
        else
        {
            sendBuffer = string.Format(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                "<methodcall>" +
                    "<requestid>0</requestid>" +
                    "<methodname>connect</methodname>" +
                    "<username>a</username>" +
                    "<password>a</password>" +
                    "<cameraid>{0}</cameraid>" +
                    "<transcode>" +
                        "<allframes>yes</allframes>" +
                    "</transcode>" +
                    "<clientcapabilities>" +
                        "<multipartdata>yes</multipartdata>" +
                    "</clientcapabilities>" +
                    "<connectparam>" +
                    "id={1}&amp;connectiontoken={2}" +
                    "</connectparam>" +
                "</methodcall>\r\n\r\n",
                _cameraGuid, _cameraGuid, _token);
        }

        return sendBuffer;
    }

    private Stream ConnectToImageServer()
    {
        Stream networkStream = null;
        String oper = "";
        try
        {
            IPAddress ipAddress;
            oper = "new Socket";
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            try
            {
                oper = "IPAddress.Parse " + _imageServer;
                ipAddress = IPAddress.Parse(_imageServer.Host);
            }
            catch
            {
                oper = "ConnInfo.ToIpv4 " + _imageServer;
                ipAddress = ConnInfo.ToIpv4(_imageServer.Host);
            }

            oper = "new IPEndPoint " + ipAddress;
            IPEndPoint ipe = new IPEndPoint(ipAddress, _imageServer.Port);
            sock.Connect(ipe);

            oper = "NetworkStream";
            networkStream = new NetworkStream(sock, true);

            if (String.Equals(_imageServer.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase))
            {
                oper = "SslStream";
                SslStream sslStream = new SslStream(networkStream, false);
                networkStream = sslStream;
                sslStream.AuthenticateAsClient(_imageServer.Host);
            }

            networkStream.ReadTimeout = 10000;
            networkStream.WriteTimeout = 2000;
        }
        catch (AuthenticationException ae)
        {
            // Tell the application I'm done
            if (OnConnectionStoppedMethod != null)
            {
                string errMsg = $"SSL error {ae.Message}.";
                OnConnectionStoppedMethod.Invoke(new ConnInfo(IscErrorCode.NoConnect, errMsg));
            }
            networkStream?.Dispose();
            networkStream = null;
        }
        catch (IOException ioe)
        {
            // Tell the application I'm done
            if (OnConnectionStoppedMethod != null)
            {
                string errMsg = $"NetworkStream error {ioe.Message}.";
                OnConnectionStoppedMethod.Invoke(new ConnInfo(IscErrorCode.NoConnect, errMsg));
            }
            networkStream?.Dispose();
            networkStream = null;
        }
        catch (SocketException se)
        {
            // Tell the application I'm done
            if (OnConnectionStoppedMethod != null)
            {
                string errMsg = $"Socket error {se.ErrorCode}. Win32 error {se.NativeErrorCode}";
                OnConnectionStoppedMethod.Invoke(new ConnInfo(IscErrorCode.NoConnect, errMsg));
            }
            networkStream?.Dispose();
            networkStream = null;
        }
        catch (Exception)
        {
            // Tell the application I'm done
            if (OnConnectionStoppedMethod != null)
            {
                OnConnectionStoppedMethod.Invoke(new ConnInfo(IscErrorCode.NoConnect, oper));
            }
            networkStream?.Dispose();
            networkStream = null;
        }

        return networkStream;
    }

Wireshark Capture - Only a part.

For more code can check: Sample in Github

My code is a implementation of the ImageServerConnection.cs playback.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source