/Languages/IronPython/IronPython.Modules/socket.cs
C# | 3078 lines | 2579 code | 348 blank | 151 comment | 580 complexity | 5c961e9e4e7e991a8290db1150c646e3 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
Large files files are truncated, but you can click here to view the full file
- /* ****************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Apache License, Version 2.0, please send an email to
- * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
- * by the terms of the Apache License, Version 2.0.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************/
- #if FEATURE_FULL_NET
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using System.Net.Security;
- using System.Runtime.InteropServices;
- using System.Security.Cryptography.X509Certificates;
- using System.Security.Authentication;
- using System.Runtime.CompilerServices;
- using System.Text;
- using Microsoft.Scripting;
- using Microsoft.Scripting.Runtime;
- using IronPython.Runtime;
- using IronPython.Runtime.Exceptions;
- using IronPython.Runtime.Operations;
- using IronPython.Runtime.Types;
- #if FEATURE_NUMERICS
- using System.Numerics;
- #else
- using Microsoft.Scripting.Math;
- #endif
- using PythonArray = IronPython.Modules.ArrayModule.array;
- using SpecialNameAttribute = System.Runtime.CompilerServices.SpecialNameAttribute;
- using Microsoft.Scripting.Utils;
- #if NETCOREAPP1_0
- using Environment = System.FakeEnvironment;
- #endif
- [assembly: PythonModule("socket", typeof(IronPython.Modules.PythonSocket))]
- namespace IronPython.Modules {
- public static class PythonSocket {
- private static readonly object _defaultTimeoutKey = new object();
- private static readonly object _defaultBufsizeKey = new object();
- private const int DefaultBufferSize = 8192;
- public static PythonTuple _delegate_methods = PythonTuple.MakeTuple("recv", "recvfrom", "recv_into", "recvfrom_into", "send", "sendto");
- [SpecialName]
- public static void PerformModuleReload(PythonContext/*!*/ context, PythonDictionary/*!*/ dict) {
- if (!context.HasModuleState(_defaultTimeoutKey)) {
- context.SetModuleState(_defaultTimeoutKey, null);
- }
- context.SetModuleState(_defaultBufsizeKey, DefaultBufferSize);
- PythonType socketErr = GetSocketError(context, dict);
- context.EnsureModuleException("socketherror", socketErr, dict, "herror", "socket");
- context.EnsureModuleException("socketgaierror", socketErr, dict, "gaierror", "socket");
- context.EnsureModuleException("sockettimeout", socketErr, dict, "timeout", "socket");
- }
- internal static PythonType GetSocketError(PythonContext context, PythonDictionary dict) {
- return context.EnsureModuleException("socketerror", PythonExceptions.IOError, dict, "error", "socket");
- }
- #if NETSTANDARD
- private static ConditionalWeakTable<Socket, object> fakeHandles = new ConditionalWeakTable<Socket, object>();
- private static long maxHandle = 0;
- #endif
- private static IntPtr GetHandle(this Socket socket)
- {
- #if NETSTANDARD
- object handle;
- lock (fakeHandles) {
- if (!fakeHandles.TryGetValue(socket, out handle)) {
- handle = (IntPtr)maxHandle++;
- fakeHandles.Add(socket, handle);
- }
- }
- return (IntPtr)handle;
- #else
- return socket.Handle;
- #endif
- }
- public const string __doc__ = "Implementation module for socket operations.\n\n"
- + "This module is a loose wrapper around the .NET System.Net.Sockets API, so you\n"
- + "may find the corresponding MSDN documentation helpful in decoding error\n"
- + "messages and understanding corner cases.\n"
- + "\n"
- + "This implementation of socket differs slightly from the standard CPython\n"
- + "socket module. Many of these differences are due to the implementation of the\n"
- + ".NET socket libraries. These differences are summarized below. For full\n"
- + "details, check the docstrings of the functions mentioned.\n"
- + " - s.accept(), s.connect(), and s.connect_ex() do not support timeouts.\n"
- + " - Timeouts in s.sendall() don't work correctly.\n"
- + " - s.dup() is not implemented.\n"
- + " - SSL support is not implemented."
- + "\n"
- + "An Extra IronPython-specific function is exposed only if the clr module is\n"
- + "imported:\n"
- + " - s.HandleToSocket() returns the System.Net.Sockets.Socket object associated\n"
- + " with a particular \"file descriptor number\" (as returned by s.fileno()).\n"
- ;
- #region Socket object
- public static PythonType SocketType = DynamicHelpers.GetPythonTypeFromType(typeof(socket));
- [PythonType]
- [Documentation("socket([family[, type[, proto]]]) -> socket object\n\n"
- + "Create a socket (a network connection endpoint) of the given family, type,\n"
- + "and protocol. socket() accepts keyword arguments.\n"
- + " - family (address family) defaults to AF_INET\n"
- + " - type (socket type) defaults to SOCK_STREAM\n"
- + " - proto (protocol type) defaults to 0, which specifies the default protocol\n"
- + "\n"
- + "This module supports only IP sockets. It does not support raw or Unix sockets.\n"
- + "Both IPv4 and IPv6 are supported.")]
- public class socket : IWeakReferenceable {
- #region Fields
- /// <summary>
- /// handleToSocket allows us to translate from Python's idea of a socket resource (file
- /// descriptor numbers) to .NET's idea of a socket resource (System.Net.Socket objects).
- /// In particular, this allows the select module to convert file numbers (as returned by
- /// fileno()) and convert them to Socket objects so that it can do something useful with them.
- /// </summary>
- private static readonly Dictionary<IntPtr, WeakReference> _handleToSocket = new Dictionary<IntPtr, WeakReference>();
- private const int DefaultAddressFamily = (int)AddressFamily.InterNetwork;
- private const int DefaultSocketType = (int)System.Net.Sockets.SocketType.Stream;
- private const int DefaultProtocolType = (int)ProtocolType.Unspecified;
- internal Socket _socket;
- internal string _hostName;
- private WeakRefTracker _weakRefTracker = null;
- private int _referenceCount = 1;
- public const string __module__ = "socket";
- internal CodeContext/*!*/ _context;
- private int _timeout;
- #endregion
- #region Public API
- public socket() {
- }
- public void __init__(CodeContext/*!*/ context, [DefaultParameterValue(DefaultAddressFamily)] int addressFamily,
- [DefaultParameterValue(DefaultSocketType)] int socketType,
- [DefaultParameterValue(DefaultProtocolType)] int protocolType,
- [DefaultParameterValue(null)]socket _sock) {
- System.Net.Sockets.SocketType type = (System.Net.Sockets.SocketType)Enum.ToObject(typeof(System.Net.Sockets.SocketType), socketType);
- if (!Enum.IsDefined(typeof(System.Net.Sockets.SocketType), type)) {
- throw MakeException(context, new SocketException((int)SocketError.SocketNotSupported));
- }
- AddressFamily family = (AddressFamily)Enum.ToObject(typeof(AddressFamily), addressFamily);
- if (!Enum.IsDefined(typeof(AddressFamily), family)) {
- throw MakeException(context, new SocketException((int)SocketError.AddressFamilyNotSupported));
- }
- ProtocolType proto = (ProtocolType)Enum.ToObject(typeof(ProtocolType), protocolType);
- if (!Enum.IsDefined(typeof(ProtocolType), proto)) {
- throw MakeException(context, new SocketException((int)SocketError.ProtocolNotSupported));
- }
- if (_sock == null) {
- Socket newSocket;
- try {
- newSocket = new Socket(family, type, proto);
- } catch (SocketException e) {
- throw MakeException(context, e);
- }
- Initialize(context, newSocket);
- } else {
- _socket = _sock._socket;
- _hostName = _sock._hostName;
- // we now own the lifetime of the socket
- GC.SuppressFinalize(_sock);
- Initialize(context, _socket);
- }
- }
- public void __del__() {
- _close();
- }
- ~socket() {
- _close();
- }
- public socket _sock {
- get {
- return this;
- }
- }
- #if !NETSTANDARD
- private IAsyncResult _acceptResult;
- #endif
- [Documentation("accept() -> (conn, address)\n\n"
- + "Accept a connection. The socket must be bound and listening before calling\n"
- + "accept(). conn is a new socket object connected to the remote host, and\n"
- + "address is the remote host's address (e.g. a (host, port) tuple for IPv4).\n"
- + "\n"
- )]
- public PythonTuple accept() {
- socket wrappedRemoteSocket;
- Socket realRemoteSocket;
- try {
- #if NETSTANDARD
- // TODO: support timeout != 0
- realRemoteSocket = _socket.Accept();
- #else
- if (_acceptResult != null && _acceptResult.IsCompleted) {
- // previous async result has completed
- realRemoteSocket = _socket.EndAccept(_acceptResult);
- } else {
- int timeoutTime = _timeout;
- if (timeoutTime != 0) {
- // use the existing or create a new async request
- var asyncResult = _acceptResult ?? _socket.BeginAccept((x) => { }, null);
- if (asyncResult.AsyncWaitHandle.WaitOne(timeoutTime)) {
- // it's completed, end and throw it away
- realRemoteSocket = _socket.EndAccept(asyncResult);
- _acceptResult = null;
- } else {
- // save the async result for later incase it completes
- _acceptResult = asyncResult;
- throw PythonExceptions.CreateThrowable(timeout(_context), 0, "timeout");
- }
- } else {
- realRemoteSocket = _socket.Accept();
- }
- }
- #endif
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- wrappedRemoteSocket = new socket(_context, realRemoteSocket);
- return PythonTuple.MakeTuple(wrappedRemoteSocket, wrappedRemoteSocket.getpeername());
- }
- [Documentation("bind(address) -> None\n\n"
- + "Bind to an address. If the socket is already bound, socket.error is raised.\n"
- + "For IP sockets, address is a (host, port) tuple. Raw sockets are not\n"
- + "supported.\n"
- + "\n"
- + "If you do not care which local address is assigned, set host to INADDR_ANY and\n"
- + "the system will assign the most appropriate network address. Similarly, if you\n"
- + "set port to 0, the system will assign an available port number between 1024\n"
- + "and 5000."
- )]
- public void bind(PythonTuple address) {
- IPEndPoint localEP = TupleToEndPoint(_context, address, _socket.AddressFamily, out _hostName);
- try {
- _socket.Bind(localEP);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("close() -> None\n\nClose the socket. It cannot be used after being closed.")]
- public void close() {
- var refs = System.Threading.Interlocked.Decrement(ref _referenceCount);
- // Don't actually close the socket if other file objects are
- // still referring to this socket.
- if (refs < 1) {
- _close();
- }
- }
- internal void _close() {
- if (_socket != null) {
- lock (_handleToSocket) {
- WeakReference weakref;
- if (_handleToSocket.TryGetValue(_socket.GetHandle(), out weakref)) {
- Socket target = (weakref.Target as Socket);
- if (target == _socket || target == null) {
- _handleToSocket.Remove(_socket.GetHandle());
- }
- }
- }
- ((IDisposable)_socket).Dispose();
- _referenceCount = 0;
- }
- }
- [Documentation("connect(address) -> None\n\n"
- + "Connect to a remote socket at the given address. IP addresses are expressed\n"
- + "as (host, port).\n"
- + "\n"
- + "Raises socket.error if the socket has been closed, the socket is listening, or\n"
- + "another connection error occurred."
- + "\n"
- + "Difference from CPython: connect() does not support timeouts in blocking mode.\n"
- + "If a timeout is set and the socket is in blocking mode, connect() will block\n"
- + "indefinitely until a connection is made or an error occurs."
- )]
- public void connect(PythonTuple address) {
- IPEndPoint remoteEP = TupleToEndPoint(_context, address, _socket.AddressFamily, out _hostName);
- try {
- _socket.Connect(remoteEP);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("connect_ex(address) -> error_code\n\n"
- + "Like connect(), but return an error code insted of raising an exception for\n"
- + "socket exceptions raised by the underlying system Connect() call. Note that\n"
- + "exceptions other than SocketException generated by the system Connect() call\n"
- + "will still be raised.\n"
- + "\n"
- + "A return value of 0 indicates that the connect call was successful."
- + "\n"
- + "Difference from CPython: connect_ex() does not support timeouts in blocking\n"
- + "mode. If a timeout is set and the socket is in blocking mode, connect_ex() will\n"
- + "block indefinitely until a connection is made or an error occurs."
- )]
- public int connect_ex(PythonTuple address) {
- IPEndPoint remoteEP = TupleToEndPoint(_context, address, _socket.AddressFamily, out _hostName);
- try {
- _socket.Connect(remoteEP);
- } catch (SocketException e) {
- return (int)e.SocketErrorCode;
- }
- return (int)SocketError.Success;
- }
- [Documentation("fileno() -> file_handle\n\n"
- + "Return the underlying system handle for this socket (a 64-bit integer)."
- )]
- public Int64 fileno() {
- try {
- return _socket.GetHandle().ToInt64();
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("getpeername() -> address\n\n"
- + "Return the address of the remote end of this socket. The address format is\n"
- + "family-dependent (e.g. a (host, port) tuple for IPv4)."
- )]
- public PythonTuple getpeername() {
- try {
- IPEndPoint remoteEP = _socket.RemoteEndPoint as IPEndPoint;
- if (remoteEP == null) {
- throw MakeException(_context, new SocketException((int)SocketError.AddressFamilyNotSupported));
- }
- return EndPointToTuple(remoteEP);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("getsockname() -> address\n\n"
- + "Return the address of the local end of this socket. The address format is\n"
- + "family-dependent (e.g. a (host, port) tuple for IPv4)."
- )]
- public PythonTuple getsockname() {
- try {
- IPEndPoint localEP = _socket.LocalEndPoint as IPEndPoint;
- if (localEP == null) {
- throw MakeException(_context, new SocketException((int)SocketError.InvalidArgument));
- }
- return EndPointToTuple(localEP);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("getsockopt(level, optname[, buflen]) -> value\n\n"
- + "Return the value of a socket option. level is one of the SOL_* constants\n"
- + "defined in this module, and optname is one of the SO_* constants. If buflen is\n"
- + "omitted or zero, an integer value is returned. If it is present, a byte string\n"
- + "whose maximum length is buflen bytes) is returned. The caller must the decode\n"
- + "the resulting byte string."
- )]
- public object getsockopt(int optionLevel, int optionName, [DefaultParameterValue(0)] int optionLength) {
- SocketOptionLevel level = (SocketOptionLevel)Enum.ToObject(typeof(SocketOptionLevel), optionLevel);
- if (!Enum.IsDefined(typeof(SocketOptionLevel), level)) {
- throw MakeException(_context, new SocketException((int)SocketError.InvalidArgument));
- }
- SocketOptionName name = (SocketOptionName)Enum.ToObject(typeof(SocketOptionName), optionName);
- if (!Enum.IsDefined(typeof(SocketOptionName), name)) {
- throw MakeException(_context, new SocketException((int)SocketError.ProtocolOption));
- }
- try {
- if (optionLength == 0) {
- // Integer return value
- return (int)_socket.GetSocketOption(level, name);
- } else {
- // Byte string return value
- return _socket.GetSocketOption(level, name, optionLength).MakeString();
- }
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("listen(backlog) -> None\n\n"
- + "Listen for connections on the socket. Backlog is the maximum length of the\n"
- + "pending connections queue. The maximum value is system-dependent."
- )]
- public void listen(int backlog) {
- try {
- _socket.Listen(backlog);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("makefile([mode[, bufsize]]) -> file object\n\n"
- + "Return a regular file object corresponding to the socket. The mode\n"
- + "and bufsize arguments are as for the built-in open() function.")]
- public PythonFile makefile([DefaultParameterValue("r")]string mode, [DefaultParameterValue(8192)]int bufSize) {
- System.Threading.Interlocked.Increment(ref _referenceCount); // dup our handle
- return new _fileobject(_context, this, mode, bufSize, false);
- }
- [Documentation("recv(bufsize[, flags]) -> string\n\n"
- + "Receive data from the socket, up to bufsize bytes. For connection-oriented\n"
- + "protocols (e.g. SOCK_STREAM), you must first call either connect() or\n"
- + "accept(). Connectionless protocols (e.g. SOCK_DGRAM) may also use recvfrom().\n"
- + "\n"
- + "recv() blocks until data is available, unless a timeout was set using\n"
- + "settimeout(). If the timeout was exceeded, socket.timeout is raised."
- + "recv() returns immediately with zero bytes when the connection is closed."
- )]
- public string recv(int maxBytes, [DefaultParameterValue(0)] int flags) {
- int bytesRead;
- if (maxBytes < 0)
- throw PythonOps.ValueError("negative buffersize in recv");
- byte[] buffer = new byte[maxBytes];
- try {
- bytesRead = _socket.Receive(buffer, (SocketFlags)flags);
- } catch (Exception e) {
- throw MakeRecvException(e, SocketError.NotConnected);
- }
- return PythonOps.MakeString(buffer, bytesRead);
- }
- [Documentation("recv_into(buffer, [nbytes[, flags]]) -> nbytes_read\n\n"
- + "A version of recv() that stores its data into a buffer rather than creating\n"
- + "a new string. Receive up to buffersize bytes from the socket. If buffersize\n"
- + "is not specified (or 0), receive up to the size available in the given buffer.\n\n"
- + "See recv() for documentation about the flags.\n"
- )]
- public int recv_into(PythonBuffer buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- if (nbytes < 0) {
- throw PythonOps.ValueError("negative buffersize in recv_into");
- }
- throw PythonOps.TypeError("buffer is read-only");
- }
- [Documentation("recv_into(buffer, [nbytes[, flags]]) -> nbytes_read\n\n"
- + "A version of recv() that stores its data into a buffer rather than creating\n"
- + "a new string. Receive up to buffersize bytes from the socket. If buffersize\n"
- + "is not specified (or 0), receive up to the size available in the given buffer.\n\n"
- + "See recv() for documentation about the flags.\n"
- )]
- public int recv_into(string buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- throw PythonOps.TypeError("Cannot use string as modifiable buffer");
- }
- [Documentation("recv_into(buffer, [nbytes[, flags]]) -> nbytes_read\n\n"
- + "A version of recv() that stores its data into a buffer rather than creating\n"
- + "a new string. Receive up to buffersize bytes from the socket. If buffersize\n"
- + "is not specified (or 0), receive up to the size available in the given buffer.\n\n"
- + "See recv() for documentation about the flags.\n"
- )]
- public int recv_into(PythonArray buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- int bytesRead;
- byte[] byteBuffer = new byte[byteBufferSize("recv_into", nbytes, buffer.__len__(), buffer.itemsize)];
- try {
- bytesRead = _socket.Receive(byteBuffer, (SocketFlags)flags);
- } catch (Exception e) {
- throw MakeRecvException(e, SocketError.NotConnected);
- }
- buffer.FromStream(new MemoryStream(byteBuffer), 0);
- return bytesRead;
- }
- [Documentation("recv_into(bytearray, [nbytes[, flags]]) -> nbytes_read\n\n"
- + "A version of recv() that stores its data into a bytearray rather than creating\n"
- + "a new string. Receive up to buffersize bytes from the socket. If buffersize\n"
- + "is not specified (or 0), receive up to the size available in the given buffer.\n\n"
- + "See recv() for documentation about the flags.\n"
- )]
- public int recv_into(ByteArray buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- int bytesRead;
- byte[] byteBuffer = new byte[byteBufferSize("recv_into", nbytes, buffer.Count, 1)];
- try {
- bytesRead = _socket.Receive(byteBuffer, (SocketFlags)flags);
- } catch (Exception e) {
- throw MakeRecvException(e, SocketError.NotConnected);
- }
- for (int i = 0; i < bytesRead; i++) {
- buffer[i] = byteBuffer[i];
- }
- return bytesRead;
- }
- [Documentation("recv_into(memoryview, [nbytes[, flags]]) -> nbytes_read\n\n"
- + "A version of recv() that stores its data into a bytearray rather than creating\n"
- + "a new string. Receive up to buffersize bytes from the socket. If buffersize\n"
- + "is not specified (or 0), receive up to the size available in the given buffer.\n\n"
- + "See recv() for documentation about the flags.\n"
- )]
- public int recv_into(MemoryView buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- int bytesRead;
- byte[] byteBuffer = buffer.tobytes().ToByteArray();
- try {
- bytesRead = _socket.Receive(byteBuffer, (SocketFlags)flags);
- }
- catch (Exception e) {
- if (_socket.SendTimeout == 0) {
- var s = new SocketException((int)SocketError.NotConnected);
- throw PythonExceptions.CreateThrowable(error(_context), (int)SocketError.NotConnected, s.Message);
- }
- else
- throw MakeException(_context, e);
- }
- buffer[new Slice(0, bytesRead)] = byteBuffer.Slice(new Slice(0, bytesRead));
- return bytesRead;
- }
- public int recv_into(object buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags){
- throw PythonOps.TypeError(string.Format("recv_into() argument 1 must be read-write buffer, not {0}",PythonOps.GetPythonTypeName(buffer)));
- }
-
- [Documentation("recvfrom(bufsize[, flags]) -> (string, address)\n\n"
- + "Receive data from the socket, up to bufsize bytes. string is the data\n"
- + "received, and address (whose format is protocol-dependent) is the address of\n"
- + "the socket from which the data was received."
- )]
- public PythonTuple recvfrom(int maxBytes, [DefaultParameterValue(0)] int flags) {
- if (maxBytes < 0) {
- throw PythonOps.ValueError("negative buffersize in recvfrom");
- }
- int bytesRead;
- byte[] buffer = new byte[maxBytes];
- IPEndPoint remoteIPEP = new IPEndPoint(IPAddress.Any, 0);
- EndPoint remoteEP = remoteIPEP;
- try {
- bytesRead = _socket.ReceiveFrom(buffer, (SocketFlags)flags, ref remoteEP);
- } catch (Exception e) {
- throw MakeRecvException(e, SocketError.InvalidArgument);
- }
- string data = PythonOps.MakeString(buffer, bytesRead);
- PythonTuple remoteAddress = EndPointToTuple((IPEndPoint)remoteEP);
- return PythonTuple.MakeTuple(data, remoteAddress);
- }
- [Documentation("recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\n"
- + "Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info.\n"
- )]
- public PythonTuple recvfrom_into(PythonBuffer buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- if (nbytes < 0) {
- throw PythonOps.ValueError("negative buffersize in recvfrom_into");
- }
- throw PythonOps.TypeError("buffer is read-only");
- }
- [Documentation("recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\n"
- + "Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info.\n"
- )]
- public PythonTuple recvfrom_into(string buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- throw PythonOps.TypeError("Cannot use string as modifiable buffer");
- }
- [Documentation("recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\n"
- + "Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info.\n"
- )]
- public PythonTuple recvfrom_into(PythonArray buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- int bytesRead;
- byte[] byteBuffer = new byte[byteBufferSize("recvfrom_into", nbytes, buffer.__len__(), buffer.itemsize)];
- IPEndPoint remoteIPEP = new IPEndPoint(IPAddress.Any, 0);
- EndPoint remoteEP = remoteIPEP;
- try {
- bytesRead = _socket.ReceiveFrom(byteBuffer, (SocketFlags)flags, ref remoteEP);
- } catch (Exception e) {
- throw MakeRecvException(e, SocketError.InvalidArgument);
- }
- buffer.FromStream(new MemoryStream(byteBuffer), 0);
- PythonTuple remoteAddress = EndPointToTuple((IPEndPoint)remoteEP);
- return PythonTuple.MakeTuple(bytesRead, remoteAddress);
- }
- [Documentation("recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\n"
- + "Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info.\n"
- )]
- public PythonTuple recvfrom_into(MemoryView buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags){
-
- int bytesRead;
- byte[] byteBuffer = buffer.tobytes().ToByteArray();
- IPEndPoint remoteIPEP = new IPEndPoint(IPAddress.Any, 0);
- EndPoint remoteEP = remoteIPEP;
- try {
- bytesRead = _socket.ReceiveFrom(byteBuffer, (SocketFlags)flags, ref remoteEP);
- }
- catch (Exception e) {
- throw MakeRecvException(e, SocketError.InvalidArgument);
- }
- buffer[new Slice(0, bytesRead)] = byteBuffer.Slice(new Slice(0, bytesRead));
- PythonTuple remoteAddress = EndPointToTuple((IPEndPoint)remoteEP);
- return PythonTuple.MakeTuple(bytesRead, remoteAddress);
- }
- [Documentation("recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\n"
- + "Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info.\n"
- )]
- public PythonTuple recvfrom_into(IList<byte> buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- int bytesRead;
- byte[] byteBuffer = new byte[byteBufferSize("recvfrom_into", nbytes, buffer.Count, 1)];
- IPEndPoint remoteIPEP = new IPEndPoint(IPAddress.Any, 0);
- EndPoint remoteEP = remoteIPEP;
- try {
- bytesRead = _socket.ReceiveFrom(byteBuffer, (SocketFlags)flags, ref remoteEP);
- } catch (Exception e) {
- throw MakeRecvException(e, SocketError.InvalidArgument);
- }
- for (int i = 0; i < byteBuffer.Length; i++) {
- buffer[i] = byteBuffer[i];
- }
- PythonTuple remoteAddress = EndPointToTuple((IPEndPoint)remoteEP);
- return PythonTuple.MakeTuple(bytesRead, remoteAddress);
- }
- public PythonTuple recvfrom_into(object buffer, [DefaultParameterValue(0)]int nbytes, [DefaultParameterValue(0)]int flags) {
- throw PythonOps.TypeError(string.Format("recvfrom_into() argument 1 must be read-write buffer, not {0}", PythonOps.GetPythonTypeName(buffer)));
- }
- private static int byteBufferSize(string funcName, int nbytes, int bufLength, int itemSize) {
- if (nbytes < 0) {
- throw PythonOps.ValueError("negative buffersize in " + funcName);
- } else if (nbytes == 0) {
- return bufLength * itemSize;
- } else {
- int remainder = nbytes % itemSize;
- return Math.Min(remainder == 0 ? nbytes : nbytes + itemSize - remainder,
- bufLength * itemSize);
- }
- }
- private Exception MakeRecvException(Exception e, SocketError errorCode = SocketError.InvalidArgument) {
- // on the socket recv throw a special socket error code when SendTimeout is zero
- if (_socket.SendTimeout == 0) {
- var s = new SocketException((int)errorCode);
- return PythonExceptions.CreateThrowable(error(_context), (int)SocketError.InvalidArgument, s.Message);
- }
- else
- return MakeException(_context, e);
- }
- [Documentation("send(string[, flags]) -> bytes_sent\n\n"
- + "Send data to the remote socket. The socket must be connected to a remote\n"
- + "socket (by calling either connect() or accept(). Returns the number of bytes\n"
- + "sent to the remote socket.\n"
- + "\n"
- + "Note that the successful completion of a send() call does not mean that all of\n"
- + "the data was sent. The caller must keep track of the number of bytes sent and\n"
- + "retry the operation until all of the data has been sent.\n"
- + "\n"
- + "Also note that there is no guarantee that the data you send will appear on the\n"
- + "network immediately. To increase network efficiency, the underlying system may\n"
- + "delay transmission until a significant amount of outgoing data is collected. A\n"
- + "successful completion of the Send method means that the underlying system has\n"
- + "had room to buffer your data for a network send"
- )]
- public int send(string data, [DefaultParameterValue(0)] int flags) {
- byte[] buffer = data.MakeByteArray();
- try {
- return _socket.Send(buffer, (SocketFlags)flags);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("send(string[, flags]) -> bytes_sent\n\n"
- + "Send data to the remote socket. The socket must be connected to a remote\n"
- + "socket (by calling either connect() or accept(). Returns the number of bytes\n"
- + "sent to the remote socket.\n"
- + "\n"
- + "Note that the successful completion of a send() call does not mean that all of\n"
- + "the data was sent. The caller must keep track of the number of bytes sent and\n"
- + "retry the operation until all of the data has been sent.\n"
- + "\n"
- + "Also note that there is no guarantee that the data you send will appear on the\n"
- + "network immediately. To increase network efficiency, the underlying system may\n"
- + "delay transmission until a significant amount of outgoing data is collected. A\n"
- + "successful completion of the Send method means that the underlying system has\n"
- + "had room to buffer your data for a network send"
- )]
- public int send(Bytes data, [DefaultParameterValue(0)] int flags) {
- byte[] buffer = data.GetUnsafeByteArray();
- try {
- return _socket.Send(buffer, (SocketFlags)flags);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("send(string[, flags]) -> bytes_sent\n\n"
- + "Send data to the remote socket. The socket must be connected to a remote\n"
- + "socket (by calling either connect() or accept(). Returns the number of bytes\n"
- + "sent to the remote socket.\n"
- + "\n"
- + "Note that the successful completion of a send() call does not mean that all of\n"
- + "the data was sent. The caller must keep track of the number of bytes sent and\n"
- + "retry the operation until all of the data has been sent.\n"
- + "\n"
- + "Also note that there is no guarantee that the data you send will appear on the\n"
- + "network immediately. To increase network efficiency, the underlying system may\n"
- + "delay transmission until a significant amount of outgoing data is collected. A\n"
- + "successful completion of the Send method means that the underlying system has\n"
- + "had room to buffer your data for a network send"
- )]
- public int send(PythonBuffer data, [DefaultParameterValue(0)] int flags) {
- byte[] buffer = data.byteCache;
- try {
- return _socket.Send(buffer, (SocketFlags)flags);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("sendall(string[, flags]) -> None\n\n"
- + "Send data to the remote socket. The socket must be connected to a remote\n"
- + "socket (by calling either connect() or accept().\n"
- + "\n"
- + "Unlike send(), sendall() blocks until all of the data has been sent or until a\n"
- + "timeout or an error occurs. None is returned on success. If an error occurs,\n"
- + "there is no way to tell how much data, if any, was sent.\n"
- + "\n"
- + "Difference from CPython: timeouts do not function as you would expect. The\n"
- + "function is implemented using multiple calls to send(), so the timeout timer\n"
- + "is reset after each of those calls. That means that the upper bound on the\n"
- + "time that it will take for sendall() to return is the number of bytes in\n"
- + "string times the timeout interval.\n"
- + "\n"
- + "Also note that there is no guarantee that the data you send will appear on the\n"
- + "network immediately. To increase network efficiency, the underlying system may\n"
- + "delay transmission until a significant amount of outgoing data is collected. A\n"
- + "successful completion of the Send method means that the underlying system has\n"
- + "had room to buffer your data for a network send"
- )]
- public void sendall(string data, [DefaultParameterValue(0)] int flags) {
- sendallWorker(data.MakeByteArray(), flags);
- }
- [Documentation("sendall(string[, flags]) -> None\n\n"
- + "Send data to the remote socket. The socket must be connected to a remote\n"
- + "socket (by calling either connect() or accept().\n"
- + "\n"
- + "Unlike send(), sendall() blocks until all of the data has been sent or until a\n"
- + "timeout or an error occurs. None is returned on success. If an error occurs,\n"
- + "there is no way to tell how much data, if any, was sent.\n"
- + "\n"
- + "Difference from CPython: timeouts do not function as you would expect. The\n"
- + "function is implemented using multiple calls to send(), so the timeout timer\n"
- + "is reset after each of those calls. That means that the upper bound on the\n"
- + "time that it will take for sendall() to return is the number of bytes in\n"
- + "string times the timeout interval.\n"
- + "\n"
- + "Also note that there is no guarantee that the data you send will appear on the\n"
- + "network immediately. To increase network efficiency, the underlying system may\n"
- + "delay transmission until a significant amount of outgoing data is collected. A\n"
- + "successful completion of the Send method means that the underlying system has\n"
- + "had room to buffer your data for a network send"
- )]
- public void sendall(Bytes data, [DefaultParameterValue(0)] int flags) {
- sendallWorker(data.GetUnsafeByteArray(), flags);
- }
- [Documentation("sendall(string[, flags]) -> None\n\n"
- + "Send data to the remote socket. The socket must be connected to a remote\n"
- + "socket (by calling either connect() or accept().\n"
- + "\n"
- + "Unlike send(), sendall() blocks until all of the data has been sent or until a\n"
- + "timeout or an error occurs. None is returned on success. If an error occurs,\n"
- + "there is no way to tell how much data, if any, was sent.\n"
- + "\n"
- + "Difference from CPython: timeouts do not function as you would expect. The\n"
- + "function is implemented using multiple calls to send(), so the timeout timer\n"
- + "is reset after each of those calls. That means that the upper bound on the\n"
- + "time that it will take for sendall() to return is the number of bytes in\n"
- + "string times the timeout interval.\n"
- + "\n"
- + "Also note that there is no guarantee that the data you send will appear on the\n"
- + "network immediately. To increase network efficiency, the underlying system may\n"
- + "delay transmission until a significant amount of outgoing data is collected. A\n"
- + "successful completion of the Send method means that the underlying system has\n"
- + "had room to buffer your data for a network send"
- )]
- public void sendall(PythonBuffer data, [DefaultParameterValue(0)] int flags) {
- sendallWorker(data.byteCache, flags);
- }
- private void sendallWorker(byte[] buffer, int flags) {
- try {
- int bytesTotal = buffer.Length;
- int bytesRemaining = bytesTotal;
- while (bytesRemaining > 0) {
- bytesRemaining -= _socket.Send(buffer, bytesTotal - bytesRemaining, bytesRemaining, (SocketFlags)flags);
- }
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("sendto(string[, flags], address) -> bytes_sent\n\n"
- + "Send data to the remote socket. The socket does not need to be connected to a\n"
- + "remote socket since the address is specified in the call to sendto(). Returns\n"
- + "the number of bytes sent to the remote socket.\n"
- + "\n"
- + "Blocking sockets will block until the all of the bytes in the buffer are sent.\n"
- + "Since a nonblocking Socket completes immediately, it might not send all of the\n"
- + "bytes in the buffer. It is your application's responsibility to keep track of\n"
- + "the number of bytes sent and to retry the operation until the application sends\n"
- + "all of the bytes in the buffer.\n"
- + "\n"
- + "Note that there is no guarantee that the data you send will appear on the\n"
- + "network immediately. To increase network efficiency, the underlying system may\n"
- + "delay transmission until a significant amount of outgoing data is collected. A\n"
- + "successful completion of the Send method means that the underlying system has\n"
- + "had room to buffer your data for a network send"
- )]
- public int sendto(string data, int flags, PythonTuple address) {
- byte[] buffer = data.MakeByteArray();
- EndPoint remoteEP = TupleToEndPoint(_context, address, _socket.AddressFamily, out _hostName);
- try {
- return _socket.SendTo(buffer, (SocketFlags)flags, remoteEP);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("sendto(string[, flags], address) -> bytes_sent\n\n"
- + "Send data to the remote socket. The socket does not need to be connected to a\n"
- + "remote socket since the address is specified in the call to sendto(). Returns\n"
- + "the number of bytes sent to the remote socket.\n"
- + "\n"
- + "Blocking sockets will block until the all of the bytes in the buffer are sent.\n"
- + "Since a nonblocking Socket completes immediately, it might not send all of the\n"
- + "bytes in the buffer. It is your application's responsibility to keep track of\n"
- + "the number of bytes sent and to retry the operation until the application sends\n"
- + "all of the bytes in the buffer.\n"
- + "\n"
- + "Note that there is no guarantee that the data you send will appear on the\n"
- + "network immediately. To increase network efficiency, the underlying system may\n"
- + "delay transmission until a significant amount of outgoing data is collected. A\n"
- + "successful completion of the Send method means that the underlying system has\n"
- + "had room to buffer your data for a network send"
- )]
- public int sendto(Bytes data, int flags, PythonTuple address) {
- byte[] buffer = data.GetUnsafeByteArray();
- EndPoint remoteEP = TupleToEndPoint(_context, address, _socket.AddressFamily, out _hostName);
- try {
- return _socket.SendTo(buffer, (SocketFlags)flags, remoteEP);
- } catch (Exception e) {
- throw MakeException(_context, e);
- }
- }
- [Documentation("")]
- public int sendto(string data, PythonTuple address) {
- return sendto(data, 0, address);
- }
- [Documentation("")]
- public int sendto(Bytes data, PythonTuple address) {
- return sendto(data, 0, address);
- }
- [Documentation("setblocking(flag) -> None\n\n"
- + "Set the blocking mode of the socket. If flag is 0, the socket will be set to\n"
- + "non-blocking mode; otherwise, it will be set to blocking mode. If the socket is\n"
- + "in blocking mode, and a method is called (such as send() or recv() which does\n"
- + "not complete immediately, the caller will block execution until the requested\n"
- + "operation completes. In non-blocking mode, a socket.timeout exception would\n"
- + "would be raised in this case.\n"
- + "\n"
- + "Note that changing blocking mode also affects the timeout setting:\n"
- + "setblocking(0) is equivalent to settimeout(0), and setblocking(1) is equivalent\n"
- + "to settimeout(None)."
- )]
- public void setblocking(int shouldBlock) {
- if (shouldBlock == 0) {
- settimeout(0);
- } else {
- settimeo…
Large files files are truncated, but you can click here to view the full file