this.address_family = addressFamily;
this.socket_type = socketType;
this.protocol_type = protocolType;
-
- int error;
- var handle = Socket_internal (addressFamily, socketType, protocolType, out error);
- this.safe_handle = new SafeSocketHandle (handle, true);
+ int error;
+ this.safe_handle = new SafeSocketHandle (Socket_internal (addressFamily, socketType, protocolType, out error), true);
if (error != 0)
throw new SocketException (error);
InitSocketAsyncEventArgs (e, AcceptAsyncCallback, e, SocketOperation.Accept);
- QueueIOSelectorJob (readQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, e.socket_async_result));
+ QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, e.socket_async_result));
return true;
}
SocketAsyncResult sockares = new SocketAsyncResult (this, callback, state, SocketOperation.Accept);
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, sockares));
+ QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptCallback, sockares));
return sockares;
}
static IOAsyncCallback BeginAcceptCallback = new IOAsyncCallback (ares => {
SocketAsyncResult sockares = (SocketAsyncResult) ares;
- Socket socket = null;
-
+ Socket acc_socket = null;
try {
- socket = sockares.socket.Accept ();
+ if (sockares.AcceptSocket == null) {
+ acc_socket = sockares.socket.Accept ();
+ } else {
+ acc_socket = sockares.AcceptSocket;
+ sockares.socket.Accept (acc_socket);
+ }
+
} catch (Exception e) {
sockares.Complete (e);
return;
}
-
- sockares.Complete (socket);
+ sockares.Complete (acc_socket);
});
public IAsyncResult BeginAccept (int receiveSize, AsyncCallback callback, object state)
SockFlags = SocketFlags.None,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
+ QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
return sockares;
}
AcceptSocket = acceptSocket,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
+ QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginAcceptReceiveCallback, sockares));
return sockares;
}
if (local_end == null)
throw new ArgumentNullException("local_end");
-
+
+ var ipEndPoint = local_end as IPEndPoint;
+ if (ipEndPoint != null) {
+ local_end = RemapIPEndPoint (ipEndPoint);
+ }
+
int error;
Bind_internal (safe_handle, local_end.Serialize(), out error);
int error = 0;
foreach (IPAddress address in addresses) {
IPEndPoint iep = new IPEndPoint (address, port);
+
+ iep = RemapIPEndPoint (iep);
Connect_internal (safe_handle, iep.Serialize (), out error);
if (error == 0) {
if (is_listening)
throw new InvalidOperationException ();
+
+ if (ep != null) {
+ remoteEP = RemapIPEndPoint (ep);
+ }
SocketAddress serial = remoteEP.Serialize ();
sockares.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
return sockares;
}
+
+ end_point = RemapIPEndPoint (ep);
}
int error = 0;
// an error. Better to just close the socket and move on.
connect_in_progress = false;
safe_handle.Dispose ();
- var handle = Socket_internal (address_family, socket_type, protocol_type, out error);
- safe_handle = new SafeSocketHandle (handle, true);
+ safe_handle = new SafeSocketHandle (Socket_internal (address_family, socket_type, protocol_type, out error), true);
if (error != 0)
throw new SocketException (error);
}
is_bound = false;
connect_in_progress = true;
- IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
+ IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginConnectCallback, sockares));
return sockares;
}
InitSocketAsyncEventArgs (e, DisconnectAsyncCallback, e, SocketOperation.Disconnect);
- IOSelector.Add (e.socket_async_result.handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, e.socket_async_result));
+ IOSelector.Add (e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, e.socket_async_result));
return true;
}
ReuseSocket = reuseSocket,
};
- IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, sockares));
+ IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginDisconnectCallback, sockares));
return sockares;
}
e.socket_async_result.Buffers = e.BufferList;
- QueueIOSelectorJob (readQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, e.socket_async_result));
+ QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, e.socket_async_result));
} else {
InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.Receive);
e.socket_async_result.Offset = e.Offset;
e.socket_async_result.Size = e.Count;
- QueueIOSelectorJob (readQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, e.socket_async_result));
+ QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, e.socket_async_result));
}
return true;
SockFlags = socket_flags,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
+ QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveCallback, sockares));
return sockares;
}
SockFlags = socketFlags,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
+ QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveGenericCallback, sockares));
return sockares;
}
e.socket_async_result.EndPoint = e.RemoteEndPoint;
e.socket_async_result.SockFlags = e.SocketFlags;
- QueueIOSelectorJob (readQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, e.socket_async_result));
+ QueueIOSelectorJob (readQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, e.socket_async_result));
return true;
}
EndPoint = remote_end,
};
- QueueIOSelectorJob (readQ, sockares.handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
+ QueueIOSelectorJob (readQ, sockares.Handle, new IOSelectorJob (IOOperation.Read, BeginReceiveFromCallback, sockares));
return sockares;
}
e.socket_async_result.Buffers = e.BufferList;
- QueueIOSelectorJob (writeQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, e.socket_async_result));
+ QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, e.socket_async_result));
} else {
InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.Send);
e.socket_async_result.Offset = e.Offset;
e.socket_async_result.Size = e.Count;
- QueueIOSelectorJob (writeQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
+ QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
}
return true;
SockFlags = socket_flags,
};
- QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
+ QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, 0), sockares));
return sockares;
}
}
if (sockares.Size > 0) {
- IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, sent_so_far), sockares));
+ IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendCallback ((SocketAsyncResult) s, sent_so_far), sockares));
return; // Have to finish writing everything. See bug #74475.
}
SockFlags = socketFlags,
};
- QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
+ QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, BeginSendGenericCallback, sockares));
return sockares;
}
e.socket_async_result.SockFlags = e.SocketFlags;
e.socket_async_result.EndPoint = e.RemoteEndPoint;
- QueueIOSelectorJob (writeQ, e.socket_async_result.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
+ QueueIOSelectorJob (writeQ, e.socket_async_result.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), e.socket_async_result));
return true;
}
EndPoint = remote_end,
};
- QueueIOSelectorJob (writeQ, sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
+ QueueIOSelectorJob (writeQ, sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, 0), sockares));
return sockares;
}
}
if (sockares.Size > 0) {
- IOSelector.Add (sockares.handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, sent_so_far), sockares));
+ IOSelector.Add (sockares.Handle, new IOSelectorJob (IOOperation.Write, s => BeginSendToCallback ((SocketAsyncResult) s, sent_so_far), sockares));
return; // Have to finish writing everything. See bug #74475.
}
public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, bool optionValue)
{
- ThrowIfDisposedAndClosed ();
-
- int error;
int int_val = optionValue ? 1 : 0;
- SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, int_val, out error);
- if (error != 0) {
- if (error == (int) SocketError.InvalidArgument)
- throw new ArgumentException ();
- throw new SocketException (error);
- }
+ SetSocketOption (optionLevel, optionName, int_val);
}
public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
{
ThrowIfDisposedAndClosed ();
+ if (optionName == SocketOptionName.ReuseAddress && optionValue != 0 && !SupportsPortReuse ())
+ throw new SocketException ((int) SocketError.OperationNotSupported, "Operating system sockets do not support ReuseAddress.\nIf your socket is not intended to bind to the same address and port multiple times remove this option, otherwise you should ignore this exception inside a try catch and check that ReuseAddress is true before binding to the same address and port multiple times.");
+
int error;
SetSocketOption_internal (safe_handle, optionLevel, optionName, null, null, optionValue, out error);
if (error != 0) {
+ if (error == (int) SocketError.InvalidArgument)
+ throw new ArgumentException ();
throw new SocketException (error);
}
}
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
+ internal extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
#endregion
void InitSocketAsyncEventArgs (SocketAsyncEventArgs e, AsyncCallback callback, object state, SocketOperation operation)
{
e.socket_async_result.Init (this, callback, state, operation);
-
+ if (e.AcceptSocket != null) {
+ e.socket_async_result.AcceptSocket = e.AcceptSocket;
+ }
e.current_socket = this;
e.SetLastOperation (SocketOperationToSocketAsyncOperation (operation));
e.SocketError = SocketError.Success;
throw new NotImplementedException (String.Format ("Operation {0} is not implemented", op));
}
}
-
+
+ IPEndPoint RemapIPEndPoint (IPEndPoint input) {
+ // If socket is DualMode ensure we automatically handle mapping IPv4 addresses to IPv6.
+ if (IsDualMode && input.AddressFamily == AddressFamily.InterNetwork)
+ return new IPEndPoint (input.Address.MapToIPv6 (), input.Port);
+
+ return input;
+ }
+
[StructLayout (LayoutKind.Sequential)]
struct WSABUF {
public int len;