<commit_before>------------------------------------------------------------------
--
--  Author: <NAME> <<EMAIL>>
--
--  Copyright (C) 2014-2016 <NAME> <<EMAIL>>
--
--  Licensed according to the included 'LICENSE' document
--
--  This file is part of lua-lluv library.
--
------------------------------------------------------------------

----------------------------------------------------------------------------
-- Implementation of LuaSocket interface.
--
-- Known wont fix problem:
--  - send does not return number of sended bytes
--  - send may not detects closed socket
--  - send do not wait until large data will be sended
----------------------------------------------------------------------------

local trace -- = function(...) print(os.date("[LLS][%x %X]"), ...) end

local uv = require "lluv"
local ut = require "lluv.utils"

local function _check_resume(status, ...)
  if not status then return error(..., 3) end
  return ...
end

local function co_resume(...)
  return _check_resume(coroutine.resume(...))
end

local function CoGetAddrInfo(co, host, port)
  local terminated = false

  uv.getaddrinfo(host, port, {
    family   = "inet";
    socktype = "stream";
    protocol = "tcp";
  }, function(_, err, res)
    if terminated then return end

    if err then co_resume(co, nil, err)
    else co_resume(co, res) end
  end)

  local ok, err = coroutine.yield()
  terminated = true

  return ok, err 
end

local EOF = uv.error(uv.ERROR_UV, uv.EOF)

----------------------------------------------------------------------------
local BaseSock = ut.class() do

function BaseSock:__init()
  self._co    = assert(coroutine.running())

  self._timer = assert(uv.timer():start(1000, function(tm)
    tm:stop()
    self:_resume(nil, "timeout")
  end):stop())

  self._wait = {
    read   = false;
    write  = false;
  }

  self._err = "closed"

  return self
end

function BaseSock:_resume(...)
  return co_resume(self._co, ...)
end

function BaseSock:_yield(...)
  return coroutine.yield(...)
end

function BaseSock:_unset_wait()
  for k in pairs(self._wait) do self._wait[k] = false end
end

function BaseSock:_waiting(op)
  if op then
    assert(nil ~= self._wait[op])
    return not not self._wait[op]
  end

  for k, v in pairs(self._wait) do
    if v then return true end
  end
end

function BaseSock:_start(op)
  if self._timeout then
    self._timer:again(self._timeout * 1000)
  end

  assert(not self:_waiting())

  assert(self._wait[op] == false, op)
  self._wait[op] = true
end

function BaseSock:_stop(op)
  if self._timer then
    self._timer:stop()
  end
  self:_unset_wait(op)
end

function BaseSock:_on_io_error(err)
  if trace then trace("BaseSock:_on_io_error", err, self:_waiting()) end

  -- This function can be called to closed socket in case when
  -- * we start write operation but write callback not called yet
  -- * in this time we recv error in read operation
  --   read callback invoke `_on_io_error` which set `_sock` to nil
  -- * after that libuv invoke write callback with ECONNRESET error
  --   and write callback call _on_io_error again
  if not self._sock then return end

  if err then
    self._raw_err, err = err, "closed"
    self._err = err
  end

  self._sock:stop_read()
  self._sock:close(function()
    if trace then trace("BaseSock:_on_io_error:close", self:_waiting()) end
    if self:_waiting() then
      self:_resume(nil, err)
    end
  end)

  self._timer:close()
  self._sock, self._timer = nil
end

function BaseSock:attach(co)
  assert(not self:_waiting())
  self._co = co or coroutine.running()
  return self
end

function BaseSock:interrupt(...)
  if self._co and self:_waiting() and self._co ~= coroutine.running() then
    self:_resume(nil, ...)
  end
end

function BaseSock:settimeout(sec)
  if sec and (sec <= 0) then sec = nil end
  self._timeout = tonumber(sec)
  return self
end

function BaseSock:setoption()
  return nil, "NYI"
end

function BaseSock:getsockname()
  if not self._sock then return nil, self._err end

  return self._sock:getsockname()
end

function BaseSock:getfd()
  if not self._sock then return -1 end
  return self._sock:fileno()
end

function BaseSock:socket()
  return self._sock
end
<commit_msg>Add. `getpeername` function to LuaSocket module<commit_after>------------------------------------------------------------------
--
--  Author: <NAME> <<EMAIL>>
--
--  Copyright (C) 2014-2016 <NAME> <<EMAIL>>
--
--  Licensed according to the included 'LICENSE' document
--
--  This file is part of lua-lluv library.
--
------------------------------------------------------------------

