richard-to
4/26/2014 - 7:45 AM

Random code for a class project

Random code for a class project

import logging
import socket
import SocketServer
import sys
import time
import threading

from ftplib import FTP
from os import listdir, remove, rename, stat
from os.path import isfile, join, splitext, isfile
from random import randint

from pydub import AudioSegment


# Module Client Settings
MODULE_HOST = '255.255.255.255'
MODULE_FTP_HOST = '255.255.255.255'
MODULE_PORT = 20000
HOSTS_FILENAME = 'hosts.txt'
UPLOAD_FILENAME = 'sound.mp3'
MODULE_UPLOAD_DIR = '/upload'
MODULE_READY_DIR = '/ready'
MODULE_LOCAL_FTP_DIR = 'ftpserver/res/home'
MODULE_LOCAL_FTP_UPLOAD_DIR = ''.join([MODULE_LOCAL_FTP_DIR, MODULE_UPLOAD_DIR])
MODULE_LOCAL_FTP_READY_DIR = ''.join([MODULE_LOCAL_FTP_DIR, MODULE_READY_DIR])
SOUND_PATH = 'sounds'

SERVER_PORT = 20000
FTP_PORT = 2021
OUTPUT_FILENAME = 'output{}.mp3'
SOUND_DURATION = 2000
DELAY = 5

# General Settings
LOG_FILE = 'sb16.log'
LOG_LEVEL = logging.INFO
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'


# Setup Logger
logging.basicConfig(level=LOG_LEVEL, format=LOG_FORMAT)

logger = logging.getLogger()
file_log_handler = logging.FileHandler(LOG_FILE)
logger.addHandler(file_log_handler)

formatter = logging.Formatter(LOG_FORMAT)
file_log_handler.setFormatter(formatter)


# Shared Variables
iteration = 0
has_file = True


class FTPThread(threading.Thread):
    def __init__(self, ip, path):
        threading.Thread.__init__(self)
        self.ip = ip
        self.path = path

    def run(self):
        # Open FTP connection
        print self.ip
        print FTP_PORT
        logger.info('Connecting to FTP server at {}:{}.'.format(self.ip.strip(), FTP_PORT))
        ftp = FTP()
        ftp.connect(self.ip.strip(), FTP_PORT)
        ftp.login()

        # Send MP3 File to Client
        file_path = join(self.path, UPLOAD_FILENAME)
        ftp.storbinary('STOR ' + file_path, open(UPLOAD_FILENAME, 'rb'))
        ftp.quit()
        remove(UPLOAD_FILENAME)


class RequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        global has_file
        logger.info('Client request received from {}.'.format(self.client_address[0]))

        # TODO(richard-to): Add timeout logic
        received = self.request.recv(1024).strip()
        print received
        
        data = received.split('\n')
        if isfile(UPLOAD_FILENAME) and (len(data) == 3 or len(data) == 5):
            if len(data) == 3:
                thread = FTPThread(data[0], data[2])
            else:
                thread = FTPThread(data[1], data[3])
            thread.start()


class ClientThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.kill_received = False    

    def run(self):
        global iteration
        global has_file

        # Get the list of host computers
        logger.info('Retrieving list of hosts.')
        hosts = [line.strip() for line in open(HOSTS_FILENAME, 'r')]

        # Get the list of sounds to add to file
        logger.info('Retrieving list of sound files.')
        sounds = []
        for mp3_file in listdir(SOUND_PATH):
            if isfile(join(SOUND_PATH, mp3_file)):
                filename, ext = splitext(mp3_file)
                if ext == ".mp3":
                    sounds.append(join(SOUND_PATH, mp3_file))

        # Start Client Process
        while True:
            for host in hosts:
                if self.kill_received:
                    logger.info('Kill received. Stopping client thread.')
                    return
                    
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        
                try:
                    # Connect to next host in list
                    logger.info('Connecting to server at {}:{}.'.format(host, SERVER_PORT))                    
                    sock.settimeout(5)
                    sock.connect((host, SERVER_PORT))
                    sock.settimeout(None)

                    # Send request information to server
                    logger.info('Sending FTP info to server at {}:{}.'.format(host, SERVER_PORT))
                    request = "{}\n{}\n{}".format(MODULE_HOST, host, '/upload/')        
                    sock.send(request)

                except Exception:
                    logger.error('Could not connect to host {}:{}.'.format(host, SERVER_PORT))
                finally:
                    logger.info('Closing connection to host {}:{}.'.format(host, SERVER_PORT))
                    # Remember to close socket
                    sock.close()

                # Check for an mp3 file
                mp3_file_path = None
                for mp3_file in listdir(MODULE_LOCAL_FTP_UPLOAD_DIR):
                    if isfile(join(MODULE_LOCAL_FTP_UPLOAD_DIR, mp3_file)):
                        filename, ext = splitext(mp3_file)
                        if ext == ".mp3":
                            logger.info('Found mp3 file in upload dir: {}.'.format(mp3_file))
                            mp3_file_path = join(MODULE_LOCAL_FTP_UPLOAD_DIR, mp3_file)
                            break

                # If we have an mp3 file, process the mp3 with out modifications
                if mp3_file_path is not None:

                    file_done = False
                    prev_size = -1
                    while file_done is False:
                        statinfo = stat(mp3_file_path)
                        if statinfo.st_size == prev_size:
                            # Append random sound fragment to downloaded sound
                            rand_sound = sounds[randint(0, len(sounds) - 1)]
                            logger.info('Adding two seconds of sound from {}.'.format(rand_sound))
                            sound1 = AudioSegment.from_mp3(mp3_file_path)
                            sound2 = AudioSegment.from_mp3(rand_sound)
                            sound3 = sound2.set_frame_rate(sound1.frame_rate)
                            output = sound1 + sound3

                            # Save new sound to our FTP path
                            output_filename = OUTPUT_FILENAME.format(iteration)                                        
                            output.export(join(MODULE_LOCAL_FTP_DIR, output_filename), format="mp3", bitrate=str(output.frame_rate))
                            rename(join(MODULE_LOCAL_FTP_DIR, output_filename), UPLOAD_FILENAME)
                            output.export(join(MODULE_LOCAL_FTP_DIR, output_filename), format="mp3", bitrate=str(output.frame_rate))
                            remove(mp3_file_path)

                            logger.info('Saving new sound file as ready.'.format(UPLOAD_FILENAME))

                            # Increment iteration
                            iteration += 1                        
                            logger.info('Incrementing iteration to {}.'.format(iteration))

                            prev_size = -1
                            file_done = True
                        else:
                            prev_size = statinfo.st_size
                            time.sleep(2)

            logger.info('Finished contacting all hosts. Waiting {} seconds before trying again.'.format(DELAY))
            # Wait X seconds after connecting to all hosts
            time.sleep(DELAY)


# Start Client Thread
try:
    thread = ClientThread()
    thread.start()
except:
   sys.exit()

try:
    logger.info('Starting TCP Server on port {}'.format(MODULE_PORT))
    server = SocketServer.TCPServer((MODULE_HOST, MODULE_PORT), RequestHandler)
    server.serve_forever()
except KeyboardInterrupt:
    logger.info('Ctrl+C detected. Please wait. Shutting down client thread')
    thread.kill_received = True
import logging
import socket
import SocketServer
import sys
import time
import threading

from ftplib import FTP
from os import listdir, remove
from os.path import isfile, join, splitext
from random import randint

from pydub import AudioSegment


# Module Server Settings
MODULE_PORT = 20000
MODULE_HOST = '255.255.255.255'
MODULE_FTP_HOST = '255.255.255.255'
MODULE_FTP_DIR = 'ftpserver/res/home'
MODULE_INITIAL_FILE = 'test.mp3'
MODULE_INITIAL_HAS_FILE = False


# Module Client Settings
HOSTS_FILENAME = 'hosts.txt'
SOUND_PATH = 'sounds'
SERVER_PORT = 20000
FTP_PORT = 2121
TEMP_FILENAME = 'temp.mp3'
OUTPUT_FILENAME = 'output{}.mp3'
SOUND_DURATION = 2000
DELAY = 5


# General Settings
LOG_FILE = 'soundblaster16.log'
LOG_LEVEL = logging.INFO
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'


# Setup Logger
logging.basicConfig(level=LOG_LEVEL, format=LOG_FORMAT)

logger = logging.getLogger()
file_log_handler = logging.FileHandler(LOG_FILE)
logger.addHandler(file_log_handler)

formatter = logging.Formatter(LOG_FORMAT)
file_log_handler.setFormatter(formatter)


