Commit cc7b7097 authored by vvaltman's avatar vvaltman

initial commit

parents
objs
dep
/*
This file is part of MTProto-proxy.
MTProto-proxy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
MTProto-proxy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with MTProto-proxy. If not, see <http://www.gnu.org/licenses/>.
This program is released under the GPL with the additional exemption
that compiling, linking, and/or using OpenSSL is allowed.
You are free to remove this exemption from derived works.
Copyright 2014-2018 Telegram Messenger Inc
*/
/*
This file is part of MTProto-proxy Library.
MTProto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
MTProto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with MTProto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2014-2018 Telegram Messenger Inc
*/
OBJ = objs
DEP = dep
EXE = ${OBJ}/bin
COMMIT := $(shell git log -1 --pretty=format:"%H")
CFLAGS = -m64 -O3 -std=gnu11 -Wall -mpclmul -march=core2 -mfpmath=sse -mssse3 -fno-strict-aliasing -fno-strict-overflow -fwrapv -DAES=1 -DCOMMIT=\"${COMMIT}\" -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64
LDFLAGS = -m64 -ggdb -rdynamic -lm -lrt -lcrypto -lz -lpthread -lcrypto
LIB = ${OBJ}/lib
CINCLUDE = -iquote common -iquote .
LIBLIST = ${LIB}/libkdb.a
PROJECTS = common jobs mtproto net crypto engine
OBJDIRS := ${OBJ} $(addprefix ${OBJ}/,${PROJECTS}) ${EXE} ${LIB}
DEPDIRS := ${DEP} $(addprefix ${DEP}/,${PROJECTS})
ALLDIRS := ${DEPDIRS} ${OBJDIRS}
.PHONY: all clean
EXELIST := ${EXE}/mtproto-proxy
OBJECTS = \
${OBJ}/mtproto/mtproto-proxy.o ${OBJ}/mtproto/mtproto-config.o ${OBJ}/net/net-tcp-rpc-ext-server.o
DEPENDENCE_CXX := $(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJECTS_CXX}))
DEPENDENCE_STRANGE := $(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJECTS_STRANGE}))
DEPENDENCE_NORM := $(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJECTS}))
LIB_OBJS_NORMAL := \
${OBJ}/common/crc32c.o \
${OBJ}/common/pid.o \
${OBJ}/common/sha1.o \
${OBJ}/common/sha256.o \
${OBJ}/common/md5.o \
${OBJ}/common/resolver.o \
${OBJ}/common/parse-config.o \
${OBJ}/crypto/aesni256.o \
${OBJ}/jobs/jobs.o ${OBJ}/common/mp-queue.o \
${OBJ}/net/net-events.o ${OBJ}/net/net-msg.o ${OBJ}/net/net-msg-buffers.o \
${OBJ}/net/net-config.o ${OBJ}/net/net-crypto-aes.o ${OBJ}/net/net-crypto-dh.o ${OBJ}/net/net-timers.o \
${OBJ}/net/net-connections.o \
${OBJ}/net/net-rpc-targets.o \
${OBJ}/net/net-tcp-connections.o ${OBJ}/net/net-tcp-rpc-common.o ${OBJ}/net/net-tcp-rpc-client.o ${OBJ}/net/net-tcp-rpc-server.o \
${OBJ}/net/net-http-server.o \
${OBJ}/common/tl-parse.o ${OBJ}/common/common-stats.o \
${OBJ}/engine/engine.o ${OBJ}/engine/engine-signals.o \
${OBJ}/engine/engine-net.o \
${OBJ}/engine/engine-rpc.o \
${OBJ}/engine/engine-rpc-common.o \
${OBJ}/net/net-thread.o ${OBJ}/net/net-stats.o ${OBJ}/common/proc-stat.o \
${OBJ}/common/kprintf.o \
${OBJ}/common/precise-time.o ${OBJ}/common/cpuid.o \
${OBJ}/common/server-functions.o ${OBJ}/common/crc32.o \
LIB_OBJS := ${LIB_OBJS_NORMAL}
DEPENDENCE_LIB := $(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${LIB_OBJS}))
DEPENDENCE_ALL := ${DEPENDENCE_NORM} ${DEPENDENCE_STRANGE} ${DEPENDENCE_LIB}
OBJECTS_ALL := ${OBJECTS} ${LIB_OBJS}
all: ${ALLDIRS} ${EXELIST}
dirs: ${ALLDIRS}
create_dirs_and_headers: ${ALLDIRS}
${ALLDIRS}:
@test -d $@ || mkdir -p $@
-include ${DEPENDENCE_ALL}
${OBJECTS}: ${OBJ}/%.o: %.c | create_dirs_and_headers
${CC} ${CFLAGS} ${CINCLUDE} -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $<
${LIB_OBJS_NORMAL}: ${OBJ}/%.o: %.c | create_dirs_and_headers
${CC} ${CFLAGS} -fpic ${CINCLUDE} -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $<
${EXELIST}: ${LIBLIST}
${EXE}/mtproto-proxy: ${OBJ}/mtproto/mtproto-proxy.o ${OBJ}/mtproto/mtproto-config.o ${OBJ}/net/net-tcp-rpc-ext-server.o
${CC} -o $@ $^ ${LIB}/libkdb.a ${LDFLAGS}
${LIB}/libkdb.a: ${LIB_OBJS}
rm -f $@ && ar rcs $@ $^
clean:
rm -rf ${OBJ} ${DEP} ${EXE} || true
force-clean: clean
to build simply run 'make'. Your binary will be objs/bin/mtproto-proxy
to run mtproto-proxy:
1. Obtain secret, which is used to connect to telegram servers.
curl -s https://digitalresistance.dog/getSecret -o proxy-secret
2. Obtail current telegram configuration. It can (rarely) change, so we encourage you to update it once per day.
curl -s https://digitalresistance.dog/getConfig -o proxy-multi.conf
3. Generate secret, which is used by users to connect to proxy
head -c 16 /dev/urandom | xxd -ps
4. Run mtproto-proxy
mtproto-proxy -u nobody -p 8888 -H 443 -S <secret> --aes-pwd proxy-secret proxy-multi.conf -M 1
where:
- nobody is user name. mtproto-proxy calls setuid() to drop privilegies
- 443 is port, used by clients to connect to proxy
- 8888 is local port. You can use it to get statistics from mtproto. Like wget localhost:8888/stats
You can only get this stat via loopback
- <secret> is secret generated on step 3.
- proxy-secret and proxy-multi.conf are obtains on steps 1 and 2
- 1 is number of workers. You can increase number of workers, if you have powerful server
- also feel free to look on other options in mtproto-prodxy help
5. generate link tg://proxy?server=SERVER_NAME&port=443&secret=SECRET
6. enjoy
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2012-2013 Vkontakte Ltd
2012-2013 Anton Maydell
Copyright 2014-2017 Telegram Messenger Inc
2014-2017 Anton Maydell
*/
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "kprintf.h"
#include "precise-time.h"
#include "server-functions.h"
#include "common/common-stats.h"
#include "net/net-connections.h"
static int read_whole_file (char *filename, void *output, int olen) {
int fd = open (filename, O_RDONLY), n = -1;
if (fd < 0) {
vkprintf (1, "%s: open (\"%s\", O_RDONLY) failed. %m\n", __func__, filename);
return -1;
}
do {
n = read (fd, output, olen);
if (n < 0) {
if (errno == EINTR) {
continue;
}
vkprintf (1, "%s: read from %s failed. %m\n", __func__, filename);
}
break;
} while (1);
while (close (fd) < 0 && errno == EINTR) {}
if (n < 0) {
return -1;
}
if (n >= olen) {
vkprintf (1, "%s: output buffer is too small (%d bytes).\n", __func__, olen);
return -1;
}
unsigned char *p = output;
p[n] = 0;
return n;
}
static int parse_statm (const char *buf, long long *a, int m) {
static long long page_size = -1;
if (page_size < 0) {
page_size = sysconf (_SC_PAGESIZE);
assert (page_size > 0);
}
int i;
if (m > 7) {
m = 7;
}
const char *p = buf;
char *q;
errno = 0;
for (i = 0; i < m; i++) {
a[i] = strtoll (p, &q, 10);
if (p == q || errno) {
return -1;
}
a[i] *= page_size;
p = q;
}
return 0;
}
int am_get_memory_usage (pid_t pid, long long *a, int m) {
char proc_filename[32];
char buf[4096];
assert (snprintf (proc_filename, sizeof (proc_filename), "/proc/%d/statm", (int) pid) < sizeof (proc_filename));
if (read_whole_file (proc_filename, buf, sizeof (buf)) < 0) {
return -1;
}
return parse_statm (buf, a, m);
}
int am_get_memory_stats (am_memory_stat_t *S, int flags) {
if (!flags) {
return -1;
}
long long a[6];
if (flags & AM_GET_MEMORY_USAGE_SELF) {
if (am_get_memory_usage (getpid (), a, 6) < 0) {
return -1;
}
S->vm_size = a[0];
S->vm_rss = a[1];
S->vm_data = a[5];
}
if (flags & AM_GET_MEMORY_USAGE_OVERALL) {
char buf[16384], *p;
if (read_whole_file ("/proc/meminfo", buf, sizeof (buf)) < 0) {
return -1;
}
vkprintf (4, "/proc/meminfo: %s\n", buf);
char suffix[32];
long long value;
int r = 0;
for (p = strtok (buf, "\n"); r != 15 && p != NULL; p = strtok (NULL, "\n")) {
switch (*p++) {
case 'C':
if (!memcmp (p, "ached:", 6)) {
if (sscanf (p + 6, "%lld%31s", &value, suffix) == 2 && !strcmp (suffix, "kB")) {
S->mem_cached = value << 10;
r |= 8;
}
}
break;
case 'M':
if (!memcmp (p, "emFree:", 7)) {
if (sscanf (p + 7, "%lld%31s", &value, suffix) == 2 && !strcmp (suffix, "kB")) {
S->mem_free = value << 10;
r |= 1;
}
}
break;
case 'S':
if (!memcmp (p, "wapTotal:", 9)) {
if (sscanf (p + 9, "%lld%31s", &value, suffix) == 2 && !strcmp (suffix, "kB")) {
S->swap_total = value << 10;
r |= 2;
}
} else if (!memcmp (p, "wapFree:", 8)) {
if (sscanf (p + 8, "%lld%31s", &value, suffix) == 2 && !strcmp (suffix, "kB")) {
S->swap_free = value << 10;
r |= 4;
}
}
break;
}
}
if (r != 15) {
return -1;
}
S->swap_used = S->swap_total - S->swap_free;
}
return 0;
}
struct stat_fun_en {
stat_fun_t func;
struct stat_fun_en *next;
};
struct stat_fun_en *stat_func_first = NULL;
int sb_register_stat_fun (stat_fun_t func) {
struct stat_fun_en *last = NULL, *p;
for (p = stat_func_first; p; p = p->next) {
last = p;
if (p->func == func) {
return 0;
}
}
p = malloc (sizeof (*p));
p->func = func;
p->next = NULL;
if (last) {
last->next = p;
} else {
stat_func_first = p;
}
return 1;
}
/************************ stats buffer functions **********************************/
void sb_init (stats_buffer_t *sb, char *buff, int size) {
sb->buff = buff;
sb->pos = 0;
sb->size = size;
sb->flags = 0;
}
void sb_alloc (stats_buffer_t *sb, int size) {
if (size < 16) {
size = 16;
}
sb->buff = malloc (size);
assert (sb->buff);
sb->pos = 0;
sb->size = size;
sb->flags = 1;
}
void sb_release (stats_buffer_t *sb) {
if (sb->flags & 1) {
free (sb->buff);
}
sb->buff = NULL;
}
static void sb_truncate (stats_buffer_t *sb) {
sb->buff[sb->size - 1] = 0;
sb->pos = sb->size - 2;
while (sb->pos >= 0 && sb->buff[sb->pos] != '\n') {
sb->buff[sb->pos--] = 0;
}
sb->pos++;
}
static int sb_full (stats_buffer_t *sb) {
return (sb->pos == sb->size - 1 && sb->buff[sb->pos]) || sb->pos >= sb->size;
}
void sb_prepare (stats_buffer_t *sb) {
sb->pos = prepare_stats (sb->buff, sb->size);
if (sb_full (sb)) {
sb_truncate (sb);
return;
}
struct stat_fun_en *p;
for (p = stat_func_first; p; p = p->next) {
p->func (sb);
if (sb_full (sb)) {
sb_truncate (sb);
return;
}
}
}
void sb_printf (stats_buffer_t *sb, const char *format, ...) {
if (sb->pos >= sb->size) { return; }
const int old_pos = sb->pos;
va_list ap;
va_start (ap, format);
sb->pos += vsnprintf (sb->buff + old_pos, sb->size - old_pos, format, ap);
va_end (ap);
if (sb->pos >= sb->size) {
if (sb->flags & 1) {
sb->size = 2 * sb->pos;
sb->buff = realloc (sb->buff, sb->size);
assert (sb->buff);
va_start (ap, format);
sb->pos = old_pos + vsnprintf (sb->buff + old_pos, sb->size - old_pos, format, ap);
va_end (ap);
assert (sb->pos < sb->size);
} else {
sb_truncate (sb);
}
}
}
/************************************************************************************/
void sb_memory (stats_buffer_t *sb, int flags) {
am_memory_stat_t S;
if (!am_get_memory_stats (&S, flags & AM_GET_MEMORY_USAGE_SELF)) {
sb_printf (sb,
"vmsize_bytes\t%lld\n"
"vmrss_bytes\t%lld\n"
"vmdata_bytes\t%lld\n",
S.vm_size, S.vm_rss, S.vm_data);
}
if (!am_get_memory_stats (&S, flags & AM_GET_MEMORY_USAGE_OVERALL)) {
sb_printf (sb,
"memfree_bytes\t%lld\n"
"memcached_bytes\t%lld\n"
"swap_used_bytes\t%lld\n"
"swap_total_bytes\t%lld\n",
S.mem_free, S.mem_cached, S.swap_used, S.swap_total);
}
}
void sb_print_queries (stats_buffer_t *sb, const char *const desc, long long q) {
sb_printf (sb, "%s\t%lld\nqps_%s\t%.3lf\n", desc, q, desc, safe_div (q, now - start_time));
}
int sb_sum_i (void **base, int len, int offset) {
int res = 0;
int i;
for (i = 0; i < len; i++) if (base[i]) {
res += *(int *)((base[i]) + offset);
}
return res;
}
long long sb_sum_ll (void **base, int len, int offset) {
long long res = 0;
int i;
for (i = 0; i < len; i++) if (base[i]) {
res += *(long long *)((base[i]) + offset);
}
return res;
}
double sb_sum_f (void **base, int len, int offset) {
double res = 0;
int i;
for (i = 0; i < len; i++) if (base[i]) {
res += *(double *)((base[i]) + offset);
}
return res;
}
void sbp_print_date (stats_buffer_t *sb, const char *key, time_t unix_time) {
struct tm b;
struct tm *t = gmtime_r (&unix_time, &b);
if (t) {
char s[256];
size_t l = strftime (s, sizeof (s), "%c", t);
if (l > 0) {
sb_printf (sb, "%s\t%s\n", key, s);
}
}
}
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2012-2013 Vkontakte Ltd
2012-2013 Anton Maydell
Copyright 2014-2017 Telegram Messenger Inc
2014-2017 Anton Maydell
*/
#pragma once
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#define AM_GET_MEMORY_USAGE_SELF 1
#define AM_GET_MEMORY_USAGE_OVERALL 2
#define SB_PRINT_I64(x) sb_printf (&sb, "%s\t%lld\n", #x, x)
#define SB_PRINT_I32(x) sb_printf (&sb, "%s\t%d\n", #x, x)
#define SB_PRINT_QUERIES(x) sb_print_queries (&sb, #x, x)
#define SB_PRINT_DOUBLE(x) sb_printf (&sb, "%s\t%.6lf\n", #x, x)
#define SB_PRINT_TIME(x) sb_printf (&sb, "%s\t%.6lfs\n", #x, x)
#define SB_PRINT_PERCENT(x) sb_printf (&sb, "%s\t%.3lf%%\n", #x, x)
#define SBP_PRINT_I32(x) sb_printf (sb, "%s\t%d\n", #x, x)
#define SBP_PRINT_I64(x) sb_printf (sb, "%s\t%lld\n", #x, x)
#define SBP_PRINT_QUERIES(x) sb_print_queries (sb, #x, x)
#define SBP_PRINT_DOUBLE(x) sb_printf (sb, "%s\t%.6lf\n", #x, x)
#define SBP_PRINT_TIME(x) sb_printf (sb, "%s\t%.6lfs\n", #x, x)
#define SBP_PRINT_PERCENT(x) sb_printf (sb, "%s\t%.3lf%%\n", #x, x)
#define SBP_PRINT_DATE(x) sbp_print_date (sb, #x, x)
#define SBM_PRINT_I32(x) sb_printf (sb, "%s%s\t%d\n", MODULE_STAT_PREFIX_NAME ?: "", #x, x)
#define SBM_PRINT_I64(x) sb_printf (sb, "%s%s\t%lld\n", MODULE_STAT_PREFIX_NAME ?: "", #x, x)
#define SBM_PRINT_DOUBLE(x) sb_printf (sb, "%s%s\t%.6lf\n", MODULE_STAT_PREFIX_NAME ?: "", #x, x)
#define SBM_PRINT_TIME(x) sb_printf (sb, "%s%s\t%.6lfs\n", MODULE_STAT_PREFIX_NAME ?: "", #x, x)
#define SBM_PRINT_PERCENT(x) sb_printf (sb, "%s%s\t%.3lf%%\n", MODULE_STAT_PREFIX_NAME ?: "", #x, x)
static inline double safe_div (double x, double y) { return y > 0 ? x/y : 0; }
typedef struct {
long long vm_size;
long long vm_rss;
long long vm_data;
long long mem_free;
long long swap_total;
long long swap_free;
long long swap_used;
long long mem_cached;
} am_memory_stat_t;
int am_get_memory_usage (pid_t pid, long long *a, int m);
int am_get_memory_stats (am_memory_stat_t *S, int flags);
typedef struct stats_buffer {
char *buff;
int pos;
int size;
int flags;
} stats_buffer_t;
void sb_init (stats_buffer_t *sb, char *buff, int size);
void sb_alloc (stats_buffer_t *sb, int size);
void sb_release (stats_buffer_t *sb);
void sb_prepare (stats_buffer_t *sb);
void sb_printf (stats_buffer_t *sb, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
void sb_memory (stats_buffer_t *sb, int flags);
void sb_print_queries (stats_buffer_t *sb, const char *const desc, long long q);
void sbp_print_date (stats_buffer_t *sb, const char *key, time_t unix_time);
typedef void (*stat_fun_t) (stats_buffer_t *sb);
int sb_register_stat_fun (stat_fun_t fun);
int sb_sum_i (void **base, int len, int offset);
long long sb_sum_ll (void **base, int len, int offset);
double sb_sum_f (void **base, int len, int offset);
#define SB_SUM_I(name) \
sb_sum_i ((void **)MODULE_STAT_ARR, max_job_thread_id + 1, offsetof (MODULE_STAT_TYPE, name))
#define SB_SUM_LL(name) \
sb_sum_ll ((void **)MODULE_STAT_ARR, max_job_thread_id + 1, offsetof (MODULE_STAT_TYPE, name))
#define SB_SUM_F(name) \
sb_sum_f ((void **)MODULE_STAT_ARR, max_job_thread_id + 1, offsetof (MODULE_STAT_TYPE, name))
#define SB_SUM_ONE_I(name) sb_printf (sb, "%s%s\t%d\n", MODULE_STAT_PREFIX_NAME ?: "", #name, SB_SUM_I(name))
#define SB_SUM_ONE_LL(name) sb_printf (sb, "%s%s\t%lld\n", MODULE_STAT_PREFIX_NAME ?: "", #name, SB_SUM_LL(name))
#define SB_SUM_ONE_F(name) sb_printf (sb, "%s%s\t%lf\n", MODULE_STAT_PREFIX_NAME ?: "", #name, SB_SUM_F(name))
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2014 Telegram Messenger Inc
2014 Anton Maydell
*/
#include <assert.h>
#include "cpuid.h"
#define CPUID_MAGIC 0x280147b8
kdb_cpuid_t *kdb_cpuid (void) {
static kdb_cpuid_t cached = { .magic = 0 };
if (cached.magic) {
assert (cached.magic == CPUID_MAGIC);
return &cached;
}
int a;
asm volatile ("cpuid\n\t"
: "=a" (a), "=b" (cached.ebx) , "=c" (cached.ecx), "=d" (cached.edx)
: "0" (1)
);
cached.magic = CPUID_MAGIC;
return &cached;
}
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2014 Telegram Messenger Inc
2014 Anton Maydell
*/
#pragma once
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
typedef long long v2di __attribute__ ((vector_size (16)));
typedef char v16qi __attribute__ ((vector_size (16)));
typedef short v8hi __attribute__ ((vector_size (16)));
typedef int v4si __attribute__ ((vector_size (16)));
typedef double v2df __attribute__ ((vector_size (16)));
typedef float v4sf __attribute__ ((vector_size (16)));
typedef struct {
int magic;
int ebx, ecx, edx;
} kdb_cpuid_t;
kdb_cpuid_t *kdb_cpuid (void);
This diff is collapsed.
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009-2012 Vkontakte Ltd
2009-2012 Nikolai Durov
2009-2012 Andrey Lopatin
2012 Anton Maydell
Copyright 2014 Telegram Messenger Inc
2014 Anton Maydell
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned (*crc32_partial_func_t) (const void *data, long len, unsigned crc);
typedef unsigned (*crc32_combine_func_t) (unsigned crc1, unsigned crc2, int64_t len2);
typedef uint64_t (*crc64_partial_func_t) (const void *data, long len, uint64_t crc);
typedef uint64_t (*crc64_combine_func_t) (uint64_t crc1, uint64_t crc2, int64_t len2);
extern crc32_partial_func_t crc32_partial;
extern crc64_partial_func_t crc64_partial;
extern crc32_combine_func_t compute_crc32_combine;
extern crc64_combine_func_t compute_crc64_combine;
static inline unsigned compute_crc32 (const void *data, long len) {
return crc32_partial (data, len, -1) ^ -1;
}
static inline uint64_t compute_crc64 (const void *data, long len) {
return crc64_partial (data, len, -1LL) ^ -1LL;
}
/* crc32_check_and_repair returns
0 : Cyclic redundancy check is ok
1 : Cyclic redundancy check fails, but we fix one bit in input
2 : Cyclic redundancy check fails, but we fix one bit in input_crc32
-1 : Cyclic redundancy check fails, no repair possible.
In this case *input_crc32 will be equal crc32 (input, l)
Case force_exit == 1 (case 1, 2: kprintf call, case -1: assert fail).
*/
int crc32_check_and_repair (void *input, int l, unsigned *input_crc32, int force_exit);
int crc32_find_corrupted_bit (int size, unsigned d);
int crc32_repair_bit (unsigned char *input, int l, int k);
/* these functions are exported only for testing purpose */
unsigned crc32_partial_generic (const void *data, long len, unsigned crc);
unsigned crc32_partial_clmul (const void *data, long len, unsigned crc);
uint64_t crc64_partial_one_table (const void *data, long len, uint64_t crc);
uint64_t crc64_partial_clmul (const void *data, long len, uint64_t crc);
uint64_t crc64_feed_byte (uint64_t crc, unsigned char b);
void gf32_compute_powers_generic (unsigned *P, int size, unsigned poly);
void gf32_compute_powers_clmul (unsigned *P, unsigned poly);
unsigned gf32_combine_generic (unsigned *powers, unsigned crc1, int64_t len2);
uint64_t gf32_combine_clmul (unsigned *powers, unsigned crc1, int64_t len2);
#ifdef __cplusplus
}
#endif
This diff is collapsed.
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009-2012 Vkontakte Ltd
2009-2012 Nikolai Durov
2009-2012 Andrey Lopatin
2012 Anton Maydell
Copyright 2014 Telegram Messenger Inc
2014 Anton Maydell
*/
#pragma once
#include "common/crc32.h"
#ifdef __cplusplus
extern "C" {
#endif
//extern unsigned int crc32c_table[256];
extern crc32_partial_func_t crc32c_partial;
extern crc32_combine_func_t compute_crc32c_combine;
static inline unsigned compute_crc32c (const void *data, int len) {
return crc32c_partial (data, len, -1) ^ -1;
}
unsigned crc32c_partial_four_tables (const void *data, long len, unsigned crc);
#ifdef __cplusplus
}
#endif
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009-2012 Vkontakte Ltd
2009-2012 Nikolai Durov
2009-2012 Andrey Lopatin
2012 Anton Maydell
Copyright 2014 Telegram Messenger Inc
2014 Anton Maydell
*/
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/file.h>
#include <unistd.h>
#include "kprintf.h"
#include "precise-time.h"
int verbosity;
const char *logname;
void reopen_logs_ext (int slave_mode) {
int fd;
fflush (stdout);
fflush (stderr);
if ((fd = open ("/dev/null", O_RDWR, 0)) != -1) {
dup2 (fd, 0);
dup2 (fd, 1);
dup2 (fd, 2);
if (fd > 2) {
close (fd);
}
}
if (logname && (fd = open (logname, O_WRONLY|O_APPEND|O_CREAT, 0640)) != -1) {
dup2 (fd, 1);
dup2 (fd, 2);
if (fd > 2) {
close (fd);
}
}
if (!slave_mode) {
vkprintf (1, "logs reopened.\n");
}
}
void reopen_logs (void) {
reopen_logs_ext (0);
}
int hexdump (const void *start, const void *end) {
char s[256];
const char *ptr = start;
while (ptr < (char *) end) {
int len = (const char *) end - ptr, i;
if (len > 16) {
len = 16;
}
int p = 0;
p += sprintf (s + p, "%08x", (int) (ptr - (char *) start));
for (i = 0; i < 16; i++) {
s[p ++] = ' ';
if (i == 8) {
s[p ++] = ' ';
}
if (i < len) {
p += sprintf (s + p, "%02x", (unsigned char) ptr[i]);
} else {
p += sprintf (s + p, " ");
}
}
s[p ++] = '\n';
nck_write (2, s, p);
ptr += 16;
}
return end - start;
}
double reindex_speed = (32 << 20);
void kdb_write (int fd, const void *buf, long long count, const char *filename) {
assert (count >= 0);
static double total_count;
static double last_time;
int write_fail_count = 0;
while (count) {
long long l = !reindex_speed ? count : count >= (1 << 20) ? (1 << 20) : count;
if (reindex_speed) {
double t = get_utime_monotonic ();
total_count = total_count * exp ((last_time - t) * 0.1);
last_time = t;
if (total_count > reindex_speed) {
double k = log (total_count / reindex_speed) * 10;
assert (k >= 0);
struct timespec ts;
ts.tv_nsec = ((int)((k - floor (k)) * 1e9)) % 1000000000;
ts.tv_sec = (int)k;
nanosleep (&ts, 0);
}
}
long long w = write (fd, buf, l);
if (w <= 0) {
assert (-1 <= w);
if (write_fail_count < 10000 && (w == 0 || errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
write_fail_count++;
continue;
}
fprintf (stderr, "kdb_write: write %lld bytes to the file '%s' returns %lld. %m\n", l, filename, w);
exit (1);
}
assert (w <= l);
write_fail_count = 0;
if (reindex_speed) {
static long long data_after_fsync;
data_after_fsync += w;
if (data_after_fsync >= (1 << 20)) {
if (fsync (fd) < 0) {
fprintf (stderr, "kdb_write: fsyncing file '%s' failed. %m\n", filename);
exit (1);
}
data_after_fsync = 0;
}
double t = get_utime_monotonic ();
total_count = total_count * exp ((last_time - t) * 0.1);
last_time = t;
total_count += w * 0.1;
}
count -= w;
buf += w;
}
}
static inline void kwrite_print_int (char **s, const char *name, int name_len, int i) {
if (i < 0) {
i = INT_MAX;
}
*--*s = ' ';
*--*s = ']';
do {
*--*s = i % 10 + '0';
i /= 10;
} while (i > 0);
*--*s = ' ';
while (--name_len >= 0) {
*--*s = name[name_len];
}
*--*s = '[';
}
int kwrite (int fd, const void *buf, int count) {
int old_errno = errno;
#define S_BUF_SIZE 100
#define S_DATA_SIZE 256
char s[S_BUF_SIZE + S_DATA_SIZE], *s_begin = s + S_BUF_SIZE;
kwrite_print_int (&s_begin, "time", 4, time (NULL));
kwrite_print_int (&s_begin, "pid" , 3, getpid ());
assert (s_begin >= s);
int s_count = s + S_BUF_SIZE - s_begin;
if (count <= S_DATA_SIZE) {
int i;
for (i = 0; i < count; i++) {
s[i + S_BUF_SIZE] = ((char *)buf)[i];
}
s_count += count;
count = 0;
}
int result = s_count + count;
while (s_count > 0) {
errno = 0;
int res = (int)write (fd, s_begin, (size_t)s_count);
if (errno && errno != EINTR) {
errno = old_errno;
return res;
}
if (!res) {
break;
}
if (res >= 0) {
s_begin += res;
s_count -= res;
}
}
while (count > 0) {
errno = 0;
int res = (int)write (fd, buf, (size_t)count);
if (errno && errno != EINTR) {
errno = old_errno;
return res;
}
if (!res) {
break;
}
if (res >= 0) {
buf += res;
count -= res;
}
}
errno = old_errno;
return result;
#undef S_BUF_SIZE
#undef S_DATA_SIZE
}
void kprintf (const char *format, ...) {
const int old_errno = errno;
struct tm t;
struct timeval tv;
char mp_kprintf_buf[PIPE_BUF];
if (gettimeofday (&tv, NULL) || !localtime_r (&tv.tv_sec, &t)) {
memset (&t, 0, sizeof (t));
}
int n = snprintf (mp_kprintf_buf, sizeof (mp_kprintf_buf), "[%d][%4d-%02d-%02d %02d:%02d:%02d.%06d local] ", getpid (), t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, (int) tv.tv_usec);
if (n < sizeof (mp_kprintf_buf) - 1) {
errno = old_errno;
va_list ap;
va_start (ap, format);
n += vsnprintf (mp_kprintf_buf + n, sizeof (mp_kprintf_buf) - n, format, ap);
va_end (ap);
}
if (n >= sizeof (mp_kprintf_buf)) {
n = sizeof (mp_kprintf_buf) - 1;
if (mp_kprintf_buf[n-1] != '\n') {
mp_kprintf_buf[n++] = '\n';
}
}
while (write (2, mp_kprintf_buf, n) < 0 && errno == EINTR);
//while (flock (2, LOCK_UN) < 0 && errno == EINTR);
errno = old_errno;
}
void nck_write (int fd, const void *data, size_t len) {
if (write (fd, data, len)) {}
}
void nck_pwrite (int fd, const void *data, size_t len, off_t offset) {
if (pwrite (fd, data, len, offset)) {}
}
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009-2012 Vkontakte Ltd
2009-2012 Nikolai Durov
2009-2012 Andrey Lopatin
2012 Anton Maydell
Copyright 2014 Telegram Messenger Inc
2014 Anton Maydell
*/
#pragma once
#include <stddef.h>
#include <sys/types.h>
extern int verbosity;
extern const char *logname;
void reopen_logs (void);
void reopen_logs_ext (int slave_mode);
int hexdump (const void *start, const void *end);
extern double reindex_speed;
// safely writes buf to fd, considering write speed limit
void kdb_write (int fd, const void *buf, long long count, const char *filename);
// write message with timestamp and pid, safe to call inside handler
int kwrite (int fd, const void *buf, int count);
// print message with timestamp
void kprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
#define vkprintf(verbosity_level, format, ...) do { \
if ((verbosity_level) > verbosity) { \
break; \
} \
kprintf ((format), ##__VA_ARGS__); \
} while (0)
void nck_write (int fd, const void *data, size_t len);
void nck_pwrite (int fd, const void *data, size_t len, off_t offset);
This diff is collapsed.
/**
* \file md5.h
*/
#ifndef XYSSL_MD5_H
#define XYSSL_MD5_H
/**
* \brief MD5 context structure
*/
typedef struct
{
unsigned long total[2]; /*!< number of bytes processed */
unsigned long state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
unsigned char ipad[64]; /*!< HMAC: inner padding */
unsigned char opad[64]; /*!< HMAC: outer padding */
}
md5_context;
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief MD5 context setup
*
* \param ctx context to be initialized
*/
void md5_starts( md5_context *ctx );
/**
* \brief MD5 process buffer
*
* \param ctx MD5 context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md5_update( md5_context *ctx, unsigned char *input, int ilen );
/**
* \brief MD5 final digest
*
* \param ctx MD5 context
* \param output MD5 checksum result
*/
void md5_finish( md5_context *ctx, unsigned char output[16] );
/**
* \brief Output = MD5( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD5 checksum result
*/
void md5( unsigned char *input, int ilen, unsigned char output[16] );
void md5_hex (char *input, int ilen, char output[32]);
/**
* \brief Output = MD5( file contents )
*
* \param path input file name
* \param output MD5 checksum result
*
* \return 0 if successful, 1 if fopen failed,
* or 2 if fread failed
*/
int md5_file( char *path, unsigned char output[16] );
/**
* \brief MD5 HMAC context setup
*
* \param ctx HMAC context to be initialized
* \param key HMAC secret key
* \param keylen length of the HMAC key
*/
void md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen );
/**
* \brief MD5 HMAC process buffer
*
* \param ctx HMAC context
* \param input buffer holding the data
* \param ilen length of the input data
*/
void md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen );
/**
* \brief MD5 HMAC final digest
*
* \param ctx HMAC context
* \param output MD5 HMAC checksum result
*/
void md5_hmac_finish( md5_context *ctx, unsigned char output[16] );
/**
* \brief Output = HMAC-MD5( hmac key, input buffer )
*
* \param key HMAC secret key
* \param keylen length of the HMAC key
* \param input buffer holding the data
* \param ilen length of the input data
* \param output HMAC-MD5 result
*/
void md5_hmac( unsigned char *key, int keylen,
unsigned char *input, int ilen,
unsigned char output[16] );
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int md5_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* md5.h */
This diff is collapsed.
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2014-2018 Telegram Messenger Inc
2014-2015 Andrey Lopatin
2014-2018 Nikolai Durov
*/
#pragma once
#define MPQ_USE_POSIX_SEMAPHORES 0
#if MPQ_USE_POSIX_SEMAPHORES
#include <semaphore.h>
#endif
typedef struct mp_semaphore {
volatile int value;
volatile int waiting;
} mp_sem_t;
#define THREAD_HPTRS 16
#define MPQ_SMALL_BLOCK_SIZE 64
#define MPQ_BLOCK_SIZE 4096 // must be a power of 2
#define MPQ_BLOCK_ALIGNMENT 64
#ifdef _LP64
typedef int int128_t __attribute__((__mode__(TI)));
# define DLONG int128_t
// # define DLONG __int128
# define MQN_SAFE (-1LL << 63)
#else
# define DLONG long long
# define MQN_SAFE (-1L << 31)
#endif
#define MQN_IDX_MASK (~MQN_SAFE)
typedef void *mqn_value_t;
typedef struct mp_queue_node {
union {
struct {
long idx;
union {
long mqn_value;
void *mqn_ptr;
mqn_value_t val;
};
};
DLONG pair;
};
} mpq_node_t;
#define MQ_BLOCK_USED_MAGIC 0x1ebacaef
#define MQ_BLOCK_FREE_MAGIC 0x2e4afeda
#define MQ_BLOCK_GARBAGE_MAGIC 0x3a04dc7d
#define MQ_BLOCK_PREPARED_MAGIC 0x4b9b13cd
#define MQ_MAGIC 0x1aed9b43
#define MQ_MAGIC_SEM 0x1aedcd21
struct mp_queue_block {
long mqb_head __attribute__ ((aligned(64)));
int mqb_magic;
int mqb_align_bytes;
int mqb_size; // power of 2; one of MPQ_BLOCK_SIZE or MPQ_SMALL_BLOCK_SIZE
long mqb_tail __attribute__ ((aligned(64)));
struct mp_queue_block *mqb_next;
int mqb_next_allocators;
mpq_node_t mqb_nodes[MPQ_BLOCK_SIZE] __attribute__ ((aligned(64)));
};
struct mp_queue {
struct mp_queue_block *mq_head __attribute__ ((aligned(64)));
int mq_magic;
struct mp_queue_block *mq_tail __attribute__ ((aligned(64)));
#if MPQ_USE_POSIX_SEMAPHORES
sem_t mq_sem __attribute__ ((aligned(64)));
#else
mp_sem_t mq_sem __attribute__ ((aligned(64)));
#endif
};
extern volatile int mpq_blocks_allocated, mpq_blocks_allocated_max, mpq_blocks_allocations, mpq_blocks_true_allocations, mpq_blocks_wasted, mpq_blocks_prepared;
extern volatile int mpq_small_blocks_allocated, mpq_small_blocks_allocated_max;
#define MAX_MPQ_THREADS 256
extern __thread int mpq_this_thread_id;
extern __thread void **thread_hazard_pointers;
extern volatile int mpq_threads;
/* initialize this thread id and return it */
int get_this_thread_id (void);
/* functions for one mp_queue_block */
struct mp_queue_block *alloc_mpq_block (mqn_value_t first_val, int allow_recursion, int is_small);
void free_mpq_block (struct mp_queue_block *QB);
mqn_value_t mpq_block_pop (struct mp_queue_block *QB);
long mpq_block_push (struct mp_queue_block *QB, mqn_value_t val);
/* functions for mp_queue = list of mp_queue_block's */
void init_mp_queue (struct mp_queue *MQ);
struct mp_queue *alloc_mp_queue (void);
struct mp_queue *alloc_mp_queue_w (void);
void init_mp_queue_w (struct mp_queue *MQ);
void clear_mp_queue (struct mp_queue *MQ); // frees all mpq block chain; invoke only if nobody else is using mp-queue
void free_mp_queue (struct mp_queue *MQ); // same + invoke free()
// flags for mpq_push / mpq_pop functions
#define MPQF_RECURSIVE 8192
#define MPQF_STORE_PTR 4096
#define MPQF_MAX_ITERATIONS (MPQF_STORE_PTR - 1)
long mpq_push (struct mp_queue *MQ, mqn_value_t val, int flags);
mqn_value_t mpq_pop (struct mp_queue *MQ, int flags);
int mpq_is_empty (struct mp_queue *MQ);
long mpq_push_w (struct mp_queue *MQ, mqn_value_t val, int flags);
mqn_value_t mpq_pop_w (struct mp_queue *MQ, int flags);
mqn_value_t mpq_pop_nw (struct mp_queue *MQ, int flags);
int mp_sem_post (mp_sem_t *sem);
int mp_sem_wait (mp_sem_t *sem);
int mp_sem_trywait (mp_sem_t *sem);
#define COMMON_HAZARD_PTR_NUM 3
int is_hazard_ptr (void *ptr, int a, int b);
extern void *mqb_hazard_ptr[MAX_MPQ_THREADS][THREAD_HPTRS];
void *get_ptr_multithread_copy (void **ptr, void (*incref)(void *ptr));
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2014 Telegram Messenger Inc
2014 Vitaly Valtman
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "md5.h"
#include "common/parse-config.h"
#include "resolver.h"
#include "kprintf.h"
#define MAX_CONFIG_SIZE (16 << 20)
static char *config_buff;
char *config_name, *cfg_start, *cfg_end, *cfg_cur;
int config_bytes, cfg_lno, cfg_lex = -1;
int cfg_skipspc (void) {
while (*cfg_cur == ' ' || *cfg_cur == 9 || *cfg_cur == 13 || *cfg_cur == 10 || *cfg_cur == '#') {
if (*cfg_cur == '#') {
do cfg_cur++; while (*cfg_cur && *cfg_cur != 10);
continue;
}
if (*cfg_cur == 10) {
cfg_lno++;
}
cfg_cur++;
}
return (unsigned char) *cfg_cur;
}
int cfg_skspc (void) {
while (*cfg_cur == ' ' || *cfg_cur == 9) {
cfg_cur++;
}
return (unsigned char) *cfg_cur;
}
int cfg_getlex (void) {
switch (cfg_skipspc()) {
case ';':
case ':':
case '{':
case '}':
return cfg_lex = *cfg_cur++;
case 0:
return cfg_lex = 0;
}
return cfg_lex = -1;
}
int cfg_getword (void) {
cfg_skspc();
char *s = cfg_cur;
if (*s != '[') {
while ((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') || (*s >= '0' && *s <= '9') || *s == '.' || *s == '-' || *s == '_') {
s++;
}
} else {
s++;
while ((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') || (*s >= '0' && *s <= '9') || *s == '.' || *s == '-' || *s == '_' || *s == ':') {
s++;
}
if (*s == ']') {
s++;
}
}
return s - cfg_cur;
}
int cfg_getstr (void) {
cfg_skspc();
char *s = cfg_cur;
if (*s == '"') { return 1; } // fix later
while (*s > ' ' && *s != ';') {
s++;
}
return s - cfg_cur;
}
long long cfg_getint (void) {
cfg_skspc ();
char *s = cfg_cur;
long long x = 0;
while (*s >= '0' && *s <= '9') {
x = x * 10 + *(s ++) - '0';
}
cfg_cur = s;
return x;
}
long long cfg_getint_zero (void) {
cfg_skspc ();
char *s = cfg_cur;
long long x = 0;
while (*s >= '0' && *s <= '9') {
x = x * 10 + *(s ++) - '0';
}
if (cfg_cur == s) {
return -1;
} else {
cfg_cur = s;
return x;
}
}
long long cfg_getint_signed_zero (void) {
cfg_skspc ();
char *s = cfg_cur;
long long x = 0;
int sgn = 1;
if (*s == '-') {
sgn = -1;
++s;
}
while (*s >= '0' && *s <= '9') {
x = x * 10 + sgn * (*(s++) - '0');
}
if (s == cfg_cur + (sgn < 0)) {
return (-1LL << 63);
} else {
cfg_cur = s;
return x;
}
}
void syntax (const char *msg, ...) {
if (!msg) {
msg = "syntax error";
}
if (cfg_lno) {
fprintf (stderr, "%s:%d: ", config_name, cfg_lno);
}
fprintf (stderr, "fatal: ");
va_list args;
va_start (args, msg);
vfprintf (stderr, msg, args);
va_end (args);
int len = 0;
while (cfg_cur[len] && cfg_cur[len] != 13 && cfg_cur[len] != 10 && len < 20) {
len++;
}
fprintf (stderr, " near %.*s%s\n", len, cfg_cur, len >= 20 ? " ..." : "");
}
void syntax_warning (const char *msg, ...) {
va_list args;
if (cfg_lno) {
fprintf (stderr, "%s:%d: ", config_name, cfg_lno);
}
fputs ("warning: ", stderr);
va_start (args, msg);
vfprintf (stderr, msg, args);
va_end (args);
int len = 0;
while (cfg_cur[len] && cfg_cur[len] != 13 && cfg_cur[len] != 10 && len < 20) {
len++;
}
fprintf (stderr, " near %.*s%s\n", len, cfg_cur, len >= 20 ? " ..." : "");
}
int expect_lexem (int lexem) {
if (cfg_lex != lexem) {
syntax ("%c expected", lexem);
return -1;
} else {
return 0;
}
}
int expect_word (const char *name, int len) {
int l = cfg_getword ();
if (len != l || memcmp (name, cfg_cur, len)) {
syntax ("Expected %.*s", len, name);
return -1;
}
cfg_cur += l;
return 0;
}
struct hostent *cfg_gethost_ex (int verb) {
struct hostent *h;
int l = cfg_getword ();
if (!l || l > 63) {
syntax ("hostname expected");
return 0;
}
char c = cfg_cur[l];
//hostname = cfg_cur;
cfg_cur[l] = 0;
if (!(h = kdb_gethostbyname (cfg_cur)) || !h->h_addr_list || !h->h_addr) {
if (verbosity >= verb) {
syntax ("cannot resolve '%s'\n", cfg_cur);
}
*(cfg_cur += l) = c;
return 0;
}
*(cfg_cur += l) = c;
return h;
}
struct hostent *cfg_gethost (void) {
return cfg_gethost_ex (0);
}
void reset_config (void) {
assert (config_buff);
cfg_cur = cfg_start = config_buff;
cfg_end = cfg_start + config_bytes;
*cfg_end = 0;
cfg_lno = 0;
}
int load_config (const char *file, int fd) {
if (!config_buff) {
config_buff = malloc (MAX_CONFIG_SIZE+4);
assert (config_buff);
}
if (fd < 0) {
fd = open (file, O_RDONLY);
if (fd < 0) {
fprintf (stderr, "Can not open file %s: %m\n", file);
return -1;
}
}
int r;
config_bytes = r = read (fd, config_buff, MAX_CONFIG_SIZE + 1);
if (r < 0) {
fprintf (stderr, "error reading configuration file %s: %m\n", config_name);
return -2;
}
if (r > MAX_CONFIG_SIZE) {
fprintf (stderr, "configuration file %s too long (max %d bytes)\n", config_name, MAX_CONFIG_SIZE);
return -2;
}
if (config_name) {
free (config_name);
}
if (file) {
config_name = strdup (file);
}
reset_config ();
return fd;
}
void md5_hex_config (char *out) {
assert (config_buff);
md5_hex (config_buff, config_bytes, out);
}
void close_config (int *fd) {
if (config_buff) {
free (config_buff);
config_buff = NULL;
}
if (config_name) {
free (config_name);
config_name = NULL;
}
config_bytes = 0;
cfg_cur = cfg_start = cfg_end = NULL;
if (fd) {
if (*fd >= 0) {
assert (!close (*fd));
*fd = -1;
}
}
}
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2014 Telegram Messenger Inc
2014 Vitaly Valtman
*/
#pragma once
extern char *config_file, *cfg_start, *cfg_end, *cfg_cur;
extern int config_bytes, cfg_lno, cfg_lex;
int cfg_skipspc (void);
int cfg_skspc (void);
int cfg_getlex (void);
int cfg_getword (void);
int cfg_getstr (void);
void syntax (const char *msg, ...);
void syntax_warning (const char *msg, ...);
int expect_lexem (int lexem);
int expect_word (const char *name, int len);
void reset_config (void);
int load_config (const char *file, int fd);
void close_config (int *fd);
void md5_hex_config (char *out);
struct hostent *cfg_gethost (void);
struct hostent *cfg_gethost_ex (int verb);
long long cfg_getint (void);
long long cfg_getint_zero (void);
long long cfg_getint_signed_zero (void);
#define Expect(l) { int t = expect_lexem (l); if (t < 0) { return t; } }
#define ExpectWord(s) { int t = expect_word (s, strlen (s)); if (t < 0) { return t; } }
#define Syntax(...) { syntax (__VA_ARGS__); return -1; }
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2011-2013 Vkontakte Ltd
2011-2013 Nikolai Durov
2011-2013 Andrey Lopatin
Copyright 2014 Telegram Messenger Inc
2014 Vitaly Valtman
*/
#define _FILE_OFFSET_BITS 64
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include "common/pid.h"
npid_t PID;
void init_common_PID (void) {
if (!PID.pid) {
int p = getpid ();
assert (!(p & 0xffff0000));
PID.pid = p;
}
if (!PID.utime) {
PID.utime = time (0);
}
}
void init_client_PID (unsigned ip) {
if (ip && ip != 0x7f000001) {
PID.ip = ip;
}
// PID.port = 0;
init_common_PID ();
};
void init_server_PID (unsigned ip, int port) {
if (ip && ip != 0x7f000001) {
PID.ip = ip;
}
if (!PID.port) {
PID.port = port;
}
init_common_PID ();
};
/* returns 1 if X is a special case of Y, 2 if they match completely */
int matches_pid (npid_t *X, npid_t *Y) {
if (!memcmp (X, Y, sizeof (struct process_id))) {
return 2;
} else if ((!Y->ip || X->ip == Y->ip) && (!Y->port || X->port == Y->port) && (!Y->pid || X->pid == Y->pid) && (!Y->utime || X->utime == Y->utime)) {
return 1;
} else {
return 0;
}
}
int process_id_is_newer (struct process_id *a, struct process_id *b) {
assert (!memcmp (a, b, 6));
if (a->utime < b->utime) { return 0; }
if (a->utime > b->utime) { return 1; }
int x = (a->pid - b->pid) & 0x7fff;
if (x && x <= 0x3fff) { return 1; }
return 0;
}
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2011-2013 Vkontakte Ltd
2011-2013 Nikolai Durov
2011-2013 Andrey Lopatin
Copyright 2014 Telegram Messenger Inc
2014 Vitaly Valtman
*/
#pragma once
#pragma pack(push,4)
struct process_id {
unsigned ip;
short port;
unsigned short pid;
int utime;
};
struct process_id_ext {
unsigned ip;
short port;
unsigned short pid;
int utime;
int actor_id;
};
#pragma pack(pop)
typedef struct process_id npid_t;
typedef struct process_id_ext npidx_t;
extern npid_t PID;
void init_common_PID (void);
void init_client_PID (unsigned ip);
void init_server_PID (unsigned ip, int port);
/* returns 1 if X is a special case of Y, 2 if they match completely */
int matches_pid (struct process_id *X, struct process_id *Y);
int process_id_is_newer (struct process_id *a, struct process_id *b);
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2014 Telegram Messenger Inc
2014 Anton Maydell
*/
#include <assert.h>
#include <sys/time.h>
#include <time.h>
/* unistd.h defines _POSIX_TIMERS */
#include <unistd.h>
#include "precise-time.h"
__thread int now;
__thread double precise_now;
__thread long long precise_now_rdtsc;
long long precise_time;
long long precise_time_rdtsc;
double get_utime_monotonic (void) __attribute__ ((weak));
double get_utime_monotonic (void) {
struct timespec T;
#if _POSIX_TIMERS
assert (clock_gettime (CLOCK_MONOTONIC, &T) >= 0);
precise_now_rdtsc = rdtsc ();
return precise_now = T.tv_sec + (double) T.tv_nsec * 1e-9;
#else
#error "No high-precision clock"
return precise_now = time ();
#endif
}
double get_double_time (void) {
static double last_double_time = -1;
static long long next_rdtsc;
long long cur_rdtsc = rdtsc ();
if (cur_rdtsc > next_rdtsc) {
struct timeval tv;
gettimeofday (&tv, NULL);
next_rdtsc = cur_rdtsc + 1000000;
return (last_double_time = tv.tv_sec + 1e-6 * tv.tv_usec);
} else {
return last_double_time;
}
}
double get_utime (int clock_id) {
struct timespec T;
#if _POSIX_TIMERS
assert (clock_gettime (clock_id, &T) >= 0);
double res = T.tv_sec + (double) T.tv_nsec * 1e-9;
#else
#error "No high-precision clock"
double res = time ();
#endif
if (clock_id == CLOCK_REALTIME) {
precise_time = (long long) (res * (1LL << 32));
precise_time_rdtsc = rdtsc ();
}
return res;
}
long long get_precise_time (unsigned precision) {
unsigned long long diff = rdtsc() - precise_time_rdtsc;
if (diff > precision) {
get_utime (CLOCK_REALTIME);
}
return precise_time;
}
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2014 Telegram Messenger Inc
2014 Anton Maydell
*/
#pragma once
#include <time.h>
/* RDTSC */
#if defined(__i386__)
static __inline__ unsigned long long rdtsc(void) {
unsigned long long int x;
__asm__ volatile ("rdtsc" : "=A" (x));
return x;
}
#elif defined(__x86_64__)
static __inline__ unsigned long long rdtsc(void) {
unsigned hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
#endif
/* net-event.h */
extern __thread int now;
extern __thread double precise_now;
extern __thread long long precise_now_rdtsc;
double get_utime_monotonic (void);
/* common/server-functions.h */
double get_utime (int clock_id);
extern long long precise_time; // (long long) (2^16 * precise unixtime)
extern long long precise_time_rdtsc; // when precise_time was obtained
long long get_precise_time (unsigned precision);
/* ??? */
double get_double_time (void);
static inline void precise_sleep (int seconds, int nanoseconds) {
struct timespec t;
t.tv_sec = seconds;
t.tv_nsec = nanoseconds;
nanosleep (&t, NULL);
}
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2014 Telegram Messenger Inc
2014 Vitaly Valtman
*/
#include "common/proc-stat.h"
#include <stdio.h>
int read_proc_stats (int pid, int tid, struct proc_stats *s) {
const char *format = "%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu %llu";
char buf[256];
if (tid <= 0) {
sprintf (buf, "/proc/%d/stat", pid);
} else {
sprintf (buf, "/proc/%d/task/%d/stat", pid, tid);
}
FILE *proc = fopen (buf, "r");
if (proc) {
if (42 == fscanf (proc, format,
&s->pid,
s->comm,
&s->state,
&s->ppid,
&s->pgrp,
&s->session,
&s->tty_nr,
&s->tpgid,
&s->flags,
&s->minflt,
&s->cminflt,
&s->majflt,
&s->cmajflt,
&s->utime,
&s->stime,
&s->cutime,
&s->cstime,
&s->priority,
&s->nice,
&s->num_threads,
&s->itrealvalue,
&s->starttime,
&s->vsize,
&s->rss,
&s->rlim,
&s->startcode,
&s->endcode,
&s->startstack,
&s->kstkesp,
&s->kstkeip,
&s->signal,
&s->blocked,
&s->sigignore,
&s->sigcatch,
&s->wchan,
&s->nswap,
&s->cnswap,
&s->exit_signal,
&s->processor,
&s->rt_priority,
&s->policy,
&s->delayacct_blkio_ticks
)
) {
fclose(proc);
return 1;
} else {
fclose(proc);
return 0;
}
} else {
return 0;
}
}
This diff is collapsed.
This diff is collapsed.
/*
This file is part of Mtproto-proxy Library.
Mtproto-proxy Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Mtproto-proxy Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2010-2013 Vkontakte Ltd
2010-2013 Nikolai Durov
2010-2013 Andrey Lopatin
*/
#pragma once
#include <netdb.h>
#ifdef __cplusplus
extern "C" {
#endif
int kdb_hosts_loaded;
int kdb_load_hosts (void);
struct hostent *kdb_gethostbyname (const char *name);
char *detect_hostname (void);
#ifdef __cplusplus
}
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment