Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 48 additions & 39 deletions std/socket.d
Original file line number Diff line number Diff line change
Expand Up @@ -2741,21 +2741,21 @@ public:


/// Get the socket's address family.
@property AddressFamily addressFamily()
@property AddressFamily addressFamily() const pure nothrow @nogc
{
return _family;
}

/// Property that indicates if this is a valid, alive socket.
@property bool isAlive() @trusted const
@property bool isAlive() @trusted const nothrow @nogc
{
int type;
socklen_t typesize = cast(socklen_t) type.sizeof;
return !getsockopt(sock, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize);
}

/// Associate a local address with this socket.
void bind(Address addr) @trusted
void bind(Address addr) @trusted const
{
if (_SOCKET_ERROR == .bind(sock, addr.name, addr.nameLen))
throw new SocketOSException("Unable to bind socket");
Expand All @@ -2766,7 +2766,7 @@ public:
* the connection to be made. If the socket is nonblocking, connect
* returns immediately and the connection attempt is still in progress.
*/
void connect(Address to) @trusted
void connect(Address to) @trusted const
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does const on a void method make sense?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes? It means that the object itself will not be modified.

A different question would be, does const on a method that mutates the state of what it is representing (OS socket) make sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const applies to this pointer so obviously yes

{
if (_SOCKET_ERROR == .connect(sock, to.name, to.nameLen))
{
Expand Down Expand Up @@ -2799,7 +2799,7 @@ public:
* can $(D listen). The $(D backlog) is a request of how many pending
* incoming connections are queued until $(D accept)ed.
*/
void listen(int backlog) @trusted
void listen(int backlog) @trusted const
{
if (_SOCKET_ERROR == .listen(sock, backlog))
throw new SocketOSException("Unable to listen on socket");
Expand All @@ -2814,7 +2814,7 @@ public:
*/
// Override to use a derived class.
// The returned socket's handle must not be set.
protected Socket accepting() pure nothrow
protected Socket accepting() const pure nothrow
{
return new Socket;
}
Expand All @@ -2824,7 +2824,7 @@ public:
* waits for a connection request. Throws $(D SocketAcceptException) if
* unable to _accept. See $(D accepting) for use with derived classes.
*/
Socket accept() @trusted
Socket accept() const @trusted
{
auto newsock = cast(socket_t).accept(sock, null, null);
if (socket_t.init == newsock)
Expand All @@ -2851,7 +2851,7 @@ public:
}

/// Disables sends and/or receives.
void shutdown(SocketShutdown how) @trusted nothrow @nogc
void shutdown(SocketShutdown how) @trusted const nothrow @nogc
{
.shutdown(sock, cast(int)how);
}
Expand Down Expand Up @@ -2896,7 +2896,7 @@ public:
}

/// Remote endpoint $(D Address).
@property Address remoteAddress() @trusted
@property Address remoteAddress() const @trusted
{
Address addr = createAddress();
socklen_t nameLen = addr.nameLen;
Expand All @@ -2909,7 +2909,7 @@ public:
}

/// Local endpoint $(D Address).
@property Address localAddress() @trusted
@property Address localAddress() const @trusted
{
Address addr = createAddress();
socklen_t nameLen = addr.nameLen;
Expand All @@ -2928,28 +2928,37 @@ public:
*/
enum int ERROR = _SOCKET_ERROR;

private static int capToInt(size_t size) nothrow @nogc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@safe pure?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@safe is implicit (declared at the top of the module). pure makes no difference here because it is a private method called only by non-pure methods.

{
// Windows uses int instead of size_t for length arguments.
// Luckily, the send/recv functions make no guarantee that
// all the data is sent, so we use that to send at most
// int.max bytes.
return size > size_t(int.max) ? int.max : cast(int)size;
}

/**
* Send data on the connection. If the socket is blocking and there is no
* buffer space left, $(D send) waits.
* Returns: The number of bytes actually sent, or $(D Socket.ERROR) on
* failure.
*/
//returns number of bytes actually sent, or -1 on error
ptrdiff_t send(const(void)[] buf, SocketFlags flags) @trusted
ptrdiff_t send(const(void)[] buf, SocketFlags flags) @trusted const nothrow @nogc
{
static if (is(typeof(MSG_NOSIGNAL)))
{
flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
}
version( Windows )
auto sent = .send(sock, buf.ptr, to!int(buf.length), cast(int)flags);
auto sent = .send(sock, buf.ptr, capToInt(buf.length), cast(int)flags);
else
auto sent = .send(sock, buf.ptr, buf.length, cast(int)flags);
return sent;
}

/// ditto
ptrdiff_t send(const(void)[] buf)
ptrdiff_t send(const(void)[] buf) @trusted const nothrow @nogc
{
return send(buf, SocketFlags.NONE);
}
Expand All @@ -2961,46 +2970,46 @@ public:
* Returns: The number of bytes actually sent, or $(D Socket.ERROR) on
* failure.
*/
ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to) @trusted
ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to) @trusted const nothrow @nogc
{
static if (is(typeof(MSG_NOSIGNAL)))
{
flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
}
version( Windows )
return .sendto(
sock, buf.ptr, std.conv.to!int(buf.length),
sock, buf.ptr, capToInt(buf.length),
cast(int)flags, to.name, to.nameLen
);
else
return .sendto(sock, buf.ptr, buf.length, cast(int)flags, to.name, to.nameLen);
}

/// ditto
ptrdiff_t sendTo(const(void)[] buf, Address to)
ptrdiff_t sendTo(const(void)[] buf, Address to) @trusted const nothrow @nogc
{
return sendTo(buf, SocketFlags.NONE, to);
}


//assumes you connect()ed
/// ditto
ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags) @trusted
ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags) @trusted const nothrow @nogc
{
static if (is(typeof(MSG_NOSIGNAL)))
{
flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
}
version(Windows)
return .sendto(sock, buf.ptr, to!int(buf.length), cast(int)flags, null, 0);
return .sendto(sock, buf.ptr, capToInt(buf.length), cast(int)flags, null, 0);
else
return .sendto(sock, buf.ptr, buf.length, cast(int)flags, null, 0);
}


