aboutsummaryrefslogtreecommitdiffstats
path: root/libaxl.h
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2020-04-24 19:47:41 +0200
committerMattias Andrée <maandree@kth.se>2020-04-24 19:47:41 +0200
commit90cd52ece1623f9b872837a88504faeb9fd593f6 (patch)
tree2c910614d39b0b8dde5eccda25de99a6f360e161 /libaxl.h
parentFirst commit (diff)
downloadlibaxl-90cd52ece1623f9b872837a88504faeb9fd593f6.tar.gz
libaxl-90cd52ece1623f9b872837a88504faeb9fd593f6.tar.bz2
libaxl-90cd52ece1623f9b872837a88504faeb9fd593f6.tar.xz
Second commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'libaxl.h')
-rw-r--r--libaxl.h282
1 files changed, 269 insertions, 13 deletions
diff --git a/libaxl.h b/libaxl.h
index d60cb17..7ecc19d 100644
--- a/libaxl.h
+++ b/libaxl.h
@@ -2,6 +2,9 @@
#ifndef LIBAXL_H
#define LIBAXL_H
+#include <stddef.h>
+#include <stdint.h>
+
#if defined(__GNUC__)
# define _LIBAXL_GCC_ONLY(...) __VA_ARGS__
#else
@@ -15,6 +18,32 @@
#include "libaxl-errors.h"
#include "libaxl-requests.h"
#include "libaxl-replies.h"
+#include "libaxl-display-info.h"
+
+/**
+ * The major version number of the highest version of X protocol
+ * of the library supports (the lowest version is 11.0). If you
+ * are using dynamic linking, you make also want to use the
+ * libaxl_protocol_major() function.
+ */
+#define LIBAXL_PROTOCOL_MAJOR 11
+
+/**
+ * The minor version number of the highest version of X protocol
+ * of the library supports (the lowest version is 11.0). If you
+ * are using dynamic linking, you make also want to use the
+ * libaxl_protocol_minor() function.
+ */
+#define LIBAXL_PROTOCOL_MINOR 0
+
+/**
+ * The version number of the highest version of X protocol of
+ * the library supports, as one integer where the major number
+ * is multiped by 100000, (the lowest version is 11.0, which is
+ * encoded as 1100000). If you are using dynamic linking, you
+ * make also want to use the libaxl_protocol_version() function.
+ */
+#define LIBAXL_PROTOCOL_VERSION ((LIBAXL_PROTOCOL_MAJOR) * 100000 + (LIBAXL_PROTOCOL_MINOR))
/* libaxl error codes */
#define LIBAXL_ERROR_SYSTEM -1 /* use `errno` */
@@ -28,8 +57,20 @@
#define LIBAXL_ERROR_MALFORMATTED_REQUEST -9
#define LIBAXL_ERROR_CONNECTION_CLOSED -10
#define LIBAXL_ERROR_INVALID_REPLY_OPCODE -11
+#define LIBAXL_ERROR_INVALID_HANDSHAKE_RESPONSE -12
+#define LIBAXL_ERROR_OUT_OF_RESOURCE_IDS -13
-union libaxl_input { /* TODO man */
+#define LIBAXL_HANDSHAKE_FAILED 0
+#define LIBAXL_HANDSHAKE_SUCCESS 1
+#define LIBAXL_HANDSHAKE_AUTHENTICATE 2
+
+/*
+ * The largest possible return of the libaxl_get_decnet_object()
+ * function, plus 1 for the terminal NUL byte
+ */
+#define LIBAXL_DECNET_OBJECT_MAX (5 + 3 * sizeof(int) - sizeof(int) / 2)
+
+union libaxl_input { /* TODO doc, man */
uint8_t type;
union libaxl_error error; /* if .type = LIBAXL_ERROR */
union libaxl_reply reply; /* if .type = LIBAXL_REPLY */
@@ -50,6 +91,118 @@ typedef struct libaxl_connection LIBAXL_CONNECTION;
typedef struct libaxl_context LIBAXL_CONTEXT;
/**
+ * Returns the major version number of the highest version of
+ * X protocol of the library supports (the lowest version is
+ * 11.0). If you are using static linking, you make also want
+ * to use the LIBAXL_PROTOCOL_MAJOR constant.
+ *
+ * @return The major version number of highest support version of the protocol
+ */
+int libaxl_protocol_version_major(void);
+
+/**
+ * Returns the minor version number of the highest version of
+ * X protocol of the library supports (the lowest version is
+ * 11.0). If you are using static linking, you make also want
+ * to use the LIBAXL_PROTOCOL_MINOR constant.
+ *
+ * @return The minor version number of highest support version of the protocol
+ */
+int libaxl_protocol_version_minor(void);
+
+/**
+ * Returns the minor version number of the highest version of
+ * X protocol of the library supports (the lowest version is 11.0,
+ * which is encoded as 1100000). If you are using static linking,
+ * you make also want to use the LIBAXL_PROTOCOL_VERSION constant.
+ *
+ * @return The version number of highest support version of the protocol,
+ * encoded as a sum of the major number multipled by 100000 (1e5)
+ * and the minor number, e.g. 1100000 for 11.0 (X11)
+ */
+int libaxl_protocol_version(void);
+
+/**
+ * Get the file description used for a connection to
+ * the X display server
+ *
+ * @param conn The connection to the display server
+ * @return The number of the file descriptor that holds
+ * the connection to the display server
+ */
+_LIBAXL_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__)))
+int libaxl_fileno(LIBAXL_CONNECTION *); /* TODO man */
+
+/**
+ * Get information about a connection and the display
+ * and display server it is connected to
+ *
+ * This information is sent to the client during the
+ * connection handshake, and is never updated hence
+ *
+ * @param conn The connection to the display server
+ * @param version Should be `LIBAXL_DISPLAY_INFO_VERSION`; used to
+ * identify if old fields that have been replaces
+ * must allocated and filled in with information
+ * from the new fields that the application does
+ ' not know about
+ * @return Information about the display, the display
+ * server, and the connection; `NULL` on error
+ *
+ * On failure, no error is returned, but the error
+ * is always LIBAXL_ERROR_SYSTEM
+ */
+_LIBAXL_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__)))
+const struct libaxl_display_info *libaxl_info(LIBAXL_CONNECTION *, int); /* TODO man */
+
+/**
+ * Get the next element in a `struct libaxl_depth *`
+ *
+ * Usage example for iterating of all elements in
+ * `screen->allowed_depths` where `screen` is a
+ * `struct libaxl_screen *`:
+ *
+ * struct libaxl_depth *depth;
+ * size_t i = 0;
+ * for (depth = screen->allowed_depths; i < screen->number_of_allowed_depths; depth = libaxl_next_depth(depth)) {
+ * ... do something with `depth` or `break` if `i` is of a desired value (index) ...
+ * }
+ *
+ * @param depth The element before the element to return
+ * @return The element after `depth`
+ */
+inline const struct libaxl_depth *
+libaxl_next_depth(const struct libaxl_depth *depth) /* TODO man */
+{
+ return (const struct libaxl_depth *)(uintptr_t)&depth->visuals[depth->number_of_visuals];
+}
+
+/**
+ * Get the next element in a `struct libaxl_screen *`
+ *
+ * Usage example for iterating of all elements in `info->screens`
+ * where `info` is a `struct libaxl_display_info *`:
+ *
+ * struct libaxl_screen *screen;
+ * size_t i = 0;
+ * for (screen = info->screens; i < info->nscreens; screen = libaxl_next_screen(screen)) {
+ * ... do something with `screen` or `break` if `i` is of a desired value (index) ...
+ * }
+ *
+ * @param screen The element before the element to return
+ * @return The element after `screen`
+ */
+inline const struct libaxl_screen *
+libaxl_next_screen(const struct libaxl_screen *screen) /* TODO man */
+{
+ uint8_t n = screen->number_of_allowed_depths;
+ const struct libaxl_depth *depth = screen->allowed_depths;
+ while (n--)
+ depth = libaxl_next_depth(depth);
+ return (const struct libaxl_screen *)(uintptr_t)depth;
+}
+
+/**
* Create context, for a thread, to use when accessing
* the display server
*
@@ -70,20 +223,26 @@ void libaxl_context_free(LIBAXL_CONTEXT *); /* TODO man */
* Generate a resource ID
*
* The generated resource ID can be deallocated
- * with the `libaxl_deallocate_id` function
+ * with the libaxl_deallocate_id() function
*
* @param ctx The thread's context for the connection
* @return The generated resource ID, 0 on failure
+ *
+ * On failure, no error is returned, but the error
+ * is always LIBAXL_ERROR_OUT_OF_RESOURCE_IDS
*/
-libaxl_id_t libaxl_generate_id(LIBAXL_CONTEXT *); /* TODO man, implement */
+_LIBAXL_GCC_ONLY(__attribute__((__nonnull__, __warn_unused_result__)))
+libaxl_id_t libaxl_generate_id(LIBAXL_CONTEXT *); /* TODO man */
/**
* Deallocate a resource ID so that it can be reused later
*
- * @param ctx The thread's context for the connection
- * @param id The generated resource ID to deallocate
+ * @param ctx The thread's context for the connection
+ * @param id The generated resource ID to deallocate
+ * @return 0 on success, a negative libaxl error code on failure
*/
-void libaxl_deallocate_id(LIBAXL_CONTEXT *, libaxl_id_t); /* TODO man, implement */
+_LIBAXL_GCC_ONLY(__attribute__((__nonnull__)))
+int libaxl_deallocate_id(LIBAXL_CONTEXT *, libaxl_id_t); /* TODO man, implement */
/**
* Parse a display name string
@@ -96,7 +255,7 @@ void libaxl_deallocate_id(LIBAXL_CONTEXT *, libaxl_id_t); /* TODO man, implement
*
* <path>[.<screen>]
*
- * @param name The display name string, $DISPLAY will be used if `NULL` or empty
+ * @param name The display name string, $DISPLAY will be used if NULL or empty
* @param hostp Output parameter for the host of or (if the protocol is "unix") path
* to the display, remember to free after successful completion
* @param protocolp Output parameter for the network protocol used to access the display,
@@ -109,6 +268,62 @@ _LIBAXL_GCC_ONLY(__attribute__((__nonnull__(2, 3, 4, 5))))
int libaxl_parse_display(const char *, char **, char **, int *, int *); /* TODO man */
/**
+ * Get the TCP port that is used for a display
+ *
+ * @param display The display's number, the function will assume that it is a valid number
+ * @return The TCP port used for the display
+ */
+_LIBAXL_GCC_ONLY(__attribute__((__warn_unused_result__)))
+inline uint16_t libaxl_get_tcp_port(int display) /* TODO man */
+{
+ return (uint16_t)(display + 6000);
+}
+
+/**
+ * Get the DECnet object name that is used for a display
+ *
+ * @param buf Buffer that the object name shall be written to, it is recommended
+ * that is size, if static, is LIBAXL_DECNET_OBJECT_MAX (which is
+ * always sufficient), otherwise it should be at least the return value
+ * of this function (for the same last argument but with NULL and 0
+ * as the first two arguments) plus 1
+ * @param size The size of the buffer in the `buf` argument
+ * @param display The display's number
+ * @return The length of the object name, will not exceed LIBAXL_DECNET_OBJECT_MAX
+ * less 1; an additional uncounted NUL byte will be written to the buffer
+ * if it is large enough; or -1 on failure (specifically snprintf(3), which
+ * the function calls, by fail with EOVERFLOW if the `size` argument is
+ * greater than {INT_MAX})
+ */
+int libaxl_get_decnet_object(char *, size_t, int); /* TODO man */
+
+/**
+ * This function is to be called once and only once, excluding any
+ * failure that does not set `errno` to EINPROGRESS and excluding
+ * any call for which the display server respond that the handshake
+ * failed or requires authentication, immediately after connecting
+ * to the socket for the display
+ *
+ * The libaxl_receive_handshake() shall be called immediately after
+ * calling this function
+ *
+ * @param ctx The thread's context for the connection to the display to send the handshake over
+ * @param auth_name The protocol name of the authorisation the client expects the server to use;
+ * valid authorisation mechanisms are not part of the core X protocol
+ * @param auth_name_len The length of `auth_name`, 0 if `auth_name` is NULL
+ * @param auth_data The authorisation data, which is specific to the choosen authorisation mechanism
+ * @param auth_data_len The length of `auth_data`, 0 if `auth_data` is NULL
+ * @param flags Flags to use for the 4th parameter when calling send(3)
+ * @return 0 on success, a negative libaxl error code on failure
+ *
+ * If the function returns LIBAXL_ERROR_SYSTEM and sets `errno`
+ * to EINPROGRESS, the message has been saved (possibly partially
+ * sent) and pending to be sent by calling libaxl_flush().
+ */
+_LIBAXL_GCC_ONLY(__attribute__((__nonnull__(1))))
+int libaxl_send_handshake(LIBAXL_CONTEXT *restrict, const char *, size_t, const char *, size_t, int); /* TODO man */
+
+/**
* Send a request to the display server
*
* May deadlock if called from an asynchronously called signal handler
@@ -150,14 +365,55 @@ _LIBAXL_GCC_ONLY(__attribute__((__nonnull__)))
int libaxl_flush(LIBAXL_CONNECTION *restrict, int); /* TODO man */
/**
+ * Receive the server's part of the handshake, this function
+ * shall be called once immediately after each successful call
+ * to the libaxl_send_handshake() function or successful call
+ * to the libaxl_flush() function due to EINPROGRESS failure
+ * of call to the libaxl_send_handshake() function
+ *
+ * @param ctx The thread's context for the connection to the display server
+ * @param majorp Output parameter for the major version number for a version
+ * of the X protocol that the display server supports, which is
+ * not necessarily the version that the library uses. Will only
+ * be set if the function returns LIBAXL_HANDSHAKE_FAILED or
+ * LIBAXL_HANDSHAKE_SUCCESS.
+ * @param minorp Output parameter for the minor version number for a version
+ * of the X protocol that the display server supports, which is
+ * not necessarily the version that the library uses. Will only
+ * be set if the function returns LIBAXL_HANDSHAKE_FAILED or
+ * LIBAXL_HANDSHAKE_SUCCESS.
+ * @param reasonp Output parameter for the reason the handshake or authorisation
+ * failed. Will be set to NULL unless the function returns
+ * LIBAXL_HANDSHAKE_FAILED or LIBAXL_HANDSHAKE_AUTHENTICATE.
+ * Remember to free after successful completion (non-negative return)
+ * @param flags Flags to use for the 4th parameter when calling recv(3)
+ * @return 0 on success, a negative libaxl error code on failure
+ *
+ * Behaviour is unspecified if SO_PEEK_OFF is active on the
+ * connection to the display server or if the MSG_PEEK flag
+ * is used
+ */
+_LIBAXL_GCC_ONLY(__attribute__((__nonnull__(1))))
+int libaxl_receive_handshake(LIBAXL_CONTEXT *restrict, int *restrict, int *restrict, char **restrict, int); /* TODO man */
+
+/**
* Receive the next pending message from the display server
*
- * @param ctx The thread's context for the connection to the display server
- * @param msgp Output parameter for the received message; the message will
- * be vaild until the next time this function is called with the
- * same `ctx` parameter or until the libaxl_context_free() function
- * is called with the same `ctx` paramter (whichever comes first)
- * @param flags Flags to use for the 4th parameter when calling recv(3)
+ * Be aware: order of replies and events is not guaranteed,
+ * and events caused by a request are sent before replies
+ * and errors, however when multiple events are generated,
+ * by some action, they are send in an uninterrupted sequence
+ * (no other event, error, or reply is send between those event).
+ * This means that it is important to check the returned
+ * sequence number.
+ *
+ * @param ctx The thread's context for the connection to the display server
+ * @param msgp Output parameter for the received message; the message will
+ * be vaild until the next time this function is called with the
+ * same `ctx` parameter or until the libaxl_context_free() function
+ * is called with the same `ctx` paramter (whichever comes first)
+ * @param flags Flags to use for the 4th parameter when calling recv(3)
+ * @return 0 on success, a negative libaxl error code on failure
*
* Behaviour is unspecified if SO_PEEK_OFF is active on the
* connection to the display server or if the MSG_PEEK flag