1
0
mirror of https://github.com/Halofreak1990/XFXFramework synced 2024-12-26 13:49:34 +01:00

Fixed String operator[] signature

Partially implemented Socket and SocketAsyncEventArgs
This commit is contained in:
Tom Lint 2014-07-22 17:02:45 +02:00
parent e234c493b4
commit 92ffadf6e0
7 changed files with 353 additions and 42 deletions

View File

@ -29,13 +29,13 @@ namespace System
{ {
private: private:
AddressFamily_t addressFamily; AddressFamily_t addressFamily;
/* true if we called Close_internal */
bool closed;
HANDLE handle; HANDLE handle;
bool isConnected; bool isConnected;
ProtocolType_t protocolType; ProtocolType_t protocolType;
protected: protected:
virtual ~Socket();
void Dispose(bool disposing); void Dispose(bool disposing);
public: public:
@ -43,6 +43,7 @@ namespace System
int Available() const; int Available() const;
bool Connected() const; bool Connected() const;
HANDLE getHandle() const; HANDLE getHandle() const;
static bool OSSupportsIPv4();
ProtocolType_t getProtocolType() const; ProtocolType_t getProtocolType() const;
int ReceiveBufferSize; int ReceiveBufferSize;
EndPoint* getRemoteEndPoint() const; EndPoint* getRemoteEndPoint() const;
@ -50,20 +51,21 @@ namespace System
short Ttl; short Ttl;
Socket(AddressFamily_t addressFamily, SocketType_t socketType, ProtocolType_t protocolType); Socket(AddressFamily_t addressFamily, SocketType_t socketType, ProtocolType_t protocolType);
virtual ~Socket();
static void CancelConnectAsync(SocketAsyncEventArgs e); static void CancelConnectAsync(SocketAsyncEventArgs * const e);
void Close(); void Close();
void Close(int timeOut); void Close(int timeOut);
static bool ConnectAsync(SocketType_t socketType, ProtocolType_t protocolType, SocketAsyncEventArgs e); static bool ConnectAsync(SocketType_t socketType, ProtocolType_t protocolType, SocketAsyncEventArgs e);
bool ConnectAsync(SocketAsyncEventArgs e); bool ConnectAsync(SocketAsyncEventArgs * const e);
void Dispose(); void Dispose();
void EndConnect(IAsyncResult * asyncResult); void EndConnect(IAsyncResult * asyncResult);
void EndDisconnect(IAsyncResult * asyncResult); void EndDisconnect(IAsyncResult * asyncResult);
static const Type& GetType(); static const Type& GetType();
bool ReceiveAsync(SocketAsyncEventArgs e); bool ReceiveAsync(SocketAsyncEventArgs * const e);
bool ReceiveFromAsync(SocketAsyncEventArgs e); bool ReceiveFromAsync(SocketAsyncEventArgs * const e);
bool SendAsync(SocketAsyncEventArgs e); bool SendAsync(SocketAsyncEventArgs * const e);
bool SendToAsync(SocketAsyncEventArgs e); bool SendToAsync(SocketAsyncEventArgs * const e);
void Shutdown(SocketShutdown_t how); void Shutdown(SocketShutdown_t how);
}; };
} }

View File

@ -23,8 +23,17 @@ namespace System
class SocketAsyncEventArgs : public EventArgs, public IDisposable class SocketAsyncEventArgs : public EventArgs, public IDisposable
{ {
private: private:
int count;
Socket* curSocket;
int inProgress;
bool isDisposed;
SocketAsyncOperation_t lastOperation;
int offset;
friend class Socket; friend class Socket;
void SetBufferInternal(byte buffer[], int offset, int count);
void SetLastOperation(SocketAsyncOperation_t op);
protected: protected:
virtual void Oncompleted(SocketAsyncEventArgs* e); virtual void Oncompleted(SocketAsyncEventArgs* e);
virtual ~SocketAsyncEventArgs(); virtual ~SocketAsyncEventArgs();
@ -44,6 +53,7 @@ namespace System
EventHandler Completed; EventHandler Completed;
SocketAsyncEventArgs(); SocketAsyncEventArgs();
~SocketAsyncEventArgs();
void Dispose(); void Dispose();
static const Type& GetType(); static const Type& GetType();

View File

@ -91,7 +91,7 @@ namespace System
String operator+=(const String& right); String operator+=(const String& right);
String operator+=(const char* right); String operator+=(const char* right);
String operator+(const String& right) const; String operator+(const String& right) const;
const char operator [](const int index) const; const char& operator[](const int index) const;
}; };
inline const String operator +(const char * left, const String& right) inline const String operator +(const char * left, const String& right)

