Source code for fatbotslim.irc.tcp

# -*- coding: utf-8 -*-
#
# This file is part of FatBotSlim.
#
# FatBotSlim is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# FatBotSlim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with FatBotSlim. If not, see <http://www.gnu.org/licenses/>.
#
"""
.. module:: fatbotslim.irc.tcp

.. moduleauthor:: Mathieu D. (MatToufoutu)

This module contains the low-level networking stuff.
"""

from fatbotslim.irc import sslwrap_patch

from gevent import spawn, joinall, killall
from gevent.queue import Queue
from gevent.socket import socket
from gevent.ssl import wrap_socket

from fatbotslim.log import create_logger


log = create_logger(__name__)


[docs]class TCP(object): """ A TCP connection. """ def __init__(self, host, port, timeout=300): """ :param host: server's hostname :type host: str :param port: server's port :type port: int :param timeout: maximum time a request/response should last. :type timeout: int """ self.host = host self.port = port self.timeout = timeout self._ibuffer = '' self._obuffer = '' self.iqueue = Queue() self.oqueue = Queue() self._socket = self._create_socket() def _create_socket(self): """ Creates a new socket and sets its timeout. :return: new socket. :rtype: :class:`gevent.socket.socket` """ s = socket() s.settimeout(self.timeout) return s def _recv_loop(self): """ Waits for data forever and feeds the input queue. """ while True: try: data = self._socket.recv(4096) self._ibuffer += data while '\r\n' in self._ibuffer: line, self._ibuffer = self._ibuffer.split('\r\n', 1) self.iqueue.put(line) except Exception: break def _send_loop(self): """ Waits for data in the output queue to send. """ while True: try: line = self.oqueue.get().splitlines()[0][:500] self._obuffer += line + '\r\n' while self._obuffer: sent = self._socket.send(self._obuffer) self._obuffer = self._obuffer[sent:] except Exception: break
[docs] def connect(self): """ Connects the socket and spawns the send/receive loops. """ jobs = [] self._socket.connect((self.host, self.port)) try: jobs = [spawn(self._recv_loop), spawn(self._send_loop)] joinall(jobs) finally: killall(jobs)
[docs] def disconnect(self): """ Closes the socket. """ self._socket.close()
[docs]class SSL(TCP): """ SSL wrapper for a :class:`fatbotslim.irc.tcp.TCP` connection. """ def _create_socket(self): """ Creates a new SSL enabled socket and sets its timeout. """ log.warning('No certificate check is performed for SSL connections') s = super(SSL, self)._create_socket() return wrap_socket(s)