diff options
Diffstat (limited to 'libxcb')
-rw-r--r-- | libxcb/src/xcb.h | 5 | ||||
-rw-r--r-- | libxcb/src/xcb_auth.c | 72 | ||||
-rw-r--r-- | libxcb/src/xcb_conn.c | 21 | ||||
-rw-r--r-- | libxcb/src/xcb_in.c | 16 | ||||
-rw-r--r-- | libxcb/src/xcb_util.c | 32 | ||||
-rw-r--r-- | libxcb/src/xcbext.h | 107 | ||||
-rw-r--r-- | libxcb/src/xcbint.h | 4 |
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]; |