def test_mult_types_gui_queue_receiver(self): nc = setup() # construct inner request startRequest = control_signals_pb2.StartRequest() startRequest.port = 0 startRequest.channels = 0xDEADBEEF # construct request wrapper containing inner requestWrapper1 = control_signals_pb2.RequestWrapper() requestWrapper1.sequence = 1 requestWrapper1.start.MergeFrom(startRequest) # can't assign directly for some reason, need to merge serialized1 = requestWrapper1.SerializeToString() # construct inner request stopRequest = control_signals_pb2.StopRequest() stopRequest.port = 0 stopRequest.channels = 0xDEADBEEF # construct request wrapper containing inner requestWrapper2 = control_signals_pb2.RequestWrapper() requestWrapper2.sequence = 2 requestWrapper2.stop.MergeFrom(stopRequest) # can't assign directly for some reason, need to merge serialized2 = requestWrapper2.SerializeToString() # pass the serialized message wrappers to the network controller # "from" the GUI from_gui_queue.put(serialized1) from_gui_queue.put(serialized2) time.sleep(0.5) # wait for nc to read from queue assert from_gui_queue.empty()
def handle_read(self): # read 16 bit length header size = bytearray(2) try: self.recv_into(size) except socket.error as serr: logging.error('ControlClient: failed to connect, error is %s', serr) self.connected = False self.handle_close() return length = (size[1] << 8) + size[0] print length logging.debug('ControlClient: received length header: %s', length) # read the message content msg = self.recv(length) logging.debug('ControlClient: received message: %s', msg) # TODO: (probably not necessary) put onto incoming_queue and have another thread handle the parsing # construct a container protobuf and parse into from serialized message ackWrapper = control_signals_pb2.RequestWrapper() ackWrapper.ParseFromString(msg) sequence = ackWrapper.sequence if sequence in self.sent_dict.keys(): serialized_acked_request = self.sent_dict.pop(sequence) logging.debug('ControlClient: ACKed request popped %s', serialized_acked_request) self.control_protobuf_conn.send(msg) self.ack_msg_from_cc_event.set()
def handle_write(self): # notify NetworkController that we are connected self.connected_event.set() # grab request to be sent from the incoming connection serialized_req_wrap = self.control_protobuf_conn.recv() logging.debug( 'ControlClient: handle_write() retrieved msg from outgoing queue') # parse the request for storage in sent_dict request_wrapper = control_signals_pb2.RequestWrapper() request_wrapper.ParseFromString(serialized_req_wrap) length = np.uint16(len(serialized_req_wrap)) logging.debug( 'ControlClient: sending message length %d over control socket', length) self.send(length) logging.debug( 'ControlClient: sending Request message over control socket') sent = self.send(serialized_req_wrap) logging.debug('ControlClient: sent message bytes: %d', sent) logging.debug('ControlClient: adding request %d to sent_dict', request_wrapper.sequence) if request_wrapper.sequence not in self.sent_dict.keys(): self.sent_dict[request_wrapper.sequence] = serialized_req_wrap else: raise RuntimeWarning( 'ControlClient: requestWrapper with sequence %d already in sent_dict' % request_wrapper.sequence)
def test_gui_queue_receiver(self): nc = setup() startRequest = control_signals_pb2.StartRequest() startRequest.port = 1 startRequest.channels = 0xDEADBEEF requestWrapper = control_signals_pb2.RequestWrapper() requestWrapper.sequence = 1 requestWrapper.start.MergeFrom(startRequest) # can't assign directly for some reason, need to merge from_gui_queue.put(requestWrapper.SerializeToString()) time.sleep(0.5) # wait for nc to read from queue assert from_gui_queue.empty()
def recv_request_wrapper(control_conn): # synchronously read in the msg length header length = '' while length == '': length = control_conn.recv(2) print length print 'ControlServer: received length header: %s' % length # read in the message content msg = control_conn.recv(int(length)) # construct a reply container and parse from the received message requestWrapper = control_signals_pb2.RequestWrapper() requestWrapper.ParseFromString(msg) print 'ControlServer: received request message:\n%s' % requestWrapper return requestWrapper
def test_control_socket_send_request(self): nc = setup() # Simulate message from GUI # first construct the inner request startRequest = control_signals_pb2.StartRequest() startRequest.port = 1 startRequest.channels = 0xDEADBEEF # then insert it into a request wrapper requestWrapper = control_signals_pb2.RequestWrapper() requestWrapper.sequence = 1 requestWrapper.start.MergeFrom(startRequest) # finally, serialize to send across boundary serialized = requestWrapper.SerializeToString() # setup a server socket to listen for control client connection server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.bind(('localhost', 10001)) server_sock.listen(1) print 'listening on %s:%d' % ('localhost', 10001) # tell the network controller to attempt a connection to the server socket nc.connect_control_port() conn, addr = server_sock.accept() print 'accepted connection from %s:%d' % (addr[0], addr[1]) # load request into queue to be sent over control socket by ControlClient from_gui_queue.put(serialized) received = recv_request_wrapper(conn) startMessage = control_signals_pb2.StartRequest() startMessage.MergeFrom(received.start) # check that we received a StartRequest back and it has the same fields assert received.HasField('start') assert startMessage.port == 1 assert startMessage.channels == 0xDEADBEEF nc.close_control_port() server_sock.close() conn.close()
global to_gui_queue global gui_data_queue stg_queue = mp.Queue() from_gui_queue = mp.Queue() to_gui_queue = mp.Queue() gui_data_queue = mp.Queue() nc = NetworkController(stg_queue, from_gui_queue, to_gui_queue, gui_data_queue) # construct the initial start streaming request startRequest = control_signals_pb2.StartRequest() startRequest.port = 10002 startRequest.channels = 0xFFFFFFFF startRequest.rate = 200000 # then insert it into a request wrapper requestWrapper = control_signals_pb2.RequestWrapper() requestWrapper.sequence = 1 requestWrapper.start.MergeFrom(startRequest) # finally, serialize to send across boundary serialized = requestWrapper.SerializeToString() # tell the network controller to attempt a connection to the control server nc.connect_control_port() # load request into queue to be sent over control socket by ControlClient from_gui_queue.put(serialized) time.sleep(1) assert nc.data_client.connected
def read_ack_messages(self): while not self.stop_event.is_set(): if self.nc_control_conn.poll(): ack = self.nc_control_conn.recv() ack_wrapper = control_signals_pb2.RequestWrapper() ack_wrapper.ParseFromString(ack) logging.info('NetworkController: received ACK message %s', ack_wrapper) if ack_wrapper.sequence in self.sent_dict.keys(): msg = self.sent_dict.pop(ack_wrapper.sequence) else: msg = {} raise RuntimeWarning( 'NetworkController: received unexpected ACK from ControlClient' ) if ack_wrapper.HasField( 'start') and not self.data_client.connected: logging.info( 'NetworkController: received start ACK, starting data client' ) start_request = control_signals_pb2.StartRequest() start_request.MergeFrom(ack_wrapper.start) # make sure that we're getting the channels we expect if start_request.channels != msg['channels']: raise RuntimeWarning( 'NetworkController: active channels in ACK differ from requested' ) # send header info to SC and notify active_channels = self.get_channels_from_bitmask( start_request.channels) bytes_per_sample = (len(active_channels) + 4) * 2 chunk_size = min( 113, int(msg['rate'] * bytes_per_sample * 0.00001)) print 'received timestamp %d' % start_request.timestamp header = (start_request.timestamp, start_request.channels, chunk_size, start_request.rate) self.file_header_sender.send(header) self.file_header_available_event.set() data_connect_success, data_serr = self.connect_data_port( self.host, start_request.port, chunk_size, active_channels) logging.debug( 'NetworkController: data_connect_success = %s', data_connect_success) if data_connect_success: # construct a success reply message reply_msg = msg reply_msg['success'] = True reply_msg[ 'message'] = 'Successfully connected control and data ports to host %s' % self.host reply_msg['timestamp'] = start_request.timestamp reply_msg['chunk'] = chunk_size # send an ACK message to GUI and notify its receiver self.gui_control_conn.send(reply_msg) self.control_msg_from_nc_event.set() else: # construct a failure reply message reply_msg = msg reply_msg['success'] = False reply_msg['message'] = 'Failed to connect DataClient to %s:%d, error is %s' % \ (self.host, start_request.port, data_serr) self.gui_control_conn.send(reply_msg) self.control_msg_from_nc_event.set() elif ack_wrapper.HasField( 'stop') and self.data_client.connected: data_port_disconnected = self.close_data_port() self.close_control_port() control_port_disconnected = self.control_client_disconnected_event.wait( timeout=5.0) if data_port_disconnected and control_port_disconnected: reply_msg = msg reply_msg['success'] = True reply_msg[ 'message'] = 'Control and Data clients disconnected successfully' self.gui_control_conn.send(reply_msg) self.control_msg_from_nc_event.set() else: reply_msg = msg reply_msg['success'] = False reply_msg[ 'message'] = 'Unable to disconnect properly or control client disconnect timed out' self.gui_control_conn.send(reply_msg) self.control_msg_from_nc_event.set() else: logging.warning( 'NetworkController: received an unexpected ACK type %s', ack_wrapper) else: while not self.stop_event.is_set(): if self.ack_msg_from_cc_event.wait(1.0): self.ack_msg_from_cc_event.clear() break
def recv_from_gui(self): while not self.stop_event.is_set(): if self.gui_control_conn.poll(): msg = self.gui_control_conn.recv() logging.info( 'NetworkController: received control message: \n%s', msg) if msg['type'] == 'CONNECT': # TODO: input validation self.host = msg['host'] self.port = msg['port'] success, serr = self.connect_control_port( self.host, self.port) if not success: # ControlClient connect failed, notify GUI reply_msg = msg reply_msg['success'] = False reply_msg['message'] = 'Failed to connect ControlClient to %s:%d, error is %s' % \ (self.host, self.port, serr) self.gui_control_conn.send(reply_msg) self.control_msg_from_nc_event.set() else: # construct a StartRequest protobuf message startRequest = control_signals_pb2.StartRequest() startRequest.port = self.port + 1 startRequest.channels = msg['channels'] startRequest.rate = msg['rate'] # wrap it up and copy sequence number requestWrapper = control_signals_pb2.RequestWrapper() requestWrapper.sequence = msg['seq'] requestWrapper.start.MergeFrom(startRequest) # serialize wrapper for sending over Pipe serialized = requestWrapper.SerializeToString() self.nc_control_conn.send(serialized) logging.debug( 'NetworkController: sent serialized requestWrapper to CC' ) # ControlClient uses asyncore so we don't need to notify it if msg['seq'] not in self.sent_dict.keys(): self.sent_dict[msg['seq']] = msg else: raise RuntimeWarning( 'NetworkController: control msg with sequence %d already in sent_dict' % msg['seq']) # asyncore client doesn't connect until it tries to recv/send, # so we need to be notified asynchronously control_client_connected = self.control_client_connected_event.wait( timeout=5.0) if not control_client_connected: # ControlClient connect timed out, notify GUI reply_msg = msg reply_msg['success'] = False reply_msg['message'] = 'Timed out while trying to connect ControlClient to %s:%d' % \ (self.host, self.port) self.gui_control_conn.send(reply_msg) self.control_msg_from_nc_event.set() elif msg['type'] == 'DISCONNECT': # construct a StopRequest protobuf message stopRequest = control_signals_pb2.StopRequest() stopRequest.port = self.port + 1 stopRequest.channels = 0xffff # wrap it up and copy sequence number requestWrapper = control_signals_pb2.RequestWrapper() requestWrapper.sequence = msg['seq'] requestWrapper.stop.MergeFrom(stopRequest) # serialize wrapper for sending over Pipe serialized = requestWrapper.SerializeToString() self.nc_control_conn.send(serialized) logging.debug( 'NetworkController: sent serialized requestWrapper to CC' ) # ControlClient uses asyncore so we don't need to notify it if msg['seq'] not in self.sent_dict.keys(): self.sent_dict[msg['seq']] = msg else: raise RuntimeWarning( 'NetworkController: control msg with sequence %d already in sent_dict' % msg['seq']) else: while not self.stop_event.is_set(): if self.control_msg_from_gui_event.wait(1.0): self.control_msg_from_gui_event.clear() break
def test_connection(self): print 'Starting Data:test_connection()' nc = setup() # construct the initial start streaming request startRequest = control_signals_pb2.StartRequest() startRequest.port = 10002 startRequest.channels = 0xFFFFFFFF # then insert it into a request wrapper requestWrapper = control_signals_pb2.RequestWrapper() requestWrapper.sequence = 1 requestWrapper.start.MergeFrom(startRequest) # finally, serialize to send across boundary serialized = requestWrapper.SerializeToString() # setup a server socket to listen for control client connection server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.bind(('localhost', 10001)) server_sock.listen(1) print 'ControlServer: listening on %s:%d' % ('localhost', 10001) # setup a server socket to listen for data client connection sender_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sender_sock.bind(('localhost', 10002)) sender_sock.listen(1) print 'DataServer: listening on %s:%d' % ('localhost', 10002) # tell the network controller to attempt a connection to the control server nc.connect_control_port() control_conn, addr = server_sock.accept() print 'ControlServer: accepted connection from %s:%d' % (addr[0], addr[1]) # load request into queue to be sent over control socket by ControlClient from_gui_queue.put(serialized) received = recv_request_wrapper(control_conn) inner_request = control_signals_pb2.StartRequest() inner_request.MergeFrom(received.start) assert inner_request.port == 10002 # construct a reply ACK and send over control connection serialized_ack = received.SerializeToString() length = sys.getsizeof(serialized_ack) control_conn.send(str(length)) control_conn.send(serialized_ack) data_conn, data_addr = sender_sock.accept() print 'DataServer: accepted connection from %s:%d' % (data_addr[0], data_addr[1]) assert data_conn.send('ayy') # cleanup and close all connections nc.close_control_port() sender_sock.close() data_conn.close() server_sock.close() control_conn.close()