Commit 70d49be9 authored by wx002's avatar wx002

added project

parent 1ecc4b91
......@@ -79,18 +79,29 @@ void dlist_remove(char * value_to_remove, struct dlist * the_list) {
if (node_to_remove->prev != NULL && node_to_remove->next != NULL){
node_to_remove->next->prev = node_to_remove->prev;
node_to_remove->prev->next = node_to_remove->next;
free(node_to_remove->word);
free(node_to_remove);
//remove first node
} else if ( node_to_remove->prev == NULL ){
the_list->head = node_to_remove->next;
//free(node_to_remove->prev->word);
//free(node_to_remove->prev);
//free(node_to_remove->word);
//free(node_to_remove);
node_to_remove->prev=NULL;
node_to_remove = NULL;
//node_to_remove = NULL;
//remove last node
} else {
//free(node_to_remove->prev->next->word);
//free(node_to_remove);
node_to_remove->prev->next = NULL;
node_to_remove = NULL;
//node_to_remove = NULL;
}
//free node_to_remove
free(node_to_remove->word);
free(node_to_remove);
} // end of list not empty
}
......@@ -141,9 +152,28 @@ struct dnode * make_node(char * word, int count) {
new_node->word = (char *)malloc(strlen(word) + 1);
strcpy(new_node->word, word);
new_node->count = count;
new_node->prev = new_node->next = NULL;
//added free
//free(new_node);
new_node->prev = new_node->next = NULL;
//free(new_node->word);
return new_node;
}
void free_dlist(struct dlist * the_list){
struct dnode * ptr;
struct dnode * next;
if (the_list == NULL)
return;
else{
ptr = the_list->head;
while (ptr != NULL){
next = ptr->next;
//printf("free the word\n");
free(ptr->word);
//printf("free the node\n");
free(ptr);
//printf("go to next node\n");
ptr = next;
}
free(the_list);
}
}
......@@ -28,6 +28,7 @@ void dlist_insert(struct dnode *, struct dlist *);
void dlist_remove(char *, struct dlist *);
bool dlist_is_empty(struct dlist *);
void dlist_traverse(struct dlist *);
void free_dlist(struct dlist *);
struct dnode * make_node(char *, int);
#endif /* ifndef LIST_H */
......@@ -49,7 +49,7 @@ int main(int argc, char* argv[]) {
dlist_remove(word[NUM_WORD-1], a_list);
printf("after the removal...\n");
dlist_traverse(a_list);
free(a_list);
free_dlist(a_list);
return 0;
}
after inserting 20 words...
0 1080
1 10-point
2 10th
3 11-point
4 12-point
5 16-point
6 18-point
7 1st
8 2
9 20-point
10 2,4,5-t
11 2,4-d
12 2D
13 2nd
14 30-30
15 3-D
16 3-d
17 3D
18 3M
19 3rd
removing 7th node ...
removing node: 0 ...
removing node: ...
after the removal...
1 10-point
2 10th
3 11-point
4 12-point
5 16-point
6 18-point
8 2
9 20-point
10 2,4,5-t
11 2,4-d
12 2D
13 2nd
14 30-30
15 3-D
16 3-d
17 3D
18 3M
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
./tmp
./files
This diff is collapsed.
from .stop_and_wait import sw
import logging
import socket
import math
import os.path
import os
from algs.utils import load_file
from algs.udp_wrapper import UdpWrapper
from algs.texcept import TransferFailed
from datetime import datetime, timedelta
log = logging.getLogger(__name__)
class StopAndWait:
# see https://en.wikipedia.org/wiki/Stop-and-wait_ARQ
def __init__(self, retries=3):
self.retries = retries
self.timeout = timedelta(seconds=5)
def run_server(self, outdir, addr, mtu):
"run the server on the given addr/port/mtu, files are stored in outdir"
# make sure directory exists
os.makedirs(outdir, exist_ok=True)
sock = UdpWrapper(addr)
# use pure blocking on the server.
sock.setblocking(True)
sock.bind(addr)
in_xfr = False
outfile = None
last = datetime.now() - self.timeout
log.info("Server started on {}".format(addr))
while True:
data,remote_addr = sock.recvfrom(mtu)
if datetime.now() - last > self.timeout:
log.info("Abort transfer due to timeout.".format())
in_xfr = False
if outfile:
outfile.close()
outfile = None
if in_xfr:
if data[:9] == B"///END\\\\\\":
log.info("Done receiving file from {}.".format(
filepath, remote_addr))
in_xfr = False
outfile.close()
outfile = None
sock.sendto(B"OKEND", remote_addr)
else:
log.debug("Got a chunk!")
# just write the data...
outfile.write(data)
sock.sendto(B'ACK', remote_addr)
else:
if data[:5] == B'BEGIN':
smsg = data.decode('utf-8').split('\n')
beginmsg = smsg[0]
filename = smsg[1]
filepath = os.path.join(outdir, filename)
# check mtu
remote_mtu= int(beginmsg.split("/")[1])
if remote_mtu > mtu:
log.error("Cannot receive {} from {}, MTU({}) is too large.".format(
filepath, remote_addr, remote_mtu))
sock.sentdo(B'ERROR_MTU', remote_addr)
else:
log.info("Begin receiving file {} from {}.".format(
filepath, remote_addr))
outfile = open(filepath, 'wb')
in_xfr = True
sock.sendto(B'OKBEGIN', remote_addr)
else:
log.info("Ignoreing junk, not in xfer.")
last = datetime.now()
def begin_xfr(self, dest, filename, mtu):
sock = UdpWrapper(dest)
#strip any path chars from filename for security
filename = os.path.basename(filename)
# timeout on recv after 1 second.
sock.settimeout(1)
tries = 0
while tries < self.retries:
msg = "BEGIN/{}\n{}".format(mtu, filename).encode('utf-8')
sock.sendto(msg, dest)
try:
data, addr = sock.recvfrom(mtu)
except socket.timeout:
tries += 1
continue
break
if (tries >= self.retries):
raise TransferFailed("No response to BEGIN message.")
if data != B"OKBEGIN":
raise TransferFailed("Bad BEGIN response from server, got {}".format(
data
))
return sock
def end_xfr(self, sock, dest, mtu):
tries = 0
while tries < self.retries:
sock.sendto(B"///END\\\\\\", dest)
try:
data, addr = sock.recvfrom(mtu)
except socket.timeout:
tries += 1
continue
break
if (tries >= self.retries):
raise TransferFailed("No response to END message.")
if data != B"OKEND":
raise TransferFailed("Bad END response from server, got {}".format(
data
))
def xfr(self, sock, payload, dest, mtu):
for i,chunk in enumerate(payload):
tries = 0
log.info("Send chunk {} of {}".format(i, len(payload)-1))
while tries < self.retries:
sock.sendto(chunk, dest)
try:
data, addr = sock.recvfrom(mtu)
except socket.timeout:
tries += 1
continue
if data == B"ACK":
break
else:
log.info("Bad response from server, got {} instead of ACK, RETRY".format(
data))
if (tries >= self.retries):
raise TransferFailed("No response to CHUNK message.")
def chunk(self, payload, mtu):
"break a payload into mtu sized chunks"
# simple chunking by MTU
chunks = math.ceil(len(payload) / mtu)
return [payload[i*mtu:(i+1)*mtu] for i in range(chunks)], len(payload)
def send_file(self, filename, dest, mtu):
"Entrypoint for stop and wait sending"
st = datetime.now()
log.info("Sending with stop-and-wait {} --> {}:{} [MTU={}].".format(
filename, dest[0], dest[1], mtu))
payload, total_bytes = self.chunk(load_file(filename), mtu)
s = self.begin_xfr(dest, filename, mtu)
self.xfr(s, payload, dest, mtu)
self.end_xfr(s, dest, mtu)
et = datetime.now()
seconds = (et-st).total_seconds()
log.info("Sent with stop-and-wait {} in {} seconds = {:.0f} bps.".format(
filename, seconds,
total_bytes / seconds))
return True
# singleton
sw = StopAndWait()
class TransferFailed(Exception):
pass
import socket
import logging
#from binascii import hexlify
log = logging.getLogger(__name__)
class UdpWrapper:
"A simple wrapper to a UDP socket that adds logging."
def __init__(self, dest):
self.name = 'UDPWrap{}'.format(dest)
self.dest = dest
log.debug("{} created.".format(self.name))
self.socket = socket.socket(family=socket.AF_INET,
type=socket.SOCK_DGRAM)
def fileno(self):
return self.socket.fileno()
def sendto(self, payload, dest):
log.debug("->{}: {}".format(dest, payload))
self.socket.sendto(payload, dest)
def recvfrom(self, mtu):
data,addr = self.socket.recvfrom(mtu)
log.debug("<-{}: {}".format(addr, data))
return data,addr
def bind(self, addr):
return self.socket.bind(addr)
def setblocking(self, flag):
return self.socket.setblocking(flag)
def settimeout(self, value):
return self.socket.settimeout(value)
def load_file(filename):
"read a file into a list of bytes for packetization"
with open(filename, 'rb') as f:
r = f.read()
return r
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"version": 1,
"formatters": {
"detailed": {
"format": "%(asctime)s %(name)-20s %(levelname)-8s %(message)s"
},
"simple": {
"format": "%(levelname)s %(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "detailed"
}
},
"loggers": {
"algs": {
"level": "DEBUG"
},
"algs.udp_wrapper": {
"level": "WARN"
}
},
"root": {
"handlers": ["console"],
"level": "DEBUG"
}
}
from socket import *
import re
dest = ('127.0.0.1', 5000)
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(dest)
fileList = []
lineStr = ''
currentHeader = None
def getHeader(string):
pass
while True:
data, addr = sock.recvfrom(1048)
print("recv data: {}".format(data))
while data != b'####':
lineStr += data.decode('utf-8')
print(lineStr)
data, addr = sock.recvfrom(1048)
if data == b'####':
sock.sendto(b'ACK', addr)
fileList.append(lineStr)
lineStr = ''
data = ''
print(fileList)
continue
This source diff could not be displayed because it is too large. You can view the blob instead.
import socket
import base64
ip = '127.0.0.1'
port = 5000
dest = (ip,port)
timeOut = 1
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(timeOut)
def load_data(fileName):
fileList = []
with open(fileName) as f:
line = f.readline()
while line:
fileList.append(line)
line = f.readline()
return fileList
def chunk(line, size=1028):
return [line[i:i+size] for i in range(0,len(line), size)]
def buildHeader(string):
header = base64.b64encode(bytes('*'+string+'*'))
return header
def send_line(socket, line, size):
if len(line) < size:
#send the line directly if is less than the max size
socket.sendto(str.encode(line), dest)
else:
lineChunks = chunk(line, size)
for c in lineChunks:
socket.sendto(str.encode(c), dest)
socket.sendto(b'####', dest)
if __name__ == '__main__':
ack = False
testLines = ['\n','\n','test line 1\n','test line 2\n','test line 3\n']
for line in testLines:
ack = False
while not ack:
try:
index = testLines.index(line)
header = buildHeader(bytes(index))
line = header + line
send_line(sock, line, 1048)
data = sock.recv(1048)
print(data)
if data == b'ACK':
ack = True
except socket.timeout:
print('timeout! resend line')
#send_line(sock, line, 1048)
"""
Reliable Reciever
The goal is to create a reliable transport protocol. This file is the side
that waits for a client to transfer files (server).
Data is transmitted over UDP. A separate udp_box can enforce data rate
limits and/or packet loss or corruption.
(c) Alan Marchiori 2019
"""
import argparse
import socket
import logging
import logging.config
import sys
import json
import algs
from algs.texcept import TransferFailed
# custom exception
class AlgorithmNotImplementedError(NotImplementedError): pass
def en_logging():
"setup loggers"
#https://docs.python.org/3/howto/logging-cookbook.html
logging.config.dictConfig(json.load(open('log_cfg.json', 'r')))
def parse_args():
"Sets up the argument parser"
parser = argparse.ArgumentParser(
description="Reliable Server (starter code)."
)
parser.add_argument('--outdir',
default='./tmp',
help="Directory to store recieved files [./tmp].")
parser.add_argument('--mtu',
default=100,
type=int,
help='Maximum transmition unit (MTU) (bytes) [100].')
parser.add_argument('--addr',
default = '0.0.0.0',
help='Local addres to listen on [0.0.0.0].')
parser.add_argument('--port',
help='Port to listen on [8888].',
default=8888,
type=int)
# add additional algorithms here.
parser.add_argument('--alg',
help='The algorithm to use [sw].',
default='sw',
choices=['sw', 'yours'])
return parser.parse_args()
if __name__ == "__main__":
en_logging()
args = parse_args()
# look at those args
logging.debug("Got args {}".format(args))
if args.alg == 'sw': # stop and wait protocol
# the server should never stop...
try:
algs.sw.run_server(
outdir=args.outdir,
addr=(args.addr, args.port),
mtu=args.mtu)
except Exception as x:
logging.error("Server died: {}".format(x))
raise(x)
sys.exit(-15)
else:
raise AlgorithmNotImplementedError()
"""
Reliable Sender
The goal is to create a reliable transport protocol. This file is the side
that initiates a transfer (client). The rserver.py file has the server codeself.
Data is transmitted over UDP. A separate udproxy server can enforce data rate
limits and/or packet loss or corruption.
(c) Alan Marchiori 2019
"""
import argparse
import socket
import logging
import logging.config
import sys
import json
import algs
from algs.texcept import TransferFailed
# custom exception
class AlgorithmNotImplementedError(NotImplementedError): pass
def en_logging():
"setup loggers"
#https://docs.python.org/3/howto/logging-cookbook.html
logging.config.dictConfig(json.load(open('log_cfg.json', 'r')))
def parse_args():
"Sets up the argument parser"
parser = argparse.ArgumentParser(
description="Reliable Sender (starter code)."
)
parser.add_argument('files',
default='alice.txt', nargs="+",
help="File(s) to send [alice.txt].")
parser.add_argument('--mtu',
default=100,
type=int,
help='Maximum transmition unit (MTU) (bytes) [100].')
parser.add_argument('--dst',
default = 'localhost',
help='Destination host, eg. hostname or 192.168.3.101 [localhost].')
parser.add_argument('--port',
help='Port on destination host [8888].',
default=8888,
type=int)
# add additional algorithms here.
parser.add_argument('--alg',
help='The algorithm to use [sw].',
default='sw',
choices=['sw', 'yours'])
return parser.parse_args()
if __name__ == "__main__":
en_logging()
# uncomment this to see every packet.
#logging.getLogger("algs.udp_wrapper").setLevel(logging.DEBUG)
args = parse_args()
# look at those args
logging.debug("Got args {}".format(args))
if args.alg == 'sw': # stop and wait protocol
# map files list into multiple calls
try:
result = list(map(lambda x: algs.sw.send_file(
filename=x,
dest=(args.dst, args.port),
mtu=args.mtu),
args.files))
except TransferFailed as x:
logging.error("Transfer failed: {}".format(x))
raise(x)
sys.exit(-5)
else:
raise AlgorithmNotImplementedError()