a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
253 lines
5.7 KiB
C#
253 lines
5.7 KiB
C#
//
|
|
// System.Net.FtpDataStream.cs
|
|
//
|
|
// Authors:
|
|
// Carlos Alberto Cortez (calberto.cortez@gmail.com)
|
|
//
|
|
// (c) Copyright 2006 Novell, Inc. (http://www.novell.com)
|
|
//
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Net.Sockets;
|
|
using System.Runtime.Remoting.Messaging;
|
|
using System.Threading;
|
|
using System.Net;
|
|
|
|
namespace System.Net
|
|
{
|
|
class FtpDataStream : Stream, IDisposable
|
|
{
|
|
FtpWebRequest request;
|
|
Stream networkStream;
|
|
bool disposed;
|
|
bool isRead;
|
|
int totalRead;
|
|
|
|
internal FtpDataStream (FtpWebRequest request, Stream stream, bool isRead)
|
|
{
|
|
if (request == null)
|
|
throw new ArgumentNullException ("request");
|
|
|
|
this.request = request;
|
|
this.networkStream = stream;
|
|
this.isRead = isRead;
|
|
}
|
|
|
|
public override bool CanRead {
|
|
get {
|
|
return isRead;
|
|
}
|
|
}
|
|
|
|
public override bool CanWrite {
|
|
get {
|
|
return !isRead;
|
|
}
|
|
}
|
|
|
|
public override bool CanSeek {
|
|
get {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public override long Length {
|
|
get {
|
|
throw new NotSupportedException ();
|
|
}
|
|
}
|
|
|
|
public override long Position {
|
|
get {
|
|
throw new NotSupportedException ();
|
|
}
|
|
set {
|
|
throw new NotSupportedException ();
|
|
}
|
|
}
|
|
|
|
internal Stream NetworkStream {
|
|
get {
|
|
CheckDisposed ();
|
|
return networkStream;
|
|
}
|
|
}
|
|
|
|
public override void Close ()
|
|
{
|
|
Dispose (true);
|
|
}
|
|
|
|
public override void Flush ()
|
|
{
|
|
// Do nothing.
|
|
}
|
|
|
|
public override long Seek (long offset, SeekOrigin origin)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
public override void SetLength (long value)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
int ReadInternal (byte [] buffer, int offset, int size)
|
|
{
|
|
int nbytes = 0;
|
|
request.CheckIfAborted ();
|
|
|
|
try {
|
|
// Probably it would be better to have the socket here
|
|
nbytes = networkStream.Read (buffer, offset, size);
|
|
} catch (IOException) {
|
|
throw new ProtocolViolationException ("Server commited a protocol violation");
|
|
}
|
|
|
|
totalRead += nbytes;
|
|
if (nbytes == 0) {
|
|
networkStream = null;
|
|
request.CloseDataConnection ();
|
|
request.SetTransferCompleted ();
|
|
}
|
|
|
|
return nbytes;
|
|
}
|
|
|
|
public override IAsyncResult BeginRead (byte [] buffer, int offset, int size, AsyncCallback cb, object state)
|
|
{
|
|
CheckDisposed ();
|
|
|
|
if (!isRead)
|
|
throw new NotSupportedException ();
|
|
if (buffer == null)
|
|
throw new ArgumentNullException ("buffer");
|
|
if (offset < 0 || offset > buffer.Length)
|
|
throw new ArgumentOutOfRangeException ("offset");
|
|
if (size < 0 || size > buffer.Length - offset)
|
|
throw new ArgumentOutOfRangeException ("offset+size");
|
|
|
|
ReadDelegate del = ReadInternal;
|
|
return del.BeginInvoke (buffer, offset, size, cb, state);
|
|
}
|
|
|
|
public override int EndRead (IAsyncResult asyncResult)
|
|
{
|
|
if (asyncResult == null)
|
|
throw new ArgumentNullException ("asyncResult");
|
|
|
|
AsyncResult ar = asyncResult as AsyncResult;
|
|
if (ar == null)
|
|
throw new ArgumentException ("Invalid asyncResult", "asyncResult");
|
|
|
|
ReadDelegate del = ar.AsyncDelegate as ReadDelegate;
|
|
if (del == null)
|
|
throw new ArgumentException ("Invalid asyncResult", "asyncResult");
|
|
|
|
return del.EndInvoke (asyncResult);
|
|
}
|
|
|
|
public override int Read (byte [] buffer, int offset, int size)
|
|
{
|
|
request.CheckIfAborted ();
|
|
IAsyncResult ar = BeginRead (buffer, offset, size, null, null);
|
|
if (!ar.IsCompleted && !ar.AsyncWaitHandle.WaitOne (request.ReadWriteTimeout, false))
|
|
throw new WebException ("Read timed out.", WebExceptionStatus.Timeout);
|
|
return EndRead (ar);
|
|
}
|
|
|
|
|
|
delegate void WriteDelegate (byte [] buffer, int offset, int size);
|
|
|
|
void WriteInternal (byte [] buffer, int offset, int size)
|
|
{
|
|
request.CheckIfAborted ();
|
|
|
|
try {
|
|
networkStream.Write (buffer, offset, size);
|
|
} catch (IOException) {
|
|
throw new ProtocolViolationException ();
|
|
}
|
|
}
|
|
|
|
public override IAsyncResult BeginWrite (byte [] buffer, int offset, int size, AsyncCallback cb, object state)
|
|
{
|
|
CheckDisposed ();
|
|
if (isRead)
|
|
throw new NotSupportedException ();
|
|
if (buffer == null)
|
|
throw new ArgumentNullException ("buffer");
|
|
if (offset < 0 || offset > buffer.Length)
|
|
throw new ArgumentOutOfRangeException ("offset");
|
|
if (size < 0 || size > buffer.Length - offset)
|
|
throw new ArgumentOutOfRangeException ("offset+size");
|
|
|
|
WriteDelegate del = WriteInternal;
|
|
return del.BeginInvoke (buffer, offset, size, cb, state);
|
|
}
|
|
|
|
public override void EndWrite (IAsyncResult asyncResult)
|
|
{
|
|
if (asyncResult == null)
|
|
throw new ArgumentNullException ("asyncResult");
|
|
|
|
AsyncResult ar = asyncResult as AsyncResult;
|
|
if (ar == null)
|
|
throw new ArgumentException ("Invalid asyncResult.", "asyncResult");
|
|
|
|
WriteDelegate del = ar.AsyncDelegate as WriteDelegate;
|
|
if (del == null)
|
|
throw new ArgumentException ("Invalid asyncResult.", "asyncResult");
|
|
|
|
del.EndInvoke (asyncResult);
|
|
}
|
|
|
|
public override void Write (byte [] buffer, int offset, int size)
|
|
{
|
|
request.CheckIfAborted ();
|
|
IAsyncResult ar = BeginWrite (buffer, offset, size, null, null);
|
|
if (!ar.IsCompleted && !ar.AsyncWaitHandle.WaitOne (request.ReadWriteTimeout, false))
|
|
throw new WebException ("Read timed out.", WebExceptionStatus.Timeout);
|
|
|
|
EndWrite (ar);
|
|
}
|
|
|
|
~FtpDataStream ()
|
|
{
|
|
Dispose (false);
|
|
}
|
|
|
|
void IDisposable.Dispose ()
|
|
{
|
|
Dispose (true);
|
|
GC.SuppressFinalize (this);
|
|
}
|
|
|
|
protected override void Dispose (bool disposing)
|
|
{
|
|
if (disposed)
|
|
return;
|
|
|
|
disposed = true;
|
|
if (networkStream != null) {
|
|
request.CloseDataConnection ();
|
|
request.SetTransferCompleted ();
|
|
request = null;
|
|
networkStream = null;
|
|
}
|
|
}
|
|
|
|
void CheckDisposed ()
|
|
{
|
|
if (disposed)
|
|
throw new ObjectDisposedException (GetType ().FullName);
|
|
}
|
|
|
|
delegate int ReadDelegate (byte [] buffer, int offset, int size);
|
|
}
|
|
}
|
|
|
|
|