Beispiel #1
0
        /// <summary>
        /// Pass the 'inStream' through exiftool and write the output to the 'outStream'.
        /// </summary>
        private void WriteTemporaryFile(Stream file, Stream input)
        {
            // get a buffer
            var buffer = BufferCache.Get();
            // read from the input stream
            int count = input.Read(buffer, 0, Global.BufferSizeLocal);

            // write the buffer to the file
            file.Write(buffer, 0, count);
            // reset the buffer
            BufferCache.Set(buffer);

            // is this the final buffer?
            if (count < Global.BufferSizeLocal)
            {
                // yes, dispose of the file stream
                file.Dispose();

                var process = _coordinator.Process.TakeItem();
                process.StandardInput.BaseStream.Write(_bytesRemoveMetadata, 0, _bytesRemoveMetadata.Length);
                byte[] pathBytes = System.Text.Encoding.ASCII.GetBytes(Path);
                process.StandardInput.BaseStream.Write(pathBytes, 0, pathBytes.Length);
                process.StandardInput.BaseStream.Write(_coordinator.BytesExecute, 0, _coordinator.BytesExecute.Length);
                process.StandardInput.BaseStream.Flush();
                _coordinator.Process.Release();

                // add this task to run with the coordinators process
                _coordinator.Add(this);
            }
            else
            {
                // continue writing the temporary file
                ManagerUpdate.Control.AddSingle(WriteTemporaryFile, file, input);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Send the specified string to the client.
        /// </summary>
        public unsafe void Send(string str, HttpSendOptions options = null, IAction onSent = null)
        {
            Log.Info("Sending string '" + str + "' to client " + this + ".");

            // is the string empty? skip
            if (string.IsNullOrEmpty(str))
            {
                return;
            }

            _lock.Take();

            // process send options
            ProcessOptions(options);

            _onSent = onSent;

            var buffer = BufferCache.Get(str.Length + str.Length);
            int count;

            // get pointers to the string and the send byte buffer
            fixed(char *src = str)
            fixed(byte *dst = &buffer[0])
            {
                // get the bytes that the string represents
                count = _encoder.GetBytes(src, str.Length, dst, buffer.Length, true);
            }

            SendBytes(buffer, 0, count);

            BufferCache.Set(buffer);
        }
Beispiel #3
0
        /// <summary>
        /// Creates a new AsyncSocket.  You must call Start() after creating the AsyncSocket
        /// in order to begin receive data.
        /// </summary>
        internal AsyncUdpSocket(Socket socket, IPEndPoint localEndpoint,
                                Action <IPEndPoint, byte[], int> onReceive, Action <Exception> onError)
        {
            Socket = socket;

            OnReceive = onReceive;
            OnError   = onError;

            LocalEndPoint  = localEndpoint;
            RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
            TargetEndPoint = RemoteEndPoint;

            _sendLock = new Lock();
            _readLock = new Lock();

            _enqueueBuffer = new BufferQueue();
            _sendQueue     = new Shared <ArrayRig <QueuedBuffer> >(new ArrayRig <QueuedBuffer>());

            _syncLock  = new LockReadWrite();
            _onReceive = new ActionSequence();

            _receiveBuffer  = BufferCache.Get();
            _receivedChunks = new Dictionary <int, ChunkedGram>();

            _disposing = false;
        }
Beispiel #4
0
        //----------------------------------//

        /// <summary>
        /// Get a byte collection of the specified string representation of a
        /// hexidecimal number.
        /// </summary>
        public static byte[] ToBytes(this string str)
        {
            // is the string the correct length?
            if (str.Length == 0 || str.Length % 2 != 0)
            {
                return(new byte[0]);
            }

            byte[] buffer = BufferCache.Get();
            int    length = str.Length / 2;
            char   c;

            for (int bx = 0, sx = 0; bx < length; ++bx, ++sx)
            {
                // convert first half of byte
                c          = str[sx];
                buffer[bx] = (byte)((c > Chars.n9 ? (c > Chars.Z ? (c - Chars.a + 10) : (c - Chars.A + 10)) : (c - Chars.n0)) << 4);

                // convert second half of byte
                c           = str[++sx];
                buffer[bx] |= (byte)(c > Chars.n9 ? (c > Chars.Z ? (c - Chars.a + 10) : (c - Chars.A + 10)) : (c - Chars.n0));
            }

            return(buffer);
        }
Beispiel #5
0
        /// <summary>
        /// Allocate an event arg for a receive operation
        /// </summary>
        public static SocketAsyncEventArgs AllocateForReceive(EventHandler <SocketAsyncEventArgs> ioCompletedHandler)
        {
            SocketAsyncEventArgs result;

            if (!_eventArgsReceive.Dequeue(out result))
            {
                result = new SocketAsyncEventArgs();
                result.SetBuffer(BufferCache.Get(), 0, Global.BufferSizeLocal);
            }

            result.Completed += ioCompletedHandler;
            return(result);
        }
Beispiel #6
0
 /// <summary>
 /// Prepare the specified number of bytes. This ensures that at least the specified
 /// number of bytes are sent to the 'Next' method each call.
 /// </summary>
 protected void BufferCount(int length)
 {
     if (length == 0)
     {
         _buffer = false;
     }
     else
     {
         _buffer       = true;
         _bufferTarget = length;
         if (_bufferBytes == null || _bufferBytes.Length < _bufferTarget)
         {
             _bufferBytes = BufferCache.Get(length);
         }
     }
 }
Beispiel #7
0
        /// <summary>
        /// Append the specified bytes to the next read.
        /// </summary>
        protected void Buffer(byte[] bytes, int offset, int length)
        {
            _buffer = true;

            // does the buffer have room for the specified bytes?
            if (length > _bufferTarget - _bufferIndex)
            {
                // no, resize the prepared byte array
                _bufferBytes = BufferCache.Get(_bufferTarget + length);
            }

            // copy the byte buffer into the prepared collection
            Micron.CopyMemory(bytes, offset, _bufferBytes, _bufferIndex, length);
            // increment the index
            _bufferIndex += length;
        }
Beispiel #8
0
        /// <summary>
        /// Send the specified element to the client.
        /// </summary>
        public unsafe void Send(Element element, bool buildStyle = true, HttpSendOptions options = null, IAction onSent = null)
        {
            Log.Info("Sending element '" + element + "' to client " + this + ".");

            if (buildStyle)
            {
                // build the style
                var style = element.FindChild("style");
                style.ContentString   = element.BuildCss();
                element.EncodeContent = false;
            }

            // build the element into a string
            string str =
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">" +
                element.Build();

            _lock.Take();

            // have the options been specified? yes, process them
            if (options == null || options.ContentType == null)
            {
                Headers[HttpResponseHeader.ContentType] = "text/html; charset=UTF-8";
            }
            ProcessOptions(options);

            _onSent = onSent;

            // resize buffer as required
            var buffer = BufferCache.Get(str.Length + str.Length);

            // get pointers to the string and the send byte buffer
            int count;

            fixed(char *src = str)
            fixed(byte *dst = &buffer[0])
            {
                // get the bytes that the string represents
                count = _encoder.GetBytes(src, str.Length, dst, buffer.Length, true);
            }

            // send the bytes
            SendBytes(buffer, 0, count);

            BufferCache.Set(buffer);
        }
Beispiel #9
0
        /// <summary>
        /// Buffer processed data and send to the receive callback.
        /// </summary>
        private void ProcessReceivedData()
        {
            // get a buffer to dequeue into
            var buffer = BufferCache.Get();

            try {
                // dequeue a buffer from the pending received data
                int count = _receivedBuffer.TakeItem().Dequeue(buffer, 0, Global.BufferSizeLocal);
                _receivedBuffer.Release();
                if (count == 0)
                {
                    // allocate the buffer cache once more
                    BufferCache.Set(buffer);
                }
                else
                {
                    // remove
                    //Log.Debug(new string(System.Text.Encoding.UTF8.GetChars(buffer, 0, count)));

                    // run the callback action
                    _onReceive.AddRun(ActionSet.New(OnReceive, buffer, count));

                    if (count == Global.BufferSizeLocal)
                    {
                        ManagerUpdate.Control.AddSingle(ProcessReceivedData);
                        return;
                    }
                }

                // no bytes to receive
                CompleteReceive();
            } catch (SocketException ex) {
                _readLock.Release();
                BufferCache.Set(buffer);
                if (ex.SocketErrorCode == SocketError.ConnectionReset)
                {
                    return;
                }
                ProcessError(ex);
            } catch (Exception ex) {
                _readLock.Release();
                BufferCache.Set(buffer);
                ProcessError(ex);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Send the specified string to the client.
        /// </summary>
        public unsafe void Send(string str, TransportOptions options = null, IAction onSent = null)
        {
            // is disposed?
            if (_disposed)
            {
                Log.Warning("Cannot send from disposed connection.");
                return;
            }

            // reset the timeout
            if (_timeoutTimer != null)
            {
                _timeoutTimer.Reset(_timeoutMilliseconds);
            }

            // is the string empty? skip
            if (string.IsNullOrEmpty(str))
            {
                return;
            }

            _lock.Take();

            // process send options
            ProcessOptions(options);

            _onSent = onSent;

            var buffer = BufferCache.Get(str.Length + str.Length);
            int count;

            // get pointers to the string and the send byte buffer
            fixed(char *src = str)
            fixed(byte *dst = &buffer[0])
            {
                // get the bytes that the string represents
                count = _encoder.GetBytes(src, str.Length, dst, buffer.Length, true);
            }

            // send the byte buffer
            SendBytes(buffer, 0, count);

            // cache the buffer
            BufferCache.Set(buffer);
        }
Beispiel #11
0
        /// <summary>
        /// Send a buffer of bytes to the client. Releases the lock.
        /// </summary>
        protected void SendBytes(byte[] bytes, int offset, int count)
        {
            try {
                // yes, does the buffer need to be compressed?
                if (_header.Compression != DecompressionMethods.None)
                {
                    // yes, compress the bytes
                    bytes = StreamHelper.Compress(_header.Compression,
                                                  System.IO.Compression.CompressionLevel.Optimal, bytes, offset, ref count);
                    offset = 0;
                }

                // are the bytes to be encrypted?
                if (_header.EncryptionPassword != null)
                {
                    // yes, encrypt them
                    byte[] buffer = BufferCache.Get(count);
                    Buffer.BlockCopy(bytes, offset, buffer, 0, count);
                    bytes = Crypto.EncryptWithPassword(buffer, _header.EncryptionPassword);

                    // send headers with the content length
                    EnqueueHeader(bytes.Length);

                    // send the bytes
                    AsyncSocket.Enqueue(bytes, 0, bytes.Length);
                    AsyncSocket.Send(_onSent);
                }
                else
                {
                    // send headers with the content length
                    EnqueueHeader(count);

                    // send the bytes
                    AsyncSocket.Enqueue(bytes, offset, count);
                    AsyncSocket.Send(_onSent);
                }
            } finally {
                _onSent = null;
                _lock.Release();
            }
        }
Beispiel #12
0
        /// <summary>
        /// Initialize a file extractor with a collection of file paths, the extraction instance and the
        /// encoding of the file.
        /// </summary>
        public FileExtractor(ArrayRig <string> files, Extract extractor = null, Encoding encoding = null)
        {
            _files = new Queue <string>();

            // add the files to the queue
            foreach (string file in files)
            {
                _files.Enqueue(file);
            }

            // persist the extractor
            Extractor = extractor;
            Decoder   = (encoding ?? Encoding.UTF8).GetDecoder();

            // initialize the buffers
            _buffer = BufferCache.Get();
            _chars  = new char[(encoding ?? Encoding.UTF8).GetMaxCharCount(Global.BufferSizeLocal)];

            _timeout = new Timer(Timeout, Run, false);
            _lock    = new Lock();
        }
Beispiel #13
0
        /// <summary>
        /// Pass the 'inStream' through exiftool and write the output to the 'outStream'.
        /// </summary>
        private void ReadTemporaryFile(Stream file)
        {
            // get a buffer
            byte[] buffer = BufferCache.Get();
            // read from the stream
            int count = file.Read(buffer, 0, Global.BufferSizeLocal);

            // write the buffer to the output stream
            Output.Write(buffer, 0, count);

            // is this the final buffer?
            if (count < Global.BufferSizeLocal)
            {
                // yes, dispose of the file stream
                file.Dispose();

                // reset the buffer
                BufferCache.Set(buffer);

                Success = true;

                // run callback
                OnComplete.Run();

                // should the file be removed?
                if (_removeTempFile)
                {
                    ManagerResources.RemoveFile(Path);
                }
            }
            else
            {
                // no, reset the buffer
                BufferCache.Set(buffer);

                // add a task to clear the metadata
                ManagerUpdate.Control.AddSingle(ReadTemporaryFile, file);
            }
        }
Beispiel #14
0
        //----------------------------------//

        /// <summary>
        /// Initialize a new buffer queue.
        /// </summary>
        public BufferQueue()
        {
            _buffer = BufferCache.Get();
        }
Beispiel #15
0
        //-------------------------------------------//

        /// <summary>
        /// Start sending data to the socket. Make sure slimLock is entered in read mode before calling this,
        /// and that disposing is not true. Ensure an error handler is implemented which forwards to ProcessError.
        /// </summary>
        private void StartSend()
        {
            if (_disposing)
            {
                _sendLock.Release();
                return;
            }

            byte[] buffer = BufferCache.Get();

            // iterate while there are more bytes to be sent
            for (;;)
            {
                // get data without removing it from the buffer and set buffer on socket
                int count;

                _sendBuffer.Take();

                if (_currentCallbackAction == null)
                {
                    count = _sendBuffer.Item.Dequeue(buffer, 0, Global.BufferSizeLocal);

                    if (count == 0)
                    {
                        _sendLock.Release();

                        // more data to send? yes, take the lock and return positive
                        if (_sendBuffer.Item.Length > 0 && _sendLock.TryTake)
                        {
                            count = _sendBuffer.Item.Dequeue(buffer, 0, Global.BufferSizeLocal);
                        }
                        else
                        {
                            _sendBuffer.Release();
                            BufferCache.Set(buffer);
                            return;
                        }
                    }
                }
                else
                {
                    _callbackLock.Take();

                    count = _sendBuffer.Item.Dequeue(buffer, 0, Global.BufferSizeLocal);

                    if (count == 0)
                    {
                        _sendLock.Release();

                        // more data to send? yes, take the lock and return positive
                        if (_sendBuffer.Item.Length > 0 && _sendLock.TryTake)
                        {
                            count = _sendBuffer.Item.Dequeue(buffer, 0, Global.BufferSizeLocal);
                        }
                        else
                        {
                            _sendBuffer.Release();
                            _callbackLock.Release();
                            BufferCache.Set(buffer);
                            return;
                        }
                    }

                    _currentCallbackIndex -= count;

                    _callbackLock.Release();
                }

                _sendBuffer.Release();

                _sendSocketArgs.SetBuffer(buffer, 0, count);

                if (_disposing)
                {
                    _sendLock.Release();
                    return;
                }

                if (Socket.Connected)
                {
                    // sendAsync returns true if the I/O operation is pending. An event will be raised upon completion.
                    // returns false if the I/O operation completed synchronously
                    if (Socket.SendAsync(_sendSocketArgs))
                    {
                        // an event is going to be raised to OnIOComplete_Send, so let's exit right now because we're done
                        return;
                    }

                    // send -- is there more data to send now? no, break iteration
                    if (!CompleteSend(_sendSocketArgs))
                    {
                        return;
                    }
                }
                else
                {
                    _sendLock.Release();
                    BufferCache.Set(buffer);
                    if (_disposing)
                    {
                        return;
                    }
                    ProcessError("Socket was disconnected mid-send.");
                    return;
                }
            }

            // in case loop is ever broken
            //_syncLock.ExitReadLock();
        }
Beispiel #16
0
        /// <summary>
        /// On socket data being received.
        /// </summary>
        private unsafe void OnReceiveSocketData(IAsyncResult ar)
        {
            int count = 0;

            try {
                // end the receive
                count = Socket.EndReceiveFrom(ar, ref _receiveEndPoint);
            } catch (Exception ex) {
                // release the read lock
                _syncLock.ReleaseRead();

                ProcessError(ex);
                return;
            }

            if (count > 0)
            {
                // is the received buffer chunked?
                byte flag = _receiveBuffer[0];
                if (flag < 60 || flag >= 188)
                {
                    count -= ChunkHeaderSize;

                    int chunkId;
                    int chunkIndex;
                    int chunkCount;

                    // sanity check for correct number of bytes received
                    if (count < 0)
                    {
                        _syncLock.ReleaseRead();
                        ProcessError("Socket didn't receive enough data for chunked information.");
                        return;
                    }

                    // yes, read the chunk details
                    fixed(byte *intP = &_receiveBuffer[1])
                    {
                        chunkId = *(int *)intP;
                    }

                    fixed(byte *intP = &_receiveBuffer[5])
                    {
                        chunkIndex = *(int *)intP;
                    }

                    fixed(byte *intP = &_receiveBuffer[9])
                    {
                        chunkCount = *(int *)intP;
                    }

                    // sanity check for the chunk data being valid
                    if (chunkIndex >= chunkCount)
                    {
                        _syncLock.ReleaseRead();
                        ProcessError("Socket received invalid chunk index and count information.");
                        return;
                    }

                    // write
                    ChunkedGram chunkedGram;
                    if (_receivedChunks.TryGetValue(chunkId, out chunkedGram))
                    {
                        chunkedGram.Length += count;
                        chunkedGram.Chunks.Insert(Teple.New(count, _receiveBuffer), chunkIndex);

                        // have all chunks been added?
                        if (chunkedGram.Chunks.Count == chunkCount)
                        {
                            // yes, remove from the collection
                            _receivedChunks.Remove(chunkId);

                            // create a byte buffer for the entire message
                            byte[] result = new byte[chunkedGram.Length];
                            int    index  = 0;
                            foreach (var chunk in chunkedGram.Chunks)
                            {
                                int length = chunk.ArgA;
                                Micron.CopyMemory(chunk.ArgB, ChunkHeaderSize, result, index, length);
                                index += length;
                            }

                            // reference the endpoint from which the data was received
                            IPEndPoint endpoint = (IPEndPoint)_receiveEndPoint;

                            // run the callback
                            _onReceive.AddRun(ActionSet.New(OnReceive,
                                                            endpoint,
                                                            result,
                                                            chunkedGram.Length));
                        }
                        else
                        {
                            // no, create a new receive buffer
                            _receiveBuffer = BufferCache.Get();
                        }
                    }
                    else
                    {
                        chunkedGram = new ChunkedGram {
                            Chunks    = new ArrayRig <Teple <int, byte[]> >(chunkCount),
                            Timestamp = Time.Timestamp
                        };

                        _receivedChunks.Add(chunkId, chunkedGram);

                        chunkedGram.Chunks.Add(Teple.New(count, _receiveBuffer));
                        chunkedGram.Length += count;

                        // create a new receive buffer
                        _receiveBuffer = BufferCache.Get();
                    }
                }
                else
                {
                    // no, copy the received buffer
                    --count;
                    byte[] buffer = BufferCache.Get(count);
                    Micron.CopyMemory(_receiveBuffer, 1, buffer, 0, count);

                    // reference the endpoint from which the data was received
                    IPEndPoint endpoint = (IPEndPoint)_receiveEndPoint;

                    // run the callback
                    _onReceive.AddRun(ActionSet.New(OnReceive,
                                                    endpoint,
                                                    buffer,
                                                    count));
                }
            }

            if (_receivedChunks.Count > 0)
            {
                // check for any chunked data timeouts
                ArrayRig <int> toRemove = null;
                foreach (var chunkedGram in _receivedChunks)
                {
                    if (Time.Timestamp - chunkedGram.Value.Timestamp > ChunkedGramTimeout)
                    {
                        if (toRemove == null)
                        {
                            toRemove = new ArrayRig <int>();
                        }
                        toRemove.Add(chunkedGram.Key);
                    }
                }
                if (toRemove != null)
                {
                    foreach (var chunkId in toRemove)
                    {
                        ChunkedGram chunked;
                        if (_receivedChunks.TryGetValue(chunkId, out chunked))
                        {
                            _receivedChunks.Remove(chunkId);
                            chunked.Chunks.Dispose();
                        }
                    }
                }
            }

            // release the read lock
            _syncLock.ReleaseRead();

            // create the endpoint for receiving data
            _receiveEndPoint = new IPEndPoint(RemoteEndPoint.Address, RemoteEndPoint.Port);

            try {
                // start receiving again
                Socket.BeginReceiveFrom(_receiveBuffer, 0, Global.BufferSizeLocal, SocketFlags.None,
                                        ref _receiveEndPoint, OnReceiveSocketData, null);
            } catch (Exception ex) {
                ProcessError(ex);
                return;
            }
        }
Beispiel #17
0
        //-------------------------------------------//

        /// <summary>
        /// Start sending data to the socket. Make sure slimLock is entered in read mode before calling this,
        /// and that disposing is not true. Ensure an error handler is implemented which forwards to ProcessError.
        /// </summary>
        private void StartSend()
        {
            if (_disposing)
            {
                _sendLock.Release();
                return;
            }

            // get a buffer used to send data
            byte[] buffer = BufferCache.Get(MaxDatagramSize);

            // iterate while there are more bytes to be sent
            for (;;)
            {
                // get data without removing it from the buffer and set buffer on socket
                int count = TryGetBuffer(buffer);

                // any bytes in the buffer?
                if (count == 0)
                {
                    _sendLock.Release();

                    // more data to send? yes, take the lock and return positive
                    if (_enqueueBuffer.Length == 0 || !_sendLock.TryTake ||
                        (count = TryGetBuffer(buffer)) == 0)
                    {
                        BufferCache.Set(buffer);
                        return;
                    }
                }

                //Log.Debug("Sending buffer '"+count+"' : " + buffer.ToString(0, count, ','));

                var args = new SocketAsyncEventArgs();
                args.Completed       += OnSocketSend;
                args.SendPacketsFlags = TransmitFileOptions.UseSystemThread;

                // set the remote endpoint of the data to be sent
                args.RemoteEndPoint = TargetEndPoint;
                // set the data
                args.SetBuffer(buffer, 0, count);

                if (_disposing)
                {
                    _sendLock.Release();
                    args.Dispose();
                    return;
                }

                if (Socket.SendToAsync(args))
                {
                    // an event is going to be raised to OnIOComplete_Send, so let's exit right now because we're done
                    return;
                }

                // send -- is there more data to send now? no, break iteration
                if (!CompleteSend(args))
                {
                    return;
                }
            }

            // in case loop is ever broken
            //_syncLock.ExitReadLock();
        }
Beispiel #18
0
        //----------------------------------//

        protected Interpret()
        {
            _bufferCapacity = Global.BufferSizeLocal;
            _bufferBytes    = BufferCache.Get(_bufferCapacity);
        }
Beispiel #19
0
        /// <summary>
        /// Run the medadata removal process.
        /// </summary>
        public void Run()
        {
            var stream = new ByteBuffer(new MemoryStream());

            bool found = false;

            if (_coordinator.Buffer != null)
            {
                while (_coordinator.BufferIndex < _coordinator.BufferCount)
                {
                    var bit = _coordinator.Buffer[_coordinator.BufferIndex];
                    stream.Write(bit);
                    ++_coordinator.BufferIndex;
                    if (_coordinator.ReadySearch.Next(bit))
                    {
                        found = true;
                        break;
                    }
                }
                if (_coordinator.BufferIndex == _coordinator.BufferCount)
                {
                    _coordinator.Buffer = null;
                }
            }

            if (!found)
            {
                // read the {ready} flag from the exiftool
                var buffer  = BufferCache.Get();
                var process = _coordinator.Process.TakeItem();
                int count   = process.StandardOutput.BaseStream.Read(buffer, 0, Global.BufferSizeLocal);

                // while there are bytes in the process standard output
                while (count > 0)
                {
                    int index = 0;

                    while (index < count)
                    {
                        // check the buffer for the {ready} flag
                        var bit = buffer[index];
                        stream.Write(bit);
                        ++index;
                        if (_coordinator.ReadySearch.Next(bit))
                        {
                            // the flag has been found - are there bytes in the buffer?
                            if (index == count)
                            {
                                BufferCache.Set(buffer);
                            }
                            else
                            {
                                // yes, remember the buffer
                                _coordinator.Buffer      = buffer;
                                _coordinator.BufferIndex = index;
                                _coordinator.BufferCount = count;
                            }
                            found = true;
                            break;
                        }
                    }
                    if (found)
                    {
                        break;
                    }
                    count = process.StandardOutput.BaseStream.Read(buffer, 0, Global.BufferSizeLocal);
                }
                _coordinator.Process.Release();
            }

            // should the file be removed?
            if (_removeTempFile)
            {
                ManagerResources.RemoveFile(Path);
            }

            // reset the stream position
            stream.Position = 0;

            // create the metadata dictionary for the callback
            Metadata = new Dictionary <MetaKey, string>();

            // while there are more bytes to read
            while (stream.Position < stream.WriteEnd)
            {
                string key;
                try {
                    // read the key of the key value pair
                    key = stream.ReadString(Chars.Colon);
                } catch {
                    // ignore and break
                    break;
                }

                // trim the key
                key = key.TrimSpace();

                // no, read the value of the key-value pair
                var value = stream.ReadString(Chars.NewLine).TrimSpace();

                if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value))
                {
                    Log.Debug("Missing metadata '" + key + "' : '" + value + "'.");
                    continue;
                }

                // parse the key and assign key-value pair
                MetaKey metaKey;
                if (MetaKeys.Map.TryGetValue(key, out metaKey))
                {
                    // determine how to parse the metadata value
                    switch (metaKey)
                    {
                    case MetaKey.FileSize:
                    {
                        // determine the scale of the file size
                        var splitFileSize = value.Split(value.IndexOf(Chars.Space));
                        switch (splitFileSize.ArgB)
                        {
                        case "bytes":
                            Metadata[metaKey] = splitFileSize.ArgA;
                            break;

                        case "MB":
                            Metadata[metaKey] = ((int)(splitFileSize.ArgA.ToDouble() * Global.Megabyte)).ToString();
                            break;

                        case "kB":
                            Metadata[metaKey] = ((int)(splitFileSize.ArgA.ToDouble() * Global.Kilobyte)).ToString();
                            break;

                        case "GB":
                            Metadata[metaKey] = ((int)(splitFileSize.ArgA.ToDouble() * Global.Gigabyte)).ToString();
                            break;

                        default:
                            Log.Error("Unknown file size scale of media '" + value + "'.");
                            break;
                        }
                    }
                    break;

                    case MetaKey.Duration:
                    {
                        // check for (approx) suffix
                        int index = value.IndexOf(Chars.Space);
                        if (index != -1)
                        {
                            value = value.Substring(0, index);
                        }

                        var splitDuration = value.Split(Chars.Colon);

                        // determine the type of duration
                        if (splitDuration.Length == 1)
                        {
                            Metadata[metaKey] = ((int)(splitDuration[0].ToDouble() * 1000)).ToString();
                        }
                        else
                        {
                            // parse each component
                            int time = splitDuration[0].ToInt32() * 60 * 60 * 1000;
                            time += splitDuration[1].ToInt32() * 60 * 1000;
                            time += splitDuration[2].ToInt32() * 1000;

                            // assign the time value
                            Metadata[metaKey] = time.ToString();
                        }
                    }
                    break;

                    case MetaKey.Bitrate:
                    {
                        // determine the scale of the file size
                        var splitBitrate = value.Split(value.IndexOf(Chars.Space));
                        switch (splitBitrate.ArgB)
                        {
                        case "bps":
                            Metadata[metaKey] = splitBitrate.ArgA;
                            break;

                        case "kbps":
                            Metadata[metaKey] = ((int)(splitBitrate.ArgA.ToDouble() * Global.Kilobyte)).ToString();
                            break;

                        case "Mbps":
                            Metadata[metaKey] = ((int)(splitBitrate.ArgA.ToDouble() * Global.Megabyte)).ToString();
                            break;

                        default:
                            Log.Warning("Unknown bitrate scale of media '" + value + "'.");
                            break;
                        }
                    }
                    break;

                    default:
                        // assign the mime type directly
                        Metadata[metaKey] = value;
                        break;
                    }
                }
                else
                {
                    Log.Warning("Unrecognized metadata key '" + key + " : " + value + "'.");
                }
            }

            // dispose of the byte stream
            stream.Close();

            // run callback
            OnComplete.Run();
        }
Beispiel #20
0
        /// <summary>
        /// Run the medadata removal process.
        /// </summary>
        public void Run()
        {
            bool found = false;

            if (_coordinator.Buffer != null)
            {
                while (_coordinator.BufferIndex < _coordinator.BufferCount)
                {
                    if (_coordinator.ReadySearch.Next(_coordinator.Buffer[_coordinator.BufferIndex]))
                    {
                        ++_coordinator.BufferIndex;
                        found = true;
                        break;
                    }
                    ++_coordinator.BufferIndex;
                }
                if (_coordinator.BufferIndex == _coordinator.BufferCount)
                {
                    _coordinator.Buffer = null;
                }
            }

            if (!found)
            {
                // read the {ready} flag from the exiftool
                var buffer  = BufferCache.Get();
                var process = _coordinator.Process.TakeItem();
                int count   = process.StandardOutput.BaseStream.Read(buffer, 0, Global.BufferSizeLocal);

                // while there are bytes in the process standard output
                while (count > 0)
                {
                    int index = 0;

                    while (index < count)
                    {
                        // check the buffer for the {ready} flag
                        if (_coordinator.ReadySearch.Next(buffer[index]))
                        {
                            ++index;
                            // are there bytes in the buffer?
                            if (index == count)
                            {
                                // no, persist the buffer
                                BufferCache.Set(buffer);
                            }
                            else
                            {
                                // yes, remember the buffer and position
                                _coordinator.Buffer      = buffer;
                                _coordinator.BufferIndex = index;
                                _coordinator.BufferCount = count;
                            }
                            found = true;
                            break;
                        }
                        ++index;
                    }
                    if (found)
                    {
                        break;
                    }
                    count = process.StandardOutput.BaseStream.Read(buffer, 0, Global.BufferSizeLocal);
                }
                _coordinator.Process.Release();
            }

            // should the file be read?
            if (Output == null)
            {
                // no, run callback
                OnComplete.Run();

                // should the file be removed?
                if (_removeTempFile)
                {
                    ManagerResources.RemoveFile(Path);
                }
                return;
            }

            FileStream fileStream;

            try {
                fileStream = new FileStream(Path, FileMode.Open, FileAccess.Read, FileShare.Read);
            } catch (IOException ex) {
                // if the file is still being used
                if (ex.HResult == -2147024864)
                {
                    // try twice more
                    ManagerUpdate.Iterant.AddSingle(TryReadTemporaryFile, 0);
                    return;
                }
                throw;
            }

            // get a stream to the clean file
            ManagerUpdate.Control.AddSingle(ReadTemporaryFile, fileStream);
        }