# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2017 Lenovo
#
# 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 handles port forwarding for web interfaces on management devices
#It will also hijack port 3900 and do best effort..

import eventlet
import eventlet.green.select as select
import eventlet.green.socket as socket
forwarders = {}
sockhandler = {}
vidtarget = None
vidforwarder = None

def handle_connection(incoming, outgoing):
    while True:
        r, _, _ = select.select((incoming, outgoing), (), (), 60)
        for mysock in r:
            data = mysock.recv(32768)
            if not data:
                return
            if mysock == incoming:
                outgoing.sendall(data)
            elif mysock == outgoing:
                incoming.sendall(data)


def forward_port(sock, target):
    while True:
        conn, _ = sock.accept()
        try:
            client = socket.create_connection((target, 443))
        except Exception:
            conn.close()
            continue
        eventlet.spawn_n(handle_connection, conn, client)


def forward_video():
    sock = eventlet.listen(('localhost', 3900, 0, 0), family=socket.AF_INET6)
    while True:
        conn, _ = sock.accept()
        if vidtarget is None:
            conn.close()
            continue
        try:
            vidclient = socket.create_connection((vidtarget, 3900))
        except Exception:
            conn.close()
            continue
        eventlet.spawn_n(handle_connection, conn, vidclient)

def get_port(addr):
    global vidtarget
    global vidforwarder
    if addr not in forwarders:
        newsock = eventlet.listen(('localhost', 0, 0, 0),
                  family=socket.AF_INET6)
        forwarders[addr] = newsock
        sockhandler[newsock] = eventlet.spawn(forward_port, newsock, addr)
        if not vidforwarder:
            vidforwarder = eventlet.spawn(forward_video)
    vidtarget = addr
    return forwarders[addr].getsockname()[1]


Add utility library to do port forwarding
Add utility library to do port forwarding

This will be useful for creating forwarding for
users.