View File

@ -17,7 +17,7 @@ namespace System
// The value to be added to the integer at location1. // The value to be added to the integer at location1.
// Returns // Returns
// The new value stored at location1. // The new value stored at location1.
static inline int Add(volatile long* const location1, const long value) static inline int Add(volatile int* const location1, const int value)
{ {
long retval = value; long retval = value;
__asm__("lock; xaddl %[retval], %[location1]" : [retval] "+r" (retval) : [location1] "m" (*location1) : "memory"); __asm__("lock; xaddl %[retval], %[location1]" : [retval] "+r" (retval) : [location1] "m" (*location1) : "memory");
@ -49,9 +49,9 @@ namespace System
// The value that is compared to the value at location1. // The value that is compared to the value at location1.
// Returns // Returns
// The original value in location1. // The original value in location1.
static inline Int64 CompareExchange(volatile Int64* const Int64 location1, const Int64 value, const Int64 comparand) static inline long long CompareExchange(volatile long long* const location1, const long long value, const long long comparand)
{ {
Int64 retval = comparand; long long retval = comparand;
__asm__ __asm__
( (
@ -87,21 +87,21 @@ namespace System
// The variable whose value is to be decremented. // The variable whose value is to be decremented.
// Returns // Returns
// The decremented value. // The decremented value.
static inline long Decrement(volatile long * const location) static inline long Decrement(volatile int * const location)
{ {
return Add(location, -1) - 1; return Add(location, -1) - 1;
} }
// Sets a 32-bit signed integer to a specified value and returns the original value, as an atomic operation. // Sets a 32-bit signed integer to a specified value and returns the original value, as an atomic operation.
// location1 // location1
// The variable to set to the specified value. // The variable to set to the specified value.
// value // value
// The value to which the location1 parameter is set. // The value to which the location1 parameter is set.
// Returns // Returns
// The original value of location1. // The original value of location1.
static inline long Exchange(volatile long* const location1, const long value) static inline int Exchange(volatile int * const location1, const int value)
{ {
long retval = value; int retval = value;
__asm__("xchgl %[retval], %[location1]" : [retval] "+r" (retval) : [location1] "m" (*location1) : "memory"); __asm__("xchgl %[retval], %[location1]" : [retval] "+r" (retval) : [location1] "m" (*location1) : "memory");
return retval; return retval;
} }
@ -125,7 +125,7 @@ namespace System
// The variable whose value is to be incremented. // The variable whose value is to be incremented.
// Returns // Returns
// The incremented value. // The incremented value.
static inline long Increment(volatile long * const location) static inline int Increment(volatile int * const location)
{ {
return Add(location, 1) + 1; return Add(location, 1) + 1;
} }

View File

@ -57,7 +57,7 @@ namespace System
bool Socket::Connected() const bool Socket::Connected() const
{ {
// TODO: implement return isConnected;
} }
HANDLE Socket::getHandle() const HANDLE Socket::getHandle() const
@ -67,11 +67,16 @@ namespace System
ProtocolType_t Socket::getProtocolType() const ProtocolType_t Socket::getProtocolType() const
{ {
// TODO: implement return protocolType;
}
EndPoint* Socket::getRemoteEndPoint() const
{
} }
Socket::Socket(AddressFamily_t addressFamily, SocketType_t socketType, ProtocolType_t protocolType) Socket::Socket(AddressFamily_t addressFamily, SocketType_t socketType, ProtocolType_t protocolType)
: addressFamily(addressFamily) : addressFamily(addressFamily), protocolType(protocolType)
{ {
// TODO: implement remainder // TODO: implement remainder
} }
@ -91,9 +96,17 @@ namespace System
// TODO: implement // TODO: implement
} }
bool Socket::ConnectAsync(SocketAsyncEventArgs e) bool Socket::ConnectAsync(SocketAsyncEventArgs * const e)
{ {
// TODO: implement // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
if (disposed && closed)
{
throw new ObjectDisposedException(GetType().ToString());
}
sassert(e->RemoteEndPoint != null, String::Format("remoteEP: %s", FrameworkResources::ArgumentNull_Generic));
return ConnectAsyncReal(e);
} }
void Socket::Dispose() void Socket::Dispose()
@ -103,12 +116,55 @@ namespace System
void Socket::EndConnect(IAsyncResult* asyncResult) void Socket::EndConnect(IAsyncResult* asyncResult)
{ {
// TODO: implement sassert(!disposed || !closed, "");
sassert(asyncResult != null, String::Format("asyncResult: %s", FrameworkResources::ArgumentNull_Generic));
SocketAsyncResult * req = as<SocketAsyncResult *>(asyncResult);
sassert(req != null, "Invalid IAsyncResult");
if (Interlocked::CompareExchange(&req.EndCalled, 1, 0) == 1)
{
throw InvalidAsyncOp("EndConnect");
}
if (!asyncResult->IsCompleted())
{
asyncResult->AsyncWaitHandle.WaitOne();
}
req.CheckIfThrowDelayedException();
} }
void Socket::EndDisconnect(IAsyncResult* asyncResult) void Socket::EndDisconnect(IAsyncResult* asyncResult)
{ {
// TODO: implement if (disposed && closed)
{
throw new ObjectDisposedException(GetType ().ToString ());
}
if (asyncResult == null)
{
throw new ArgumentNullException("asyncResult");
}
SocketAsyncResult * req = as<SocketAsyncResult *>(asyncResult);
if (req == null)
throw new ArgumentException ("Invalid IAsyncResult", "asyncResult");
if (Interlocked::CompareExchange(&req.EndCalled, 1, 0) == 1)
{
throw InvalidAsyncOp("EndDisconnect");
}
if (!asyncResult->IsCompleted())
{
asyncResult->AsyncWaitHandle.WaitOne();
}
req->CheckIfThrowDelayedException();
} }
const Type& Socket::GetType() const Type& Socket::GetType()
@ -116,29 +172,208 @@ namespace System
return SocketTypeInfo; return SocketTypeInfo;
} }
bool Socket::ReceiveAsync(SocketAsyncEventArgs e) bool Socket::ReceiveAsync(SocketAsyncEventArgs * const e)
{ {
// TODO: implement // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
if (disposed && closed)
{
throw new ObjectDisposedException(GetType ().ToString ());
}
// LAME SPEC: the ArgumentException is never thrown, instead an NRE is
// thrown when e.Buffer and e.BufferList are null (works fine when one is
// set to a valid object)
if (e->getBuffer() == null && e->BufferList == null)
{
throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers.");
}
e->curSocket = this;
SocketOperation op = (e->getBuffer() != null) ? SocketOperation::Receive : SocketOperation::ReceiveGeneric;
e->Worker.Init (this, e, op);
SocketAsyncResult res = e->Worker.result;
if (e->getBuffer() != null)
{
res.Buffer = e->getBuffer();
res.Offset = e->getOffset();
res.Size = e->Count();
}
else
{
res.Buffers = e->BufferList;
}
res.SockFlags = e->SocketFlags;
int count;
lock (readQ)
{
readQ.Enqueue(e->Worker);
count = readQ.Count;
}
if (count == 1)
{
// Receive takes care of ReceiveGeneric
socket_pool_queue(Worker.Dispatcher, res);
}
return true;
} }
bool Socket::ReceiveFromAsync(SocketAsyncEventArgs e) bool Socket::ReceiveFromAsync(SocketAsyncEventArgs * const e)
{ {
// TODO: implement if (disposed && closed)
{
throw new ObjectDisposedException(GetType ().ToString ());
}
// We do not support recv into multiple buffers yet
if (e->getBufferList() != null)
{
throw new NotSupportedException("Mono doesn't support using BufferList at this point.");
}
if (e->RemoteEndPoint == null)
{
throw new ArgumentNullException("remoteEP", "Value cannot be null.");
}
e->curSocket = this;
e->Worker.Init(this, e, SocketOperation::ReceiveFrom);
SocketAsyncResult res = e->Worker.result;
res.Buffer = e->getBuffer();
res.Offset = e->getOffset();
res.Size = e->Count();
res.EndPoint = e->RemoteEndPoint;
res.SockFlags = e->SocketFlags;
int count;
lock (readQ)
{
readQ.Enqueue(e.Worker);
count = readQ.Count;
}
if (count == 1)
{
socket_pool_queue (Worker.Dispatcher, res);
}
return true;
} }
bool Socket::SendAsync(SocketAsyncEventArgs e) bool Socket::SendAsync(SocketAsyncEventArgs * const e)
{ {
// TODO: implement // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
if (disposed && closed)
{
throw new ObjectDisposedException (GetType ().ToString ());
}
if (e->getBuffer() == null && e->BufferList == null)
{
throw new NullReferenceException("Either e.Buffer or e.BufferList must be valid buffers.");
}
e->curSocket = this;
SocketOperation op = (e->getBuffer() != null) ? SocketOperation::Send : SocketOperation::SendGeneric;
e->Worker.Init(this, e, op);
SocketAsyncResult res = e->Worker.result;
if (e->getBuffer() != null)
{
res.Buffer = e->getBuffer();
res.Offset = e->getOffset();
res.Size = e->Count();
}
else
{
res.Buffers = e->BufferList;
}
res.SockFlags = e->SocketFlags;
int count;
lock (writeQ)
{
writeQ.Enqueue(e.Worker);
count = writeQ.Count;
}
if (count == 1)
{
// Send takes care of SendGeneric
socket_pool_queue(Worker.Dispatcher, res);
}
return true;
} }
bool Socket::SendToAsync(SocketAsyncEventArgs e) bool Socket::SendToAsync(SocketAsyncEventArgs * const e)
{ {
// TODO: implement // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
if (disposed && closed)
{
throw new ObjectDisposedException (GetType().ToString());
}
if (e->BufferList != null)
{
throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
}
if (e->RemoteEndPoint == null)
{
throw new ArgumentNullException("remoteEP", "Value cannot be null.");
}
e->curSocket = this;
e->Worker.Init(this, e, SocketOperation::SendTo);
SocketAsyncResult res = e->Worker.result;
res.Buffer = e->getBuffer();
res.Offset = e->getOffset();
res.Size = e->Count;
res.SockFlags = e->SocketFlags;
res.EndPoint = e->RemoteEndPoint;
int count;
lock (writeQ)
{
writeQ.Enqueue(e->Worker);
count = writeQ.Count;
}
if (count == 1)
{
socket_pool_queue(Worker.Dispatcher, res);
}
return true;
} }
void Socket::Shutdown(SocketShutdown_t how) void Socket::Shutdown(SocketShutdown_t how)
{ {
if (disposed && closed)
{
throw new ObjectDisposedException(GetType ().ToString ());
}
if (!isConnected)
{
throw new SocketException(10057); // Not connected
}
int error;
// TODO: implement // TODO: implement
Shutdown_internal(socket, how, out error);
if (error != 0)
{
throw new SocketException(error);
}
} }
} }
} }