# Shared Variables
iteration = 0
output_filename = MODULE_INITIAL_FILE
has_file = MODULE_INITIAL_HAS_FILE


class RequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        global has_file
        logger.info('Client request received from {}.'.format(self.client_address[0]))
        if has_file:
            logger.info('Sending FTP info to client at {}.'.format(self.client_address[0]))
            response = "{}\n{}\n{}".format(MODULE_HOST, MODULE_FTP_HOST, output_filename)        
            self.request.sendall(response)
            has_file = False


class ClientThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.kill_received = False    

    def run(self):
        global iteration
        global output_filename
        global has_file

        # Get the list of host computers
        logger.info('Retrieving list of hosts.')
        hosts = [line.strip() for line in open(HOSTS_FILENAME, 'r')]

        # Get the list of sounds to add to file
        logger.info('Retrieving list of sound files.')
        sounds = []
        for mp3_file in listdir(SOUND_PATH):
            if isfile(join(SOUND_PATH, mp3_file)):
                filename, ext = splitext(mp3_file)
                if ext == ".mp3":
                    sounds.append(join(SOUND_PATH, mp3_file))


        # Start Client Process
        while True:
            for host in hosts:
                if self.kill_received:
                    logger.info('Kill received. Stopping client thread.')
                    return
                    
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        
                try:
                    # Connect to next host in list
                    logger.info('Connecting to server at {}:{}.'.format(host, SERVER_PORT))                    
                    sock.connect((host, SERVER_PORT))
                    received = sock.recv(1024)
                    data = received.split('\n')

                    # Make sure we received 3 lines of data
                    # Probably should check that data is in correct format
                    if len(data) == 3:
                        # Open FTP connection
                        logger.info('Connecting to FTP server at {}:{}.'.format(data[1], FTP_PORT))
                        ftp = FTP()
                        ftp.connect(data[1], FTP_PORT)
                        ftp.login()
                        ftp.cwd('.')

                        temp_mp3_file = open(TEMP_FILENAME, 'wb')

                        # Download the sound from FTP server
                        logger.info('Downloading {} from FTP server.'.format(data[2]))
                        ftp.retrbinary('RETR %s' % data[2], temp_mp3_file.write)
                        ftp.quit()

                        # Append random sound fragment to downloaded sound
                        rand_sound = sounds[randint(0, len(sounds) - 1)]
                        logger.info('Adding two seconds of sound from {}.'.format(rand_sound))
                        sound1 = AudioSegment.from_mp3(TEMP_FILENAME)
                        sound2 = AudioSegment.from_mp3(rand_sound)
                        sound3 = sound2.set_frame_rate(sound1.frame_rate)
                        output = sound1 + sound3[-SOUND_DURATION:]

                        output_filename = OUTPUT_FILENAME.format(iteration)
                        # Save new sound to our FTP path
                        logger.info('Saving new sound file to FTP folder as {}.'.format(output_filename))                        
                        output.export(join(MODULE_FTP_DIR, output_filename), format="mp3", bitrate=str(output.frame_rate))

                        # Clean up temp file
                        logger.info('Deleting temporary file')
                        remove(TEMP_FILENAME)

                        # Increment iteration
                        iteration += 1                        
                        logger.info('Incrementing iteration to {}.'.format(iteration))

                        # Notify our server process that we have the file to pass on
                        logger.info('Notifying server process that we are in possession of the file.')
                        has_file = True
                except Exception:
                    logger.error('Could not connect to host {}:{}.'.format(host, SERVER_PORT))
                finally:
                    logger.info('Closing connection to host {}:{}.'.format(host, SERVER_PORT))
                    # Remember to close socket
                    sock.close()

            logger.info('Finished contacting all hosts. Waiting {} seconds before trying again.'.format(DELAY))
            # Wait X seconds after connecting to all hosts
            time.sleep(DELAY)


# Start Client Thread
thread = ClientThread()
thread.start()

try:
    logger.info('Starting TCP Server on port {}'.format(MODULE_PORT))
    server = SocketServer.TCPServer((MODULE_HOST, MODULE_PORT), RequestHandler)
    server.serve_forever()
except KeyboardInterrupt:
    logger.info('Ctrl+C detected. Please wait. Shutting down client thread')
    thread.kill_received = True