//assumes you connect()ed
/// ditto
ptrdiff_t sendTo(const(void)[] buf)
ptrdiff_t sendTo(const(void)[] buf) @trusted const nothrow @nogc
{
return sendTo(buf, SocketFlags.NONE);
}
Expand All @@ -3013,12 +3022,12 @@ public:
* has closed the connection, or $(D Socket.ERROR) on failure.
*/
//returns number of bytes actually received, 0 on connection closure, or -1 on error
ptrdiff_t receive(void[] buf, SocketFlags flags) @trusted
ptrdiff_t receive(void[] buf, SocketFlags flags) @trusted const nothrow @nogc
{
version(Windows) // Does not use size_t
{
return buf.length
? .recv(sock, buf.ptr, to!int(buf.length), cast(int)flags)
? .recv(sock, buf.ptr, capToInt(buf.length), cast(int)flags)
: 0;
} else {
return buf.length
Expand All @@ -3028,7 +3037,7 @@ public:
}

/// ditto
ptrdiff_t receive(void[] buf)
ptrdiff_t receive(void[] buf) @trusted const nothrow @nogc
{
return receive(buf, SocketFlags.NONE);
}
Expand All @@ -3040,7 +3049,7 @@ public:
* Returns: The number of bytes actually received, $(D 0) if the remote side
* has closed the connection, or $(D Socket.ERROR) on failure.
*/
ptrdiff_t receiveFrom(void[] buf, SocketFlags flags, ref Address from) @trusted
ptrdiff_t receiveFrom(void[] buf, SocketFlags flags, ref Address from) @trusted const nothrow
{
if (!buf.length) //return 0 and don't think the connection closed
return 0;
Expand All @@ -3049,7 +3058,7 @@ public:
socklen_t nameLen = from.nameLen;
version(Windows)
{
auto read = .recvfrom(sock, buf.ptr, to!int(buf.length), cast(int)flags, from.name, &nameLen);
auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int)flags, from.name, &nameLen);
assert(from.addressFamily == _family);
// if (!read) //connection closed
return read;
Expand All @@ -3063,21 +3072,21 @@ public:


/// ditto
ptrdiff_t receiveFrom(void[] buf, ref Address from)
ptrdiff_t receiveFrom(void[] buf, ref Address from) @trusted const nothrow
{
return receiveFrom(buf, SocketFlags.NONE, from);
}


//assumes you connect()ed
/// ditto
ptrdiff_t receiveFrom(void[] buf, SocketFlags flags) @trusted
ptrdiff_t receiveFrom(void[] buf, SocketFlags flags) @trusted const nothrow @nogc
{
if (!buf.length) //return 0 and don't think the connection closed
return 0;
version(Windows)
{
auto read = .recvfrom(sock, buf.ptr, to!int(buf.length), cast(int)flags, null, null);
auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int)flags, null, null);
// if (!read) //connection closed
return read;
} else {
Expand All @@ -3090,7 +3099,7 @@ public:

//assumes you connect()ed
/// ditto
ptrdiff_t receiveFrom(void[] buf)
ptrdiff_t receiveFrom(void[] buf) @trusted const nothrow @nogc
{
return receiveFrom(buf, SocketFlags.NONE);
}
Expand All @@ -3099,7 +3108,7 @@ public:
/// Get a socket option.
/// Returns: The number of bytes written to $(D result).
//returns the length, in bytes, of the actual result - very different from getsockopt()
int getOption(SocketOptionLevel level, SocketOption option, void[] result) @trusted
int getOption(SocketOptionLevel level, SocketOption option, void[] result) @trusted const
{
socklen_t len = cast(socklen_t) result.length;
if (_SOCKET_ERROR == .getsockopt(sock, cast(int)level, cast(int)option, result.ptr, &len))
Expand All @@ -3109,21 +3118,21 @@ public:


/// Common case of getting integer and boolean options.
int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) @trusted
int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) @trusted const
{
return getOption(level, option, (&result)[0 .. 1]);
}


