First commit
This commit is contained in:
commit
716a6223a7
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
cmake-*/
|
||||||
|
.idea/workspace.xml
|
29
.idea/codeStyles/Project.xml
Normal file
29
.idea/codeStyles/Project.xml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<Objective-C-extensions>
|
||||||
|
<file>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||||
|
</file>
|
||||||
|
<class>
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||||
|
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||||
|
</class>
|
||||||
|
<extensions>
|
||||||
|
<pair source="cpp" header="h" fileNamingConvention="NONE" />
|
||||||
|
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||||
|
</extensions>
|
||||||
|
</Objective-C-extensions>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
2
.idea/esc.iml
Normal file
2
.idea/esc.iml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
4
.idea/misc.xml
Normal file
4
.idea/misc.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/esc.iml" filepath="$PROJECT_DIR$/.idea/esc.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
13
CMakeLists.txt
Normal file
13
CMakeLists.txt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# cmake_minimum_required(VERSION <specify CMake version here>)
|
||||||
|
project(esc C)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
|
include_directories(c:/Users/nicol/dev/thirdparty/protobuf-c)
|
||||||
|
link_directories(c:/Users/nicol/dev/thirdparty/protobuf-c/protobuf-c/.libs)
|
||||||
|
|
||||||
|
add_executable(esc main.c mutex.c mutex.h thread.c thread.h socket.c socket.h esc.c esc.h ClientMessageDtos.pb-c.c ClientMessageDtos.pb-c.h uuid.c uuid.h)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
target_link_libraries(esc wsock32 ws2_32 libprotobuf-c.a)
|
||||||
|
endif()
|
5421
ClientMessageDtos.pb-c.c
Normal file
5421
ClientMessageDtos.pb-c.c
Normal file
File diff suppressed because it is too large
Load Diff
1693
ClientMessageDtos.pb-c.h
Normal file
1693
ClientMessageDtos.pb-c.h
Normal file
File diff suppressed because it is too large
Load Diff
348
esc.c
Normal file
348
esc.c
Normal file
|
@ -0,0 +1,348 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <mem.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include "esc.h"
|
||||||
|
#include "socket.h"
|
||||||
|
#include "uuid.h"
|
||||||
|
#include "ClientMessageDtos.pb-c.h"
|
||||||
|
|
||||||
|
struct st_buffer {
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t* data;
|
||||||
|
};
|
||||||
|
typedef struct st_buffer buffer_t;
|
||||||
|
|
||||||
|
const buffer_t buffer_create(uint32_t size) {
|
||||||
|
buffer_t buf = {size, malloc(size)};
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const buffer_t buffer_from(uint8_t* data, uint32_t size) {
|
||||||
|
buffer_t buf = {size, data};
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void buffer_free(buffer_t buffer) {
|
||||||
|
free(buffer.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st_tcp_package {
|
||||||
|
uint8_t command;
|
||||||
|
uint8_t flags;
|
||||||
|
esc_uuid_t correlation_id;
|
||||||
|
const char* login;
|
||||||
|
const char* password;
|
||||||
|
buffer_t data;
|
||||||
|
};
|
||||||
|
typedef struct st_tcp_package tcp_package_t;
|
||||||
|
|
||||||
|
const uint32_t CommandOffset = 0;
|
||||||
|
const uint32_t FlagsOffset = 1;
|
||||||
|
const uint32_t CorrelationOffset = 2;
|
||||||
|
const uint32_t AuthOffset = 18;
|
||||||
|
const uint32_t MandatorySize = 18;
|
||||||
|
|
||||||
|
const tcp_package_t* tcp_package_create(uint8_t command, const esc_uuid_t* correlation_id, buffer_t data) {
|
||||||
|
tcp_package_t* pkg = malloc(sizeof(tcp_package_t));
|
||||||
|
pkg->command = command;
|
||||||
|
pkg->flags = 0;
|
||||||
|
pkg->correlation_id = *correlation_id;
|
||||||
|
pkg->login = 0;
|
||||||
|
pkg->password = 0;
|
||||||
|
pkg->data = data;
|
||||||
|
return pkg;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tcp_package_t* tcp_package_create_authenticated(uint8_t command, const esc_uuid_t* correlation_id, buffer_t data, const char* username, const char* password) {
|
||||||
|
tcp_package_t* pkg = malloc(sizeof(tcp_package_t));
|
||||||
|
pkg->command = command;
|
||||||
|
pkg->flags = 1;
|
||||||
|
pkg->correlation_id = *correlation_id;
|
||||||
|
pkg->login = username;
|
||||||
|
pkg->password = password;
|
||||||
|
pkg->data = data;
|
||||||
|
return pkg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_package_free(const tcp_package_t* pkg) {
|
||||||
|
buffer_free(pkg->data);
|
||||||
|
free((void*)pkg);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_t tcp_package_to_buffer(const tcp_package_t* pkg) {
|
||||||
|
uint8_t* _dst = malloc(MandatorySize + pkg->data.size + (pkg->flags ? 257*2 : 0));
|
||||||
|
_dst[CommandOffset] = pkg->command;
|
||||||
|
_dst[FlagsOffset] = pkg->flags;
|
||||||
|
memcpy(&_dst[CorrelationOffset], &pkg->correlation_id, sizeof(esc_uuid_t));
|
||||||
|
size_t size = MandatorySize;
|
||||||
|
if (pkg->flags) {
|
||||||
|
size_t l_len = strlen(pkg->login);
|
||||||
|
_dst[AuthOffset] = l_len;
|
||||||
|
strcpy(&_dst[AuthOffset+1], pkg->login);
|
||||||
|
size_t p_len = strlen(pkg->password);
|
||||||
|
_dst[AuthOffset+1+l_len] = p_len;
|
||||||
|
strcpy(&_dst[AuthOffset+2+l_len], pkg->password);
|
||||||
|
memcpy(&_dst[AuthOffset+2+l_len+p_len], pkg->data.data, pkg->data.size);
|
||||||
|
size += 2 + l_len + p_len + pkg->data.size;
|
||||||
|
} else {
|
||||||
|
memcpy(&_dst[AuthOffset], pkg->data.data, pkg->data.size);
|
||||||
|
size += pkg->data.size;
|
||||||
|
}
|
||||||
|
return buffer_from(_dst, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tcp_package_t* tcp_package_from_buffer(buffer_t buffer) {
|
||||||
|
tcp_package_t* pkg = malloc(sizeof(tcp_package_t));
|
||||||
|
pkg->command = buffer.data[CommandOffset];
|
||||||
|
pkg->flags = buffer.data[FlagsOffset];
|
||||||
|
memcpy(&pkg->correlation_id, &buffer.data[CorrelationOffset], sizeof(esc_uuid_t));
|
||||||
|
if (pkg->flags) {
|
||||||
|
size_t l_len = buffer.data[AuthOffset];
|
||||||
|
size_t p_len = buffer.data[AuthOffset+1+l_len];
|
||||||
|
pkg->data = buffer_create(buffer.size - MandatorySize - 2 - l_len - p_len);
|
||||||
|
memcpy(pkg->data.data, &buffer.data[MandatorySize + 2 + l_len + p_len], buffer.size - MandatorySize - 2 - l_len - p_len);
|
||||||
|
} else {
|
||||||
|
pkg->login = 0;
|
||||||
|
pkg->password = 0;
|
||||||
|
pkg->data = buffer_create(buffer.size - MandatorySize);
|
||||||
|
memcpy(pkg->data.data, &buffer.data[MandatorySize], buffer.size - MandatorySize);
|
||||||
|
}
|
||||||
|
return pkg;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct st_connection_settings {
|
||||||
|
unsigned char use_ssl_connection;
|
||||||
|
};
|
||||||
|
|
||||||
|
const esc_connection_settings_t default_connection_settings = {
|
||||||
|
};
|
||||||
|
|
||||||
|
const esc_connection_settings_t* esc_default_connection_settings = &default_connection_settings;
|
||||||
|
|
||||||
|
struct st_tcp_endpoint {
|
||||||
|
char* host;
|
||||||
|
unsigned short port;
|
||||||
|
};
|
||||||
|
typedef struct st_tcp_endpoint tcp_endpoint_t;
|
||||||
|
|
||||||
|
struct st_node_endpoints {
|
||||||
|
tcp_endpoint_t tcp_endpoint;
|
||||||
|
tcp_endpoint_t secure_tcp_endpoint;
|
||||||
|
};
|
||||||
|
typedef struct st_node_endpoints node_endpoints_t;
|
||||||
|
|
||||||
|
typedef const node_endpoints_t* (*endpoint_discoverer_t)(const void* discover_data, const tcp_endpoint_t* failed_tcp_endpoint);
|
||||||
|
|
||||||
|
struct st_connection {
|
||||||
|
esc_connection_settings_t settings;
|
||||||
|
void* discoverer_data;
|
||||||
|
endpoint_discoverer_t discover;
|
||||||
|
socket_t tcp_conn;
|
||||||
|
ProtobufCAllocator protobuf_c_allocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct st_static_endpoint_discoverer {
|
||||||
|
tcp_endpoint_t tcp_endpoint;
|
||||||
|
unsigned char use_ssl_connection;
|
||||||
|
};
|
||||||
|
typedef struct st_static_endpoint_discoverer static_endpoint_discoverer_t;
|
||||||
|
|
||||||
|
const node_endpoints_t* static_discover(const static_endpoint_discoverer_t* discover_data, const tcp_endpoint_t* failed_tcp_endpoint) {
|
||||||
|
node_endpoints_t* result = malloc(sizeof(node_endpoints_t));
|
||||||
|
if (discover_data->use_ssl_connection) {
|
||||||
|
result->secure_tcp_endpoint = discover_data->tcp_endpoint;
|
||||||
|
} else {
|
||||||
|
result->tcp_endpoint = discover_data->tcp_endpoint;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int connection_send_tcp_package(const esc_connection_t* conn, const tcp_package_t* pkg) {
|
||||||
|
char uuid_buf[37];
|
||||||
|
printf("connection_send_tcp_package: %u %u %s %u\n", pkg->command, pkg->flags, esc_uuid_format(&pkg->correlation_id, uuid_buf, 37), pkg->data.size);
|
||||||
|
buffer_t send_buffer = tcp_package_to_buffer(pkg);
|
||||||
|
if (socket_send(conn->tcp_conn, (char *) &send_buffer.size, sizeof(uint32_t)) <= 0) {
|
||||||
|
buffer_free(send_buffer);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (socket_send(conn->tcp_conn, (char *) send_buffer.data, send_buffer.size) <= 0) {
|
||||||
|
buffer_free(send_buffer);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
buffer_free(send_buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tcp_package_t* connection_recv_tcp_package(const esc_connection_t* conn) {
|
||||||
|
uint32_t recv_size;
|
||||||
|
int rc;
|
||||||
|
if ((rc = socket_recv(conn->tcp_conn, (char *)&recv_size, sizeof(uint32_t))) != 4) {
|
||||||
|
printf("%d %d", rc, socket_error());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
buffer_t recv_buffer = buffer_create(recv_size);
|
||||||
|
while(recv_size > 0) {
|
||||||
|
int pos = recv_buffer.size - recv_size;
|
||||||
|
rc = socket_recv(conn->tcp_conn, (char *)&recv_buffer.data[pos], recv_size);
|
||||||
|
recv_size -= rc;
|
||||||
|
}
|
||||||
|
const tcp_package_t* recv_pkg = tcp_package_from_buffer(recv_buffer);
|
||||||
|
buffer_free(recv_buffer);
|
||||||
|
char uuid_buf[37];
|
||||||
|
printf("connection_recv_tcp_package: %u %u %s %u\n", recv_pkg->command, recv_pkg->flags, esc_uuid_format(&recv_pkg->correlation_id, uuid_buf, 37), recv_pkg->data.size);
|
||||||
|
//for (int32_t i=0;i<recv_pkg->data.size;i++) {
|
||||||
|
// printf("%x (%c) ", recv_pkg->data.data[i], recv_pkg->data.data[i]);
|
||||||
|
//}
|
||||||
|
//printf("\n");
|
||||||
|
return recv_pkg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* protobuf_c_alloc(void *alloc_data, size_t size) {
|
||||||
|
return malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void protobuf_c_free(void *alloc_data, void* p) {
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
const esc_connection_t* esc_connection_create(const esc_connection_settings_t* connection_settings, const char* addr, const char* connection_name) {
|
||||||
|
if (strncmp(addr, "tcp://", 6) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char* pos = strrchr(addr, ':');
|
||||||
|
if (pos == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char* host = malloc(pos - addr - 5);
|
||||||
|
strncpy(host, addr+6, pos-addr-6);
|
||||||
|
host[pos-addr-6] = 0;
|
||||||
|
unsigned short port = (unsigned short)atoi(pos+1);
|
||||||
|
static_endpoint_discoverer_t discover_data = {
|
||||||
|
{host, port}, connection_settings->use_ssl_connection
|
||||||
|
};
|
||||||
|
struct st_connection* conn = malloc(sizeof(struct st_connection));
|
||||||
|
conn->settings = *connection_settings;
|
||||||
|
conn->discoverer_data = malloc(sizeof(static_endpoint_discoverer_t));
|
||||||
|
memcpy(conn->discoverer_data, &discover_data, sizeof(static_endpoint_discoverer_t));
|
||||||
|
conn->discover = (endpoint_discoverer_t)static_discover;
|
||||||
|
conn->protobuf_c_allocator.alloc = protobuf_c_alloc;
|
||||||
|
conn->protobuf_c_allocator.free = protobuf_c_free;
|
||||||
|
conn->protobuf_c_allocator.allocator_data = 0;
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return 0 on success
|
||||||
|
// return non-zero on failure and sets last_error on connection
|
||||||
|
int esc_connection_connect(const esc_connection_t* conn) {
|
||||||
|
// Discover endpoint
|
||||||
|
const node_endpoints_t* endpoints = conn->discover(conn->discoverer_data, 0);
|
||||||
|
if (endpoints == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Establish Tcp Connection
|
||||||
|
esc_connection_t* _conn = (esc_connection_t*)conn;
|
||||||
|
_conn->tcp_conn = socket_create(SOCKET_TYPE_TCP);
|
||||||
|
tcp_endpoint_t endpoint = conn->settings.use_ssl_connection ? endpoints->secure_tcp_endpoint : endpoints->tcp_endpoint;
|
||||||
|
if (socket_connect(conn->tcp_conn, endpoint.host, endpoint.port) != 0) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
// Identify
|
||||||
|
// build message
|
||||||
|
EventStore__Client__Messages__IdentifyClient identify_client;
|
||||||
|
event_store__client__messages__identify_client__init(&identify_client);
|
||||||
|
identify_client.connection_name = "abc123";
|
||||||
|
identify_client.version = 1;
|
||||||
|
size_t s = event_store__client__messages__identify_client__get_packed_size(&identify_client);
|
||||||
|
uint8_t buffer[s];
|
||||||
|
event_store__client__messages__identify_client__pack(&identify_client, buffer);
|
||||||
|
// build tcp_package
|
||||||
|
const tcp_package_t* send_pkg = tcp_package_create(0xF5, esc_uuid_create(), buffer_from(buffer, s));
|
||||||
|
if (connection_send_tcp_package(conn, send_pkg) != 0) {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
const tcp_package_t* recv_pkg = connection_recv_tcp_package(conn);
|
||||||
|
if (recv_pkg == 0) {
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
if (recv_pkg->command != 0xF6) {
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const esc_credentials_t* esc_credentials_create(const char* username, const char* password) {
|
||||||
|
esc_credentials_t* creds = malloc(sizeof(struct st_credentials));
|
||||||
|
creds->username = username;
|
||||||
|
creds->password = password;
|
||||||
|
return creds;
|
||||||
|
}
|
||||||
|
|
||||||
|
const esc_recorded_event_t* recorded_event_create(EventStore__Client__Messages__EventRecord* msg) {
|
||||||
|
if (msg == 0) return 0;
|
||||||
|
esc_recorded_event_t* ev = malloc(sizeof(esc_recorded_event_t));
|
||||||
|
ev->event_id = esc_uuid_from(msg->event_id.data, msg->event_id.len);
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
esc_resolved_event_t* resolved_event_create(EventStore__Client__Messages__ResolvedEvent* msg) {
|
||||||
|
esc_resolved_event_t* ev = malloc(sizeof(esc_resolved_event_t));
|
||||||
|
ev->original_position.prepare_position = msg->prepare_position;
|
||||||
|
ev->original_position.commit_position = msg->commit_position;
|
||||||
|
ev->event = recorded_event_create(msg->event);
|
||||||
|
ev->link = recorded_event_create(msg->link);
|
||||||
|
return ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
const esc_all_events_slice_t* esc_connection_read_all_forward(const esc_connection_t* conn, const esc_position_t* last_checkpoint, unsigned int count, const esc_credentials_t* credentials) {
|
||||||
|
EventStore__Client__Messages__ReadAllEvents send_msg;
|
||||||
|
event_store__client__messages__read_all_events__init(&send_msg);
|
||||||
|
send_msg.prepare_position = last_checkpoint ? last_checkpoint->prepare_position : 0;
|
||||||
|
send_msg.commit_position = last_checkpoint ? last_checkpoint->commit_position : 0;
|
||||||
|
send_msg.max_count = count;
|
||||||
|
send_msg.require_master = 0;
|
||||||
|
send_msg.resolve_link_tos = 0;
|
||||||
|
size_t s = event_store__client__messages__read_all_events__get_packed_size(&send_msg);
|
||||||
|
uint8_t buffer[s];
|
||||||
|
event_store__client__messages__read_all_events__pack(&send_msg, buffer);
|
||||||
|
const tcp_package_t* send_pkg = tcp_package_create_authenticated(0xB6, esc_uuid_create(), buffer_from(buffer, s), credentials->username, credentials->password);
|
||||||
|
if (connection_send_tcp_package(conn, send_pkg) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tcp_package_t* recv_pkg = connection_recv_tcp_package(conn);
|
||||||
|
if (recv_pkg == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (recv_pkg->command != 0xB7) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventStore__Client__Messages__ReadAllEventsCompleted *recv_msg =
|
||||||
|
event_store__client__messages__read_all_events_completed__unpack(&conn->protobuf_c_allocator, recv_pkg->data.size, recv_pkg->data.data);
|
||||||
|
|
||||||
|
esc_all_events_slice_t* result = malloc(sizeof(esc_all_events_slice_t));
|
||||||
|
result->read_direction = "forward";
|
||||||
|
result->is_end_of_stream = (recv_msg->events == 0 || recv_msg->n_events == 0) ? 1 : 0;
|
||||||
|
result->from_position.prepare_position = recv_msg->prepare_position;
|
||||||
|
result->from_position.commit_position = recv_msg->commit_position;
|
||||||
|
result->next_position.prepare_position = recv_msg->next_prepare_position;
|
||||||
|
result->next_position.commit_position = recv_msg->next_commit_position;
|
||||||
|
result->n_events = recv_msg->n_events;
|
||||||
|
result->events = malloc(recv_msg->n_events * sizeof(esc_resolved_event_t*));
|
||||||
|
for (size_t i = 0; i < recv_msg->n_events; i++) {
|
||||||
|
result->events[i] = resolved_event_create(recv_msg->events[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* esc_position_format(const esc_position_t* position, char* buffer, size_t buf_size) {
|
||||||
|
snprintf(buffer, buf_size, "%llu/%llu", position->prepare_position, position->commit_position);
|
||||||
|
return buffer;
|
||||||
|
}
|
58
esc.h
Normal file
58
esc.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESC_ESC_H
|
||||||
|
#define ESC_ESC_H
|
||||||
|
|
||||||
|
#include "uuid.h"
|
||||||
|
|
||||||
|
struct st_connection_settings;
|
||||||
|
typedef struct st_connection_settings esc_connection_settings_t;
|
||||||
|
|
||||||
|
struct st_connection;
|
||||||
|
typedef struct st_connection esc_connection_t;
|
||||||
|
|
||||||
|
struct st_credentials {
|
||||||
|
const char* username;
|
||||||
|
const char* password;
|
||||||
|
};
|
||||||
|
typedef struct st_credentials esc_credentials_t;
|
||||||
|
|
||||||
|
struct st_esc_position {
|
||||||
|
__int64 prepare_position;
|
||||||
|
__int64 commit_position;
|
||||||
|
};
|
||||||
|
typedef struct st_esc_position esc_position_t;
|
||||||
|
|
||||||
|
struct st_recorded_event {
|
||||||
|
const esc_uuid_t* event_id;
|
||||||
|
};
|
||||||
|
typedef struct st_recorded_event esc_recorded_event_t;
|
||||||
|
|
||||||
|
struct st_resolved_event {
|
||||||
|
const esc_recorded_event_t* event;
|
||||||
|
const esc_recorded_event_t* link;
|
||||||
|
esc_position_t original_position;
|
||||||
|
};
|
||||||
|
typedef struct st_resolved_event esc_resolved_event_t;
|
||||||
|
|
||||||
|
struct st_all_events_slice {
|
||||||
|
char* read_direction;
|
||||||
|
esc_position_t from_position;
|
||||||
|
esc_position_t next_position;
|
||||||
|
size_t n_events;
|
||||||
|
esc_resolved_event_t** events;
|
||||||
|
int is_end_of_stream;
|
||||||
|
};
|
||||||
|
typedef struct st_all_events_slice esc_all_events_slice_t;
|
||||||
|
|
||||||
|
const esc_connection_settings_t* esc_default_connection_settings;
|
||||||
|
|
||||||
|
const esc_connection_t* esc_connection_create(const esc_connection_settings_t* connection_settings, const char* addr, const char* connection_name);
|
||||||
|
int esc_connection_connect(const esc_connection_t* conn);
|
||||||
|
const esc_credentials_t* esc_credentials_create(const char* username, const char* password);
|
||||||
|
const esc_all_events_slice_t* esc_connection_read_all_forward(const esc_connection_t* conn, const esc_position_t* last_checkpoint, unsigned int count, const esc_credentials_t* credentials);
|
||||||
|
const char* esc_position_format(const esc_position_t* position, char* buffer, size_t buf_size);
|
||||||
|
|
||||||
|
#endif //ESC_ESC_H
|
84
main.c
Normal file
84
main.c
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "mutex.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "socket.h"
|
||||||
|
#include "esc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
unsigned long my_first_thread(void* arg) {
|
||||||
|
mutex_t mut = arg;
|
||||||
|
mutex_lock(mut);
|
||||||
|
printf("1\n");
|
||||||
|
mutex_unlock(mut);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long my_second_thread(void* arg) {
|
||||||
|
mutex_t mut = arg;
|
||||||
|
mutex_lock(mut);
|
||||||
|
printf("2\n");
|
||||||
|
mutex_unlock(mut);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSADATA wsaData;
|
||||||
|
WSAStartup(MAKEWORD(2,0), &wsaData);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const esc_connection_t* conn = esc_connection_create(esc_default_connection_settings, "tcp://127.0.0.1:1113", NULL);
|
||||||
|
if (conn == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (esc_connection_connect(conn) != 0) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
const esc_credentials_t* credentials = esc_credentials_create("admin", "changeit");
|
||||||
|
const esc_all_events_slice_t* result = esc_connection_read_all_forward(conn, NULL, 1024, credentials);
|
||||||
|
if (result == 0) {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
char posbuf1[44];
|
||||||
|
char posbuf2[44];
|
||||||
|
printf("%s %s %s %u\n", result->read_direction,
|
||||||
|
esc_position_format(&result->from_position, posbuf1, 44),
|
||||||
|
esc_position_format(&result->next_position, posbuf2, 44),
|
||||||
|
result->is_end_of_stream);
|
||||||
|
char uuid_buf[37];
|
||||||
|
for(size_t i = 0; i < result->n_events; i++) {
|
||||||
|
printf("%s\n", esc_uuid_format(result->events[i]->event->event_id, uuid_buf, 37));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
socket_t s = socket_create(IPPROTO_TCP);
|
||||||
|
socket_connect(s, "www.google.ca", 80);
|
||||||
|
char* req = "GET / HTTP/1.1\r\nHost: www.google.ca\r\nConnection: close\r\n\r\n";
|
||||||
|
socket_send(s, req, strlen(req));
|
||||||
|
char buffer[4096];
|
||||||
|
memset(buffer, 0, 4096);
|
||||||
|
int rc;
|
||||||
|
while ((rc = socket_recv(s, buffer, 4096)) > 0) {
|
||||||
|
printf_s("%s", buffer);
|
||||||
|
memset(buffer, 0, 4096);
|
||||||
|
}
|
||||||
|
socket_close(s);
|
||||||
|
|
||||||
|
mutex_t sync = mutex_create();
|
||||||
|
thread_t one = thread_create(my_first_thread, sync);
|
||||||
|
thread_t two = thread_create(my_second_thread, sync);
|
||||||
|
thread_start(one);
|
||||||
|
thread_start(two);
|
||||||
|
printf("Hello, World!\n");
|
||||||
|
thread_destroy(one);
|
||||||
|
thread_destroy(two);
|
||||||
|
mutex_destroy(sync);
|
||||||
|
*/
|
||||||
|
#ifdef _WIN32
|
||||||
|
WSACleanup();
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
28
mutex.c
Normal file
28
mutex.c
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
#include "mutex.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
mutex_t mutex_create() {
|
||||||
|
mutex_t mutex = malloc(sizeof(CRITICAL_SECTION));
|
||||||
|
InitializeCriticalSection(mutex);
|
||||||
|
return mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_lock(mutex_t mutex) {
|
||||||
|
EnterCriticalSection(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_unlock(mutex_t mutex) {
|
||||||
|
LeaveCriticalSection(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mutex_destroy(mutex_t mutex) {
|
||||||
|
DeleteCriticalSection(mutex);
|
||||||
|
}
|
||||||
|
#endif
|
18
mutex.h
Normal file
18
mutex.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESC_MUTEX_H
|
||||||
|
#define ESC_MUTEX_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
typedef LPCRITICAL_SECTION mutex_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mutex_t mutex_create();
|
||||||
|
void mutex_lock(mutex_t mutex);
|
||||||
|
void mutex_unlock(mutex_t mutex);
|
||||||
|
void mutex_destroy(mutex_t mutex);
|
||||||
|
|
||||||
|
#endif //ESC_MUTEX_H
|
61
socket.c
Normal file
61
socket.c
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "socket.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
struct st_socket {
|
||||||
|
SOCKET s;
|
||||||
|
int af;
|
||||||
|
int type;
|
||||||
|
int proto;
|
||||||
|
};
|
||||||
|
|
||||||
|
socket_t socket_create(int type) {
|
||||||
|
if (type == SOCKET_TYPE_TCP) {
|
||||||
|
socket_t s = malloc(sizeof(struct st_socket));
|
||||||
|
s->af = AF_INET;
|
||||||
|
s->type = SOCK_STREAM;
|
||||||
|
s->proto = IPPROTO_TCP;
|
||||||
|
s->s = socket(s->af, s->type, s->proto);
|
||||||
|
if (s->s == INVALID_SOCKET) {
|
||||||
|
free(s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void socket_close(socket_t s) {
|
||||||
|
closesocket(s->s);
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket_connect(socket_t s, char* addr, unsigned short port) {
|
||||||
|
char port_s[6];
|
||||||
|
ADDRINFO hints;
|
||||||
|
memset(&hints, 0, sizeof(ADDRINFO));
|
||||||
|
hints.ai_family = s->af;
|
||||||
|
hints.ai_socktype = s->type;
|
||||||
|
hints.ai_protocol = s->proto;
|
||||||
|
ADDRINFO* result;
|
||||||
|
if (getaddrinfo(addr, itoa(port, port_s, 10), &hints, &result) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return connect(s->s, result->ai_addr, (int)result->ai_addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket_send(socket_t s, char* data, int len) {
|
||||||
|
return send(s->s, data, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket_recv(socket_t s, char* buf, int len) {
|
||||||
|
return recv(s->s, buf, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket_error() {
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
#endif
|
23
socket.h
Normal file
23
socket.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESC_SOCKET_H
|
||||||
|
#define ESC_SOCKET_H
|
||||||
|
|
||||||
|
struct st_socket;
|
||||||
|
typedef struct st_socket* socket_t;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SOCKET_TYPE_TCP = 1,
|
||||||
|
SOCKET_TYPE_UDP = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
socket_t socket_create(int type);
|
||||||
|
void socket_close(socket_t s);
|
||||||
|
int socket_connect(socket_t s, char* addr, unsigned short port);
|
||||||
|
int socket_send(socket_t s, char* data, int len);
|
||||||
|
int socket_recv(socket_t s, char* buf, int len);
|
||||||
|
int socket_error();
|
||||||
|
|
||||||
|
#endif //ESC_SOCKET_H
|
32
thread.c
Normal file
32
thread.c
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
thread_t thread_create(thread_start_t thread_start, thread_arg_t thread_arg) {
|
||||||
|
thread_t thread = malloc(sizeof(struct st_thread));
|
||||||
|
thread->handle = CreateThread(NULL, 0, thread_start, thread_arg, CREATE_SUSPENDED, &thread->id);
|
||||||
|
if (thread->handle == NULL) {
|
||||||
|
free(thread);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
int thread_start(thread_t thread) {
|
||||||
|
if (ResumeThread(thread->handle) == -1) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int thread_wait(thread_t thread) {
|
||||||
|
if (WaitForSingleObject(thread->handle, INFINITE) != WAIT_OBJECT_0) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int thread_destroy(thread_t thread) {
|
||||||
|
if (thread_wait(thread) != 0) SuspendThread(thread->handle);
|
||||||
|
CloseHandle(thread->handle);
|
||||||
|
}
|
||||||
|
#endif
|
19
thread.h
Normal file
19
thread.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESC_THREAD_H
|
||||||
|
#define ESC_THREAD_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
struct st_thread {
|
||||||
|
DWORD id;
|
||||||
|
HANDLE handle;
|
||||||
|
};
|
||||||
|
typedef struct st_thread* thread_t;
|
||||||
|
typedef LPTHREAD_START_ROUTINE thread_start_t;
|
||||||
|
typedef LPVOID thread_arg_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //ESC_THREAD_H
|
47
uuid.c
Normal file
47
uuid.c
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "uuid.h"
|
||||||
|
|
||||||
|
const esc_uuid_t* esc_uuid_create() {
|
||||||
|
esc_uuid_t* result = malloc(sizeof(esc_uuid_t));
|
||||||
|
srand(time(NULL));
|
||||||
|
for(int i=0;i<16;i++)
|
||||||
|
result->data[i] = (uint8_t)(rand() & 0xff);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const esc_uuid_t* esc_uuid_from(uint8_t* src, size_t size) {
|
||||||
|
if (size != 16) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
esc_uuid_t* uuid = malloc(sizeof(esc_uuid_t));
|
||||||
|
for (size_t i=0; i<size; i++)
|
||||||
|
uuid->data[i] = src[i];
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* esc_uuid_format(const esc_uuid_t* uuid, char* buffer, size_t buf_size) {
|
||||||
|
snprintf(buffer, buf_size, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||||
|
uuid->data[0],
|
||||||
|
uuid->data[1],
|
||||||
|
uuid->data[2],
|
||||||
|
uuid->data[3],
|
||||||
|
uuid->data[4],
|
||||||
|
uuid->data[5],
|
||||||
|
uuid->data[6],
|
||||||
|
uuid->data[7],
|
||||||
|
uuid->data[8],
|
||||||
|
uuid->data[9],
|
||||||
|
uuid->data[10],
|
||||||
|
uuid->data[11],
|
||||||
|
uuid->data[12],
|
||||||
|
uuid->data[13],
|
||||||
|
uuid->data[14],
|
||||||
|
uuid->data[15]);
|
||||||
|
return buffer;
|
||||||
|
}
|
19
uuid.h
Normal file
19
uuid.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
//
|
||||||
|
// Created by nicol on 2018-03-18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESC_UUID_H
|
||||||
|
#define ESC_UUID_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct st_uuid {
|
||||||
|
uint8_t data[16];
|
||||||
|
};
|
||||||
|
typedef struct st_uuid esc_uuid_t;
|
||||||
|
|
||||||
|
const esc_uuid_t* esc_uuid_create();
|
||||||
|
const esc_uuid_t* esc_uuid_from(uint8_t* src, size_t size);
|
||||||
|
const char* esc_uuid_format(const esc_uuid_t* uuid, char* buffer, size_t buf_size);
|
||||||
|
|
||||||
|
#endif //ESC_UUID_H
|
Loading…
Reference in New Issue
Block a user