----------------------------------------------------------------------------
-- Implementation of LuaSocket interface.
--
-- Known wont fix problem:
--  - send does not return number of sended bytes
--  - send may not detects closed socket
--  - send do not wait until large data will be sended
----------------------------------------------------------------------------

local trace -- = function(...) print(os.date("[LLS][%x %X]"), ...) end

local uv = require "lluv"
local ut = require "lluv.utils"

local function _check_resume(status, ...)
  if not status then return error(..., 3) end
  return ...
end

local function co_resume(...)
  return _check_resume(coroutine.resume(...))
end

local function CoGetAddrInfo(co, host, port)
  local terminated = false

  uv.getaddrinfo(host, port, {
    family   = "inet";
    socktype = "stream";
    protocol = "tcp";
  }, function(_, err, res)
    if terminated then return end

    if err then co_resume(co, nil, err)
    else co_resume(co, res) end
  end)

  local ok, err = coroutine.yield()
  terminated = true

  return ok, err 
end

local EOF = uv.error(uv.ERROR_UV, uv.EOF)

----------------------------------------------------------------------------
local BaseSock = ut.class() do

function BaseSock:__init()
  self._co    = assert(coroutine.running())

  self._timer = assert(uv.timer():start(1000, function(tm)
    tm:stop()
    self:_resume(nil, "timeout")
  end):stop())

  self._wait = {
    read   = false;
    write  = false;
  }

  self._err = "closed"

  return self
end

function BaseSock:_resume(...)
  return co_resume(self._co, ...)
end

function BaseSock:_yield(...)
  return coroutine.yield(...)
end

function BaseSock:_unset_wait()
  for k in pairs(self._wait) do self._wait[k] = false end
end

function BaseSock:_waiting(op)
  if op then
    assert(nil ~= self._wait[op])
    return not not self._wait[op]
  end

  for k, v in pairs(self._wait) do
    if v then return true end
  end
end

function BaseSock:_start(op)
  if self._timeout then
    self._timer:again(self._timeout * 1000)
  end

  assert(not self:_waiting())

  assert(self._wait[op] == false, op)
  self._wait[op] = true
end

function BaseSock:_stop(op)
  if self._timer then
    self._timer:stop()
  end
  self:_unset_wait(op)
end

function BaseSock:_on_io_error(err)
  if trace then trace("BaseSock:_on_io_error", err, self:_waiting()) end

  -- This function can be called to closed socket in case when
  -- * we start write operation but write callback not called yet
  -- * in this time we recv error in read operation
  --   read callback invoke `_on_io_error` which set `_sock` to nil
  -- * after that libuv invoke write callback with ECONNRESET error
  --   and write callback call _on_io_error again
  if not self._sock then return end

  if err then
    self._raw_err, err = err, "closed"
    self._err = err
  end

  self._sock:stop_read()
  self._sock:close(function()
    if trace then trace("BaseSock:_on_io_error:close", self:_waiting()) end
    if self:_waiting() then
      self:_resume(nil, err)
    end
  end)

  self._timer:close()
  self._sock, self._timer = nil
end

function BaseSock:attach(co)
  assert(not self:_waiting())
  self._co = co or coroutine.running()
  return self
end

function BaseSock:interrupt(...)
  if self._co and self:_waiting() and self._co ~= coroutine.running() then
    self:_resume(nil, ...)
  end
end

function BaseSock:settimeout(sec)
  if sec and (sec <= 0) then sec = nil end
  self._timeout = tonumber(sec)
  return self
end

function BaseSock:setoption()
  return nil, "NYI"
end

function BaseSock:getsockname()
  if not self._sock then return nil, self._err end

  return self._sock:getsockname()
end

function BaseSock:getpeername()
  if not self._sock then return nil, self._err end

  return self._sock:getpeername()
end

function BaseSock:getfd()
  if not self._sock then return -1 end
  return self._sock:fileno()
end

function BaseSock:socket()
  return self._sock
end

{'fraction_non_alphanumeric': 0.1936426317634685, 'fraction_numerical': 0.00444080869463597, 'mean_word_length': 2.381272224417226, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5599953', 'n_tokens_mistral': 2731, 'n_tokens_neox': 2634, 'n_words': 836}