You can attempt to look for classes of vulnerabilities, but the complexity of the code will likely exhaust you before you exhaust even the smallest possibility space. This is why compiler aware machine learning fuzzers exist.
Check out american fuzzy lop: https://en.wikipedia.org/wiki/American_fuzzy_lop_(fuzzer)
You build a small, contained test program that calls your network logic directly with 'network data' provided by the fuzzer. The fuzzer will manipulate a 'zoo' of samples (data files in a directory) making changes to the samples and calling your logic. It is best to manually capture (wireshark) some tests and extract the client packets for each response to a sample file for the fuzzer. It is smart enough to recognize a nonce provided in the samples.
It found a 1 in 4.4 billion infinite loop for me in a few seconds.
With the right options and a bit of engineering it can even find your read beyond buffer errors.
It helps if your response logic is already well encapsulated and doesn't reach out to slow services (like the network) on every message.
You do not want it to write to your DB.
This will probably require some special initialization of your state to either accept the same nonce code for the duration of a test run or you should forcibly set a valid nonce into the data for each call. Happily one of the capabilities of the fuzzer is to copy your state and reset it before each variation. If the nonce is set during session initialization before any client response data, this performance option will set you free.
If it wasn't obvious you'll need to bypass SSL functionality for this test executable.
Of course other testing solutions exist, like Selenium, but the focus is different. You want to find all the vulnerabilities with minimal test generation effort, and get reliable reproduction? American fuzzy lop.