Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
/build/*
/dist/*
/cqc.egg-info/*
/cqc/settings.ini

.idea/*
470 changes: 470 additions & 0 deletions cqc/MessageHandler.py

Large diffs are not rendered by default.

178 changes: 178 additions & 0 deletions cqc/Protocol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Copyright (c) 2017, Stephanie Wehner and Axel Dahlberg
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Stephanie Wehner, QuTech.
# 4. Neither the name of the QuTech organization nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import logging

from twisted.internet.defer import inlineCallbacks
from twisted.internet.protocol import Protocol, connectionDone

from cqc.cqcHeader import CQC_HDR_LENGTH, CQC_VERSION, CQCHeader

###############################################################################
#
# CQC Protocol
#
# Execute the CQC Protocol giving access to the SimulaQron backend via the
# universal interface.
#


class CQCProtocol(Protocol):
# Dictionary storing the next unique qubit id for each used app_id
_next_q_id = {}

# Dictionary storing the next unique entanglement id for each used
# (host_app_id,remote_node,remote_app_id)
_next_ent_id = {}

def __init__(self, factory):

# CQC Factory, including our connection to the SimulaQron backend
self.factory = factory

# Default application ID, typically one connection per application but
# we will deliberately NOT check for that since this is the task of
# higher layers or an OS
self.app_id = 0

# Define the backend to use. Is a setting in settings.ini
self.messageHandler = factory.backend

# Flag to determine whether we already received _all_ of the CQC header
self.gotCQCHeader = False

# Header for which we are currently processing a packet
self.currHeader = None

# Buffer received data (which may arrive in chunks)
self.buf = None

# Convenience
self.name = self.factory.name

logging.debug("CQC %s: Initialized Protocol", self.name)

def connectionMade(self):
pass

def connectionLost(self, reason=connectionDone):
pass

def dataReceived(self, data):
"""
Receive data. We will always wait to receive enough data for the
header, and then the entire packet first before commencing processing.
"""
# Read whatever we received into a buffer
if self.buf:
self.buf = self.buf + data
else:
self.buf = data

# If we don't have the CQC header yet, try and read it in full.
if not self.gotCQCHeader:
if len(self.buf) < CQC_HDR_LENGTH:
# Not enough data for CQC header, return and wait for the rest
return

# Got enough data for the CQC Header so read it in
self.gotCQCHeader = True
raw_header = self.buf[0:CQC_HDR_LENGTH]
self.currHeader = CQCHeader(raw_header)

# Remove the header from the buffer
self.buf = self.buf[CQC_HDR_LENGTH: len(self.buf)]

logging.debug("CQC %s: Read CQC Header: %s", self.name, self.currHeader.printable())

# Check whether we already received all the data
if len(self.buf) < self.currHeader.length:
# Still waiting for data
logging.debug(
"CQC %s: Incomplete data. Waiting. Current length %s, " "required length %s",
self.name,
len(self.buf),
self.currHeader.length,
)
return

# We got the header and all the data for this packet. Start processing.
# Update our app ID
self.app_id = self.currHeader.app_id
# Invoke the relevant message handler, processing the possibly
# remaining data
try:
self._parseData(self.currHeader, self.buf[0: self.currHeader.length])
except Exception as e:
print(e)
import traceback

traceback.print_exc()

# if self.currHeader.tp in self.messageHandlers:
# self.messageHandlers[self.currHeader.tp](self.currHeader, )
# else:
# self._send_back_cqc(self.currHeader, CQC_ERR_UNSUPP)

# Reset and await the next packet
self.gotCQCHeader = False

# Check if we received data already for the next packet, if so save it
if self.currHeader.length < len(self.buf):
self.buf = self.buf[self.currHeader.length: len(self.buf)]
self.dataReceived(b"")
else:
self.buf = None

@inlineCallbacks
def _parseData(self, header, data):
try:
yield self.messageHandler.handle_cqc_message(header, data)
messages = self.messageHandler.retrieve_return_messages()
except Exception as e:
raise e

if messages:
# self.factory._lock.acquire()
for msg in messages:
self.transport.write(msg)
# self.factory._lock.release()

def _send_back_cqc(self, header, msgType, length=0):
"""
Return a simple CQC header with the specified type.

header CQC header of the packet we respond to
msgType Message type to return
length Length of additional message
"""
hdr = CQCHeader()
hdr.setVals(CQC_VERSION, msgType, header.app_id, length)

msg = hdr.pack()
self.transport.write(msg)
26 changes: 26 additions & 0 deletions cqc/entInfoHeader.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,32 @@ class EntInfoHeader(Header):
HDR_LENGTH = ENT_INFO_LENGTH
packaging_format = "!LHHLHHLQQHBB"

def __init__(self, headerBytes=None):
"""
Initialize using values received from a packet, if available.
"""
super().__init__(headerBytes)
if headerBytes is None:
self.node_A = 0
self.port_A = 0
self.app_id_A = 0

self.node_B = 0
self.port_B = 0
self.app_id_B = 0

self.id_AB = 0

self.timestamp = 0
self.ToG = 0
self.goodness = 0
self.DF = 0
self.is_set = False
else:
self.unpack(headerBytes)
self.is_set = True


def _setVals(self, node_A=0, port_A=0, app_id_A=0, node_B=0, port_B=0, app_id_B=0, id_AB=0, timestamp=0, ToG=0,
goodness=0, DF=0):
"""
Expand Down
1 change: 0 additions & 1 deletion cqc/pythonLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@
from cqc.hostConfig import cqc_node_id_from_addrinfo, networkConfig



def shouldReturn(command):
return command in {
CQC_CMD_NEW,
Expand Down
1 change: 1 addition & 0 deletions cqc/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def set_config(config):
with open(settings_file, 'w') as f:
config.write(f)


def get_cqc_file():
"""
Gets the path to the CQC file used
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
numpy>=1.14.0
bitstring>=3.1.5
flake>=3.6.0
flake8>=3.6.0
twisted>=18.7.0
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

setuptools.setup(
name="cqc",
version="2.0.1",
version="2.2.0",
author="Axel Dahlberg",
author_email="[email protected]",
description="The CQC interface",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/SoftwareQuTech/CQC",
url="https://github.com/SoftwareQuTech/CQC-Python",
include_package_data=True,
package_data={
'cqc': ['settings.ini']
Expand Down