<commit_before># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2013 IBM Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This represents the low layer message framing portion of IPMI

import atexit
import collections
import fcntl
import hashlib
import hmac
import os
import random
import select
import socket
import struct
import threading

from Crypto.Cipher import AES

import pyghmi.exceptions as exc
from pyghmi.ipmi.private import constants


initialtimeout = 0.5  # minimum timeout for first packet to retry in any given
                     # session.  This will be randomized to stagger out retries
                     # in case of congestion
iothread = None  # the thread in which all IO will be performed
                 # While the model as-is works fine for it's own coroutine
                 # structure, when combined with threading or something like
                 # eventlet, it becomes difficult for the calling code to cope
                 # This thread will tuck away the threading situation such that
                 # calling code doesn't have to do any gymnastics to cope with
                 # the nature of things.
ioqueue = collections.deque([])
selectbreak = None
selectdeadline = 0
running = True
iosockets = []  # set of iosockets that will be shared amongst Session objects


def _ioworker(initialized):
    global selectbreak
    global selectdeadline
    selectbreak = os.pipe()
    fcntl.fcntl(selectbreak[0], fcntl.F_SETFL, os.O_NONBLOCK)
    iosockets.append(selectbreak[0])
    iowaiters = []
    timeout = 300
    initialized.set()
    while running:
        if timeout < 0:
            timeout = 0
        selectdeadline = _monotonic_time() + timeout
        tmplist, _, _ = select.select(iosockets, (), (), timeout)
        # pessimistically move out the deadline
        # doing it this early (before ioqueue is evaluated)
        # this avoids other threads making a bad assumption
        # about not having to break into the select
        selectdeadline = _monotonic_time() + 300
        rdylist = []
        for handle in tmplist:
            if handle is selectbreak[0]:
                try:  # flush all requests to interrupt that may be pending
                    while True:
                        os.read(handle, 1)
                except OSError:
                    # this means an EWOULDBLOCK occurred, ignore that as that
                    # was the endgame
                    pass
            else:
                rdylist.append(handle)
        for w in iowaiters:
            w[2].append(tuple(rdylist))
            w[3].set()
        iowaiters = []
        timeout = 300
        while ioqueue:
            workitem = ioqueue.popleft()
            # structure is function, args, list to append to ,event to set
            if isinstance(workitem[1], tuple):  # positional arguments
                workitem[2].append(workitem[0](*workitem[1]))
                workitem[3].set()
            elif isinstance(workitem[1], dict):
                workitem[2].append(workitem[0](**workitem[1]))
                workitem[3].set()
            elif workitem[0] == 'wait':
                if len(rdylist) > 0:
                    workitem[2].append(tuple(rdylist))
                    workitem[3].set()
                else:
                    ltimeout = workitem[1] - _monotonic_time()
                    if ltimeout < timeout:
                        timeout = ltimeout
                    iowaiters.append(workitem)


def _io_apply(function, args):
    global selectbreak
    evt = threading.Event()
    result = []
    ioqueue.append((function, args, result, evt))
    if not (function == 'wait' and selectdeadline < args):
        os.write(selectbreak[1], '1')
    evt.wait()
    return result[0]


selectdeadline = 0
selectwait = None


def _io_sendto(mysocket, packet, sockaddr):
    #Want sendto to act reasonably sane..
    mysocket.setblocking(1)
    mysocket.sendto(packet, sockaddr)


def _io_recvfrom(mysocket, size):
    mysocket.setblocking(0)
    try:
        return mysocket.recvfrom(size)
    except socket.error:
        return None


def _monotonic_time():
    """Provides a monotonic timer

    This code is concerned with relative, not absolute time.
    This function facilitates that prior to python 3.3
    """
    # Python does not provide one until 3.3, so we make do
    # for most OSes, os.times()[4] works well.
    # for microsoft, GetTickCount64
    return os.times()[4]


def _poller(readhandles, timeout=0):
    rdylist = _io_apply('wait', timeout + _monotonic_time())
    return rdylist


