GitHunt
MU

mucel29/pcom-3

Archive of the third homework for the Communication Protocols course.

Communication Protocols - HW3

Asavoae Cosmin-Stefan, 321CD



'Borrowed' library

For this assignment I chose to go with parson for parsing & working with JSON payloads.


Notable API calls

Because this implementation follows closely the given specs (and most of the calls only send a request and print the result), I chose to detail only the more complex API calls and the helpers I've made to create a better program flow.


context_t

This is not an API call, but is an important part of the calls that are made.

The context_t stores the runtime information about

  • Admin session cookie
  • User session cookie
  • User access JWT

The cookie field is used for storing the session cookie that will be used for the next API call. This avoids duplicate functions for both the user and admin requests.

login / logout


These are basic API calls, but they also update / delete the user / admin cookie stored inside the context (also the JWT for users)


add_collection


This API call makes use of the create_collection & update_collection helpers to:

  • Create a collection with the given title
  • Add movies using the provided movie_id[i]

The call reports an error if:

  • The collection couldn't be created
  • Any movie couldn't be added (or it doesn't exist)

purge

While not being a required command, purge is used during debugging to delete all the users created by the admin.

Flow:

  • Get all the users
  • Use the response to make a delete_user call for every user



Helpers

To simplify my work, I've created some helper functions for:

  • Sending / Receiving TCP packets
  • Sending HTTP requests
  • Parsing HTTP responses
  • Constructing API payloads
  • Making API calls
  • Dispatching commands

TCP Helpers

send_tcp & recv_tcp are used for communicating with the HTTP server. Not much to be said about them considering that they're reused from HW2.


send_request

This function builds the HTTP payload to be sent to the server based on the parameters present in req. A cookie is set if the context cookie pointer is valid, the same for the JWT. The provided JSON body is serialized and appended at the end (if it exists).

After the server responds, the packet is then parsed and returned.


parse_response

This helper reads the HTTP response from the server and builds the body into a JSON value. The functions returns a response_t which contains the status code of the result, any cookie that was set and the deserialized JSON body.


build_body

Using the provided fields and their types, this helper asks the user for input and builds a JSON value to be used as the body for an HTTP request.


build_path

Asks the user for the provided field value and concatenates it to the provided path. A new string is returned, but it is reused by the function on every call (it's static, duh).


send_api

This is a beefed-up version of send_request which takes care of:

  • Setting the correct cookie
  • Making the HTTP request
  • Handling a basic SUCCESS or ERROR
  • Discarding the response if it will not be used or an error occurred
  • Returning whether the call was successful or not

If the response doesn't contain a message or error field, the fallbacks provided in req will be used.

If the res pointer is not NULL, the helper will store the response in it (also if the call was successful).


d_table_t

To avoid writing a tower if if-else-if statements, I decided to use a dispatch table.

Each entry contains the command name and its corresponding function pointer

On each command input, the table is searched for the provided name, making the corresponding API call or quitting if it's invalid



Personal Notes (Feedback)

Please note that these are just things I found annoying while solving this assignment and can be skipped

The collection queries are the odd ones among the commands. If every other command demanded a JSON payload with exact fields, this 'family' of queries needs to pass mostly pairs of IDs using the API path, instead of one ID for the collection and a movie payload.

While not hard to get around, it just broke the whole flow I had going with the other queries, making me give up on the whole build_* idea and resort to just raw-dogging the params in the functions themselves.

Why on earth is the rating field from the get_movie response a string instead of a number?

I see what you did there with <invalid user to del>. You cheeky people :) (This was the only client-side check I had to do)

A pretty fun assignment, considering I beat the time to complete given by Catalin (just 7.5 hrs instead of 12!)

This assignment made me appreciate the tools given to us by standard libraries like in Javascript / Node.js, also no, I would not want to send HTTP requests by hand again.

This assignment gets a 10/10 from me!