View File

@ -25,16 +25,21 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
#include <System/Threading/Interlocked.h>
#include <System/Net/Sockets/SocketAsyncEventArgs.h> #include <System/Net/Sockets/SocketAsyncEventArgs.h>
#include <System/Type.h> #include <System/Type.h>
#include <sassert.h>
using namespace System::Threading;
namespace System namespace System
{ {
namespace Net namespace Net
{ {
namespace Sockets namespace Sockets
{ {
const Type SocketAsyncEventArgsTypeInfo("SocketAsyncEventArgs", "SYstem::Net::Sockets::SocketAsyncEventArgs", TypeCode::Object); const Type SocketAsyncEventArgsTypeInfo("SocketAsyncEventArgs", "System::Net::Sockets::SocketAsyncEventArgs", TypeCode::Object);
byte * SocketAsyncEventArgs::getBuffer() const byte * SocketAsyncEventArgs::getBuffer() const
{ {
@ -48,36 +53,50 @@ namespace System
Socket * SocketAsyncEventArgs::getConnectSocket() const Socket * SocketAsyncEventArgs::getConnectSocket() const
{ {
// TODO: implement switch (this->SocketError)
{
case SocketError::AccessDenied:
return null;
default:
return curSocket;
}
} }
int SocketAsyncEventArgs::Count() const int SocketAsyncEventArgs::Count() const
{ {
// TODO: implement return count;
} }
SocketAsyncOperation_t SocketAsyncEventArgs::getLastOperation() const SocketAsyncOperation_t SocketAsyncEventArgs::getLastOperation() const
{ {
// TODO: implement return lastOperation;
} }
int SocketAsyncEventArgs::getOffset() const int SocketAsyncEventArgs::getOffset() const
{ {
// TODO: implement return offset;
} }
SocketAsyncEventArgs::SocketAsyncEventArgs() SocketAsyncEventArgs::SocketAsyncEventArgs()
{ {
lastOperation = SocketAsyncOperation::None;
this->SocketError = SocketError::Success;
// TODO: implement // TODO: implement
} }
SocketAsyncEventArgs::SocketAsyncEventArgs() SocketAsyncEventArgs::~SocketAsyncEventArgs()
{ {
// TODO: implement if (!isDisposed)
{
// TODO: implement
}
} }
void SocketAsyncEventArgs::Dispose() void SocketAsyncEventArgs::Dispose()
{ {
isDisposed = true;
// TODO: implement // TODO: implement
} }
@ -86,10 +105,55 @@ namespace System
return SocketAsyncEventArgsTypeInfo; return SocketAsyncEventArgsTypeInfo;
} }
void SocketAsyncEventArgs::Oncompleted(SocketAsyncEventArgs* e) void SocketAsyncEventArgs::Oncompleted(SocketAsyncEventArgs * e)
{ {
if (e == null)
{
return;
}
Completed(this, e); Completed(this, e);
} }
void SocketAsyncEventArgs::SetBuffer(const int offset, const int count)
{
SetBufferInternal(getBuffer(), offset, count);
}
void SocketAsyncEventArgs::SetBuffer(byte buffer[], const int offset, const int count)
{
SetBufferInternal(buffer, offset, count);
}
void SocketAsyncEventArgs::SetBufferInternal(byte buffer[], int offset, int count)
{
if (buffer != null)
{
sassert(getBufferList() != null, "Buffer and BufferList properties cannot both be non-null.");
int buflen = buffer.Length;
sassert(offset >= 0 && offset < buflen, "");
//throw new ArgumentOutOfRangeException("offset");
sassert(count >= 0 && count <= buflen - offset, "");
//throw new ArgumentOutOfRangeException("count");
this->count = count;
this->offset = offset;
}
Buffer = buffer;
}
void SocketAsyncEventArgs::SetLastOperation(SocketAsyncOperation_t op)
{
sassert(!isDisposed, "");
sassert(Interlocked::Exchange(&inProgress, 1) == 0, "");
lastOperation = op;
}
} }
} }
} }

View File

@ -532,7 +532,7 @@ namespace System
return result; return result;
} }
const char String::operator [](const int index) const const char& String::operator [](const int index) const
{ {
sassert(index > 0 && index < Length, "index out of range."); sassert(index > 0 && index < Length, "index out of range.");