-
Notifications
You must be signed in to change notification settings - Fork 0
/
Grapple.py
135 lines (123 loc) · 5.54 KB
/
Grapple.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from Pocket import Pocket
from Inbox import Inbox
from Outbox import Outbox
from socket import *
# import scapy
# import getmac
import sys
class Grapple:
'''handles all connections to and exchange of information with remote nodes'''
def __init__(self):
self.socket = None # stores TCP connection with node
# https://stackoverflow.com/a/26641964/4513452
self.big_drop = "" # stores all messages, to be sent all at once
def get_socket(self):
'''returns current socket (active or otherwise)'''
return self.socket
def find_node(self):
'''identifies, returns addr of node on local network'''
# should run network scan to get all IPs
# then compare mac addresses of all IPs to prefix for rpis
# (https://raspberrypi.stackexchange.com/a/13937)
# perform some sort of handshake with node to verify correctness
return ("127.0.0.1", 13337) # for the scope of hackathon, node address addr is hardcoded
def setup(self, server_info):
'''sets up socket for communication with node'''
# create new socket, using ipv4 type address, tcp protocol
new_socket = socket(AF_INET, SOCK_STREAM)
# connect to the node with given info
new_socket.connect(server_info)
return new_socket
def close(self):
'''close socket and end communication with node'''
self.socket.close()
return
def add_to_drop(self, new_message):
'''adds message to string with "|" as dellineator'''
# I apologize to anyone who reads this--no time to justify it right now
self.big_drop += new_message + "$$$$"
return
def socket_message(self, message):
'''encode and send given message over socket'''
# https://stackoverflow.com/a/14473492/4513452
# janky, but default bytes() method for pgpy was causing encoding issues
message = str(message)
# print("size of message being sent: ", sys.getsizeof(message))
# print("message being sent: ", message)
# self.socket.send( bytes(message, encoding='utf8') )
# as temporary fix, instead of sending, add to compiled message
self.add_to_drop(message)
return
def identify_self(self):
'''identify self to node by sending own pub key'''
# *should* sign own public key and send that as message, node can verify ownership
public_key = Pocket().public_key() # grab own pub key as bytes
# for now will just send own public key to node
self.socket_message(public_key)
return
def receive_messages(self, own_inbox):
'''receive incoming messages via socket'''
# wait to receive the response from the server (using buffer size of 2048)
# incoming_messages = [] # make list to hold all incoming messages
# # while not received end indicator (breaks out if received)
# while True: # easier this way because each read of socket is new message
# caught_message = self.socket.recv(2048).decode() # decoded socket data
# print("\n\tcaught message: ", caught_message)
# if (caught_message == "RECV_FINISHED"): # received end indicator
# break
# incoming_messages.append(caught_message) # append to message list
# catch incoming messages (really just one big one)
# incoming_data = self.socket.recv(2048).decode()
incoming_data = ""
while True:
# receive data stream
data_catch = self.socket.recv(2048).decode()
# print("data_catch: ", data_catch)
# continually add incoming data to storage string
incoming_data += data_catch
# wait for end of message indicator
if (incoming_data[-4:] == "####"):
break
incoming_messages = incoming_data.split("$$$$")[:-1] # cut off end because it's not msg
for i in range(len(incoming_messages)): # for all received messages
# don't know what I was doing here, but pretty sure this method doesn't exist
# own_inbox.add_transit_message(incoming_messages[i]) # add to given inbox
# print("incoming message type: ", type(incoming_messages[i]))
# print("incoming message: ", incoming_messages[i])
own_inbox.add_message( incoming_messages[i] ) # add to given inbox
return
def send_messages(self, own_outbox):
'''send messages to node over socket'''
# may want to check if message has already been delivered to a given node later
outgoing_messages = [] # make list to hold outgoing messages
for i in range(own_outbox.count_messages()): # for num messages in outbox
# "send" message at front of outbox by adding to outgoing messages list
# and decrementing remaining deliveries to make
outgoing_messages.append(own_outbox.send_message())
# send all messages in outgoing messages list
for i in range(len(outgoing_messages)):
self.socket_message( outgoing_messages[i] )
# send message indicating end of send
# self.socket_message("SEND_FINISHED") # not for new type
# temporary fix
# print("actual message: ", (self.big_drop + "####")
self.socket.send( bytes((self.big_drop + "####"), encoding='utf8') )
return
def embrace(self, own_inbox, own_outbox):
'''identifies node on local network, instantiates connection and exchanges messages'''
node_address = self.find_node() # identify and record node location
self.socket = self.setup(node_address) # instantiate socket and save to self
self.identify_self() # identify self to node (just add to front of out data)
self.send_messages(own_outbox) # send all outgoing messages from outbox
self.receive_messages(own_inbox) # collect incoming messages and add to inbox
self.close()
if __name__ == '__main__':
# pickle testing (just for testing which types have pickle issues)
import pickler as pr
var_name = 'new_grapple'
og_init = " = " + "Grapple()"
if pr.is_pickled(var_name):
exec(var_name + " = pr.get_pickled(var_name)")
else:
exec(var_name + og_init)
pr.pickle_it(var_name, eval(var_name))