Skip to content

Lab0Milestone4

sethnielson edited this page Apr 8, 2019 · 2 revisions

This is milestone 3 deliverable for Lab 0: Company Product. Although part of a larger lab, it is submitted for grading as an independent assignment.

Lab 0 Milestone 4: Technical functionality 2

Assigned 3/25/2019
Due 4/13/2019
Points 25

Overview

You should already have code created from milestone 1. For this milestone, you need to integrate in some bitpoint-money into the client and server exchange. That is, you should be able to demonstrate a basic transaction for your system that involves the client making a request of the bank, getting the receipt, and transmitting it to the server for validation.

Sample Code

To help you with this, there is a sample "Escape Room" client/server in the class github. The files are found under src/samples/escape_room_for_profit. There are four files:

  1. escape_room_core.py
  2. escape_room_client.py
  3. escape_room_server.py
  4. escape_room_packets.py

The escape room core file is just the basic escape room class. This is similar to previous escape room classes. It just provides the basic game logic.

The packets file has some network packets that are used by both client and server. By putting them in one file, both the client and server can import them. The packets defined are:

  • RequestGame
  • RequestAdmission
  • ProofOfPayment
  • PaymentResult
  • GameRequest
  • GameResult

We will start with the server. In you look at escape_room_server.py you will see a EscapeRoomServerProtocol class. The data_received method uses the type of message and state information to route packets.

It first checks if the message is a RequestGame. If so, it uses a helper class (that tracks admissions) to create a RequestAdmission packet. This packet is a request to the client to pay for admission. The helper class, payment processing tracks admission requests and creates tokens for each one. This really isn't necessary if you use a secured session. Once you have secure channels, the channel itself is the "token." But I wrote it this way in case I wanted to make the connection stateless.

Let's discuss this a little, because the concept is important. When you care creating a client server application, you can rely on the underlying data connection to give you some kind of state information. For example, TCP "guarantees" that the underlying connection is reliable. But how strong is that guarantee? No very. Add TLS on top of TCP, however, and you now have cryptographic assurances that every packet in the session belongs to the same party, has not been modified, and was delivered correctly. Once you have that kind of assurance in a session, you really don't need to keep a "token" because the session itself is guaranteed to be uninterrupted.

On the other hand, if you were working over a non-session channel, such as UDP, there is no guarantee that any message is related to any other message. So you hand out a token that needs to be included in every subsequent message that is related. That way, the server can access appropriate state.

Here's another way of thinking about it.

Secure Session

Client: Hi, I'd like to buy a ticket Server: Ok, that's 10USD Client: Here's a receipt of 10USD I deposited to your bank account Server: Great. You can play the game now. Client: For my first move, I would like to "look mirror."

The Server knows that the client in all three messages is the same party because the session is guaranteed to be secure.

  • Non-Session *

Client A: Hi, I'd like to buy a ticket Server: Ok, here's your token 3280. Please pay 10USD Client B: Hi. I'm the same client as Client A because I have token 3280. I deposited 10USD to your bank account Server: Let me look up 3280. Yes, I see, you are client A and I asked you to deposit 10USD. You're admitted Client C: Hi. I'm the same client as client A because I have token 3280. For my first move, I would like to "look mirror" Server: Let me look up 3280. Yes, you paid and I have an escape room game for you. Your response is...

The Server can't tell that each client (A, B, and C) are the same, so the client has to provide some proof or token.

What prevents someone from stealing this token? Nothing! If someone eavesdrops, they could just reuse the token (3280) and claim to be Client A. So you still might need encryption for each message, but the individual messages don't have to be tied together.

This, by the way, is how amazon shopping works. How does the browser know that you're the same person from one webpage to the next? Cookies! A Cookie is a token that enables the browser to connect individual web requests together.

For your system, you can either assume secure sessions (which we'll have soon) or you can have individually secure messages and a token.

The code in the sample assumes a secure session, but also has tokens to illustrate the idea. For example, the RequestAdmission packet looks like this:

class RequestAdmission(PacketType):
    DEFINITION_IDENTIFIER = "samples.escape_room_for_profit.RequestAdmission"
    DEFINITION_VERSION = "1.0"
    FIELDS = [
        ("account", STRING),
        ("amount",  UINT16),
        ("token",   UINT32)
    ]

The token is just a random number that is an ID. The account is the account that the client needs to deposit to and the amount is hopefully self explanatory. This information informs the client of the requirements to be admitted to the escape room.

Jumping over to the client, you'll see that there's a RequestGame that's sent right on start-up (connection_made). Then, in response, it gets back the RequestAdmission from the server. It hands this data off to an async method pay_for_admission. This method relies on a helper class's make_payment. Let's look at this function:

async def make_payment(self, dst_account, amount, memo):
    loop = asyncio.get_event_loop()
    bank_addr = self._bankconfig.get_parameter("CLIENT","bank_addr")
    bank_port = int(self._bankconfig.get_parameter("CLIENT","bank_port"))

    print("Connect to bank {}:{} for payment.".format(bank_addr, bank_port))

    transport, protocol = await playground.create_connection(
        lambda: BankClientProtocol(self._bank_cert, self._login_name, self._password),
        bank_addr,
        bank_port)
    try:
        result = await protocol.loginToServer()
    except Exception as e:
        print("Could not log in because", e)
        self.transport.close()
        return None

    try:
        result = await protocol.switchAccount(self._src_account)
        result = await protocol.transfer(dst_account, amount, memo)
    except Exception as e:
        result = None
        print("Could not transfer funds because", e)

    try:
        protocol.close()
    except Exception as e:
        print ("Warning, could not close bank connection because", e)
    return result

You can ignore the bank config stuff. You could put in the bank address and port directly. Regardless, after you create a connection, you use the BankClientProtocol, which is available to you from the OnlineBank.py file in the Bank github. This class allows you to login, switch accounts, etc. And these are async functions so we're running them async with await to wait for them to finish.

Look how easy this code is when you boil it down:

  • create connection to bank with the client protocol
  • login to the bank
  • switch to the source account
  • transfer funds to the destination account
  • the result of the transfer is a receipt

I'll leave the rest up to you to look at but basically you transfer this receipt and its signature to the server as proof of payment.

Submit a Summary

Please write a 1-page summary of how your system works:

  • How do you decide how much to charge? Is it fixed? Is it based on types of service?
  • How do you associate a client with a payment? Token? Session?
  • Does the payment have a time expiration? If they don't use the services within a period of time, do they lose them?

You need to submit both code and the summary.

Grading

Submit your lab 0 milestone 3 technical report in your team github as follows:

<team_repository_root>/doc/lab0/technial_update2.[ext]

We will accept contracts as PDF's, word documents, text, or html. The summary should also include the github locations of the client and server code for this update.

The contract has two grading pieces. First, you will receive 25 points for the class as explained in the syllabus. Second, you will also receive 5000 bit points that will be deposited into a team bank account. You can divide up bitpoints into personal accounts if you wish.

There is no grading breakdown. This is a pass/fail assignment, although we may ask you to add more information to your contract or update it for clarity/content. We will only deduct points if we feel your team is not making a good faith effort.