def _aespad(data):
    """ipmi demands a certain pad scheme,
    per table 13-20 AES-CBC encrypted payload fields.
    """
    newdata = list(data)
    currlen = len(data) + 1  # need to count the pad length field as well
    neededpad = currlen % 16
    if neededpad:  # if it happens to be zero, hurray, but otherwise invert the
                  # sense of the padding
        neededpad = 16 - neededpad
    padval = 1
    while padval <= neededpad:
        newdata.append(padval)
        padval += 1
    newdata.append(neededpad)
    return newdata


def get_ipmi_error(response, suffix=""):
    if 'error' in response:
        return response['error'] + suffix
    code = response['code']
    if code == 0:
        return False
    command = response['command']
    netfn = response['netfn']
    if ((netfn, command) in constants.command_completion_codes
            and code in constants.command_completion_codes[(netfn, command)]):
        res = constants.command_completion_codes[(netfn, command)][code]
        res += suffix
    elif code in constants.ipmi_completion_codes:
        res = constants.ipmi_completion_codes[code] + suffix
    else:
        res = "Unknown code 0x%2x encountered" % code
    return res


class Session(object):
    """A class to manage common IPMI session logistics

    Almost all developers should not worry about this class and instead be
    looking toward ipmi.Command and ipmi.Console.

    For those that do have to worry, the main interesting thing is that the
    event loop can go one of two ways.  Either a larger manager can query using
    class methods
    the soonest timeout deadline and the filehandles to poll and assume
    responsibility for the polling, or it can register filehandles to be
    watched.  This is primarily of interest to Console class, which may have an
    input filehandle to watch and can pass it to Session.

    :param bmc: hostname or ip address of the BMC
    :param userid: username to use to connect
    :param password: password to connect to the BMC
    :param kg: optional parameter if BMC requires Kg be set
    :param port: UDP port to communicate with, pretty much always 623
    :param onlogon: callback to receive notification of login completion
    """
    bmc_handlers = {}
    waiting_sessions = {}
    keepalive_sessions = {}
    peeraddr_to_nodes = {}
    iterwaiters = []
    # Upon exit of python, make sure we play nice with BMCs by assuring closed
    # sessions for all that we tracked

    @classmethod
    def _cleanup(cls):
        global running
        for session in cls.bmc_handlers.itervalues():
            session.cleaningup = True
            session.logout()
        running = False

    @classmethod
    def _createsocket(cls):
        global iowork
        global iothread
        global iosockets
        if iothread is None:
            initevt = threading.Event()
            iothread = threading.Thread(target=_ioworker, args=(initevt,))
            iothread.daemon = True
            iothread.start()
            initevt.wait()
        atexit.register(cls._cleanup)
        cls.socket = _io_apply(socket.socket,
                               (socket.AF_INET6, socket.SOCK_DGRAM))  # INET6
                                    # can do IPv4 if you are nice to it
        try:  # we will try to fixup our receive buffer size if we are smaller
             # than allowed.
            maxmf = open("/proc/sys/net/core/rmem_max")
            rmemmax = int(maxmf.read())
            rmemmax = rmemmax / 2
            curmax = cls.socket.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
            curmax = curmax / 2
            if (rmemmax > curmax):
                _io_apply(cls.socket.setsockopt, (socket.SOL_SOCKET,
                                                  socket.SO_RCVBUF,
                                                  rmemmax))
        except Exception:
            # FIXME: be more selective in catching exceptions
            pass

        curmax = _io_apply(cls.socket.getsockopt,
                           (socket.SOL_SOCKET, socket.SO_RCVBUF))
        iosockets.append(cls.socket)
        curmax = curmax / 2
        # we throttle such that we never have no more outstanding packets than
        # our receive buffer should be able to handle
        cls.pending = 0
        cls.maxpending = curmax / 1000
        # pessimistically assume 1 kilobyte messages,<commit_msg>Fix mass thread initialization of sessions<commit_after># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2013 IBM Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This represents the low layer message framing portion of IPMI

import atexit
import collections
import fcntl
import hashlib
import hmac
import os
import random
import select
import socket
import struct
import threading

from Crypto.Cipher import AES

import pyghmi.exceptions as exc
from pyghmi.ipmi.private import constants


