Add optional locks to socket.
This commit is contained in:
parent
400920b3bb
commit
51c00755ac
@ -38,6 +38,8 @@
|
||||
#ifndef _GUAC_SOCKET_H
|
||||
#define _GUAC_SOCKET_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -187,6 +189,18 @@ struct guac_socket {
|
||||
*/
|
||||
char* __instructionbuf_elementv[64];
|
||||
|
||||
/**
|
||||
* Whether instructions should be guaranteed atomic across threads using
|
||||
* locks. By default, thread safety is disabled on sockets.
|
||||
*/
|
||||
bool __threadsafe_instructions;
|
||||
|
||||
/**
|
||||
* Lock which is acquired when an instruction is being written, and
|
||||
* released when the instruction is finished being written.
|
||||
*/
|
||||
pthread_mutex_t __instruction_write_lock;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -205,6 +219,35 @@ guac_socket* guac_socket_alloc();
|
||||
*/
|
||||
void guac_socket_free(guac_socket* socket);
|
||||
|
||||
/**
|
||||
* Declares that the given socket must behave in a threadsafe way. Calling
|
||||
* this function on a socket guarantees that the socket will send instructions
|
||||
* atomically. Without automatic threadsafe sockets, multiple threads writing
|
||||
* to the same socket must ensure that instructions will not potentially
|
||||
* overlap.
|
||||
*
|
||||
* @param socket The guac_socket to declare as threadsafe.
|
||||
*/
|
||||
void guac_socket_require_threadsafe(guac_socket* socket);
|
||||
|
||||
/**
|
||||
* Marks the beginning of a Guacamole protocol instruction. If threadsafety
|
||||
* is enabled on the socket, other instructions will be blocked from sending
|
||||
* until this instruction is complete.
|
||||
*
|
||||
* @param socket The guac_socket beginning an instruction.
|
||||
*/
|
||||
void guac_socket_instruction_begin(guac_socket* socket);
|
||||
|
||||
/**
|
||||
* Marks the end of a Guacamole protocol instruction. If threadsafety
|
||||
* is enabled on the socket, other instructions will be allowed to send.
|
||||
*
|
||||
* @param socket The guac_socket ending an instruction.
|
||||
*/
|
||||
void guac_socket_instruction_end(guac_socket* socket);
|
||||
|
||||
|
||||
/**
|
||||
* Allocates and initializes a new guac_socket object with the given open
|
||||
* file descriptor.
|
||||
|
@ -36,13 +36,14 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <winsock2.h>
|
||||
@ -154,6 +155,11 @@ guac_socket* guac_socket_alloc() {
|
||||
socket->__instructionbuf_parse_start = 0;
|
||||
socket->__instructionbuf_elementc = 0;
|
||||
|
||||
|
||||
/* Default to unsafe threading */
|
||||
socket->__threadsafe_instructions = false;
|
||||
pthread_mutex_init(&(socket->__instruction_write_lock), NULL);
|
||||
|
||||
/* No handlers yet */
|
||||
socket->read_handler = NULL;
|
||||
socket->write_handler = NULL;
|
||||
@ -164,6 +170,26 @@ guac_socket* guac_socket_alloc() {
|
||||
|
||||
}
|
||||
|
||||
void guac_socket_require_threadsafe(guac_socket* socket) {
|
||||
socket->__threadsafe_instructions = true;
|
||||
}
|
||||
|
||||
void guac_socket_instruction_begin(guac_socket* socket) {
|
||||
|
||||
/* Lock writes if threadsafety enabled */
|
||||
if (socket->__threadsafe_instructions)
|
||||
pthread_mutex_lock(&(socket->__instruction_write_lock));
|
||||
|
||||
}
|
||||
|
||||
void guac_socket_instruction_end(guac_socket* socket) {
|
||||
|
||||
/* Lock writes if threadsafety enabled */
|
||||
if (socket->__threadsafe_instructions)
|
||||
pthread_mutex_unlock(&(socket->__instruction_write_lock));
|
||||
|
||||
}
|
||||
|
||||
void guac_socket_free(guac_socket* socket) {
|
||||
|
||||
/* Call free handler if defined */
|
||||
@ -171,6 +197,7 @@ void guac_socket_free(guac_socket* socket) {
|
||||
socket->free_handler(socket);
|
||||
|
||||
guac_socket_flush(socket);
|
||||
pthread_mutex_destroy(&(socket->__instruction_write_lock));
|
||||
free(socket->__instructionbuf);
|
||||
free(socket);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user