#pragma once #include #include struct transport; // Takes ownership of socket. // Returns NULL and closes socket if setup fails. struct transport* tsp_start(int fd, bool is_server); // Also closes socket. void tsp_close(struct transport *tsp); // Get file descriptor that can be used in e.g. select(2) to detect possible // data on the transport. If there is data, the tsp_recv() function must be // used to handle it, because it may be protocol-level data for the integrity // of the transport. int tsp_select_fd(const struct transport *tsp); // If successful, returns true. // If unsuccessful, returns false and closes the transport (after which the // transport may not be used again). bool tsp_send(struct transport *tsp, const char *data, size_t length); struct received_data { char *data; size_t length; bool error; }; void received_data_nullify(struct received_data data); // If no data is avilable yet, returns {.data=NULL, length=0, error=false}. // If an error occurred, returns {.data=NULL, length=0, error=true}. // If data is avilable, returns {.data=..., length=(length of data), error=false}. // This function also handles protocol-level actions that do not actually // return application-level data, but that are indeed necessary. struct received_data tsp_recv(struct transport *tsp);