mirror of
https://github.com/payden/libwsclient
synced 2024-10-27 17:54:01 +00:00
Add libwsclient_helper_socket function.
This function binds UNIX socket listener with specified path. Any data received by this UNIX socket is sent out as a WebSocket text frame. This allows a user to send data on behalf of a running libwsclient program. Will add some documentation for the entire library soon. Will go into depth there.
This commit is contained in:
parent
1ddfa42529
commit
05a0f6309c
6
test.c
6
test.c
@ -18,13 +18,12 @@ int onmessage(wsclient *c, wsclient_message *msg) {
|
||||
}
|
||||
|
||||
int onopen(wsclient *c) {
|
||||
fprintf(stderr, "onopen called.\n");
|
||||
libwsclient_send(c, "testing::testing::demo.paydensutherland.com");
|
||||
fprintf(stderr, "onopen called: %d\n", c->sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
wsclient *client = libwsclient_new("ws://ip6-localhost:8080");
|
||||
wsclient *client = libwsclient_new("ws://websocket.mtgox.com/mtgox");
|
||||
if(!client) {
|
||||
fprintf(stderr, "Unable to initialize new WS client.\n");
|
||||
exit(1);
|
||||
@ -33,6 +32,7 @@ int main(int argc, char **argv) {
|
||||
libwsclient_onmessage(client, &onmessage);
|
||||
libwsclient_onerror(client, &onerror);
|
||||
libwsclient_onclose(client, &onclose);
|
||||
libwsclient_helper_socket(client, "test.sock");
|
||||
libwsclient_run(client);
|
||||
libwsclient_finish(client);
|
||||
return 0;
|
||||
|
83
wsclient.c
83
wsclient.c
@ -7,6 +7,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
@ -351,6 +352,88 @@ int libwsclient_open_connection(const char *host, const char *port) {
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
int libwsclient_helper_socket(wsclient *c, const char *path) {
|
||||
socklen_t len;
|
||||
int sockfd;
|
||||
if(c->helper_sa.sun_family) {
|
||||
fprintf(stderr, "Can only bind one UNIX socket for helper program communications.\n");
|
||||
return WS_HELPER_ALREADY_BOUND_ERR;
|
||||
}
|
||||
c->helper_sa.sun_family = AF_UNIX;
|
||||
strncpy(c->helper_sa.sun_path, path, sizeof(c->helper_sa.sun_path) - 1);
|
||||
unlink(c->helper_sa.sun_path);
|
||||
len = strlen(c->helper_sa.sun_path) + sizeof(c->helper_sa.sun_family);
|
||||
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if(sockfd == -1) {
|
||||
fprintf(stderr, "Error creating UNIX socket.\n");
|
||||
return WS_HELPER_CREATE_SOCK_ERR;
|
||||
}
|
||||
|
||||
if(bind(sockfd, (struct sockaddr *)&c->helper_sa, len) == -1) {
|
||||
fprintf(stderr, "Error binding UNIX socket.\n");
|
||||
perror("bind");
|
||||
close(sockfd);
|
||||
memset(&c->helper_sa, 0, sizeof(struct sockaddr_un));
|
||||
return WS_HELPER_BIND_ERR;
|
||||
}
|
||||
|
||||
if(listen(sockfd, 5) == -1) {
|
||||
fprintf(stderr, "Error listening on UNIX socket.\n");
|
||||
close(sockfd);
|
||||
memset(&c->helper_sa, 0, sizeof(struct sockaddr_un));
|
||||
return WS_HELPER_LISTEN_ERR;
|
||||
}
|
||||
|
||||
c->helper_sock = sockfd;
|
||||
pthread_create(&c->helper_thread, NULL, libwsclient_helper_socket_thread, (void *)c);
|
||||
}
|
||||
|
||||
void *libwsclient_helper_socket_thread(void *ptr) {
|
||||
wsclient *c = ptr;
|
||||
struct sockaddr_un remote;
|
||||
socklen_t len;
|
||||
int remote_sock, n, payload_idx, payload_sz;
|
||||
char recv_buf[HELPER_RECV_BUF_SIZE];
|
||||
char *payload = NULL, *payload_tmp = NULL;
|
||||
|
||||
|
||||
for(;;) { //TODO: some way to cleanly break this loop
|
||||
len = sizeof(remote);
|
||||
if((remote_sock = accept(c->helper_sock, (struct sockaddr *)&remote, &len)) == -1) {
|
||||
continue;
|
||||
}
|
||||
payload_idx = 0;
|
||||
payload = (char *)malloc(HELPER_RECV_BUF_SIZE);
|
||||
memset(payload, 0, payload_sz);
|
||||
payload_sz = HELPER_RECV_BUF_SIZE;
|
||||
do {
|
||||
memset(recv_buf, 0, HELPER_RECV_BUF_SIZE);
|
||||
n = recv(remote_sock, recv_buf, HELPER_RECV_BUF_SIZE - 1, 0);
|
||||
if(n > 0) {
|
||||
if(n + payload_idx >= payload_sz) {
|
||||
payload_tmp = payload;
|
||||
payload_sz += HELPER_RECV_BUF_SIZE;
|
||||
payload = (char *)realloc(payload, payload_sz);
|
||||
if(!payload) {
|
||||
payload = payload_tmp;
|
||||
fprintf(stderr, "Unable to realloc, data sent will be truncated.\n");
|
||||
break;
|
||||
}
|
||||
memset(payload + payload_idx, 0, payload_sz - payload_idx);
|
||||
}
|
||||
memcpy(payload + payload_idx, recv_buf, n);
|
||||
payload_idx += n;
|
||||
}
|
||||
|
||||
} while(n > 0);
|
||||
close(remote_sock);
|
||||
libwsclient_send(c, payload);
|
||||
free(payload);
|
||||
payload = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wsclient *libwsclient_new(const char *URI) {
|
||||
wsclient *client = NULL;
|
||||
|
||||
|
13
wsclient.h
13
wsclient.h
@ -1,10 +1,14 @@
|
||||
#include <stdint.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#ifndef WSCLIENT_H_
|
||||
#define WSCLIENT_H_
|
||||
|
||||
#define FRAME_CHUNK_LENGTH 1024
|
||||
#define HELPER_RECV_BUF_SIZE 1024
|
||||
|
||||
#define CLIENT_IS_SSL (1 << 0)
|
||||
#define CLIENT_CONNECTING (1 << 1)
|
||||
@ -41,6 +45,10 @@
|
||||
#define WS_HANDSHAKE_NO_UPGRADE_ERR -16
|
||||
#define WS_HANDSHAKE_NO_CONNECTION_ERR -17
|
||||
#define WS_HANDSHAKE_BAD_ACCEPT_ERR -18
|
||||
#define WS_HELPER_ALREADY_BOUND_ERR -19
|
||||
#define WS_HELPER_CREATE_SOCK_ERR -20
|
||||
#define WS_HELPER_BIND_ERR -21
|
||||
#define WS_HELPER_LISTEN_ERR -22
|
||||
|
||||
typedef struct _wsclient_frame {
|
||||
unsigned int fin;
|
||||
@ -69,6 +77,7 @@ typedef struct _wsclient_error {
|
||||
} wsclient_error;
|
||||
|
||||
typedef struct _wsclient {
|
||||
pthread_t helper_thread;
|
||||
pthread_t handshake_thread;
|
||||
pthread_t run_thread;
|
||||
pthread_mutex_t lock;
|
||||
@ -80,6 +89,8 @@ typedef struct _wsclient {
|
||||
int (*onerror)(struct _wsclient *, wsclient_error *err);
|
||||
int (*onmessage)(struct _wsclient *, wsclient_message *msg);
|
||||
wsclient_frame *current_frame;
|
||||
struct sockaddr_un helper_sa;
|
||||
int helper_sock;
|
||||
|
||||
} wsclient;
|
||||
|
||||
@ -100,6 +111,8 @@ void libwsclient_cleanup_frames(wsclient_frame *first);
|
||||
void libwsclient_in_data(wsclient *c, char in);
|
||||
void libwsclient_dispatch_message(wsclient *c, wsclient_frame *current);
|
||||
void libwsclient_close(wsclient *c);
|
||||
int libwsclient_helper_socket(wsclient *c, const char *path);
|
||||
void *libwsclient_helper_socket_thread(void *ptr);
|
||||
|
||||
//Define errors
|
||||
char *errors[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user