initialtimeout = 0.5  # minimum timeout for first packet to retry in any given
                     # session.  This will be randomized to stagger out retries
                     # in case of congestion
iothread = None  # the thread in which all IO will be performed
                 # While the model as-is works fine for it's own coroutine
                 # structure, when combined with threading or something like
                 # eventlet, it becomes difficult for the calling code to cope
                 # This thread will tuck away the threading situation such that
                 # calling code doesn't have to do any gymnastics to cope with
                 # the nature of things.
iothreadready = False  # whether io thread is yet ready to work
iothreadwaiters = []  # threads waiting for iothreadready
ioqueue = collections.deque([])
selectbreak = None
selectdeadline = 0
running = True
iosockets = []  # set of iosockets that will be shared amongst Session objects


def _ioworker():
    global iothreadready
    global selectbreak
    global selectdeadline
    selectbreak = os.pipe()
    fcntl.fcntl(selectbreak[0], fcntl.F_SETFL, os.O_NONBLOCK)
    iosockets.append(selectbreak[0])
    iowaiters = []
    timeout = 300
    iothreadready = True
    while running:
        while iothreadwaiters:
            waiter = iothreadwaiters.pop()
            waiter.set()
        if timeout < 0:
            timeout = 0
        selectdeadline = _monotonic_time() + timeout
        tmplist, _, _ = select.select(iosockets, (), (), timeout)
        # pessimistically move out the deadline
        # doing it this early (before ioqueue is evaluated)
        # this avoids other threads making a bad assumption
        # about not having to break into the select
        selectdeadline = _monotonic_time() + 300
        rdylist = []
        for handle in tmplist:
            if handle is selectbreak[0]:
                try:  # flush all requests to interrupt that may be pending
                    while True:
                        os.read(handle, 1)
                except OSError:
                    # this means an EWOULDBLOCK occurred, ignore that as that
                    # was the endgame
                    pass
            else:
                rdylist.append(handle)
        for w in iowaiters:
            w[2].append(tuple(rdylist))
            w[3].set()
        iowaiters = []
        timeout = 300
        while ioqueue:
            workitem = ioqueue.popleft()
            # structure is function, args, list to append to ,event to set
            if isinstance(workitem[1], tuple):  # positional arguments
                workitem[2].append(workitem[0](*workitem[1]))
                workitem[3].set()
            elif isinstance(workitem[1], dict):
                workitem[2].append(workitem[0](**workitem[1]))
                workitem[3].set()
            elif workitem[0] == 'wait':
                if len(rdylist) > 0:
                    workitem[2].append(tuple(rdylist))
                    workitem[3].set()
                else:
                    ltimeout = workitem[1] - _monotonic_time()
                    if ltimeout < timeout:
                        timeout = ltimeout
                    iowaiters.append(workitem)


def _io_apply(function, args):
    global selectbreak
    evt = threading.Event()
    result = []
    ioqueue.append((function, args, result, evt))
    if not (function == 'wait' and selectdeadline < args):
        os.write(selectbreak[1], '1')
    evt.wait()
    return result[0]


selectdeadline = 0
selectwait = None


def _io_sendto(mysocket, packet, sockaddr):
    #Want sendto to act reasonably sane..
    mysocket.setblocking(1)
    mysocket.sendto(packet, sockaddr)


def _io_recvfrom(mysocket, size):
    mysocket.setblocking(0)
    try:
        return mysocket.recvfrom(size)
    except socket.error:
        return None


def _monotonic_time():
    """Provides a monotonic timer

    This code is concerned with relative, not absolute time.
    This function facilitates that prior to python 3.3
    """
    # Python does not provide one until 3.3, so we make do
    # for most OSes, os.times()[4] works well.
    # for microsoft, GetTickCount64
    return os.times()[4]


def _poller(readhandles, timeout=0):
    rdylist = _io_apply('wait', timeout + _monotonic_time())
    return rdylist


