mirror of
https://github.com/payden/libwsclient
synced 2024-10-27 17:54:01 +00:00
Modify the API a little bit
Needed to have wsclient structure passed to callbacks for references to sockfd or other API functions that need it. (libwsclient_close) Also, respond to close frames correctly. Right now, we just wait on server to close TCP connection without a timeout.
This commit is contained in:
parent
c24b62d0db
commit
a10c910559
16
test.c
16
test.c
@ -4,24 +4,26 @@
|
|||||||
|
|
||||||
#include <wsclient/wsclient.h>
|
#include <wsclient/wsclient.h>
|
||||||
|
|
||||||
int onopen(void) {
|
int onmessage(wsclient *c, libwsclient_message *msg) {
|
||||||
fprintf(stderr, "Connection opened.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int onmessage(libwsclient_message *msg) {
|
|
||||||
fprintf(stderr, "Received (%llu): %s\n", msg->payload_len, msg->payload);
|
fprintf(stderr, "Received (%llu): %s\n", msg->payload_len, msg->payload);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int onopen(wsclient *c) {
|
||||||
|
fprintf(stderr, "onopen called.\n");
|
||||||
|
libwsclient_close(c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
wsclient *client = libwsclient_new("ws://websocket.mtgox.com/mtgox");
|
wsclient *client = libwsclient_new("ws://localhost:3333");
|
||||||
if(!client) {
|
if(!client) {
|
||||||
fprintf(stderr, "Unable to initialize new WS client.\n");
|
fprintf(stderr, "Unable to initialize new WS client.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
libwsclient_onopen(client, &onopen);
|
libwsclient_onopen(client, &onopen);
|
||||||
libwsclient_onmessage(client, &onmessage);
|
libwsclient_onmessage(client, &onmessage);
|
||||||
|
libwsclient_send(client, "testing");
|
||||||
libwsclient_run(client);
|
libwsclient_run(client);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
73
wsclient.c
73
wsclient.c
@ -13,7 +13,6 @@
|
|||||||
#include "wsclient.h"
|
#include "wsclient.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
|
|
||||||
|
|
||||||
void libwsclient_run(wsclient *c) {
|
void libwsclient_run(wsclient *c) {
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
int n, i;
|
int n, i;
|
||||||
@ -41,18 +40,80 @@ void libwsclient_run(wsclient *c) {
|
|||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void libwsclient_onopen(wsclient *client, int (*cb)(void)) {
|
void libwsclient_onclose(wsclient *client, int (*cb)(wsclient *c)) {
|
||||||
|
pthread_mutex_lock(&client->lock);
|
||||||
|
client->onclose = cb;
|
||||||
|
pthread_mutex_unlock(&client->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void libwsclient_onopen(wsclient *client, int (*cb)(wsclient *c)) {
|
||||||
pthread_mutex_lock(&client->lock);
|
pthread_mutex_lock(&client->lock);
|
||||||
client->onopen = cb;
|
client->onopen = cb;
|
||||||
pthread_mutex_unlock(&client->lock);
|
pthread_mutex_unlock(&client->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void libwsclient_onmessage(wsclient *client, int (*cb)(libwsclient_message *msg)) {
|
void libwsclient_onmessage(wsclient *client, int (*cb)(wsclient *c, libwsclient_message *msg)) {
|
||||||
pthread_mutex_lock(&client->lock);
|
pthread_mutex_lock(&client->lock);
|
||||||
client->onmessage = cb;
|
client->onmessage = cb;
|
||||||
pthread_mutex_unlock(&client->lock);
|
pthread_mutex_unlock(&client->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void libwsclient_close(wsclient *client) {
|
||||||
|
char data[6];
|
||||||
|
int i = 0, n, mask_int;
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv);
|
||||||
|
srand(tv.tv_sec * tv.tv_usec);
|
||||||
|
mask_int = rand();
|
||||||
|
memcpy(data+2, &mask_int, 4);
|
||||||
|
data[0] = 0x88;
|
||||||
|
data[1] = 0x80;
|
||||||
|
do {
|
||||||
|
n = send(client->sockfd, data, 6, 0);
|
||||||
|
i += n;
|
||||||
|
} while(i < 6 && n > 0);
|
||||||
|
pthread_mutex_lock(&client->lock);
|
||||||
|
client->flags |= CLIENT_SENT_CLOSE_FRAME;
|
||||||
|
pthread_mutex_unlock(&client->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void libwsclient_handle_control_frame(wsclient *c, libwsclient_frame *ctl_frame) {
|
||||||
|
int i;
|
||||||
|
char mask[4];
|
||||||
|
int mask_int;
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv);
|
||||||
|
srand(tv.tv_sec * tv.tv_usec);
|
||||||
|
mask_int = rand();
|
||||||
|
memcpy(mask, &mask_int, 4);
|
||||||
|
switch(ctl_frame->opcode) {
|
||||||
|
case 0x8:
|
||||||
|
fprintf(stderr, "Recived close frame.\n");
|
||||||
|
//close frame
|
||||||
|
if((c->flags & CLIENT_SENT_CLOSE_FRAME) == 0) {
|
||||||
|
//server request close. Send close frame as acknowledgement.
|
||||||
|
for(i=0;i<ctl_frame->payload_len;i++)
|
||||||
|
*(ctl_frame->rawdata + ctl_frame->payload_offset + i) ^= (mask[i % 4] & 0xff); //mask payload
|
||||||
|
*(ctl_frame->rawdata + 1) |= 0x80; //turn mask bit on
|
||||||
|
i = 0;
|
||||||
|
while(i < ctl_frame->payload_offset + ctl_frame->payload_len) {
|
||||||
|
i += send(c->sockfd, ctl_frame->rawdata + i, ctl_frame->payload_offset + ctl_frame->payload_len - i, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_lock(&c->lock);
|
||||||
|
c->flags |= CLIENT_SHOULD_CLOSE;
|
||||||
|
pthread_mutex_unlock(&c->lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
libwsclient_frame *ptr = NULL;
|
||||||
|
ptr = ctl_frame->prev_frame; //This very well may be a NULL pointer, but just in case we preserve it.
|
||||||
|
free(ctl_frame->rawdata);
|
||||||
|
memset(ctl_frame, 0, sizeof(libwsclient_frame));
|
||||||
|
ctl_frame->prev_frame = ptr;
|
||||||
|
ctl_frame->rawdata = (char *)malloc(FRAME_CHUNK_LENGTH);
|
||||||
|
memset(ctl_frame->rawdata, 0, FRAME_CHUNK_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
void libwsclient_in_data(wsclient *c, char in) {
|
void libwsclient_in_data(wsclient *c, char in) {
|
||||||
libwsclient_frame *current = NULL, *new = NULL;
|
libwsclient_frame *current = NULL, *new = NULL;
|
||||||
unsigned char payload_len_short;
|
unsigned char payload_len_short;
|
||||||
@ -75,7 +136,7 @@ void libwsclient_in_data(wsclient *c, char in) {
|
|||||||
if(current->fin == 1) {
|
if(current->fin == 1) {
|
||||||
//is control frame
|
//is control frame
|
||||||
if((current->opcode & 0x08) == 0x08) {
|
if((current->opcode & 0x08) == 0x08) {
|
||||||
//handle control frame
|
libwsclient_handle_control_frame(c, current);
|
||||||
} else {
|
} else {
|
||||||
libwsclient_dispatch_message(c, current);
|
libwsclient_dispatch_message(c, current);
|
||||||
c->current_frame = NULL;
|
c->current_frame = NULL;
|
||||||
@ -125,7 +186,7 @@ void libwsclient_dispatch_message(wsclient *c, libwsclient_frame *current) {
|
|||||||
msg->payload_len = message_offset;
|
msg->payload_len = message_offset;
|
||||||
msg->payload = message_payload;
|
msg->payload = message_payload;
|
||||||
if(c->onmessage != NULL) {
|
if(c->onmessage != NULL) {
|
||||||
c->onmessage(msg);
|
c->onmessage(c, msg);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "No onmessage call back registered with libwsclient.\n");
|
fprintf(stderr, "No onmessage call back registered with libwsclient.\n");
|
||||||
}
|
}
|
||||||
@ -415,7 +476,7 @@ void *libwsclient_handshake_thread(void *ptr) {
|
|||||||
pthread_mutex_lock(&client->lock);
|
pthread_mutex_lock(&client->lock);
|
||||||
client->flags &= ~CLIENT_CONNECTING;
|
client->flags &= ~CLIENT_CONNECTING;
|
||||||
if(client->onopen != NULL) {
|
if(client->onopen != NULL) {
|
||||||
client->onopen();
|
client->onopen(client);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&client->lock);
|
pthread_mutex_unlock(&client->lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
14
wsclient.h
14
wsclient.h
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#define CLIENT_IS_SSL (1 << 0)
|
#define CLIENT_IS_SSL (1 << 0)
|
||||||
#define CLIENT_CONNECTING (1 << 1)
|
#define CLIENT_CONNECTING (1 << 1)
|
||||||
|
#define CLIENT_SHOULD_CLOSE (1 << 2)
|
||||||
|
#define CLIENT_SENT_CLOSE_FRAME (1 << 3)
|
||||||
|
|
||||||
|
|
||||||
#define REQUEST_HAS_CONNECTION (1 << 0)
|
#define REQUEST_HAS_CONNECTION (1 << 0)
|
||||||
@ -41,10 +43,10 @@ typedef struct _wsclient {
|
|||||||
char *URI;
|
char *URI;
|
||||||
int sockfd;
|
int sockfd;
|
||||||
int flags;
|
int flags;
|
||||||
int (*onopen)(void);
|
int (*onopen)(struct _wsclient *);
|
||||||
int (*onclose)(void);
|
int (*onclose)(struct _wsclient *);
|
||||||
int (*onerror)(void);
|
int (*onerror)(struct _wsclient *);
|
||||||
int (*onmessage)(libwsclient_message *msg);
|
int (*onmessage)(struct _wsclient *, libwsclient_message *msg);
|
||||||
libwsclient_frame *current_frame;
|
libwsclient_frame *current_frame;
|
||||||
|
|
||||||
} wsclient;
|
} wsclient;
|
||||||
@ -55,10 +57,12 @@ typedef struct _wsclient {
|
|||||||
wsclient *libwsclient_new(const char *URI);
|
wsclient *libwsclient_new(const char *URI);
|
||||||
int libwsclient_open_connection(const char *host, const char *port);
|
int libwsclient_open_connection(const char *host, const char *port);
|
||||||
int stricmp(const char *s1, const char *s2);
|
int stricmp(const char *s1, const char *s2);
|
||||||
|
int libwsclient_complete_frame(libwsclient_frame *frame);
|
||||||
|
void libwsclient_handle_control_frame(wsclient *c, libwsclient_frame *ctl_frame);
|
||||||
void libwsclient_run(wsclient *c);
|
void libwsclient_run(wsclient *c);
|
||||||
void *libwsclient_handshake_thread(void *ptr);
|
void *libwsclient_handshake_thread(void *ptr);
|
||||||
void libwsclient_cleanup_frames(libwsclient_frame *first);
|
void libwsclient_cleanup_frames(libwsclient_frame *first);
|
||||||
void libwsclient_in_data(wsclient *c, char in);
|
void libwsclient_in_data(wsclient *c, char in);
|
||||||
int libwsclient_complete_frame(libwsclient_frame *frame);
|
|
||||||
void libwsclient_dispatch_message(wsclient *c, libwsclient_frame *current);
|
void libwsclient_dispatch_message(wsclient *c, libwsclient_frame *current);
|
||||||
|
void libwsclient_close(wsclient *c);
|
||||||
#endif /* WSCLIENT_H_ */
|
#endif /* WSCLIENT_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user