/// Get the linger option.
int getOption(SocketOptionLevel level, SocketOption option, out Linger result) @trusted
int getOption(SocketOptionLevel level, SocketOption option, out Linger result) @trusted const
{
//return getOption(cast(SocketOptionLevel)SocketOptionLevel.SOCKET, SocketOption.LINGER, (&result)[0 .. 1]);
return getOption(level, option, (&result.clinger)[0 .. 1]);
}

/// Get a timeout (duration) option.
void getOption(SocketOptionLevel level, SocketOption option, out Duration result) @trusted
void getOption(SocketOptionLevel level, SocketOption option, out Duration result) @trusted const
{
enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
Expand All @@ -3147,7 +3156,7 @@ public:
}

/// Set a socket option.
void setOption(SocketOptionLevel level, SocketOption option, void[] value) @trusted
void setOption(SocketOptionLevel level, SocketOption option, void[] value) @trusted const
{
if (_SOCKET_ERROR == .setsockopt(sock, cast(int)level,
cast(int)option, value.ptr, cast(uint) value.length))
Expand All @@ -3156,14 +3165,14 @@ public:


/// Common case for setting integer and boolean options.
void setOption(SocketOptionLevel level, SocketOption option, int32_t value) @trusted
void setOption(SocketOptionLevel level, SocketOption option, int32_t value) @trusted const
{
setOption(level, option, (&value)[0 .. 1]);
}


/// Set the linger option.
void setOption(SocketOptionLevel level, SocketOption option, Linger value) @trusted
void setOption(SocketOptionLevel level, SocketOption option, Linger value) @trusted const
{
//setOption(cast(SocketOptionLevel)SocketOptionLevel.SOCKET, SocketOption.LINGER, (&value)[0 .. 1]);
setOption(level, option, (&value.clinger)[0 .. 1]);
Expand Down Expand Up @@ -3210,7 +3219,7 @@ public:
* sw.peek.msecs);
* ---
*/
void setOption(SocketOptionLevel level, SocketOption option, Duration value) @trusted
void setOption(SocketOptionLevel level, SocketOption option, Duration value) @trusted const
{
enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
Expand Down Expand Up @@ -3238,7 +3247,7 @@ public:

/// Get a text description of this socket's error status, and clear the
/// socket's error status.
string getErrorText()
string getErrorText() const
{
int32_t error;
getOption(SocketOptionLevel.SOCKET, SocketOption.ERROR, error);
Expand All @@ -3258,7 +3267,7 @@ public:
* $(D SocketFeatureException) if setting keep-alive parameters is
* unsupported on the current platform.
*/
void setKeepAlive(int time, int interval) @trusted
void setKeepAlive(int time, int interval) @trusted const
{
version(Windows)
{
Expand Down Expand Up @@ -3417,7 +3426,7 @@ public:

/// Returns a new Address object for the current address family.
/// Can be overridden to support other addresses.
protected Address createAddress() pure nothrow
protected Address createAddress() const pure nothrow
{
Address result;
switch (_family)
Expand Down