def _aespad(data):
    """ipmi demands a certain pad scheme,
    per table 13-20 AES-CBC encrypted payload fields.
    """
    newdata = list(data)
    currlen = len(data) + 1  # need to count the pad length field as well
    neededpad = currlen % 16
    if neededpad:  # if it happens to be zero, hurray, but otherwise invert the
                  # sense of the padding
        neededpad = 16 - neededpad
    padval = 1
    while padval <= neededpad:
        newdata.append(padval)
        padval += 1
    newdata.append(neededpad)
    return newdata


def get_ipmi_error(response, suffix=""):
    if 'error' in response:
        return response['error'] + suffix
    code = response['code']
    if code == 0:
        return False
    command = response['command']
    netfn = response['netfn']
    if ((netfn, command) in constants.command_completion_codes
            and code in constants.command_completion_codes[(netfn, command)]):
        res = constants.command_completion_codes[(netfn, command)][code]
        res += suffix
    elif code in constants.ipmi_completion_codes:
        res = constants.ipmi_completion_codes[code] + suffix
    else:
        res = "Unknown code 0x%2x encountered" % code
    return res


class Session(object):
    """A class to manage common IPMI session logistics

    Almost all developers should not worry about this class and instead be
    looking toward ipmi.Command and ipmi.Console.

    For those that do have to worry, the main interesting thing is that the
    event loop can go one of two ways.  Either a larger manager can query using
    class methods
    the soonest timeout deadline and the filehandles to poll and assume
    responsibility for the polling, or it can register filehandles to be
    watched.  This is primarily of interest to Console class, which may have an
    input filehandle to watch and can pass it to Session.

    :param bmc: hostname or ip address of the BMC
    :param userid: username to use to connect
    :param password: password to connect to the BMC
    :param kg: optional parameter if BMC requires Kg be set
    :param port: UDP port to communicate with, pretty much always 623
    :param onlogon: callback to receive notification of login completion
    """
    bmc_handlers = {}
    waiting_sessions = {}
    keepalive_sessions = {}
    peeraddr_to_nodes = {}
    iterwaiters = []
    # Upon exit of python, make sure we play nice with BMCs by assuring closed
    # sessions for all that we tracked

    @classmethod
    def _cleanup(cls):
        global running
        for session in cls.bmc_handlers.itervalues():
            session.cleaningup = True
            session.logout()
        running = False

    @classmethod
    def _createsocket(cls):
        global iowork
        global iothread
        global iothreadready
        global iosockets
        if iothread is None:
            initevt = threading.Event()
            iothreadwaiters.append(initevt)
            iothread = threading.Thread(target=_ioworker)
            iothread.daemon = True
            iothread.start()
            initevt.wait()
        elif not iothreadready:
            initevt = threading.Event()
            iothreadwaiters.append(initevt)
            initevt.wait()
        atexit.register(cls._cleanup)
        cls.socket = _io_apply(socket.socket,
                               (socket.AF_INET6, socket.SOCK_DGRAM))  # INET6
                                    # can do IPv4 if you are nice to it
        try:  # we will try to fixup our receive buffer size if we are smaller
             # than allowed.
            maxmf = open("/proc/sys/net/core/rmem_max")
            rmemmax = int(maxmf.read())
            rmemmax = rmemmax / 2
            curmax = cls.socket.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)
            curmax = curmax / 2
            if (rmemmax > curmax):
                _io_apply(cls.socket.setsockopt, (socket.SOL_SOCKET,
                                                  socket.SO_RCVBUF,
                                                  rmemmax))
        except Exception:
            # FIXME: be more selective in catching exceptions
            pass

        curmax = _io_apply(cls.socket.getsockopt,
                           (socket.SOL_SOCKET, socket.SO_RCVBUF))
        iosockets.append(cls.socket)
        curmax = curmax / 2
        # we throttle such that we never have no more outstanding packets than
        # our receive buffer should be able to handle
        cls.pending = 0
        cls.maxpending = curmax / 1000
        # pessimistically assume 1 kilobyte messages,
{'fraction_non_alphanumeric': 0.07120885881267303, 'fraction_numerical': 0.009227929867733005, 'mean_word_length': 2.176518482331868, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4203432', 'n_tokens_mistral': 5476, 'n_tokens_neox': 5196, 'n_words': 1900}