Added clibs-net and clibs-buffer to 3rdparty
This commit is contained in:
parent
b5cba7bf57
commit
16fff2fd51
12 changed files with 1589 additions and 0 deletions
16
src/3rdparty/clib-net/CHANGELOGS
vendored
Normal file
16
src/3rdparty/clib-net/CHANGELOGS
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
# Change Logs
|
||||
|
||||
2014-4-13(v0.1.1):
|
||||
|
||||
* add a fake function: tls_get_peer_cert
|
||||
|
||||
* tls_handle_bio_error and tls_handle_ssl_error added for a common usage
|
||||
|
||||
* fix a high cpu bug in uv lines
|
||||
|
||||
* make SSL_MODE_RELEASE_BUFFERS be gracefully imported
|
||||
|
||||
* correct onConnect and onRead for ssl
|
||||
|
||||
* fix a memory leak in ssl part
|
17
src/3rdparty/clib-net/Makefile
vendored
Normal file
17
src/3rdparty/clib-net/Makefile
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
CC ?= gcc
|
||||
SRC = $(wildcard src/*.c) tests/simple.c
|
||||
DEPS = $(wildcard deps/*/*.c)
|
||||
CFLAGS = -std=c++11\
|
||||
-Iinclude\
|
||||
-Isrc\
|
||||
-Ideps\
|
||||
-Ideps/libuv/include\
|
||||
-Ldeps/libuv/build/Release\
|
||||
-Wall -Wno-unused-function
|
||||
LDFLAGS = -lcrypto -lssl -luv
|
||||
|
||||
test: $(SRC)
|
||||
$(CC) $(CFLAGS) -o $@ $(SRC) $(DEPS) $(LDFLAGS)
|
||||
|
||||
.PHONY: test
|
40
src/3rdparty/clib-net/deps/buffer/History.md
vendored
Normal file
40
src/3rdparty/clib-net/deps/buffer/History.md
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
0.4.0 / 2015-01-05
|
||||
==================
|
||||
|
||||
* refactor
|
||||
* buffer: Remove printf() statement
|
||||
* Add `buffer_appendf()` (#10, marcomorain)
|
||||
|
||||
0.3.0 / 2014-12-24
|
||||
==================
|
||||
|
||||
* travis: Fail the build if any memory is leaked
|
||||
* test: Fix memory leaks
|
||||
* travis: setup
|
||||
* Add `buffer_append_n(buffer_t *, const char *, size_t)`
|
||||
|
||||
0.2.1 / 2014-12-23
|
||||
==================
|
||||
|
||||
* fix header guard
|
||||
* fix compilation on linux
|
||||
* Add missing null terminator after realloc (buffer resize)
|
||||
* Make it safe to always use `data` as a character string
|
||||
|
||||
0.2.0 / 2013-01-05
|
||||
==================
|
||||
|
||||
* add print_buffer()
|
||||
* add buffer_compact()
|
||||
|
||||
0.1.0 / 2012-12-26
|
||||
==================
|
||||
|
||||
* add trim functions
|
||||
* add buffer_clear(buffer_t *self)
|
||||
* add buffer_fill(buffer_t *self, int c)
|
||||
* add buffer_new_with_string_length(char *str, size_t len)
|
||||
* add buffer_new_with_copy(char *str)
|
||||
* add buffer_indexof()
|
||||
|
6
src/3rdparty/clib-net/deps/buffer/Makefile
vendored
Normal file
6
src/3rdparty/clib-net/deps/buffer/Makefile
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
test: buffer.c test.c
|
||||
@$(CC) $^ -std=c99 -o $@
|
||||
@./test
|
||||
|
||||
.PHONY: test
|
82
src/3rdparty/clib-net/deps/buffer/Readme.md
vendored
Normal file
82
src/3rdparty/clib-net/deps/buffer/Readme.md
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
|
||||
# buffer
|
||||
|
||||
Tiny C string manipulation library.
|
||||
|
||||
## Installation
|
||||
|
||||
Install with [clib](https://github.com/clibs/clib):
|
||||
|
||||
```
|
||||
$ clib install clibs/buffer
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```c
|
||||
buffer_t *
|
||||
buffer_new();
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_size(size_t n);
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_string(char *str);
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_string_length(char *str, size_t len);
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_copy(char *str);
|
||||
|
||||
size_t
|
||||
buffer_size(buffer_t *self);
|
||||
|
||||
size_t
|
||||
buffer_length(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_free(buffer_t *self);
|
||||
|
||||
int
|
||||
buffer_prepend(buffer_t *self, char *str);
|
||||
|
||||
int
|
||||
buffer_append(buffer_t *self, char *str);
|
||||
|
||||
int
|
||||
buffer_equals(buffer_t *self, buffer_t *other);
|
||||
|
||||
ssize_t
|
||||
buffer_indexof(buffer_t *self, char *str);
|
||||
|
||||
buffer_t *
|
||||
buffer_slice(buffer_t *self, size_t from, ssize_t to);
|
||||
|
||||
ssize_t
|
||||
buffer_compact(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_fill(buffer_t *self, int c);
|
||||
|
||||
void
|
||||
buffer_clear(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_trim_left(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_trim_right(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_trim(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_print(buffer_t *self);
|
||||
|
||||
#define buffer_string(self) (self->data)
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
353
src/3rdparty/clib-net/deps/buffer/buffer.c
vendored
Normal file
353
src/3rdparty/clib-net/deps/buffer/buffer.c
vendored
Normal file
|
@ -0,0 +1,353 @@
|
|||
//
|
||||
// buffer.c
|
||||
//
|
||||
// Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>
|
||||
//
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include "buffer.h"
|
||||
|
||||
// TODO: shared with reference counting
|
||||
// TODO: linked list for append/prepend etc
|
||||
|
||||
/*
|
||||
* Compute the nearest multiple of `a` from `b`.
|
||||
*/
|
||||
|
||||
#define nearest_multiple_of(a, b) \
|
||||
(((b) + ((a) - 1)) & ~((a) - 1))
|
||||
|
||||
/*
|
||||
* Allocate a new buffer with BUFFER_DEFAULT_SIZE.
|
||||
*/
|
||||
|
||||
buffer_t *
|
||||
buffer_new() {
|
||||
return buffer_new_with_size(BUFFER_DEFAULT_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new buffer with `n` bytes.
|
||||
*/
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_size(size_t n) {
|
||||
buffer_t *self = malloc(sizeof(buffer_t));
|
||||
if (!self) return NULL;
|
||||
self->len = n;
|
||||
self->data = self->alloc = calloc(n + 1, 1);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new buffer with `str`.
|
||||
*/
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_string(char *str) {
|
||||
return buffer_new_with_string_length(str, strlen(str));
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new buffer with `str` and `len`.
|
||||
*/
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_string_length(char *str, size_t len) {
|
||||
buffer_t *self = malloc(sizeof(buffer_t));
|
||||
if (!self) return NULL;
|
||||
self->len = len;
|
||||
self->data = self->alloc = str;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new buffer with a copy of `str`.
|
||||
*/
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_copy(char *str) {
|
||||
size_t len = strlen(str);
|
||||
buffer_t *self = buffer_new_with_size(len);
|
||||
if (!self) return NULL;
|
||||
memcpy(self->alloc, str, len);
|
||||
self->data = self->alloc;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deallocate excess memory, the number
|
||||
* of bytes removed or -1.
|
||||
*/
|
||||
|
||||
ssize_t
|
||||
buffer_compact(buffer_t *self) {
|
||||
size_t len = buffer_length(self);
|
||||
size_t rem = self->len - len;
|
||||
char *buf = calloc(len + 1, 1);
|
||||
if (!buf) return -1;
|
||||
memcpy(buf, self->data, len);
|
||||
free(self->alloc);
|
||||
self->len = len;
|
||||
self->data = self->alloc = buf;
|
||||
return rem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the buffer.
|
||||
*/
|
||||
|
||||
void
|
||||
buffer_free(buffer_t *self) {
|
||||
free(self->alloc);
|
||||
free(self);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return buffer size.
|
||||
*/
|
||||
|
||||
size_t
|
||||
buffer_size(buffer_t *self) {
|
||||
return self->len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return string length.
|
||||
*/
|
||||
|
||||
size_t
|
||||
buffer_length(buffer_t *self) {
|
||||
return strlen(self->data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize to hold `n` bytes.
|
||||
*/
|
||||
|
||||
int
|
||||
buffer_resize(buffer_t *self, size_t n) {
|
||||
n = nearest_multiple_of(1024, n);
|
||||
self->len = n;
|
||||
self->alloc = self->data = realloc(self->alloc, n + 1);
|
||||
if (!self->alloc) return -1;
|
||||
self->alloc[n] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append a printf-style formatted string to the buffer.
|
||||
*/
|
||||
|
||||
int buffer_appendf(buffer_t *self, const char *format, ...) {
|
||||
va_list ap;
|
||||
va_list tmpa;
|
||||
char *dst = NULL;
|
||||
int length = 0;
|
||||
int required = 0;
|
||||
int bytes = 0;
|
||||
|
||||
va_start(ap, format);
|
||||
|
||||
length = buffer_length(self);
|
||||
|
||||
// First, we compute how many bytes are needed
|
||||
// for the formatted string and allocate that
|
||||
// much more space in the buffer.
|
||||
va_copy(tmpa, ap);
|
||||
required = vsnprintf(NULL, 0, format, tmpa);
|
||||
va_end(tmpa);
|
||||
if (-1 == buffer_resize(self, length + required)) {
|
||||
va_end(ap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Next format the string into the space that we
|
||||
// have made room for.
|
||||
dst = self->data + length;
|
||||
bytes = vsnprintf(dst, 1 + required, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return bytes < 0
|
||||
? -1
|
||||
: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append `str` to `self` and return 0 on success, -1 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
buffer_append(buffer_t *self, const char *str) {
|
||||
return buffer_append_n(self, str, strlen(str));
|
||||
}
|
||||
|
||||
/*
|
||||
* Append the first `len` bytes from `str` to `self` and
|
||||
* return 0 on success, -1 on failure.
|
||||
*/
|
||||
int
|
||||
buffer_append_n(buffer_t *self, const char *str, size_t len) {
|
||||
size_t prev = strlen(self->data);
|
||||
size_t needed = len + prev;
|
||||
|
||||
// enough space
|
||||
if (self->len > needed) {
|
||||
strncat(self->data, str, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// resize
|
||||
int ret = buffer_resize(self, needed);
|
||||
if (-1 == ret) return -1;
|
||||
strncat(self->data, str, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepend `str` to `self` and return 0 on success, -1 on failure.
|
||||
*/
|
||||
|
||||
int
|
||||
buffer_prepend(buffer_t *self, char *str) {
|
||||
size_t len = strlen(str);
|
||||
size_t prev = strlen(self->data);
|
||||
size_t needed = len + prev;
|
||||
|
||||
// enough space
|
||||
if (self->len > needed) goto move;
|
||||
|
||||
// resize
|
||||
int ret = buffer_resize(self, needed);
|
||||
if (-1 == ret) return -1;
|
||||
|
||||
// move
|
||||
move:
|
||||
memmove(self->data + len, self->data, len + 1);
|
||||
memcpy(self->data, str, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a new buffer based on the `from..to` slice of `buf`,
|
||||
* or NULL on error.
|
||||
*/
|
||||
|
||||
buffer_t *
|
||||
buffer_slice(buffer_t *buf, size_t from, ssize_t to) {
|
||||
size_t len = strlen(buf->data);
|
||||
|
||||
// bad range
|
||||
if (to < from) return NULL;
|
||||
|
||||
// relative to end
|
||||
if (to < 0) to = len - ~to;
|
||||
|
||||
// cap end
|
||||
if (to > len) to = len;
|
||||
|
||||
size_t n = to - from;
|
||||
buffer_t *self = buffer_new_with_size(n);
|
||||
memcpy(self->data, buf->data + from, n);
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if the buffers contain equivalent data.
|
||||
*/
|
||||
|
||||
int
|
||||
buffer_equals(buffer_t *self, buffer_t *other) {
|
||||
return 0 == strcmp(self->data, other->data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the index of the substring `str`, or -1 on failure.
|
||||
*/
|
||||
|
||||
ssize_t
|
||||
buffer_indexof(buffer_t *self, char *str) {
|
||||
char *sub = strstr(self->data, str);
|
||||
if (!sub) return -1;
|
||||
return sub - self->data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Trim leading whitespace.
|
||||
*/
|
||||
|
||||
void
|
||||
buffer_trim_left(buffer_t *self) {
|
||||
int c;
|
||||
while ((c = *self->data) && isspace(c)) {
|
||||
++self->data;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Trim trailing whitespace.
|
||||
*/
|
||||
|
||||
void
|
||||
buffer_trim_right(buffer_t *self) {
|
||||
int c;
|
||||
size_t i = buffer_length(self) - 1;
|
||||
while ((c = self->data[i]) && isspace(c)) {
|
||||
self->data[i--] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Trim trailing and leading whitespace.
|
||||
*/
|
||||
|
||||
void
|
||||
buffer_trim(buffer_t *self) {
|
||||
buffer_trim_left(self);
|
||||
buffer_trim_right(self);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the buffer with `c`.
|
||||
*/
|
||||
|
||||
void
|
||||
buffer_fill(buffer_t *self, int c) {
|
||||
memset(self->data, c, self->len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the buffer with 0.
|
||||
*/
|
||||
|
||||
void
|
||||
buffer_clear(buffer_t *self) {
|
||||
buffer_fill(self, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a hex dump of the buffer.
|
||||
*/
|
||||
|
||||
void
|
||||
buffer_print(buffer_t *self) {
|
||||
int i;
|
||||
size_t len = self->len;
|
||||
|
||||
printf("\n ");
|
||||
|
||||
// hex
|
||||
for (i = 0; i < len; ++i) {
|
||||
printf(" %02x", self->alloc[i]);
|
||||
if ((i + 1) % 8 == 0) printf("\n ");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
101
src/3rdparty/clib-net/deps/buffer/buffer.h
vendored
Normal file
101
src/3rdparty/clib-net/deps/buffer/buffer.h
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
|
||||
//
|
||||
// buffer.h
|
||||
//
|
||||
// Copyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>
|
||||
//
|
||||
|
||||
#ifndef BUFFER_H
|
||||
#define BUFFER_H 1
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* Default buffer size.
|
||||
*/
|
||||
|
||||
#ifndef BUFFER_DEFAULT_SIZE
|
||||
#define BUFFER_DEFAULT_SIZE 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Buffer struct.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
char *alloc;
|
||||
char *data;
|
||||
} buffer_t;
|
||||
|
||||
// prototypes
|
||||
|
||||
buffer_t *
|
||||
buffer_new();
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_size(size_t n);
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_string(char *str);
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_string_length(char *str, size_t len);
|
||||
|
||||
buffer_t *
|
||||
buffer_new_with_copy(char *str);
|
||||
|
||||
size_t
|
||||
buffer_size(buffer_t *self);
|
||||
|
||||
size_t
|
||||
buffer_length(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_free(buffer_t *self);
|
||||
|
||||
int
|
||||
buffer_prepend(buffer_t *self, char *str);
|
||||
|
||||
int
|
||||
buffer_append(buffer_t *self, const char *str);
|
||||
|
||||
int
|
||||
buffer_appendf(buffer_t *self, const char *format, ...);
|
||||
|
||||
int
|
||||
buffer_append_n(buffer_t *self, const char *str, size_t len);
|
||||
|
||||
int
|
||||
buffer_equals(buffer_t *self, buffer_t *other);
|
||||
|
||||
ssize_t
|
||||
buffer_indexof(buffer_t *self, char *str);
|
||||
|
||||
buffer_t *
|
||||
buffer_slice(buffer_t *self, size_t from, ssize_t to);
|
||||
|
||||
ssize_t
|
||||
buffer_compact(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_fill(buffer_t *self, int c);
|
||||
|
||||
void
|
||||
buffer_clear(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_trim_left(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_trim_right(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_trim(buffer_t *self);
|
||||
|
||||
void
|
||||
buffer_print(buffer_t *self);
|
||||
|
||||
#define buffer_string(self) (self->data)
|
||||
|
||||
#endif
|
177
src/3rdparty/clib-net/include/net.h
vendored
Normal file
177
src/3rdparty/clib-net/include/net.h
vendored
Normal file
|
@ -0,0 +1,177 @@
|
|||
|
||||
/*
|
||||
* Copyright 2014 <yorkiefixer@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __NET_H__
|
||||
#define __NET_H__
|
||||
|
||||
#include <uv.h>
|
||||
#include <buffer/buffer.h>
|
||||
|
||||
#ifndef XMRIG_NO_SSL_TLS
|
||||
#include "tls.h"
|
||||
#endif
|
||||
|
||||
#define NOT_SSL 0x00
|
||||
#define USE_SSL 0x01
|
||||
|
||||
#define NET_OK 0
|
||||
#define NET_VERSION_MAJOR 0
|
||||
#define NET_VERSION_MINOR 1
|
||||
#define NET_VERSION_PATCH 2
|
||||
#define NET_VERSION_IS_RELEASE 0
|
||||
|
||||
typedef struct net_s net_t;
|
||||
typedef struct addrinfo net_ai;
|
||||
typedef struct sockaddr_in socketPair_t;
|
||||
|
||||
#define NET_FIELDS \
|
||||
NET_CONNECTION_FIELDS \
|
||||
NET_UV_FIELDS \
|
||||
NET_TLS_FIELDS \
|
||||
|
||||
#define NET_CONNECTION_FIELDS \
|
||||
char *hostname; \
|
||||
int port; \
|
||||
int connected; \
|
||||
|
||||
|
||||
#define NET_UV_FIELDS \
|
||||
uv_getaddrinfo_t *resolver; \
|
||||
uv_loop_t *loop; \
|
||||
uv_tcp_t *handle; \
|
||||
uv_connect_t *conn; \
|
||||
|
||||
#ifndef XMRIG_NO_SSL_TLS
|
||||
#define NET_TLS_FIELDS \
|
||||
int use_ssl; \
|
||||
int tls_established; \
|
||||
tls_t *tls;
|
||||
#else
|
||||
#define NET_TLS_FIELDS \
|
||||
int use_ssl; \
|
||||
int tls_established;
|
||||
#endif
|
||||
|
||||
|
||||
struct net_s {
|
||||
NET_FIELDS;
|
||||
void *data;
|
||||
void (*conn_cb)(net_t*);
|
||||
void (*read_cb)(net_t*, size_t, char*);
|
||||
void (*error_cb)(net_t*, int, char*);
|
||||
void (*close_cb)(uv_handle_t*);
|
||||
};
|
||||
|
||||
/*
|
||||
* Create an new network.
|
||||
*/
|
||||
net_t *
|
||||
net_new(char * hostname, int port);
|
||||
|
||||
|
||||
#ifndef XMRIG_NO_SSL_TLS
|
||||
/*
|
||||
* Set SSL's Context
|
||||
*/
|
||||
int
|
||||
net_set_tls(net_t * net, tls_ctx * ctx);
|
||||
#endif
|
||||
/*
|
||||
* Do connect to new
|
||||
*/
|
||||
int
|
||||
net_connect(net_t * net);
|
||||
|
||||
/*
|
||||
* Just close the holding connection
|
||||
*/
|
||||
int
|
||||
net_close(net_t * net, void (*cb)(uv_handle_t*));
|
||||
|
||||
/*
|
||||
* free connection
|
||||
*/
|
||||
int
|
||||
net_free(net_t * net);
|
||||
|
||||
/*
|
||||
* real free function
|
||||
*/
|
||||
void
|
||||
net_free_cb(uv_handle_t * handle);
|
||||
|
||||
/*
|
||||
* DNS resolve
|
||||
*/
|
||||
int
|
||||
net_resolve(net_t * net);
|
||||
|
||||
/*
|
||||
* DNS -> IP done, and call `net_resolve_cb`
|
||||
*/
|
||||
void
|
||||
net_resolve_cb(uv_getaddrinfo_t *rv, int stat, net_ai * ai);
|
||||
|
||||
/*
|
||||
* connect created, and call `net_connect_cb`
|
||||
*/
|
||||
void
|
||||
net_connect_cb(uv_connect_t *conn, int stat);
|
||||
|
||||
/*
|
||||
* realloc buffer before you read
|
||||
*/
|
||||
void
|
||||
net_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf);
|
||||
|
||||
/*
|
||||
* read buffer
|
||||
*/
|
||||
void
|
||||
net_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf);
|
||||
|
||||
/*
|
||||
* write buffer
|
||||
*/
|
||||
int
|
||||
net_write(net_t * net, char * buf);
|
||||
|
||||
/*
|
||||
* write buffer with length specified
|
||||
*/
|
||||
int
|
||||
net_write2(net_t * net, char * buf, unsigned int len);
|
||||
|
||||
/*
|
||||
* return use_ssl
|
||||
*/
|
||||
int
|
||||
net_use_ssl(net_t * net);
|
||||
|
||||
/*
|
||||
* continue to read after on data
|
||||
*/
|
||||
int
|
||||
net_resume(net_t * net);
|
||||
|
||||
/*
|
||||
* pause read
|
||||
*/
|
||||
int
|
||||
net_pause(net_t * net);
|
||||
|
||||
/*
|
||||
* set error_cb
|
||||
*/
|
||||
int
|
||||
net_set_error_cb(net_t * net, void * cb);
|
||||
|
||||
/*
|
||||
* write buffer, and call `net_write_cb`.
|
||||
*/
|
||||
void
|
||||
net_write_cb(uv_write_t *writer, int stat);
|
||||
|
||||
#endif /* __NET_H__ */
|
133
src/3rdparty/clib-net/include/tls.h
vendored
Normal file
133
src/3rdparty/clib-net/include/tls.h
vendored
Normal file
|
@ -0,0 +1,133 @@
|
|||
|
||||
/*
|
||||
* Copyright 2014 <yorkiefixer@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __TLS_H__
|
||||
#define __TLS_H__
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <buffer/buffer.h>
|
||||
|
||||
#define SSL_CHUNK_SIZE 512
|
||||
|
||||
typedef SSL_CTX tls_ctx;
|
||||
typedef struct tls_s {
|
||||
SSL_CTX * ctx;
|
||||
SSL * ssl;
|
||||
BIO * bio_in;
|
||||
BIO * bio_out;
|
||||
buffer_t * buffer;
|
||||
int connected;
|
||||
char * data;
|
||||
char buf[SSL_CHUNK_SIZE]; /* internal usage */
|
||||
} tls_t;
|
||||
|
||||
static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
|
||||
| ASN1_STRFLGS_ESC_MSB
|
||||
| XN_FLAG_SEP_MULTILINE
|
||||
| XN_FLAG_FN_SN;
|
||||
|
||||
/*
|
||||
* initialize the ssl
|
||||
*/
|
||||
void
|
||||
ssl_init();
|
||||
|
||||
/*
|
||||
* destroy the ssl settings and internal tables
|
||||
*/
|
||||
void
|
||||
ssl_destroy();
|
||||
|
||||
/*
|
||||
* create a context for ssl
|
||||
*/
|
||||
tls_ctx *
|
||||
tls_ctx_new();
|
||||
|
||||
/*
|
||||
* create a tls instance
|
||||
*/
|
||||
tls_t *
|
||||
tls_create(tls_ctx * ctx);
|
||||
|
||||
/*
|
||||
* shutdown tls
|
||||
*/
|
||||
int
|
||||
tls_shutdown(tls_t * tls);
|
||||
|
||||
/*
|
||||
* destroy a tls instance
|
||||
*/
|
||||
int
|
||||
tls_free(tls_t * tls);
|
||||
|
||||
/*
|
||||
* get peer certification info
|
||||
*/
|
||||
int
|
||||
tls_get_peer_cert(tls_t * tls);
|
||||
|
||||
/*
|
||||
* do connect to tls
|
||||
*/
|
||||
int
|
||||
tls_connect(tls_t * tls);
|
||||
|
||||
/*
|
||||
* handle error in bio
|
||||
*/
|
||||
int
|
||||
tls_handle_bio_error(tls_t * tls, int err);
|
||||
|
||||
/*
|
||||
* handle error in ssl
|
||||
*/
|
||||
int
|
||||
tls_handle_ssl_error(tls_t *tls, int err);
|
||||
|
||||
/*
|
||||
* a port in tls for `bio_read`
|
||||
*/
|
||||
int
|
||||
tls_bio_read(tls_t * tls, int len);
|
||||
|
||||
/*
|
||||
* a port in tls for `bio_write`
|
||||
*/
|
||||
int
|
||||
tls_bio_write(tls_t * tls, char * written, int len);
|
||||
|
||||
/*
|
||||
* read
|
||||
*/
|
||||
int
|
||||
tls_read(tls_t * tls);
|
||||
|
||||
/*
|
||||
* write
|
||||
*/
|
||||
int
|
||||
tls_write(tls_t * tls, char * written, int len);
|
||||
|
||||
/*
|
||||
* write a tls packet
|
||||
*/
|
||||
#define REQUEST_TLS_WRITE(name, cmd, read, req) do { \
|
||||
tls_write(req->tls, cmd); \
|
||||
do { \
|
||||
read = tls_bio_read(req->tls, 0); \
|
||||
if (read > 0) { \
|
||||
REQUEST_WRITE(req, req->tls->buf, read, name); \
|
||||
} \
|
||||
} while (read > 0); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
||||
#endif /* __TLS_H__ */
|
53
src/3rdparty/clib-net/readme.md
vendored
Normal file
53
src/3rdparty/clib-net/readme.md
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
|
||||
# net-client
|
||||
|
||||
Simple network client
|
||||
|
||||
### Requirement
|
||||
|
||||
* libuv 0.10.x
|
||||
|
||||
* buffer 0.2.0
|
||||
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
$ clib install clibs/net
|
||||
$ git clone https://github.com/joyent/libuv.git deps/libuv
|
||||
$ checkout v0.10.25
|
||||
```
|
||||
|
||||
### Run tests
|
||||
|
||||
```sh
|
||||
make test
|
||||
./test
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```c
|
||||
static void
|
||||
imap_parser(net_t * net, size_t read, char * buf) {
|
||||
printf("%s\n", buf);
|
||||
printf("%zu\n", read);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
ssl_init();
|
||||
tls_ctx * ctx = tls_ctx_new();
|
||||
net_t * net = net_new("imap.gmail.com", 993);
|
||||
net->onRead = imap_parser;
|
||||
|
||||
// convert this socket to ssl
|
||||
net_set_tls(net, ctx);
|
||||
net_connect(net);
|
||||
|
||||
uv_run(net->loop, UV_RUN_DEFAULT);
|
||||
}
|
||||
```
|
||||
|
||||
### License
|
||||
|
||||
MIT
|
390
src/3rdparty/clib-net/src/net.c
vendored
Normal file
390
src/3rdparty/clib-net/src/net.c
vendored
Normal file
|
@ -0,0 +1,390 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <uv.h>
|
||||
#include "net.h"
|
||||
|
||||
net_t *
|
||||
net_new(char * hostname, int port) {
|
||||
net_t * net = (net_t*) malloc(sizeof(net_t));
|
||||
net->loop = uv_default_loop();
|
||||
net->hostname = hostname;
|
||||
net->port = port;
|
||||
net->connected = 0;
|
||||
net->tls_established = 0;
|
||||
net->use_ssl = 0;
|
||||
net->conn_cb = NULL;
|
||||
net->read_cb = NULL;
|
||||
net->error_cb = NULL;
|
||||
net->close_cb = NULL;
|
||||
net->handle = (uv_tcp_t *) malloc(sizeof(uv_tcp_t));
|
||||
net->conn = (uv_connect_t *) malloc(sizeof(uv_connect_t));
|
||||
net->handle->data
|
||||
= net->conn->data
|
||||
= (void *) net;
|
||||
|
||||
return net;
|
||||
}
|
||||
|
||||
#ifndef XMRIG_NO_SSL_TLS
|
||||
int
|
||||
net_set_tls(net_t * net, tls_ctx * ctx) {
|
||||
net->use_ssl = USE_SSL;
|
||||
net->tls = tls_create(ctx);
|
||||
return NET_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
net_connect(net_t * net) {
|
||||
net_resolve(net);
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
int
|
||||
net_close(net_t * net, void (*cb)(uv_handle_t*)) {
|
||||
int r = net->connected;
|
||||
if (r == 1) {
|
||||
net->connected = 0;
|
||||
net->tls_established = 0;
|
||||
|
||||
#ifndef XMRIG_NO_SSL_TLS
|
||||
if (net->use_ssl) {
|
||||
tls_shutdown(net->tls);
|
||||
}
|
||||
#endif
|
||||
|
||||
uv_close((uv_handle_t*)net->handle, cb);
|
||||
|
||||
#ifndef XMRIG_NO_SSL_TLS
|
||||
if (net->use_ssl) {
|
||||
tls_free(net->tls);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
net_free(net_t * net) {
|
||||
net_close(net, NULL);
|
||||
free(net->resolver);
|
||||
free(net);
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
void
|
||||
net_free_cb(uv_handle_t * handle) {
|
||||
net_t * net = (net_t *) handle->data;
|
||||
if (net->handle != NULL) {
|
||||
free(net->handle);
|
||||
net->handle = NULL;
|
||||
}
|
||||
if (net->conn != NULL) {
|
||||
free(net->conn);
|
||||
net->conn = NULL;
|
||||
}
|
||||
if (net->resolver != NULL) {
|
||||
free(net->resolver);
|
||||
net->resolver = NULL;
|
||||
}
|
||||
if (net != NULL) {
|
||||
free(net);
|
||||
net = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
net_resolve(net_t * net) {
|
||||
net_ai hints;
|
||||
int ret;
|
||||
char buf[6];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", net->port);
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
net->resolver = malloc(sizeof(uv_getaddrinfo_t));
|
||||
if (!net->resolver) {
|
||||
/*
|
||||
* TODO(Yorkie): depent parital handles
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
net->resolver->data = (void *) net;
|
||||
ret = uv_getaddrinfo(net->loop, net->resolver,
|
||||
net_resolve_cb, net->hostname, NULL, &hints);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
net_resolve_cb(uv_getaddrinfo_t *rv, int err, net_ai * ai) {
|
||||
net_t * net = (net_t*) rv->data;
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
int ret;
|
||||
struct sockaddr_in dest;
|
||||
|
||||
if (err != 0) {
|
||||
if (net->error_cb) {
|
||||
net->error_cb(net, err, (char *) uv_strerror(err));
|
||||
} else {
|
||||
printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(err));
|
||||
net_free(net);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uv_ip4_name((socketPair_t *) ai->ai_addr, addr, INET6_ADDRSTRLEN);
|
||||
ret = uv_ip4_addr(addr, net->port, &dest);
|
||||
|
||||
if (ret != 0) {
|
||||
if (net->error_cb) {
|
||||
net->error_cb(net, ret, (char *) uv_strerror(err));
|
||||
} else {
|
||||
printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(err));
|
||||
net_free(net);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* create tcp instance.
|
||||
*/
|
||||
uv_tcp_init(net->loop, net->handle);
|
||||
ret = uv_tcp_connect(net->conn, net->handle, (const struct sockaddr*) &dest, net_connect_cb);
|
||||
if (ret != NET_OK) {
|
||||
if (net->error_cb) {
|
||||
net->error_cb(net, ret, (char *) uv_strerror(err));
|
||||
} else {
|
||||
printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(err));
|
||||
net_free(net);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* free
|
||||
*/
|
||||
uv_freeaddrinfo(ai);
|
||||
}
|
||||
|
||||
void
|
||||
net_connect_cb(uv_connect_t *conn, int err) {
|
||||
net_t * net = (net_t *) conn->data;
|
||||
int read;
|
||||
|
||||
if (err < 0) {
|
||||
if (net->error_cb) {
|
||||
net->error_cb(net, err, (char *) uv_strerror(err));
|
||||
} else {
|
||||
printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(err));
|
||||
net_free(net);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* change the `connected` state
|
||||
*/
|
||||
net->connected = 1;
|
||||
|
||||
/*
|
||||
* read buffers via uv
|
||||
*/
|
||||
uv_read_start((uv_stream_t *) net->handle, net_alloc, net_read);
|
||||
|
||||
/*
|
||||
* call `onConnect`, the tcp connection has been
|
||||
* established in user-land.
|
||||
*/
|
||||
if (net->use_ssl == NOT_SSL && net->conn_cb != NULL) {
|
||||
net->conn_cb(net);
|
||||
}
|
||||
|
||||
#ifndef XMRIG_NO_SSL_TLS
|
||||
/*
|
||||
* Handle TLS Partial
|
||||
*/
|
||||
if (net->use_ssl == USE_SSL && tls_connect(net->tls) == NET_OK) {
|
||||
read = 0;
|
||||
do {
|
||||
read = tls_bio_read(net->tls, 0);
|
||||
if (read > 0) {
|
||||
char buf[read];
|
||||
uv_write_t * req = malloc(sizeof(uv_write_t));
|
||||
req->data = net;
|
||||
memset(buf, 0, read);
|
||||
memcpy(buf, net->tls->buf, read);
|
||||
uv_buf_t uvbuf = uv_buf_init(buf, read);
|
||||
uv_write(req, (uv_stream_t*)net->handle, &uvbuf, 1, net_write_cb);
|
||||
}
|
||||
} while (read > 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
net_alloc(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
|
||||
buf->base = (char *) calloc(size, 1);
|
||||
buf->len = size;
|
||||
}
|
||||
|
||||
void
|
||||
net_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) {
|
||||
net_t * net = (net_t *) handle->data;
|
||||
|
||||
if (nread < 0) {
|
||||
if (net->error_cb) {
|
||||
net->error_cb(net, nread, (char *) uv_strerror(nread));
|
||||
} else {
|
||||
printf("error(%s:%d) %s", net->hostname, net->port, (char *) uv_strerror(nread));
|
||||
net_free(net);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef XMRIG_NO_SSL_TLS
|
||||
/*
|
||||
* BIO Return rule:
|
||||
* All these functions return either the amount of data successfully
|
||||
* read or written (if the return value is positive) or that no data
|
||||
* was successfully read or written if the result is 0 or -1. If the
|
||||
* return value is -2 then the operation is not implemented in the specific BIO type.
|
||||
*/
|
||||
if (net->use_ssl) {
|
||||
tls_bio_write(net->tls, buf->base, nread);
|
||||
free(buf->base);
|
||||
|
||||
int read = 0;
|
||||
int stat = tls_read(net->tls);
|
||||
if (stat == 1) {
|
||||
/*
|
||||
* continue: Say hello
|
||||
*/
|
||||
do {
|
||||
read = tls_bio_read(net->tls, 0);
|
||||
if (read > 0) {
|
||||
char buf2[read];
|
||||
uv_write_t * req = malloc(sizeof(uv_write_t));
|
||||
req->data = net;
|
||||
memset(buf2, 0, read);
|
||||
memcpy(buf2, net->tls->buf, read);
|
||||
uv_buf_t uvbuf = uv_buf_init(buf2, read);
|
||||
uv_write(req, (uv_stream_t*)net->handle, &uvbuf, 1, net_write_cb);
|
||||
}
|
||||
} while (read > 0);
|
||||
|
||||
} else {
|
||||
/*
|
||||
* SSL Connection is created
|
||||
* Here need to call user-land callback
|
||||
*/
|
||||
if (!net->tls_established) {
|
||||
net->tls_established = 1;
|
||||
if (net->conn_cb != NULL) {
|
||||
net->conn_cb(net);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* read buffer
|
||||
*/
|
||||
if (stat == 0) {
|
||||
if (buffer_string(net->tls->buffer) > 0)
|
||||
// uv_read_stop((uv_stream_t*)net->handle);
|
||||
|
||||
if (net->read_cb != NULL && net->connected && net->tls_established) {
|
||||
net->read_cb(net, buffer_length(net->tls->buffer),
|
||||
buffer_string(net->tls->buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TCP Part, no SSL, just proxy of uv.
|
||||
*/
|
||||
uv_read_stop(handle);
|
||||
buf->base[nread] = 0;
|
||||
if (net->read_cb != NULL) {
|
||||
net->read_cb(net, nread, buf->base);
|
||||
free(buf->base);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
net_write(net_t * net, char * buf) {
|
||||
return net_write2(net, buf, strlen(buf));
|
||||
}
|
||||
|
||||
int
|
||||
net_write2(net_t * net, char * buf, unsigned int len) {
|
||||
uv_write_t * req;
|
||||
uv_buf_t uvbuf;
|
||||
int read = 0;
|
||||
|
||||
switch (net->use_ssl) {
|
||||
case USE_SSL:
|
||||
#ifndef XMRIG_NO_SSL_TLS
|
||||
tls_write(net->tls, buf, (int)len);
|
||||
do {
|
||||
read = tls_bio_read(net->tls, 0);
|
||||
if (read > 0) {
|
||||
req = (uv_write_t *) malloc(sizeof(uv_write_t));
|
||||
req->data = net;
|
||||
uvbuf = uv_buf_init(net->tls->buf, read);
|
||||
uv_write(req, (uv_stream_t*)net->handle,
|
||||
&uvbuf,
|
||||
1,
|
||||
net_write_cb);
|
||||
}
|
||||
} while (read > 0);
|
||||
break;
|
||||
#endif
|
||||
case NOT_SSL:
|
||||
req = (uv_write_t *) malloc(sizeof(uv_write_t));
|
||||
req->data = net;
|
||||
uvbuf = uv_buf_init(buf, len);
|
||||
uv_write(req, (uv_stream_t*)net->handle,
|
||||
&uvbuf,
|
||||
1,
|
||||
net_write_cb);
|
||||
break;
|
||||
}
|
||||
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
int
|
||||
net_use_ssl(net_t * net) {
|
||||
return net->use_ssl == USE_SSL;
|
||||
}
|
||||
|
||||
int
|
||||
net_resume(net_t * net) {
|
||||
uv_read_start((uv_stream_t *)net->handle, net_alloc, net_read);
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
int
|
||||
net_pause(net_t * net) {
|
||||
uv_read_stop((uv_stream_t *)net->handle);
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
int
|
||||
net_set_error_cb(net_t * net, void * cb) {
|
||||
net->error_cb = cb;
|
||||
return NET_OK;
|
||||
}
|
||||
|
||||
void
|
||||
net_write_cb(uv_write_t *req, int stat) {
|
||||
net_resume((net_t*)req->data);
|
||||
free(req);
|
||||
}
|
221
src/3rdparty/clib-net/src/tls.c
vendored
Normal file
221
src/3rdparty/clib-net/src/tls.c
vendored
Normal file
|
@ -0,0 +1,221 @@
|
|||
|
||||
/*
|
||||
* Copyright 2014 <yorkiefixer@gmail.com>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "tls.h"
|
||||
|
||||
void
|
||||
ssl_init() {
|
||||
SSL_library_init();
|
||||
OpenSSL_add_all_algorithms();
|
||||
SSL_load_error_strings();
|
||||
ERR_load_crypto_strings();
|
||||
}
|
||||
|
||||
void
|
||||
ssl_destroy() {
|
||||
EVP_cleanup();
|
||||
ERR_free_strings();
|
||||
}
|
||||
|
||||
tls_ctx *
|
||||
tls_ctx_new() {
|
||||
tls_ctx *ctx = SSL_CTX_new(SSLv23_method());
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
|
||||
#endif
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
tls_t *
|
||||
tls_create(tls_ctx *ctx) {
|
||||
tls_t * tls = (tls_t *) malloc(sizeof(tls_t)+1);
|
||||
if (tls == NULL)
|
||||
fprintf(stderr, "tls> %s", "Out of Memory");
|
||||
|
||||
tls->ctx = ctx;
|
||||
tls->ssl = SSL_new(tls->ctx);
|
||||
tls->bio_in = BIO_new(BIO_s_mem());
|
||||
tls->bio_out = BIO_new(BIO_s_mem());
|
||||
tls->connected = -1;
|
||||
tls->buffer = buffer_new();
|
||||
|
||||
#ifdef SSL_MODE_RELEASE_BUFFERS
|
||||
long mode = SSL_get_mode(tls->ssl);
|
||||
SSL_set_mode(tls->ssl, mode | SSL_MODE_RELEASE_BUFFERS);
|
||||
#endif
|
||||
|
||||
if (tls->ssl == NULL)
|
||||
printf("tls> %s", "Out of Memory");
|
||||
|
||||
SSL_set_connect_state(tls->ssl);
|
||||
SSL_set_bio(tls->ssl, tls->bio_in, tls->bio_out);
|
||||
return tls;
|
||||
}
|
||||
|
||||
int
|
||||
tls_shutdown(tls_t * tls) {
|
||||
assert(tls != NULL);
|
||||
if (SSL_shutdown(tls->ssl) == 0) {
|
||||
SSL_shutdown(tls->ssl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tls_free(tls_t * tls) {
|
||||
if (tls->ssl) {
|
||||
SSL_free(tls->ssl);
|
||||
SSL_CTX_free(tls->ctx);
|
||||
tls->ssl = NULL;
|
||||
}
|
||||
|
||||
buffer_free(tls->buffer);
|
||||
free(tls);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tls_get_peer_cert(tls_t *tls) {
|
||||
X509* peer_cert = SSL_get_peer_certificate(tls->ssl);
|
||||
if (peer_cert != NULL) {
|
||||
/*
|
||||
* TODO(Yorkie): This function is used just for debug
|
||||
*/
|
||||
X509_free(peer_cert);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tls_connect(tls_t *tls) {
|
||||
int rv;
|
||||
int er;
|
||||
|
||||
rv = SSL_do_handshake(tls->ssl);
|
||||
if (rv == 1) {
|
||||
/*
|
||||
* `SSL_do_handshake()` could not return 1,
|
||||
* that caused no message could be returned in `SSL_get_error()`.
|
||||
* TODO(Yorkie): handle error, exit?
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!SSL_is_init_finished(tls->ssl))
|
||||
er = SSL_connect(tls->ssl);
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (er < 0 && SSL_get_error(tls->ssl, er) == SSL_ERROR_WANT_READ)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
tls_handle_bio_error(tls_t *tls, int err) {
|
||||
int rv;
|
||||
int retry = BIO_should_retry(tls->bio_out);
|
||||
if (BIO_should_write(tls->bio_out))
|
||||
rv = -retry;
|
||||
else if (BIO_should_read(tls->bio_out))
|
||||
rv = -retry;
|
||||
else {
|
||||
char ssl_error_buf[512];
|
||||
ERR_error_string_n(err, ssl_error_buf, sizeof(ssl_error_buf));
|
||||
fprintf(stderr, "[%p] BIO: read failed: (%d) %s\n", tls->ssl, err, ssl_error_buf);
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
tls_handle_ssl_error(tls_t *tls, int err) {
|
||||
int ret;
|
||||
int rv = SSL_get_error(tls->ssl, err);
|
||||
switch (rv) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = -2;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
tls_bio_read(tls_t *tls, int buf_len) {
|
||||
if (buf_len == 0) {
|
||||
buf_len = sizeof(tls->buf);
|
||||
}
|
||||
memset(tls->buf, 0, buf_len);
|
||||
|
||||
int ret = BIO_read(tls->bio_out, tls->buf, buf_len);
|
||||
if (ret >= 0) {
|
||||
tls->buf[ret] = 0;
|
||||
return ret;
|
||||
} else {
|
||||
return tls_handle_bio_error(tls, ret);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tls_bio_write(tls_t *tls, char *buf, int len) {
|
||||
int ret = BIO_write(tls->bio_in, buf, len);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
else
|
||||
return tls_handle_bio_error(tls, ret);
|
||||
}
|
||||
|
||||
int
|
||||
tls_read(tls_t *tls) {
|
||||
int err;
|
||||
int ret;
|
||||
int read;
|
||||
|
||||
int done = SSL_is_init_finished(tls->ssl);
|
||||
if (!done) {
|
||||
err = SSL_connect(tls->ssl);
|
||||
if (err <= 0) {
|
||||
return tls_handle_ssl_error(tls, err);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(Yorkie): returns not 1 nor < 0
|
||||
*/
|
||||
assert(err == 1);
|
||||
}
|
||||
|
||||
/* finished */
|
||||
buffer_clear(tls->buffer);
|
||||
|
||||
ret = -1;
|
||||
do {
|
||||
read = SSL_read(tls->ssl, tls->buf, SSL_CHUNK_SIZE);
|
||||
if (read > 0) {
|
||||
ret = 0;
|
||||
tls->buf[read] = 0;
|
||||
buffer_append(tls->buffer, tls->buf);
|
||||
} else {
|
||||
tls_handle_ssl_error(tls, read);
|
||||
}
|
||||
} while (read > 0);
|
||||
|
||||
if (tls->connected == -1) {
|
||||
tls->connected = 1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
tls_write(tls_t *tls, char *buf_w, int len) {
|
||||
return SSL_write(tls->ssl, buf_w, len);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue