Skip to content
Snippets Groups Projects
Commit 6cb91479 authored by Fernando Erd's avatar Fernando Erd :ok_hand:
Browse files

removendo lixo

parent b264e9fc
Branches
No related tags found
No related merge requests found
Showing
with 0 additions and 1545 deletions
/* fpont 12/99 */
/* pont.net */
/* udpClient.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h> /* memset() */
#include <sys/time.h> /* select() */
#include <stdlib.h>
#define REMOTE_SERVER_PORT 1500
#define MAX_MSG 100
int main(int argc, char *argv[]) {
int sd, rc, i;
struct sockaddr_in cliAddr, remoteServAddr;
struct hostent *h;
/* check command line args */
if(argc<3) {
printf("usage : %s <server> <data1> ... <dataN> \n", argv[0]);
exit(1);
}
/* get server IP address (no check if input is IP address or DNS name */
h = gethostbyname(argv[1]);
if(h==NULL) {
printf("%s: unknown host '%s' \n", argv[0], argv[1]);
exit(1);
}
printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name,
inet_ntoa(*(struct in_addr *)h->h_addr_list[0]));
remoteServAddr.sin_family = h->h_addrtype;
memcpy((char *) &remoteServAddr.sin_addr.s_addr,
h->h_addr_list[0], h->h_length);
remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT);
/* socket creation */
sd = socket(AF_INET,SOCK_DGRAM,0);
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
/* bind any port */
cliAddr.sin_family = AF_INET;
cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliAddr.sin_port = htons(0);
rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr));
if(rc<0) {
printf("%s: cannot bind port\n", argv[0]);
exit(1);
}
/* send data */
for(i=2;i<argc;i++) {
rc = sendto(sd, argv[i], strlen(argv[i])+1, 0,
(struct sockaddr *) &remoteServAddr,
sizeof(remoteServAddr));
if(rc<0) {
printf("%s: cannot send data %d \n",argv[0],i-1);
close(sd);
exit(1);
}
}
return 1;
}
/* fpont 12/99 */
/* pont.net */
/* udpClient.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h> /* memset() */
#include <sys/time.h> /* select() */
#include <stdlib.h>
#define REMOTE_SERVER_PORT 1500
#define MAX_MSG 100
int main(int argc, char *argv[]) {
int sd, rc, i;
struct sockaddr_in cliAddr, remoteServAddr;
struct hostent *h;
/* check command line args */
if(argc<3) {
printf("usage : %s <server> <data1> ... <dataN> \n", argv[0]);
exit(1);
}
/* get server IP address (no check if input is IP address or DNS name */
h = gethostbyname(argv[1]);
if(h==NULL) {
printf("%s: unknown host '%s' \n", argv[0], argv[1]);
exit(1);
}
printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name,
inet_ntoa(*(struct in_addr *)h->h_addr_list[0]));
remoteServAddr.sin_family = h->h_addrtype;
memcpy((char *) &remoteServAddr.sin_addr.s_addr,
h->h_addr_list[0], h->h_length);
remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT);
/* socket creation */
sd = socket(AF_INET,SOCK_DGRAM,0);
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
/* bind any port */
cliAddr.sin_family = AF_INET;
cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliAddr.sin_port = htons(0);
rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr));
if(rc<0) {
printf("%s: cannot bind port\n", argv[0]);
exit(1);
}
/* send data */
for(i=2;i<argc;i++) {
rc = sendto(sd, argv[i], strlen(argv[i])+1, 0,
(struct sockaddr *) &remoteServAddr,
sizeof(remoteServAddr));
if(rc<0) {
printf("%s: cannot send data %d \n",argv[0],i-1);
close(sd);
exit(1);
}
}
return 1;
}
/* fpont 12/99 */
/* pont.net */
/* udpClient.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h> /* memset() */
#include <sys/time.h> /* select() */
#include <stdlib.h>
#define REMOTE_SERVER_PORT 1500
#define MAX_MSG 100
int main(int argc, char *argv[]) {
int sd, rc, i;
struct sockaddr_in cliAddr, remoteServAddr;
struct hostent *h;
/* check command line args */
if(argc<3) {
printf("usage : %s <server> <data1> ... <dataN> \n", argv[0]);
exit(1);
}
/* get server IP address (no check if input is IP address or DNS name */
h = gethostbyname(argv[1]);
if(h==NULL) {
printf("%s: unknown host '%s' \n", argv[0], argv[1]);
exit(1);
}
printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name,
inet_ntoa(*(struct in_addr *)h->h_addr_list[0]));
remoteServAddr.sin_family = h->h_addrtype;
memcpy((char *) &remoteServAddr.sin_addr.s_addr,
h->h_addr_list[0], h->h_length);
remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT);
/* socket creation */
sd = socket(AF_INET,SOCK_DGRAM,0);
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
/* bind any port */
cliAddr.sin_family = AF_INET;
cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliAddr.sin_port = htons(0);
rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr));
if(rc<0) {
printf("%s: cannot bind port\n", argv[0]);
exit(1);
}
/* send data */
for(i=2;i<argc;i++) {
rc = sendto(sd, argv[i], strlen(argv[i])+1, 0,
(struct sockaddr *) &remoteServAddr,
sizeof(remoteServAddr));
if(rc<0) {
printf("%s: cannot send data %d \n",argv[0],i-1);
close(sd);
exit(1);
}
}
return 1;
}
Abrir o Servidor
Abrir o Cliente <data> <mensagem>
Ex: 127.0.0.1 mensagem
http://www.inf.pucrs.br/~cnunes/redes_si/Sockets.htm
/* fpont 12/99 */
/* pont.net */
/* udpServer.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> /* close() */
#include <string.h> /* memset() */
#include <stdlib.h>
#define LOCAL_SERVER_PORT 1500
#define MAX_MSG 100
int main(int argc, char *argv[]) {
int sd, rc, n, cliLen;
struct sockaddr_in cliAddr, servAddr;
char msg[MAX_MSG];
/* socket creation */
sd=socket(AF_INET, SOCK_DGRAM, 0);
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
/* bind local server port */
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(LOCAL_SERVER_PORT);
rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr));
if(rc<0) {
printf("%s: cannot bind port number %d \n",
argv[0], LOCAL_SERVER_PORT);
exit(1);
}
printf("%s: waiting for data on port UDP %u\n",
argv[0],LOCAL_SERVER_PORT);
/* server infinite loop */
while(1) {
/* init buffer */
memset(msg,0x0,MAX_MSG);
/* receive message */
cliLen = sizeof(cliAddr);
n = recvfrom(sd, msg, MAX_MSG, 0,
(struct sockaddr *) &cliAddr, &cliLen);
if(n<0) {
printf("%s: cannot receive data \n",argv[0]);
continue;
}
/* print received message */
printf("%s: from %s:UDP%u : %s \n",
argv[0],inet_ntoa(cliAddr.sin_addr),
ntohs(cliAddr.sin_port),msg);
}/* end of server infinite loop */
return 0;
}
*.pyc
*.log
# TolkienRing
Chat de até quatro máquinas sobre uma rede Token Ring: Trabalho 2 de Redes 1
## Rodando
`chat -p [communicationPort] -s [serverPort] -c`
* -p: porta de comunicação do anel
* -s: porta do servidor de configuração do anel
* -c: Inicia em modo servidor de configuração do anel
## Funcionamento
O TolkienRing é um chat de até 4 máquinas sobre uma rede Token Ring.
A primeira máquina (ou alguma delas, mas só uma) inicia executando em modo de
configuração de rede. Esta máquina é conhecida como servidora (de configuração) do anel.
Este modo funciona da seguinte maneira:
1. Uma primeira máquina (A) manda um *handshake* (um tipo especial de mensagem) para
a servidora.
* A servidora responde com o IP e porta do nodo com quem ela se conecta
* A máquina (A) responde um OK e se conecta
* Como esta é a primeira máquina, ela se conecta com a servidora
* A servidora define que esta máquina (A) é o próximo nodo da rede
* A rede é: [servidora] -> [A] -> [servidora]
* Uma segunda máquina (B) manda o *handshake*
* A servidora responde com o IP e porta da última máquina que se conectou (A)
* A máquina (B) responde um OK e se conecta
* A servidora se conecta com a máquina (B)
* A rede é: [servidora] -> [B] -> [A] -> [servidora]
* Uma terceira e última máquina (C) manda o *handshake*
* A servidora responde com o IP e porta da última máquina que se conectou (B)
* A máquina (C) responde um OK e se conecta
* A servidora se conecta com a máquina (C)
* A rede é: [servidora] -> [C] -> [B] -> [A]
* A servidora então cria o bastão da rede e envia para a próxima máquina
* O bastão passa por todas as máquinas e retorna para a servidora
* Vendo que a rede está correta, a servidora envia a primeira mensagem em modo de
broadcast: o nome de todas as máquinas na rede
* As outras máquinas armazenam essa informação para que os usuários possam escolher
para quem querem enviar algo.
* A partir de então, a máquina servidora vira a última máquina da rede (D) e pode
enviar normalmente as mensagens
O modo de configuração da rede pode ser fechado por um comando do usuário com
menos do que 4 máquinas na rede. Caso isso ocorra e uma máquina queira entrar no chat
ela deve enviar o *handhsake* para a porta de configuração (note que existe uma porta
para a configuração da rede e uma para a comunicação do anel) de qualquer máquina.
Ao fazer isso, a máquina entra em modo de configuração e passa o bastão (quando sob sua posse)
pelo anel indicando o modo de configuração. Esta máquina então segue os passos normais
do servidor de configuração.
## Mensagem
A mensagem é definida assim
|Indicador de início|Controle|Origem|Destino|Tamanho|Dados|Paridade|Resposta|
|-------------------|--------|------|-------|-------|-----|---|--------|
|1 Byte|1 Byte|6 Bytes|6 Bytes|1 Byte|<= 1004 Bytes|4 Bytes|1 Byte|
**Controle**
|Token|Monitor|Configuração|Handshake|Reservado|
|-----|-------|------------|---------|---------|
|1 bit|1 bit|1 bit|1bit|4 bits|
## Especificação do trabalho
Implementar um chat entre 4 máquinas montadas como um anel com passagem de bastão temporizado.
Anel deve ser criado logicamente entre 4 servidores do Dinf usando Socket Datagram.
As 4 máquinas **devem** ter acesso de usuário.
Usuário deve digitar primeiro um número (máquina a qual a mensagem é destinada) depois ':' e depois a mensagem.
Exemplo: `1:teste`. Caso especial: `5:mensagem` -> mensagem para todo mundo.
Protocolo: definido pelos membros do trabalho.
* Respostas de carona são obrigatórias
* Protocolo deve especifcar enquadramento (sequencialização/detecção de erros/mensagens)
* Timeout de mensagens que não voltam p/ origem não precisa ser implementado
* Implementar timeout de bastão
Entregar:
* Relatório com o protocolo detalhado e as escolhas de implementação feitas pela equipe
* Nota: 1,0
* Código: por e-mail depois da apresentação
* Em duplas
* Linguagem: qualquer uma
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import select
import argparse
import sys
import curses
import string
from connection import Connection
import message
import time
import datetime
import logging
import ast
from timeout import Timer
logging.basicConfig(filename='tolkien.log', level=logging.DEBUG)
def parseArgs():
parser = argparse.ArgumentParser(description="TolkienRing: Chat em anel de até 4 máquinas", prog="chat")
parser.add_argument("-p", "--port", type=int, help="Porta de comunicação", default=1337)
parser.add_argument("-s", "--serverPort", type=int, help="Porta do servidor do anel", default=5050)
parser.add_argument("-c", "--configurationServer", help="Inicia no modo de configuração", action="store_true")
return parser.parse_args()
def printHeader(screen, hostname, ip, status):
screen.clear()
screen.addstr(0, 0, "Máquina: %s" % hostname)
screen.addstr(1, 0, "IP: %s" % ip)
screen.addstr(2, 0, "Status: %s" % status)
x = screen.getmaxyx()[1]
title = "### TolkienRing ###"
screen.addstr(3, (x - len(title))/2, title, curses.A_REVERSE)
def printMessages(screen, messages):
y = screen.getmaxyx()[0] - 2 #-2 pelas bordas
i = 1
for msg in messages[-y:]:
screen.addstr(i, 1, msg[0], msg[1])
i+=1
def printMachines(screen, machines):
x = screen.getmaxyx()[1]
title = "HOSTS"
screen.addstr(1, (x - len(title))/2, title, curses.A_BOLD)
i = 2
for host, index in machines.items():
screen.addstr(i, 1, "%s - %s" % (index, getMachineName(host[0])))
i+=1
#screen.addstr(i, 1, "%s" % str(machines))
def getMachineName(host):
return socket.gethostbyaddr(host)[0].split('.')[0]
def connectToMachine(textbox):
textbox.nodelay(False)
curses.echo()
textbox.addstr(0, 1, "Digite o nome da máquina:")
textbox.refresh()
n = textbox.getstr(1, 1)
textbox.clear()
textbox.box()
textbox.refresh()
textbox.addstr(0, 1, "Digite a porta (a porta padrão é 5050):")
textbox.refresh()
p = textbox.getstr(1, 1)
textbox.clear()
textbox.box()
textbox.refresh()
curses.noecho()
textbox.nodelay(True)
return (socket.gethostbyname(n), int(p, 10)) if n and p else False
def parseUserMessage(msg, messages, machines, host, connection, s, nextHost):
lose_token = False
try:
delim_index = msg.index(':')
machine_index = ''.join(msg[0:delim_index])
machine_index.strip(string.whitespace)
if machine_index != 0:
m = message.Message()
data = ''.join(msg[delim_index+1:])
data.strip(string.whitespace)
m.setData(data)
m.setOrigin(machines[host])
m.setDestiny(machine_index)
messages.append(("Você para %s: %s" % (machine_index, m.getData()), curses.A_NORMAL))
connection.put_message(s, m.getMessage(), nextHost)
except Exception, e:
s = ''.join(msg)
s.strip(string.whitespace)
if s:
if s[0] == '/':
action = s[1:]
if action == "quit":
sys.exit(0)
elif action == "token":
lose_token = True
else:
messages.append(("ERRO: A mensagem deve ter o formato: <host>:<mensagem>\n%s"%e, curses.A_BOLD))
logging.debug(e)
finally:
msg = []
return (msg, lose_token)
def main(stdscr, args):
stdscr.nodelay(True)
connectionTimeout = Timer("conn", 5.0)
tokenTimeout = Timer("token", 15.0)
timeouts = {"conn":connectionTimeout, "token":tokenTimeout}
machines = {}
messages = []
msg = []
hostname = socket.gethostname()
host = socket.gethostbyname(hostname)
has_msg_on_ring = False
has_token = False
lose_token = False
quantum = 0.25
lose_token = False
if args.port == args.serverPort:
# TODO: mostrar uma mensagem de erro melhor
raise ValueError("O valor da porta de rede não pode ser igual ao do servidor de configuração")
sys.exit(2)
port = args.port
serverPort = args.serverPort
nextHost = (host, port)
connection = Connection()
s = connection.open_socket(host, port)
confserver = connection.open_socket(host, serverPort)
connection.input_sockets = [confserver,s]
connection.output_sockets = [confserver,s]
machines[(host, port)] = '1'
printHeader(stdscr, hostname, host, "Desconectado")
yx = stdscr.getmaxyx()
chatscreen = stdscr.subpad(yx[0]-7, yx[1]-20, 4, 0)
machinescreen = stdscr.subwin(yx[0]-7, 18, 4, yx[1]-19)
textbox = stdscr.subwin(3, yx[1]-1, yx[0]-3, 0)
textbox.nodelay(True)
curses.curs_set(0)
messages.append(("INFO: Você não está conectado", curses.A_BOLD))
messages.append(("INFO: Aperte 'c' para se conectar a alguém", curses.A_BOLD))
messages.append(("INFO: Aperte 'q' para sair", curses.A_BOLD))
messages.append(("INFO: Durante o anel digite '/quit' para sair", curses.A_BOLD))
messages.append(("INFO: Durante o anel digite '/token' para perder o bastão", curses.A_BOLD))
messages.append(("INFO: Nome da máquina: %s" % hostname, curses.A_BOLD))
messages.append(("INFO: Porta do servidor: %s" % serverPort, curses.A_BOLD))
messages.append(("INFO: Porta da rede: %s" % port, curses.A_BOLD))
curses.cbreak()
t0 = 0.0
while True:
chatscreen.box()
textbox.box()
machinescreen.box()
printMessages(chatscreen, messages)
printMachines(machinescreen, machines)
if len(machines) <= 1 or nextHost == (host, port):
key = stdscr.getch()
if key == ord('q'):
sys.exit(0)
elif key == ord('c'):
# Pega informações do host
nextHost = connectToMachine(textbox)
# Send handshake
if nextHost:
connection.send_handshake(confserver, nextHost, port)
messages.append(("INFO: Tentando conectar...", curses.A_BOLD))
timeouts["conn"].start()
else:
nextHost = (host, port)
else:
key = textbox.getch()
if key != -1:
if (key == curses.KEY_BACKSPACE or key == 127) and msg:
msg.pop()
else:
try:
c = chr(key)
if c == '\n':
msg, lose_token = parseUserMessage(msg, messages, machines, (host, port), connection, s, nextHost)
elif c in string.printable and len(msg) <= message.maxSize:
msg.append(c)
except ValueError:
pass
textbox.addstr(1, 1, ''.join(msg[-(textbox.getmaxyx()[1]-2):]))
textbox.noutrefresh()
if has_token:
if lose_token:
lose_token = False
has_token = False
logging.debug("Perdi o token")
printHeader(stdscr, hostname, host, "Conectado: Sem Token")
elif (time.time() - t0) >= quantum:
connection.send_token(s, nextHost)
has_token = False
timeouts["token"].start()
printHeader(stdscr, hostname, host, "Conectado: Sem Token")
logging.debug("Enviei o token")
# Checa os timeouts
for name, t in timeouts.items():
if t.hasTimedOut():
if t is connectionTimeout:
messages.append(("INFO: Não foi possível se conectar. Tente novamente.", curses.A_BOLD))
timeouts["conn"].reset()
elif t is tokenTimeout:
messages.append(("INFO: Token Timeout", curses.A_BOLD))
connection.send_token(s, nextHost, True, machines[(host, port)])
timeouts["token"].start()
ready_to_read,ready_to_write,in_error = connection.poll()
for sock in ready_to_read:
data, addr = sock.recvfrom(1024)
if data:
n = datetime.datetime.now()
m = message.Message()
m.setMessage(data)
if not m.isToken():
logging.debug("Raw data: %s" % m.getReadableMessage())
# messages.append(("Raw data: %s" % m.getReadableMessage(), curses.A_NORMAL))
if sock is confserver:
if m.isHandshake() and not m.isConfiguration():
if len(machines) < 4:
connection.ack_handshake(confserver, addr, nextHost)
nextHost = (addr[0], int(m.getData(), 10))
machines[nextHost] = str(len(machines) + 1)
messages.append(("INFO: %s se conectou" % getMachineName(addr[0]), curses.A_BOLD))
printHeader(stdscr, hostname, host, "Conectado")
# Se só tem 2 máquinas, é a primeira conexão
if len(machines) == 2:
connection.send_token(s, nextHost)
timeouts["token"].start()
conf = message.Message()
conf.setConfiguration()
conf.setOrigin(machines[(host, port)])
conf.setDestiny("5")
conf.setData(str(machines))
connection.put_message(confserver, conf.getMessage(), nextHost)
elif m.isHandshake() and m.isConfiguration():
# Recebeu um ack_handshake
timeouts["conn"].reset()
otherHost = m.getData()
delim_index = otherHost.index(':')
nextHost = (otherHost[0:delim_index], int(otherHost[delim_index+1:], 10))
messages.append(("INFO: Você se conectou a rede", curses.A_BOLD))
printHeader(stdscr, hostname, host, "Conectado")
else:
m.setReceived(machines[(host, port)])
now = datetime.datetime.now()
if m.isToken():
timeouts["token"].reset()
has_token = True
t0 = time.time()
printHeader(stdscr, hostname, host, "Conectado: Com token")
if m.isMonitor() and m.getOrigin() != machines[(host, port)]:
connection.put_message(confserver, m.getMessage(), nextHost)
elif m.isConfiguration():
if m.checkParity():
machines = ast.literal_eval(m.getData())
m.setRead(machines[(host, port)])
logging.debug("Machines: %s" % str(machines))
else:
if m.getDestiny() == machines[(host, port)] or m.getDestiny() == "5" and m.getOrigin() != machines[(host, port)]:
if m.checkParity():
m.setRead(machines[(host, port)])
hour = '{:%H:%M:%S}'.format(now)
messages.append(("%s-%s: %s" % (hour, m.getOrigin(), m.getData()), curses.A_NORMAL))
if m.getOrigin() == machines[(host, port)]:
is_received = True
is_read = True
has_msg_on_ring = False
if m.getDestiny() == "5":
for h, index in machines.items():
if index != machines[h]:
if not m.getReceived(index):
is_received = False
if not m.getRead(index):
is_read = False
else:
is_received = m.getReceived(m.getOrigin())
is_read = m.getRead(m.getOrigin())
# messages.append(("INFO: r:%r l:%r - %s" % (is_received, is_read, m.getData()), curses.A_BOLD))
#if not is_read or not is_received:
#connection.put_message(s, m.getMessage(), nextHost)
if not m.isToken() and m.getOrigin() != machines[(host, port)]:
connection.put_message(s, m.getMessage(), nextHost)
for sock in ready_to_write:
if sock is s:
if connection.has_message(sock):
m = message.Message()
m.setMessage(connection.messages[sock][0][0])
if has_token or m.isToken():
connection.send_message(sock)
has_msg_on_ring = True
else:
if connection.has_message(sock):
connection.send_message(sock)
chatscreen.noutrefresh()
machinescreen.noutrefresh()
stdscr.noutrefresh()
curses.doupdate()
if __name__ == "__main__":
args = parseArgs()
curses.wrapper(main, args)
import socket, select
import message
# Recommended for queues on python doc
from collections import deque
import logging
logging.basicConfig(filename='tolkien.log', level=logging.DEBUG)
class Connection(object):
def __init__(self):
self._input_sockets = []
self._output_sockets = []
self._monitor_sockets = []
self.messages = {}
def open_socket(self, host, port):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
s.setblocking(False)
return s
def poll(self):
return select.select(self._input_sockets, self._output_sockets, self._monitor_sockets,0)
def send_handshake(self, sock, addr, port=1337):
handshake = message.makeHandshake(port)
logging.debug("Criando handshake")
logging.debug(handshake.getMessage())
self.messages[sock].append((handshake.getMessage(), addr))
def ack_handshake(self, sock, addr, host):
ack = message.makeAckHandshake(host)
logging.debug("Criando ack_handshake")
logging.debug(ack.getMessage())
self.messages[sock].append((ack.getMessage(), addr))
def send_token(self, sock, addr, monitor = False, origin="0"):
token = message.makeMonitor() if monitor else message.makeToken()
if monitor:
token.setOrigin(origin)
self.messages[sock].append((token.getMessage(), addr))
def put_message(self, sock, msg, addr):
self.messages[sock].append((msg, addr))
def send_message(self, sock):
# * -> expands tuple as arguments
sock.sendto(*(self.messages[sock].popleft()))
def has_message(self, sock):
return bool(self.messages[sock])
def add_output_socket(self, sock):
if sock not in self._output_sockets:
self._output_sockets.append(sock)
self.messages[sock] = deque()
@property
def input_sockets(self):
return self._input_sockets
@input_sockets.setter
def input_sockets(self, value):
self._input_sockets = value
@property
def output_sockets(self):
return self._output_sockets
@output_sockets.setter
def output_sockets(self, value):
self._output_sockets = value
for s in value:
self.messages[s] = deque()
@property
def monitor_sockets(self):
return self._monitor_sockets
@monitor_sockets.setter
def monitor_sockets(self, value):
self._monitor_sockets = value
# -*- coding:utf-8 -*-
from binascii import crc32
maxSize = 4095
# Converte um caracter em uma lista que representa o valor binário
def chrToBitList(c):
return list('{0:08b}'.format(ord(c)))
def intToBitList(i):
return list('{0:08b}'.format(i))
def chrToBitString(c):
return '{0:08b}'.format(ord(c))
# Converte uma lista para um caracter
def bitListToChar(l):
return chr(int(''.join(l), 2))
def bitStringToChr(s):
return chr(int(s, 2))
def setBitOneFromChr(c, i):
l = chrToBitList(c)
l[i] = '1'
return bitListToChar(l)
class Message(object):
def __init__(self):
# Controle: |TMCHRRRR|
# T = token, M = monitor, C = configuração, H = handshake, R = reservado
self.control = chr(0)
self.origin = '0'
self.destiny = '0'
# 3 bytes
self.size = '0'
self.data = '0'
# 4 bytes
self.parity = chr(0)
self.response = chr(0)
def setControl(self, control):
self.control = bitStringToChr(control)
def setToken(self):
self.control = setBitOneFromChr(self.control, 0)
def setMonitor(self):
self.control = setBitOneFromChr(self.control, 1)
def setConfiguration(self):
self.control = setBitOneFromChr(self.control, 2)
def setHandshake(self):
self.control = setBitOneFromChr(self.control, 3)
def setOrigin(self, origin):
self.origin = origin
def setDestiny(self, destiny):
self.destiny = destiny
def setSize(self, size):
if size <= maxSize:
self.size = '{0:03x}'.format(size)
else:
# Throw error
pass
def setData(self, data):
if len(data) <= maxSize:
self.data = data
self.setSize(len(data))
else:
# Throw error
pass
def calcParity(self):
data = self.getMessageWithoutParity()
parity = crc32(data) & 0xffffffff
bitList = intToBitList(parity)
chrList = [bitListToChar(bitList[0:8]), bitListToChar(bitList[8:16]), bitListToChar(bitList[16:24]), bitListToChar(bitList[24:32])]
self.parity = ''.join(chrList)
def setResponse(self, response):
self.response = chr(response)
def setReceived(self, machine):
i = int(machine, 10) - 1
# machine é o número da máquina no anel (0, 3)
# O bit mais a esquerda diz que a msg foi recebida
# O bit mais a direita diz que a msg foi aceita
# |Resposta|
# |AABBCCDD|
self.response = setBitOneFromChr(self.response, i * 2)
def setRead(self, machine):
i = int(machine, 10) - 1
self.response = setBitOneFromChr(self.response, i * 2 + 1)
def getControl(self):
return self.control
def isToken(self):
return chrToBitString(self.control)[0] == '1'
def isMonitor(self):
return chrToBitString(self.control)[1] == '1'
def isConfiguration(self):
return chrToBitString(self.control)[2] == '1'
def isHandshake(self):
return chrToBitString(self.control)[3] == '1'
def getOrigin(self):
return self.origin
def getDestiny(self):
return self.destiny
def getSize(self):
return int(self.size, 16)
def getData(self):
return self.data
def getParity(self):
return self.parity
def checkParity(self):
data = self.getMessageWithoutParity()
parity = crc32(data) & 0xffffffff
bitList = intToBitList(parity)
chrList = [bitListToChar(bitList[0:8]), bitListToChar(bitList[8:16]), bitListToChar(bitList[16:24]), bitListToChar(bitList[24:32])]
return (''.join(chrList) == self.parity)
def getResponse(self):
return self.response
def getReceived(self, machine):
i = int(machine, 10) - 1
return chrToBitString(self.response)[i*2] == "1"
def getAllReceived(self, machine):
# machine é a máquina que enviou
i = int(machine, 10) - 1
m = [0, 1, 2, 3]
del m[i]
response = chrToBitString(self.response)
for r in m:
if response[r*2] == "0":
return False
return True
def getRead(self, machine):
i = int(machine, 10) - 1
return chrToBitString(self.response)[i * 2 + 1] == "1"
def getAllRead(self, machine):
# machine é a máquina que enviou
i = int(machine, 10) - 1
m = [0, 1, 2, 3]
del m[i]
response = chrToBitString(self.response)
for r in m:
if response[r*2 + 1] == "0":
return False
return True
def setMessage(self, message):
msgSize = len(message)
self.control = message[0]
self.origin = message[1]
self.destiny = message[2]
self.size = message[3:6]
self.data = message[6:-5]
self.parity = message[-5:-1]
self.response = message[-1]
def getMessage(self):
self.calcParity()
m = [self.control, self.origin, self.destiny, self.size, self.data, self.parity, self.response]
return ''.join(m)
def getMessageWithoutParity(self):
m = [self.control, self.origin, self.destiny, self.size, self.data]
return ''.join(m)
def getReadableMessage(self):
m = ['{0:08b}'.format(ord(self.control)), self.origin, self.destiny, self.size, self.data, '{0:08b}'.format(ord(self.response))]
return '|'.join(m)
def makeHandshake(port):
data = str(port)
m = Message()
m.setHandshake()
m.setData(data)
return m
def makeAckHandshake(host):
data = "%s:%s" % (host[0], str(host[1]))
m = Message()
m.setConfiguration()
m.setHandshake()
m.setData(data)
return m
def makeToken():
m = Message()
m.setToken()
return m
def makeMonitor():
m = Message()
m.setToken()
m.setMonitor()
return m
def makeMessage(message):
m = Message()
m.setData(message)
return m
import time
class TimeoutError(Exception):
pass
class Timer(object):
def __init__(self, name='', maxTime=0.0):
self.time = 0.0
self.timeout = False
self.name = name
self.maxTime = maxTime
self.active = False
def time(self):
return self.time
def time(self, time):
self.time = time
def timeout(self):
return self.timeout
def name(self):
return self.name
def name(self, name):
self.name = name
def maxTime(self):
return self.maxTime
def maxTime(self, maxTime):
self.maxTime = maxTime
def start(self):
self.time = time.time()
self.active = True
def hasTimedOut(self):
self.timeout = (time.time() - self.time) >= self.maxTime
return self.timeout and self.active
def reset(self):
self.time = 0.0
self.active = False
CHAT FELIZ
----------
* Execução:
Para executar o programa, basta invocar o script "chat.sh" na pasta "src"
Alternativamente, é possível invocar o Python diretamente no arquivo "main.py", ou chamar o makefile.
* Dependências:
- Python 2.7
- zlib
* Uso:
Na inicialização, é necessário fornecer o ID do computador (1-4, que define as portas a serem utilizadas). Em seguida, é necessário informar o IP da máquina seguinte.
Após a conexão com sucesso no Anel, você tem as seguintes possibilidades:
- Enviar mensagem: "[maquina de destino]:[mensagem]" (sem aspas) + ENTER
- Jogar o bastão fora: "x" (sem aspas) + ENTER
- Sair do programa: "q" (sem aspas) + ENTER
Protocolo "JOKAKOMK (nome beta)"
*Campos:
Delimitador Inicio - 8 bits ("01011010")
Controle de Acesso - 8 bits \
Maq. Destino - 4 bits \ Calcula
Maq. Origem - 4 bits )
Tamanho - 4 bytes / o CRC32
Dados - n bytes /
CRC-32 - 32 bits
Status da mensagem - 8 bits
* Controle de Acesso
+------------+--------------+----------------+
| Token (1b) | Monitor (1b) | Reservado (6b) |
+------------+--------------+----------------+
[*] Token e Monitor estarão em '1' no momento da inicialização
* Status da Mensagem
CMx = Copy Maquina X
+---------+---------+---------+---------+---------+---------+---------+--------+
| CM1(1b) | CM2(1b) | CM3(1b) | CM4(1b) | CM1(1b) | CM2(1b) | CM3(1b) | CM4(1b)|
+---------+---------+---------+---------+---------+---------+---------+--------+
all:
@echo "Rodando chat.sh. Voce pode chama-lo ao inves de utilizar esse makefile."
@echo "Ele foi implementado para utilizarmos o clean durante o projeto."
@echo
@bash chat.sh
clean:
rm -f *.pyc
#!/bin/bash
python2 main.py
import networkManager as netMgr
import socketManager as sockMgr
import threading
import os
class threadTermInput(threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
while True:
newmessage = raw_input()
if len(newmessage) > 0:
if newmessage[0] >= '1' and newmessage[0] <= '5' and newmessage[1] == ':':
netMgr.addToOutQueue(newmessage[2:], ord(newmessage[0])-ord('1'))
elif newmessage[0] == 'x':
netMgr.loseToken()
elif newmessage[0] == 'q':
os._exit(0)
else:
print "*** ERRO *** Comando nao reconhecido!"
#class threadTermOutput(threading.Thread):
# def __init__(self, threadID, name, counter):
# threading.Thread.__init__(self)
# self.threadID = threadID
# self.name = name
# self.counter = counter
# def run(self):
# while True:
# if(netMgr.hasReceivedMessage()):
# print netMgr.getNextReceivedMessage()
relPortas = [(1334, 1335), (1335, 1336), (1336, 1337), (1337, 1334)]
pcId = raw_input("Bem-vindo ao batepapo UOL\nEscolha o seu ID (1-4): ")
while int(pcId) < 1 or int(pcId) > 4:
pcId = raw_input("Bem-vindo ao batepapo UOL\nEscolha o seu ID (1-4): ")
pcId = int(pcId) - 1
#sockets destino,origem
outsocket = sockMgr.openSocket()
insocket = sockMgr.openSocket()
#conexao endereco de origem para receber msgs
sockMgr.bindSocket(insocket, relPortas[pcId][0])
nmip = raw_input("Digite o IP da proxima maquina: ")
while nmip == "":
nmip = raw_input("Digite o IP da proxima maquina: ")
nmport = relPortas[pcId][1]
print("Conectando...")
sendToken = False
if pcId == 0:
sendToken = True
netMgr.startNetwork((insocket, outsocket), nmip, nmport, sendToken) #inicia rede entre sockets adjacentes
netMgr.setPcID(pcId) #PCID = pcId(0-3)
threadLeitura = threadTermInput(1, "Thread-Leitura", 1)
#threadOutput = threadTermOutput(1, "Thread-Output", 1)
threadLeitura.start()
#threadOutput.start()
while True:
netMgr.updateNetwork()
import protocolo as prot
import socketManager as sockmgr
import time
import socket
import exceptions
# nm = next machine
nip, nport, insocket, outsocket = None, None, None, None
outqueue, outqueuedest, inqueue = [], [], []
hasToken, sentMessage, genToken = False, False, False
hasToKillToken = False
lastTokenTime, pcId = 0, 0
def addToOutQueue(message, dest):
global outqueue, outqueuedest
outqueue.append(message)
outqueuedest.append(dest)
def addToInQueue(message):
global inqueue
inqueue.append(message)
def hasReceivedMessage():
#if len(outqueue) > 0:
# return True
#else:
# return False
global inqueue
return True if len(inqueue) > 0 else False
def hasMessageToSend():
global outqueue
return True if len(outqueue) > 0 else False
def getNextMessageToSend():
global outqueue
return outqueue.pop(0)
def getNextReceivedMessage():
global inqueue
return inqueue.pop(0)
def didAllReceived(status, dest):
pstatus = ord(status)
if dest < 4:
pdest = 2**dest
if(pstatus == ((pdest << 4) | pdest)):
return True
else:
return False
else:
target = (0xFF ^ (1 << pcId) ^ (1 << (pcId+4)))
if(pstatus == target):
return True
else:
return False
def updateNetwork():
global hasToken, lastTokenTime, outqueue, inqueue, sentMessage
global isWaitingForMonitor, genToken, hasToKillToken
curTime = int(round(time.time() * 1000))
if hasToken:
if sentMessage:
data = tryToGetMessage()
if data != False:
maqdest = (ord(data['maqconf']) >> 4)
maqorig = (ord(data['maqconf']) % 4)
if((ord(data['accessctrl']) & 0x40) == 0x40):
lastTokenTime = curTime
prot.loadDecodedPacket(data)
forwardPacket(prot.getPacket())
print "* Possivel erro no envio da mensagem, tente novamente!"
hasToken = False
sentMessage = False
elif(ord(data['accessctrl']) == 0x00):
if ((maqdest != maqorig) and (not didAllReceived(data['status'], maqdest))):
print "*** ERRO *** Nem todos os peers receberam a mensagem corretamente!"
sentMessage = False
else:
print "Erro na rede! Bastao recebido enquanto ja tinha bastao"
else:
if hasToKillToken:
hasToken = False
hasToKillToken = False
print "Eliminei o Token"
elif curTime - lastTokenTime > 200:
#Fim do periodo com o Token
tokenPass()
elif hasMessageToSend():
sendMessage()
#else:
# tokenPass()
else:
data = tryToGetMessage()
if data != False:
maqdest = (ord(data['maqconf']) >> 4)
maqorig = (ord(data['maqconf']) % 4)
if (data['accessctrl'] != None):
if ((ord(data['accessctrl']) & 0x80) == 0x80):
hasToken = True
genToken = False
lastTokenTime = curTime
elif((ord(data['accessctrl']) & 0x40) == 0x40):
if genToken:
if(maqorig == pcId):
print "* Token recriado com sucesso!"
lastTokenTime = curTime
genToken = False
hasToken = True
elif(maqorig < pcId):
lastTokenTime = curTime
genToken = False
prot.loadDecodedPacket(data)
forwardPacket(prot.getPacket())
else:
lastTokenTime = curTime
prot.loadDecodedPacket(data)
forwardPacket(prot.getPacket())
else:
if(maqorig != pcId):
if(maqdest == pcId or maqdest == 4):
print "Incoming from [" + str(maqorig+1) + "]: " + data['data']
data['status'] = chr(ord(data['status']) | (1 << pcId) | (1 << (pcId+4)))
prot.loadDecodedPacket(data)
forwardPacket(prot.getPacket())
if curTime - lastTokenTime > 2000:
#generate new token
generateNewToken()
lastTokenTime = curTime
genToken = True
def loseToken():
global hasToKillToken
hasToKillToken = True
def generateNewToken():
prot.resetMessage()
prot.setAccessCtrl(0,1)
prot.setMaqorig(pcId)
prot.setMaqdest(4)
sockmgr.sendPacket(outsocket, nip, nport, prot.getPacket())
def tokenPass():
global hasToken, lastTokenTime
if hasToken:
hasToken = False
lastTokenTime = int(round(time.time() * 1000))
prot.resetMessage()
prot.setAccessCtrl(1, 0)
prot.setMaqorig(pcId)
prot.setMaqdest((pcId+1) % 4)
packet = prot.getPacket()
sockmgr.sendPacket(outsocket, nip, nport, packet)
def sendMessage():
global outqueue, outqueuedest, sentMessage
if hasMessageToSend():
dest = outqueuedest.pop(0)
prot.resetMessage()
prot.setAccessCtrl(0, 0)
prot.setMaqdest(dest)
prot.setMaqorig(pcId)
prot.setMensagem(getNextMessageToSend())
packet = prot.getPacket()
sockmgr.sendPacket(outsocket, nip, nport, packet)
sentMessage = True
def sendMessageToTarget(target):
global sendMessage
if hasMessageToSend():
prot.resetMessage()
prot.setAccessCtrl(0, 0)
prot.setMaqdest(target)
prot.setMaqorig(pcId)
prot.setMensagem(getNextMessageToSend())
packet = prot.getPacket()
sockmgr.sendPacket(outsocket, nip, nport, packet)
sentMessage = True
def tryToGetMessage():
try:
rawpacket = insocket.recv(8096)
packet = prot.decodePacket(rawpacket)
#maqdest = ord(packet['maqconf']) >> 4
#forwardPacket(rawpacket)
return packet
except ValueError:
print "*** ERRO *** Mensagem recebida e invalida."
return False
except socket.error:
return False
def forwardPacket(fpacket):
sockmgr.sendPacket(outsocket, nip, nport, fpacket)
def setPcID(newpcid):
global pcId
pcId = newpcid
#sockets = (insocket, outsocket) - tip: IO - [I]nput/[O]utput Socket
def startNetwork(sockets, nmip, nmport, sendToken): # Inicia a rede
global insocket, outsocket, nip, nport, pcId, lastTokenTime, hasToken
insocket = sockets[0]
outsocket = sockets[1]
nip = nmip
nport = nmport
iniciou = False
while not iniciou:
aguardaPacote = True
if sendToken:
precisaReenviar = True
else:
precisaReenviar = False
while aguardaPacote:
if precisaReenviar:
prot.resetMessage()
prot.setAccessCtrl(1, 0)
prot.setMaqorig(0)
prot.setMaqdest(4)
prot.setMaquinaLeu(1)
packet = prot.getPacket()
sockmgr.sendPacket(outsocket, nmip, nmport, packet)
precisaReenviar = False
insocket.settimeout(0.5)
packetData = None
try:
packetData = insocket.recv(8096)
dictPacket = prot.decodePacket(packetData)
isValidPacket = True
if(ord(dictPacket['accessctrl']) != 0b01000000 and
ord(dictPacket['accessctrl']) != 0b10000000):
isValidPacket = False
if(isValidPacket and (ord(dictPacket['status']) == 0xFF or
ord(dictPacket['accessctrl']) == 0b1000000)):
# Pacote proprio retornou, rede ok
prot.resetMessage()
prot.setAccessCtrl(0, 1)
prot.setMaqorig(0)
prot.setMaqdest(4)
for i in range(0,4):
prot.setMaquinaLeu(i+1)
packet = prot.getPacket()
sockmgr.sendPacket(outsocket, nmip, nmport, packet)
if pcId == 0:
while not hasToken:
insocket.settimeout(1000.0) # Testar None ou 0 aqui depois.
packetData = insocket.recv(8096)
packet = prot.decodePacket(packetData)
if((ord(packet['accessctrl']) & 0x40) == 0x40):
print "Comecei com o Token"
hasToken = True
print("Conectado com sucesso!")
insocket.setblocking(0)
lastTokenTime = int(round(time.time() * 1000))
return
else:
# Pacote de rede de outro computador
i = 1
while(((ord(dictPacket['status']) & 0xF) >> i) > 0):
i += 1
pcId = i
prot.resetMessage()
prot.setAccessCtrl(1,0)
prot.setMaqorig(0)
prot.setMaqdest(4)
for i in range(0, pcId+1):
prot.setMaquinaLeu(i+1)
newPacket = prot.getPacket()
sockmgr.sendPacket(outsocket, nmip, nmport, newPacket)
except socket.timeout:
if sendToken:
precisaReenviar = True
File deleted
import struct
import zlib
inidelim = 0b01011010
accessctrl = 0
maqdest = 0
maqorig = 0
tamanho = 0
data = ""
crc = 0
msgstatus = 0
def resetMessage():
global accessctrl, maqdest, maqorig, tamanho, data, crc, msgstatus
accessctrl = 0
maqdest = 0
maqorig = 0
tamanho = 0
data = ""
crc = 0
msgstatus = 0
def setAccessCtrl(isToken, isMonitor):
global accessctrl
accessctrl = accessctrl | (0b10000000 if isToken else 0b0) | (0b01000000 if isMonitor else 0b0)
def setMaqorig(origem):
global maqorig
maqorig = origem
def setMaqdest(destino):
global maqdest
maqdest = destino
def setMensagem(mensagem):
global tamanho, data
data = mensagem
tamanho = len(mensagem)
def calcCRC(packet):
global crc
#confmaq = ((maqdest << 4) + maqorig) % 256
#csformat = "2ci%ds" % tamanho
#cs = struct.pack(csformat, chr(accessctrl % 256), chr(confmaq), tamanho, data.encode('ascii'))
crc = zlib.crc32(packet[1:(8+tamanho)]) & 0xFFFFFFFF
def setMaquinaLeu(maq):
global msgstatus
maq -= 1
if(maq > 3):
maq = 3
msgstatus = msgstatus | (0b1 << maq) | (0b1 << (maq + 4))
def getPacket():
global crc
msgformat = "3ci%dsIc" % tamanho
confmaq = ((maqdest << 4) + maqorig) % 256
crc = 0
calcCRC(struct.pack(msgformat, chr(inidelim), chr(accessctrl & 255), chr(confmaq), tamanho, data, crc, chr(msgstatus & 255)))
return struct.pack(msgformat, chr(inidelim), chr(accessctrl & 255), chr(confmaq), tamanho,
data, crc, chr(msgstatus & 255))
def decodePacket(packet):
pinidelim, paccessctrl, pmaqconf, ptamanho = struct.unpack("3ci", packet[:8])
pdata, pcrc, pmsgstatus = struct.unpack("%dsic" % ptamanho, packet[8:])
newcrc = zlib.crc32(packet[1:(8+ptamanho)]) & 0xFFFFFFFF
if(ord(pinidelim) != inidelim or (pcrc & 0xFFFFFFFF) != newcrc):
raise ValueError("packet malformatado")
return {'accessctrl': paccessctrl, 'maqconf': pmaqconf, 'tamanho': ptamanho, 'data': pdata,
'crc': pcrc, 'status': pmsgstatus}
def loadDecodedPacket(dpacket):
global accessctrl, maqorig, maqdest, tamanho, data, msgstatus
accessctrl = ord(dpacket['accessctrl'])
maqdest = ord(dpacket['maqconf']) >> 4
maqorig = ord(dpacket['maqconf']) % (2**4)
tamanho = dpacket['tamanho']
data = dpacket['data']
msgstatus = ord(dpacket['status'])
File deleted
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment