Add optional locks to socket.
This commit is contained in:
parent
400920b3bb
commit
51c00755ac
@ -38,6 +38,8 @@
|
|||||||
#ifndef _GUAC_SOCKET_H
|
#ifndef _GUAC_SOCKET_H
|
||||||
#define _GUAC_SOCKET_H
|
#define _GUAC_SOCKET_H
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -187,6 +189,18 @@ struct guac_socket {
|
|||||||
*/
|
*/
|
||||||
char* __instructionbuf_elementv[64];
|
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);
|
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
|
* Allocates and initializes a new guac_socket object with the given open
|
||||||
* file descriptor.
|
* file descriptor.
|
||||||
|
@ -36,13 +36,14 @@
|
|||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
@ -154,6 +155,11 @@ guac_socket* guac_socket_alloc() {
|
|||||||
socket->__instructionbuf_parse_start = 0;
|
socket->__instructionbuf_parse_start = 0;
|
||||||
socket->__instructionbuf_elementc = 0;
|
socket->__instructionbuf_elementc = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* Default to unsafe threading */
|
||||||
|
socket->__threadsafe_instructions = false;
|
||||||
|
pthread_mutex_init(&(socket->__instruction_write_lock), NULL);
|
||||||
|
|
||||||
/* No handlers yet */
|
/* No handlers yet */
|
||||||
socket->read_handler = NULL;
|
socket->read_handler = NULL;
|
||||||
socket->write_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) {
|
void guac_socket_free(guac_socket* socket) {
|
||||||
|
|
||||||
/* Call free handler if defined */
|
/* Call free handler if defined */
|
||||||
@ -171,6 +197,7 @@ void guac_socket_free(guac_socket* socket) {
|
|||||||
socket->free_handler(socket);
|
socket->free_handler(socket);
|
||||||
|
|
||||||
guac_socket_flush(socket);
|
guac_socket_flush(socket);
|
||||||
|
pthread_mutex_destroy(&(socket->__instruction_write_lock));
|
||||||
free(socket->__instructionbuf);
|
free(socket->__instructionbuf);
|
||||||
free(socket);
|
free(socket);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user