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) {
|
int onopen(wsclient *c) {
|
||||||
fprintf(stderr, "onopen called.\n");
|
fprintf(stderr, "onopen called: %d\n", c->sockfd);
|
||||||
libwsclient_send(c, "testing::testing::demo.paydensutherland.com");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
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) {
|
if(!client) {
|
||||||
fprintf(stderr, "Unable to initialize new WS client.\n");
|
fprintf(stderr, "Unable to initialize new WS client.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -33,6 +32,7 @@ int main(int argc, char **argv) {
|
|||||||
libwsclient_onmessage(client, &onmessage);
|
libwsclient_onmessage(client, &onmessage);
|
||||||
libwsclient_onerror(client, &onerror);
|
libwsclient_onerror(client, &onerror);
|
||||||
libwsclient_onclose(client, &onclose);
|
libwsclient_onclose(client, &onclose);
|
||||||
|
libwsclient_helper_socket(client, "test.sock");
|
||||||
libwsclient_run(client);
|
libwsclient_run(client);
|
||||||
libwsclient_finish(client);
|
libwsclient_finish(client);
|
||||||
return 0;
|
return 0;
|
||||||
|
83
wsclient.c
83
wsclient.c
@ -7,6 +7,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
@ -351,6 +352,88 @@ int libwsclient_open_connection(const char *host, const char *port) {
|
|||||||
return sockfd;
|
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 *libwsclient_new(const char *URI) {
|
||||||
wsclient *client = NULL;
|
wsclient *client = NULL;
|
||||||
|
|
||||||
|
13
wsclient.h
13
wsclient.h
@ -1,10 +1,14 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
#ifndef WSCLIENT_H_
|
#ifndef WSCLIENT_H_
|
||||||
#define WSCLIENT_H_
|
#define WSCLIENT_H_
|
||||||
|
|
||||||
#define FRAME_CHUNK_LENGTH 1024
|
#define FRAME_CHUNK_LENGTH 1024
|
||||||
|
#define HELPER_RECV_BUF_SIZE 1024
|
||||||
|
|
||||||
#define CLIENT_IS_SSL (1 << 0)
|
#define CLIENT_IS_SSL (1 << 0)
|
||||||
#define CLIENT_CONNECTING (1 << 1)
|
#define CLIENT_CONNECTING (1 << 1)
|
||||||
@ -41,6 +45,10 @@
|
|||||||
#define WS_HANDSHAKE_NO_UPGRADE_ERR -16
|
#define WS_HANDSHAKE_NO_UPGRADE_ERR -16
|
||||||
#define WS_HANDSHAKE_NO_CONNECTION_ERR -17
|
#define WS_HANDSHAKE_NO_CONNECTION_ERR -17
|
||||||
#define WS_HANDSHAKE_BAD_ACCEPT_ERR -18
|
#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 {
|
typedef struct _wsclient_frame {
|
||||||
unsigned int fin;
|
unsigned int fin;
|
||||||
@ -69,6 +77,7 @@ typedef struct _wsclient_error {
|
|||||||
} wsclient_error;
|
} wsclient_error;
|
||||||
|
|
||||||
typedef struct _wsclient {
|
typedef struct _wsclient {
|
||||||
|
pthread_t helper_thread;
|
||||||
pthread_t handshake_thread;
|
pthread_t handshake_thread;
|
||||||
pthread_t run_thread;
|
pthread_t run_thread;
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
@ -80,6 +89,8 @@ typedef struct _wsclient {
|
|||||||
int (*onerror)(struct _wsclient *, wsclient_error *err);
|
int (*onerror)(struct _wsclient *, wsclient_error *err);
|
||||||
int (*onmessage)(struct _wsclient *, wsclient_message *msg);
|
int (*onmessage)(struct _wsclient *, wsclient_message *msg);
|
||||||
wsclient_frame *current_frame;
|
wsclient_frame *current_frame;
|
||||||
|
struct sockaddr_un helper_sa;
|
||||||
|
int helper_sock;
|
||||||
|
|
||||||
} wsclient;
|
} wsclient;
|
||||||
|
|
||||||
@ -100,6 +111,8 @@ void libwsclient_cleanup_frames(wsclient_frame *first);
|
|||||||
void libwsclient_in_data(wsclient *c, char in);
|
void libwsclient_in_data(wsclient *c, char in);
|
||||||
void libwsclient_dispatch_message(wsclient *c, wsclient_frame *current);
|
void libwsclient_dispatch_message(wsclient *c, wsclient_frame *current);
|
||||||
void libwsclient_close(wsclient *c);
|
void libwsclient_close(wsclient *c);
|
||||||
|
int libwsclient_helper_socket(wsclient *c, const char *path);
|
||||||
|
void *libwsclient_helper_socket_thread(void *ptr);
|
||||||
|
|
||||||
//Define errors
|
//Define errors
|
||||||
char *errors[] = {
|
char *errors[] = {
|
||||||
|
Loading…
Reference in New Issue
Block a user