/// <summary> /// Send the specified byte collection to the client. This may take a number of buffers to complete /// and therefore not be synchronous. /// </summary> public void Send(byte[] buffer, int offset, int count, 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); } _lock.Take(); // process the options ProcessOptions(options); _onSent = onSent; // perform the send SendBytes(buffer, offset, count); }
/// <summary> /// Send the file at the specified local path. /// </summary> public void SendLocal(string path, 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); } // get the extension from the path string extension; int extensionIndex = path.LastIndexOf(Chars.Stop); extension = extensionIndex == -1 ? null : path.Substring(extensionIndex); // open a file stream to the resource Stream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); // start sending the file StartSendStream(fileStream, (int)fileStream.Length, options, onSent); }
/// <summary> /// Start sending the stream. The client is locked until the stream is complete. /// </summary> protected void StartSendStream(Stream stream, int length, TransportOptions options = null, IAction onSent = null) { // does the buffer need to be compressed? if (options != null && options.Compression != DecompressionMethods.None || _defaultCompression != DecompressionMethods.None) { // yes, compress the stream stream = StreamHelper.Compress(options == null ? _defaultCompression : options.Compression, System.IO.Compression.CompressionLevel.Fastest, stream, length); length = (int)stream.Length; // take the send lock _lock.Take(); // process the options ProcessOptions(options); // is the stream to be encrypted? yes, encrypt it if (_header.EncryptionPassword != null) { var encryptedStream = Crypto.EncryptWithPassword(stream, _header.EncryptionPassword); // dispose of the compressed stream stream.Dispose(); // reference the encrypted stream stream = encryptedStream; // set the new stream length length = (int)stream.Length; } } else { // no, take the send lock _lock.Take(); // process the options ProcessOptions(options); // is the stream to be encrypted? yes, encrypt it if (_header.EncryptionPassword != null) { stream = Crypto.EncryptWithPassword(stream, _header.EncryptionPassword); length = (int)stream.Length; } } try { // enqueue the header EnqueueHeader(length); // send the stream AsyncSocket.Enqueue(stream, length); AsyncSocket.Send(onSent); } finally { _lock.Release(); } }
/// <summary> /// Process the send options into headers for a following send operation. /// </summary> protected void ProcessOptions(TransportOptions options) { if (options == null) { _header.Compression = _defaultCompression; _header.EncryptionPassword = null; return; } _header.Compression = options.Compression; _header.EncryptionPassword = options.EncryptionPassword; }
/// <summary> /// Send the specified web resource. /// </summary> public void Send(WebResource resource, TransportOptions options = null, IAction onSent = null) { // is disposed? if (_disposed) { Log.Warning("Cannot send from disposed connection."); return; } // get the resource stream then prepare to send the resource stream data resource.GetStream(ActionSet.New(SendResource, (Stream)null, (Lock)null, resource, options, onSent)); }
/// <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); }
/// <summary> /// Send the specified stream, optionally with a byte length. This method is /// asynchronous and will close the stream on completion. /// </summary> public void Send(Stream stream, int length = -1, 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); } // start sending the stream StartSendStream(stream, length == -1 ? (int)(stream.Length - stream.Position) : length, options, onSent); }
/// <summary> /// Deserialize transport options. Returns 'Null' if the transport options weren't serialized. /// </summary> public static TransportOptions Deserialize(ByteBuffer reader) { // read a flag to indicate a transport option instance follows if (!reader.ReadBoolean()) { return(null); } // create the transport options TransportOptions options = new TransportOptions(); // read the compression enum options.Compression = (DecompressionMethods)reader.ReadByte(); // read the encryption flag options.EncryptionPassword = reader.ReadString(); return(options); }
/// <summary> /// Send the specified udp message. This assumes the stream was written /// </summary> public void Send(UdpMessage message, 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); } // reset the message stream position message.Buffer.Position = 0; // start sending the message stream StartSendStream(message.Buffer.Stream, (int)message.Buffer.WriteEnd, options, onSent); }
/// <summary> /// Begin sending the stream of a web resource and prepare to release the resource lock on completion. /// </summary> protected void SendResource(Stream stream, Lock resourceLock, WebResource resource, TransportOptions options, IAction onSent) { // was the stream retrieved? if (stream == null) { // no, unlock the resource resourceLock.Release(); // callback ProcessError(new Exception("A resource stream '" + resource.FullPath + "' was unable to be resolved.")); return; } _lock.Take(); if (onSent == null) { _onSent = new ActionSet(resourceLock.Release); } else { _onSent = new ActionPair(resourceLock.Release, onSent); } // set the content type ProcessOptions(options); int length = resource.Size == -1 ? (int)stream.Length : (int)resource.Size; // start sending the stream StartSendStream(stream, length, resource); }