aboutsummaryrefslogtreecommitdiff
path: root/libxcb
diff options
context:
space:
mode:
Diffstat (limited to 'libxcb')
-rw-r--r--libxcb/src/xcb.h5
-rw-r--r--libxcb/src/xcb_auth.c72
-rw-r--r--libxcb/src/xcb_conn.c21
-rw-r--r--libxcb/src/xcb_in.c16
-rw-r--r--libxcb/src/xcb_util.c32
-rw-r--r--libxcb/src/xcbext.h107
-rw-r--r--libxcb/src/xcbint.h4
7 files changed, 182 insertions, 75 deletions
diff --git a/libxcb/src/xcb.h b/libxcb/src/xcb.h
index 18704c3f2..ec5cd3301 100644
--- a/libxcb/src/xcb.h
+++ b/libxcb/src/xcb.h
@@ -324,7 +324,7 @@ typedef struct xcb_special_event xcb_special_event_t;
*/
xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c,
xcb_special_event_t *se);
-
+
/**
* @brief Returns the next event from a special queue, blocking until one arrives
*/
@@ -335,7 +335,6 @@ xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
*/
typedef struct xcb_extension_t xcb_extension_t; /**< Opaque structure used as key for xcb_get_extension_data_t. */
-
/**
* @brief Listen for a special event
*/
@@ -489,7 +488,7 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info);
* @param c: The connection.
*
* Closes the file descriptor and frees all memory associated with the
- * connection @c c.
+ * connection @c c. If @p c is @c NULL, nothing is done.
*/
void xcb_disconnect(xcb_connection_t *c);
diff --git a/libxcb/src/xcb_auth.c b/libxcb/src/xcb_auth.c
index 0514a77e7..de628a6e4 100644
--- a/libxcb/src/xcb_auth.c
+++ b/libxcb/src/xcb_auth.c
@@ -89,11 +89,11 @@ static int authnameslen[N_AUTH_PROTOS] = {
static size_t memdup(char **dst, void *src, size_t len)
{
if(len)
- *dst = malloc(len);
+ *dst = malloc(len);
else
- *dst = 0;
+ *dst = 0;
if(!*dst)
- return 0;
+ return 0;
memcpy(*dst, src, len);
return len;
}
@@ -101,9 +101,9 @@ static size_t memdup(char **dst, void *src, size_t len)
static int authname_match(enum auth_protos kind, char *name, size_t namelen)
{
if(authnameslen[kind] != namelen)
- return 0;
+ return 0;
if(memcmp(authnames[kind], name, namelen))
- return 0;
+ return 0;
return 1;
}
@@ -183,7 +183,7 @@ static void do_append(char *buf, int *idxp, void *val, size_t valsize) {
*idxp += valsize;
}
#endif
-
+
static int compute_auth(xcb_auth_info_t *info, Xauth *authptr, struct sockaddr *sockname)
{
if (authname_match(AUTH_MC1, authptr->name, authptr->name_length)) {
@@ -195,22 +195,22 @@ static int compute_auth(xcb_auth_info_t *info, Xauth *authptr, struct sockaddr *
#ifdef HASXDMAUTH
#define APPEND(buf,idx,val) do_append((buf),&(idx),&(val),sizeof(val))
if (authname_match(AUTH_XA1, authptr->name, authptr->name_length)) {
- int j;
+ int j;
- info->data = malloc(192 / 8);
- if(!info->data)
- return 0;
+ info->data = malloc(192 / 8);
+ if(!info->data)
+ return 0;
- for (j = 0; j < 8; j++)
- info->data[j] = authptr->data[j];
- switch(sockname->sa_family) {
+ for (j = 0; j < 8; j++)
+ info->data[j] = authptr->data[j];
+ switch(sockname->sa_family) {
case AF_INET:
/*block*/ {
- struct sockaddr_in *si = (struct sockaddr_in *) sockname;
- APPEND(info->data, j, si->sin_addr.s_addr);
- APPEND(info->data, j, si->sin_port);
- }
- break;
+ struct sockaddr_in *si = (struct sockaddr_in *) sockname;
+ APPEND(info->data, j, si->sin_addr.s_addr);
+ APPEND(info->data, j, si->sin_port);
+ }
+ break;
#ifdef AF_INET6
case AF_INET6:
/*block*/ {
@@ -235,26 +235,26 @@ static int compute_auth(xcb_auth_info_t *info, Xauth *authptr, struct sockaddr *
#endif
case AF_UNIX:
/*block*/ {
- uint32_t fakeaddr = htonl(0xffffffff - next_nonce());
- uint16_t fakeport = htons(getpid());
- APPEND(info->data, j, fakeaddr);
- APPEND(info->data, j, fakeport);
- }
- break;
+ uint32_t fakeaddr = htonl(0xffffffff - next_nonce());
+ uint16_t fakeport = htons(getpid());
+ APPEND(info->data, j, fakeaddr);
+ APPEND(info->data, j, fakeport);
+ }
+ break;
default:
free(info->data);
return 0; /* do not know how to build this */
- }
- {
- uint32_t now = htonl(time(0));
- APPEND(info->data, j, now);
- }
- assert(j <= 192 / 8);
- while (j < 192 / 8)
- info->data[j++] = 0;
- info->datalen = j;
- XdmcpWrap ((unsigned char *) info->data, (unsigned char *) authptr->data + 8, (unsigned char *) info->data, info->datalen);
- return 1;
+ }
+ {
+ uint32_t now = htonl(time(0));
+ APPEND(info->data, j, now);
+ }
+ assert(j <= 192 / 8);
+ while (j < 192 / 8)
+ info->data[j++] = 0;
+ info->datalen = j;
+ XdmcpWrap ((unsigned char *) info->data, (unsigned char *) authptr->data + 8, (unsigned char *) info->data, info->datalen);
+ return 1;
}
#undef APPEND
#endif
@@ -273,7 +273,7 @@ typedef int (*LPFN_GETPEERNAME)(int,struct sockaddr *,socklen_t *);
(according to POSIX, applications should not assume a particular
length for `sockaddr_un.sun_path') */
static struct sockaddr *get_peer_sock_name(LPFN_GETPEERNAME socket_func,
- int fd)
+ int fd)
{
socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
socklen_t actual_socknamelen = socknamelen;
diff --git a/libxcb/src/xcb_conn.c b/libxcb/src/xcb_conn.c
index 7a4ae5646..e9ab62a0d 100644
--- a/libxcb/src/xcb_conn.c
+++ b/libxcb/src/xcb_conn.c
@@ -70,21 +70,30 @@ typedef struct {
uint16_t length;
} xcb_setup_generic_t;
+/* Keep this list in sync with is_static_error_conn()! */
static const int xcb_con_error = XCB_CONN_ERROR;
static const int xcb_con_closed_mem_er = XCB_CONN_CLOSED_MEM_INSUFFICIENT;
static const int xcb_con_closed_parse_er = XCB_CONN_CLOSED_PARSE_ERR;
static const int xcb_con_closed_screen_er = XCB_CONN_CLOSED_INVALID_SCREEN;
+static int is_static_error_conn(xcb_connection_t *c)
+{
+ return c == (xcb_connection_t *) &xcb_con_error ||
+ c == (xcb_connection_t *) &xcb_con_closed_mem_er ||
+ c == (xcb_connection_t *) &xcb_con_closed_parse_er ||
+ c == (xcb_connection_t *) &xcb_con_closed_screen_er;
+}
+
static int set_fd_flags(const int fd)
{
/* Win32 doesn't have file descriptors and the fcntl function. This block sets the socket in non-blocking mode */
#ifdef _WIN32
- u_long iMode = 1; /* non-zero puts it in non-blocking mode, 0 in blocking mode */
+ u_long iMode = 1; /* non-zero puts it in non-blocking mode, 0 in blocking mode */
int ret;
ret = ioctlsocket(fd, FIONBIO, &iMode);
- if(ret != 0)
+ if(ret != 0)
return 0;
return 1;
#else
@@ -201,7 +210,7 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
an iovec would require more work and I'm not sure of the benefit....works for now */
vec = *vector;
while(i < cnt)
- {
+ {
char *p= vec->iov_base;
size_t l= vec->iov_len;
while (l > 0)
@@ -233,7 +242,7 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
assert(!c->out.queue_len);
n = *count;
if (n > IOV_MAX)
- n = IOV_MAX;
+ n = IOV_MAX;
#if HAVE_SENDMSG
if (c->out.out_fd.nfd) {
@@ -271,7 +280,7 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
return 1;
}
-#endif /* _WIN32 */
+#endif /* _WIN32 */
if(n <= 0)
{
@@ -362,7 +371,7 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
void xcb_disconnect(xcb_connection_t *c)
{
- if(c->has_error)
+ if(c == NULL || is_static_error_conn(c))
return;
free(c->setup);
diff --git a/libxcb/src/xcb_in.c b/libxcb/src/xcb_in.c
index 1eef6caf5..559a6e3ea 100644
--- a/libxcb/src/xcb_in.c
+++ b/libxcb/src/xcb_in.c
@@ -201,9 +201,9 @@ static int read_packet(xcb_connection_t *c)
c->in.request_completed = c->in.request_read - 1;
}
- while(c->in.pending_replies &&
+ while(c->in.pending_replies &&
c->in.pending_replies->workaround != WORKAROUND_EXTERNAL_SOCKET_OWNER &&
- XCB_SEQUENCE_COMPARE (c->in.pending_replies->last_request, <=, c->in.request_completed))
+ XCB_SEQUENCE_COMPARE (c->in.pending_replies->last_request, <=, c->in.request_completed))
{
pending_reply *oldpend = c->in.pending_replies;
c->in.pending_replies = oldpend->next;
@@ -387,11 +387,11 @@ static int read_block(const int fd, void *buf, const ssize_t len)
FD_ZERO(&fds);
FD_SET(fd, &fds);
- /* Initializing errno here makes sure that for Win32 this loop will execute only once */
- errno = 0;
- do {
- ret = select(fd + 1, &fds, 0, 0, 0);
- } while (ret == -1 && errno == EINTR);
+ /* Initializing errno here makes sure that for Win32 this loop will execute only once */
+ errno = 0;
+ do {
+ ret = select(fd + 1, &fds, 0, 0, 0);
+ } while (ret == -1 && errno == EINTR);
#endif /* USE_POLL */
}
if(ret <= 0)
@@ -747,7 +747,7 @@ xcb_register_for_special_xge(xcb_connection_t *c,
pthread_mutex_unlock(&c->iolock);
return NULL;
}
-
+
se->extension = ext_reply->major_opcode;
se->eid = eid;
diff --git a/libxcb/src/xcb_util.c b/libxcb/src/xcb_util.c
index bfb6fca83..3cf752644 100644
--- a/libxcb/src/xcb_util.c
+++ b/libxcb/src/xcb_util.c
@@ -250,8 +250,8 @@ static int _xcb_open(const char *host, char *protocol, const int display)
free(file);
if (fd < 0 && !protocol && *host == '\0') {
- unsigned short port = X_TCP_PORT + display;
- fd = _xcb_open_tcp(host, protocol, port);
+ unsigned short port = X_TCP_PORT + display;
+ fd = _xcb_open_tcp(host, protocol, port);
}
return fd;
@@ -268,10 +268,10 @@ static int _xcb_socket(int family, int type, int proto)
if (fd == -1 && errno == EINVAL)
#endif
{
- fd = socket(family, type, proto);
+ fd = socket(family, type, proto);
#ifndef _WIN32
- if (fd >= 0)
- fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (fd >= 0)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif
}
return fd;
@@ -279,15 +279,15 @@ static int _xcb_socket(int family, int type, int proto)
static int _xcb_do_connect(int fd, const struct sockaddr* addr, int addrlen) {
- char on = 1;
+ char on = 1;
- if(fd < 0)
- return -1;
+ if(fd < 0)
+ return -1;
- setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
- setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
+ setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+ setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
- return connect(fd, addr, addrlen);
+ return connect(fd, addr, addrlen);
}
#ifdef WIN32
@@ -319,13 +319,13 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
#ifdef AF_INET6
- && strcmp("inet6",protocol)
+ && strcmp("inet6",protocol)
#endif
- )
+ )
return -1;
-
+
if (*host == '\0')
- host = "localhost";
+ host = "localhost";
#if HAVE_GETADDRINFO
memset(&hints, 0, sizeof(hints));
@@ -463,7 +463,7 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname,
xcb_connection_t *c;
int parsed = _xcb_parse_display(displayname, &host, &protocol, &display, screenp);
-
+
if(!parsed) {
c = _xcb_conn_ret_error(XCB_CONN_CLOSED_PARSE_ERR);
goto out;
diff --git a/libxcb/src/xcbext.h b/libxcb/src/xcbext.h
index 20ec1c37a..7587513d7 100644
--- a/libxcb/src/xcbext.h
+++ b/libxcb/src/xcbext.h
@@ -58,11 +58,56 @@ enum xcb_send_request_flags_t {
XCB_REQUEST_REPLY_FDS = 1 << 3
};
+/**
+ * @brief Send a request to the server.
+ * @param c: The connection to the X server.
+ * @param flags: A combination of flags from the xcb_send_request_flags_t enumeration.
+ * @param vector: Data to send; must have two iovecs before start for internal use.
+ * @param request: Information about the request to be sent.
+ * @return The request's sequence number on success, 0 otherwise.
+ *
+ * This function sends a new request to the X server. The data of the request is
+ * given as an array of @c iovecs in the @p vector argument. The length of that
+ * array and the neccessary management information are given in the @p request
+ * argument.
+ *
+ * When this function returns, the request might or might not be sent already.
+ * Use xcb_flush() to make sure that it really was sent.
+ *
+ * Please note that this function is not the prefered way for sending requests.
+ * It's better to use the generated wrapper functions.
+ *
+ * Please note that xcb might use index -1 and -2 of the @p vector array internally,
+ * so they must be valid!
+ */
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request);
+/**
+ * @brief Send a file descriptor to the server in the next call to xcb_send_request.
+ * @param c: The connection to the X server.
+ * @param fd: The file descriptor to send.
+ *
+ * After this function returns, the file descriptor given is owned by xcb and
+ * will be closed eventually.
+ *
+ * FIXME: How the heck is this supposed to work in a thread-safe way? There is a
+ * race between two threads doing xcb_send_fd(); xcb_send_request(); at the same
+ * time.
+ */
void xcb_send_fd(xcb_connection_t *c, int fd);
-/* xcb_take_socket allows external code to ask XCB for permission to
+/**
+ * @brief Take over the write side of the socket
+ * @param c: The connection to the X server.
+ * @param return_socket: Callback function that will be called when xcb wants
+ * to use the socket again.
+ * @param closure: Argument to the callback function.
+ * @param flags: A combination of flags from the xcb_send_request_flags_t enumeration.
+ * @param sent: Location to the sequence number of the last sequence request.
+ * Must not be NULL.
+ * @return 1 on success, else 0.
+ *
+ * xcb_take_socket allows external code to ask XCB for permission to
* take over the write side of the socket and send raw data with
* xcb_writev. xcb_take_socket provides the sequence number of the last
* request XCB sent. The caller of xcb_take_socket must supply a
@@ -71,10 +116,24 @@ void xcb_send_fd(xcb_connection_t *c, int fd);
* external socket owner and flushes any output queues if appropriate.
* If you are sending requests which won't cause a reply, please note the
* comment for xcb_writev which explains some sequence number wrap issues.
- * */
+ *
+ * All replies that are generated while the socket is owned externally have
+ * @p flags applied to them. For example, use XCB_REQUEST_CHECK if you don't
+ * want errors to go to xcb's normal error handling, but instead having to be
+ * picked up via xcb_wait_for_reply(), xcb_poll_for_reply() or
+ * xcb_request_check().
+ */
int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent);
-/* You must own the write-side of the socket (you've called
+/**
+ * @brief Send raw data to the X server.
+ * @param c: The connection to the X server.
+ * @param vector: Array of data to be sent.
+ * @param count: Number of entries in @p vector.
+ * @param requests: Number of requests that are being sent.
+ * @return 1 on success, else 0.
+ *
+ * You must own the write-side of the socket (you've called
* xcb_take_socket, and haven't returned from return_socket yet) to call
* xcb_writev. Also, the iovec must have at least 1 byte of data in it.
* You have to make sure that xcb can detect sequence number wraps correctly.
@@ -83,20 +142,60 @@ int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), v
* requests without a reply, you have to insert a request which will cause a
* reply. You can again use GetInputFocus for this. You do not have to wait for
* any of the GetInputFocus replies, but can instead handle them via
- * xcb_discard_reply(). */
+ * xcb_discard_reply().
+ */
int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t requests);
/* xcb_in.c */
+/**
+ * @brief Wait for the reply of a given request.
+ * @param c: The connection to the X server.
+ * @param request: Sequence number of the request as returned by xcb_send_request().
+ * @param e: Location to store errors in, or NULL. Ignored for unchecked requests.
+ *
+ * Returns the reply to the given request or returns null in the event of
+ * errors. Blocks until the reply or error for the request arrives, or an I/O
+ * error occurs.
+ */
void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e);
+
+/**
+ * @brief Poll for the reply of a given request.
+ * @param c: The connection to the X server.
+ * @param request: Sequence number of the request as returned by xcb_send_request().
+ * @param reply: Location to store the reply in, must not be NULL.
+ * @param e: Location to store errors in, or NULL. Ignored for unchecked requests.
+ * @return 1 when the reply to the request was returned, else 0.
+ *
+ * Checks if the reply to the given request already received. Does not block.
+ */
int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, xcb_generic_error_t **error);
+
+/**
+ * @brief Don't use this, only needed by the generated code.
+ * @param c: The connection to the X server.
+ * @param reply: A reply that was received from the server
+ * @param replylen: The size of the reply.
+ * @return Pointer to the location where received file descriptors are stored.
+ */
int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t replylen);
/* xcb_util.c */
+/**
+ * @param mask: The mask to check
+ * @return The number of set bits in the mask
+ */
int xcb_popcount(uint32_t mask);
+
+/**
+ * @param list: The base of an array
+ * @param len: The length of the array
+ * @return The sum of all entries in the array.
+ */
int xcb_sumof(uint8_t *list, int len);
#ifdef __cplusplus
diff --git a/libxcb/src/xcbint.h b/libxcb/src/xcbint.h
index 67cf5711e..f89deba4a 100644
--- a/libxcb/src/xcbint.h
+++ b/libxcb/src/xcbint.h
@@ -53,7 +53,7 @@ enum lazy_reply_tag
#define XCB_PAD(i) (-(i) & 3)
-#define XCB_SEQUENCE_COMPARE(a,op,b) ((int64_t) ((a) - (b)) op 0)
+#define XCB_SEQUENCE_COMPARE(a,op,b) ((int64_t) ((a) - (b)) op 0)
#ifndef offsetof
#define offsetof(type,member) ((size_t) &((type *)0)->member)
@@ -80,7 +80,7 @@ void *_xcb_map_remove(_xcb_map *q, unsigned int key);
/* xcb_out.c */
#if HAVE_SENDMSG
-#define XCB_MAX_PASS_FD 16
+#define XCB_MAX_PASS_FD 16
typedef struct _xcb_fd {
int fd[XCB_MAX_PASS_FD];