mirror of
https://github.com/payden/libwsclient
synced 2024-10-27 17:54:01 +00:00
Merge branch 'master' of https://github.com/payden/libwsclient
Conflicts: wsclient.c
This commit is contained in:
commit
de9d192fcb
92
wsclient.c
92
wsclient.c
@ -356,18 +356,18 @@ wsclient *libwsclient_new(const char *URI) {
|
|||||||
client = (wsclient *)malloc(sizeof(wsclient));
|
client = (wsclient *)malloc(sizeof(wsclient));
|
||||||
if(!client) {
|
if(!client) {
|
||||||
fprintf(stderr, "Unable to allocate memory in libwsclient_new.\n");
|
fprintf(stderr, "Unable to allocate memory in libwsclient_new.\n");
|
||||||
exit(1);
|
exit(WS_EXIT_MALLOC);
|
||||||
}
|
}
|
||||||
memset(client, 0, sizeof(wsclient));
|
memset(client, 0, sizeof(wsclient));
|
||||||
if(pthread_mutex_init(&client->lock, NULL) != 0) {
|
if(pthread_mutex_init(&client->lock, NULL) != 0) {
|
||||||
fprintf(stderr, "Unable to init mutex in libwsclient_new.\n");
|
fprintf(stderr, "Unable to init mutex in libwsclient_new.\n");
|
||||||
exit(5);
|
exit(WS_EXIT_PTHREAD_MUTEX_INIT);
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&client->lock);
|
pthread_mutex_lock(&client->lock);
|
||||||
client->URI = (char *)malloc(strlen(URI)+1);
|
client->URI = (char *)malloc(strlen(URI)+1);
|
||||||
if(!client->URI) {
|
if(!client->URI) {
|
||||||
fprintf(stderr, "Unable to allocate memory in libwsclient_new.\n");
|
fprintf(stderr, "Unable to allocate memory in libwsclient_new.\n");
|
||||||
exit(3);
|
exit(WS_EXIT_MALLOC);
|
||||||
}
|
}
|
||||||
memset(client->URI, 0, strlen(URI)+1);
|
memset(client->URI, 0, strlen(URI)+1);
|
||||||
strncpy(client->URI, URI, strlen(URI));
|
strncpy(client->URI, URI, strlen(URI));
|
||||||
@ -375,8 +375,8 @@ wsclient *libwsclient_new(const char *URI) {
|
|||||||
pthread_mutex_unlock(&client->lock);
|
pthread_mutex_unlock(&client->lock);
|
||||||
|
|
||||||
if(pthread_create(&client->handshake_thread, NULL, libwsclient_handshake_thread, (void *)client)) {
|
if(pthread_create(&client->handshake_thread, NULL, libwsclient_handshake_thread, (void *)client)) {
|
||||||
perror("pthread");
|
fprintf(stderr, "Unable to create handshake thread.\n");
|
||||||
exit(4);
|
exit(WS_EXIT_PTHREAD_CREATE);
|
||||||
}
|
}
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
@ -403,20 +403,20 @@ void *libwsclient_handshake_thread(void *ptr) {
|
|||||||
URI_copy = (char *)malloc(strlen(URI)+1);
|
URI_copy = (char *)malloc(strlen(URI)+1);
|
||||||
if(!URI_copy) {
|
if(!URI_copy) {
|
||||||
fprintf(stderr, "Unable to allocate memory in libwsclient_new.\n");
|
fprintf(stderr, "Unable to allocate memory in libwsclient_new.\n");
|
||||||
exit(2);
|
exit(WS_EXIT_MALLOC);
|
||||||
}
|
}
|
||||||
memset(URI_copy, 0, strlen(URI)+1);
|
memset(URI_copy, 0, strlen(URI)+1);
|
||||||
strncpy(URI_copy, URI, strlen(URI));
|
strncpy(URI_copy, URI, strlen(URI));
|
||||||
p = strstr(URI_copy, "://");
|
p = strstr(URI_copy, "://");
|
||||||
if(p == NULL) {
|
if(p == NULL) {
|
||||||
fprintf(stderr, "Malformed or missing scheme for URI.\n");
|
fprintf(stderr, "Malformed or missing scheme for URI.\n");
|
||||||
exit(3);
|
exit(WS_EXIT_BAD_SCHEME);
|
||||||
}
|
}
|
||||||
strncpy(scheme, URI_copy, p-URI_copy);
|
strncpy(scheme, URI_copy, p-URI_copy);
|
||||||
scheme[p-URI_copy] = '\0';
|
scheme[p-URI_copy] = '\0';
|
||||||
if(strcmp(scheme, "ws") != 0 && strcmp(scheme, "wss") != 0) {
|
if(strcmp(scheme, "ws") != 0 && strcmp(scheme, "wss") != 0) {
|
||||||
fprintf(stderr, "Invalid scheme for URI: %s\n", scheme);
|
fprintf(stderr, "Invalid scheme for URI: %s\n", scheme);
|
||||||
exit(4);
|
exit(WS_EXIT_BAD_SCHEME);
|
||||||
}
|
}
|
||||||
for(i=p-URI_copy+3,z=0;*(URI_copy+i) != '/' && *(URI_copy+i) != ':' && *(URI_copy+i) != '\0';i++,z++) {
|
for(i=p-URI_copy+3,z=0;*(URI_copy+i) != '/' && *(URI_copy+i) != ':' && *(URI_copy+i) != '\0';i++,z++) {
|
||||||
host[z] = *(URI_copy+i);
|
host[z] = *(URI_copy+i);
|
||||||
@ -484,11 +484,31 @@ void *libwsclient_handshake_thread(void *ptr) {
|
|||||||
n = recv(client->sockfd, recv_buf + z, 1023 - z, 0);
|
n = recv(client->sockfd, recv_buf + z, 1023 - z, 0);
|
||||||
z += n;
|
z += n;
|
||||||
} while((z < 4 || strstr(recv_buf, "\r\n\r\n") == NULL) && n > 0);
|
} while((z < 4 || strstr(recv_buf, "\r\n\r\n") == NULL) && n > 0);
|
||||||
|
|
||||||
|
if(n == 0) {
|
||||||
|
if(client->onerror) {
|
||||||
|
err = libwsclient_new_error(WS_HANDSHAKE_REMOTE_CLOSED_ERR);
|
||||||
|
client->onerror(client, err);
|
||||||
|
free(err);
|
||||||
|
err = NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(n < 0) {
|
||||||
|
if(client->onerror) {
|
||||||
|
err = libwsclient_new_error(WS_HANDSHAKE_RECV_ERR);
|
||||||
|
err->extra_code = n;
|
||||||
|
client->onerror(client, err);
|
||||||
|
free(err);
|
||||||
|
err = NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
//parse recv_buf for response headers and assure Accept matches expected value
|
//parse recv_buf for response headers and assure Accept matches expected value
|
||||||
rcv = (char *)malloc(strlen(recv_buf)+1);
|
rcv = (char *)malloc(strlen(recv_buf)+1);
|
||||||
if(!rcv) {
|
if(!rcv) {
|
||||||
fprintf(stderr, "Unable to allocate memory in libwsclient_new.\n");
|
fprintf(stderr, "Unable to allocate memory in libwsclient_new.\n");
|
||||||
exit(6);
|
exit(WS_EXIT_MALLOC);
|
||||||
}
|
}
|
||||||
memset(rcv, 0, strlen(recv_buf)+1);
|
memset(rcv, 0, strlen(recv_buf)+1);
|
||||||
strncpy(rcv, recv_buf, strlen(recv_buf));
|
strncpy(rcv, recv_buf, strlen(recv_buf));
|
||||||
@ -509,8 +529,13 @@ void *libwsclient_handshake_thread(void *ptr) {
|
|||||||
p = strchr(p+1, ' ');
|
p = strchr(p+1, ' ');
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
if(strcmp(tok, "HTTP/1.1 101") != 0 && strcmp(tok, "HTTP/1.0 101") != 0) {
|
if(strcmp(tok, "HTTP/1.1 101") != 0 && strcmp(tok, "HTTP/1.0 101") != 0) {
|
||||||
fprintf(stderr, "Invalid HTTP version or invalid HTTP status from server: %s\n", tok);
|
if(client->onerror) {
|
||||||
exit(7);
|
err = libwsclient_new_error(WS_HANDSHAKE_BAD_STATUS_ERR);
|
||||||
|
client->onerror(client, err);
|
||||||
|
free(err);
|
||||||
|
err = NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
flags |= REQUEST_VALID_STATUS;
|
flags |= REQUEST_VALID_STATUS;
|
||||||
} else {
|
} else {
|
||||||
@ -534,16 +559,31 @@ void *libwsclient_handshake_thread(void *ptr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!flags & REQUEST_HAS_UPGRADE) {
|
if(!flags & REQUEST_HAS_UPGRADE) {
|
||||||
fprintf(stderr, "Response from server did not include Upgrade header, failing.\n");
|
if(client->onerror) {
|
||||||
exit(8);
|
err = libwsclient_new_error(WS_HANDSHAKE_NO_UPGRADE_ERR);
|
||||||
|
client->onerror(client, err);
|
||||||
|
free(err);
|
||||||
|
err = NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
if(!flags & REQUEST_HAS_CONNECTION) {
|
if(!flags & REQUEST_HAS_CONNECTION) {
|
||||||
fprintf(stderr, "Response from server did not include Connection header, failing.\n");
|
if(client->onerror) {
|
||||||
exit(9);
|
err = libwsclient_new_error(WS_HANDSHAKE_NO_CONNECTION_ERR);
|
||||||
|
client->onerror(client, err);
|
||||||
|
free(err);
|
||||||
|
err = NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
if(!flags & REQUEST_VALID_ACCEPT) {
|
if(!flags & REQUEST_VALID_ACCEPT) {
|
||||||
fprintf(stderr, "Server did not send valid Sec-WebSocket-Accept header, failing.\n");
|
if(client->onerror) {
|
||||||
exit(10);
|
err = libwsclient_new_error(WS_HANDSHAKE_BAD_ACCEPT_ERR);
|
||||||
|
client->onerror(client, err);
|
||||||
|
free(err);
|
||||||
|
err = NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -616,6 +656,24 @@ wsclient_error *libwsclient_new_error(int errcode) {
|
|||||||
case WS_SEND_SEND_ERR:
|
case WS_SEND_SEND_ERR:
|
||||||
err->str = *(errors + 12);
|
err->str = *(errors + 12);
|
||||||
break;
|
break;
|
||||||
|
case WS_HANDSHAKE_REMOTE_CLOSED_ERR:
|
||||||
|
err->str = *(errors + 13);
|
||||||
|
break;
|
||||||
|
case WS_HANDSHAKE_RECV_ERR:
|
||||||
|
err->str = *(errors + 14);
|
||||||
|
break;
|
||||||
|
case WS_HANDSHAKE_BAD_STATUS_ERR:
|
||||||
|
err->str = *(errors + 15);
|
||||||
|
break;
|
||||||
|
case WS_HANDSHAKE_NO_UPGRADE_ERR:
|
||||||
|
err->str = *(errors + 16);
|
||||||
|
break;
|
||||||
|
case WS_HANDSHAKE_NO_CONNECTION_ERR:
|
||||||
|
err->str = *(errors + 17);
|
||||||
|
break;
|
||||||
|
case WS_HANDSHAKE_BAD_ACCEPT_ERR:
|
||||||
|
err->str = *(errors + 18);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
err->str = *errors;
|
err->str = *errors;
|
||||||
break;
|
break;
|
||||||
|
18
wsclient.h
18
wsclient.h
@ -17,6 +17,12 @@
|
|||||||
#define REQUEST_VALID_STATUS (1 << 2)
|
#define REQUEST_VALID_STATUS (1 << 2)
|
||||||
#define REQUEST_VALID_ACCEPT (1 << 3)
|
#define REQUEST_VALID_ACCEPT (1 << 3)
|
||||||
|
|
||||||
|
#define WS_EXIT_MALLOC -1
|
||||||
|
#define WS_EXIT_PTHREAD_MUTEX_INIT -2
|
||||||
|
#define WS_EXIT_PTHREAD_CREATE -3
|
||||||
|
#define WS_EXIT_BAD_SCHEME -4
|
||||||
|
|
||||||
|
|
||||||
#define WS_OPEN_CONNECTION_ADDRINFO_ERR -1
|
#define WS_OPEN_CONNECTION_ADDRINFO_ERR -1
|
||||||
#define WS_OPEN_CONNECTION_ADDRINFO_EXHAUSTED_ERR -2
|
#define WS_OPEN_CONNECTION_ADDRINFO_EXHAUSTED_ERR -2
|
||||||
#define WS_RUN_THREAD_RECV_ERR -3
|
#define WS_RUN_THREAD_RECV_ERR -3
|
||||||
@ -29,6 +35,12 @@
|
|||||||
#define WS_SEND_NULL_DATA_ERR -10
|
#define WS_SEND_NULL_DATA_ERR -10
|
||||||
#define WS_SEND_DATA_TOO_LARGE_ERR -11
|
#define WS_SEND_DATA_TOO_LARGE_ERR -11
|
||||||
#define WS_SEND_SEND_ERR -12
|
#define WS_SEND_SEND_ERR -12
|
||||||
|
#define WS_HANDSHAKE_REMOTE_CLOSED_ERR -13
|
||||||
|
#define WS_HANDSHAKE_RECV_ERR -14
|
||||||
|
#define WS_HANDSHAKE_BAD_STATUS_ERR -15
|
||||||
|
#define WS_HANDSHAKE_NO_UPGRADE_ERR -16
|
||||||
|
#define WS_HANDSHAKE_NO_CONNECTION_ERR -17
|
||||||
|
#define WS_HANDSHAKE_BAD_ACCEPT_ERR -18
|
||||||
|
|
||||||
typedef struct _wsclient_frame {
|
typedef struct _wsclient_frame {
|
||||||
unsigned int fin;
|
unsigned int fin;
|
||||||
@ -104,6 +116,12 @@ char *errors[] = {
|
|||||||
"Attempted to send null payload",
|
"Attempted to send null payload",
|
||||||
"Attempted to send too much data",
|
"Attempted to send too much data",
|
||||||
"Error during send in libwsclient_send",
|
"Error during send in libwsclient_send",
|
||||||
|
"Remote end closed connection during handshake",
|
||||||
|
"Problem receiving data during handshake",
|
||||||
|
"Remote web server responded with bad HTTP status during handshake",
|
||||||
|
"Remote web server did not respond with upgrade header during handshake",
|
||||||
|
"Remote web server did not respond with connection header during handshake",
|
||||||
|
"Remote web server did not specify the appropriate Sec-WebSocket-Accept header during handshake",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user