Added libconfig to parse config. Something fixed in net

This commit is contained in:
vysheng 2013-11-08 22:58:28 +04:00
parent a064540223
commit c04a0f5d6a
7 changed files with 162 additions and 102 deletions

View File

@ -1,6 +1,6 @@
CC=cc CC=cc
CFLAGS=-c -Wall -Wextra -Werror -fPIC -ggdb -O2 -fno-omit-frame-pointer -fno-strict-aliasing -rdynamic CFLAGS=-c -Wall -Wextra -Werror -fPIC -ggdb -O2 -fno-omit-frame-pointer -fno-strict-aliasing -rdynamic
LDFLAGS=-lreadline -lssl -lcrypto -lrt -lz -ggdb -rdynamic LDFLAGS=-lreadline -lssl -lcrypto -lrt -lz -lconfig -ggdb -rdynamic
LD=cc LD=cc
SRC=main.c loop.c interface.c net.c mtproto-common.c mtproto-client.c queries.c structures.c SRC=main.c loop.c interface.c net.c mtproto-common.c mtproto-client.c queries.c structures.c

3
loop.c
View File

@ -43,6 +43,7 @@
extern char *default_username; extern char *default_username;
extern char *auth_token; extern char *auth_token;
extern int test_dc;
void set_default_username (const char *s); void set_default_username (const char *s);
int default_dc_num; int default_dc_num;
@ -188,7 +189,7 @@ void read_dc (int auth_file_fd, int id, unsigned ver) {
} }
void empty_auth_file (void) { void empty_auth_file (void) {
struct dc *DC = alloc_dc (1, strdup (TG_SERVER), 443); struct dc *DC = alloc_dc (1, strdup (test_dc ? TG_SERVER_TEST : TG_SERVER), 443);
assert (DC); assert (DC);
dc_working_num = 1; dc_working_num = 1;
auth_state = 0; auth_state = 0;

187
main.c
View File

@ -16,6 +16,7 @@
Copyright Vitaly Valtman 2013 Copyright Vitaly Valtman 2013
*/ */
#define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
@ -31,6 +32,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <execinfo.h> #include <execinfo.h>
#include <signal.h> #include <signal.h>
#include <libconfig.h>
#include "loop.h" #include "loop.h"
#include "mtproto-client.h" #include "mtproto-client.h"
@ -38,12 +40,12 @@
#define PROGNAME "telegram-client" #define PROGNAME "telegram-client"
#define VERSION "0.01" #define VERSION "0.01"
#define CONFIG_DIRECTORY ".telegram/" #define CONFIG_DIRECTORY ".telegram"
#define CONFIG_FILE CONFIG_DIRECTORY "config" #define CONFIG_FILE "config"
#define AUTH_KEY_FILE CONFIG_DIRECTORY "auth" #define AUTH_KEY_FILE "auth"
#define STATE_FILE CONFIG_DIRECTORY "state" #define STATE_FILE "state"
#define SECRET_CHAT_FILE CONFIG_DIRECTORY "secret" #define SECRET_CHAT_FILE "secret"
#define DOWNLOADS_DIRECTORY "downloads/" #define DOWNLOADS_DIRECTORY "downloads"
#define CONFIG_DIRECTORY_MODE 0700 #define CONFIG_DIRECTORY_MODE 0700
@ -52,9 +54,16 @@
"# Feel free to put something here\n" "# Feel free to put something here\n"
char *default_username; char *default_username;
int setup_mode;
char *auth_token; char *auth_token;
int msg_num_mode; int msg_num_mode;
char *config_filename;
char *prefix;
int test_dc;
char *auth_file_name;
char *state_file_name;
char *secret_chat_file_name;
char *downloads_directory;
char *config_directory;
void set_default_username (const char *s) { void set_default_username (const char *s) {
if (default_username) { if (default_username) {
@ -63,11 +72,6 @@ void set_default_username (const char *s) {
default_username = strdup (s); default_username = strdup (s);
} }
void set_setup_mode (void) {
setup_mode = 1;
}
/* {{{ TERMINAL */ /* {{{ TERMINAL */
tcflag_t old_lflag; tcflag_t old_lflag;
cc_t old_vtime; cc_t old_vtime;
@ -100,7 +104,7 @@ char *get_home_directory (void) {
return current_passwd->pw_dir; return current_passwd->pw_dir;
} }
} }
return 0; return "";
} }
char *get_config_directory (void) { char *get_config_directory (void) {
@ -115,63 +119,47 @@ char *get_config_directory (void) {
} }
char *get_config_filename (void) { char *get_config_filename (void) {
char *config_filename;
int length = strlen (get_home_directory ()) + strlen (CONFIG_FILE) + 2;
config_filename = (char *) calloc (length, sizeof (char));
sprintf (config_filename, "%s/" CONFIG_FILE, get_home_directory ());
return config_filename; return config_filename;
} }
char *get_auth_key_filename (void) { char *get_auth_key_filename (void) {
char *auth_key_filename; return auth_file_name;
int length = strlen (get_home_directory ()) + strlen (AUTH_KEY_FILE) + 2;
auth_key_filename = (char *) calloc (length, sizeof (char));
sprintf (auth_key_filename, "%s/" AUTH_KEY_FILE, get_home_directory ());
return auth_key_filename;
} }
char *get_state_filename (void) { char *get_state_filename (void) {
char *state_filename; return state_file_name;
int length = strlen (get_home_directory ()) + strlen (STATE_FILE) + 2;
state_filename = (char *) calloc (length, sizeof (char));
sprintf (state_filename, "%s/" STATE_FILE, get_home_directory ());
return state_filename;
} }
char *get_secret_chat_filename (void) { char *get_secret_chat_filename (void) {
char *secret_chat_filename; return secret_chat_file_name;
int length = strlen (get_home_directory ()) + strlen (SECRET_CHAT_FILE) + 2;
secret_chat_filename = (char *) calloc (length, sizeof (char));
sprintf (secret_chat_filename, "%s/" SECRET_CHAT_FILE, get_home_directory ());
return secret_chat_filename;
} }
char *get_downloads_directory (void) char *get_downloads_directory (void) {
{
char *downloads_directory;
int length = strlen (get_config_directory ()) + strlen (DOWNLOADS_DIRECTORY) + 2;
downloads_directory = (char *) calloc (length, sizeof (char));
sprintf (downloads_directory, "%s/" DOWNLOADS_DIRECTORY, get_config_directory ());
return downloads_directory; return downloads_directory;
} }
char *make_full_path (char *s) {
if (*s != '/') {
char *t = s;
assert (asprintf (&s, "%s/%s", get_home_directory (), s) >= 0);
free (t);
}
return s;
}
void running_for_first_time (void) { void running_for_first_time (void) {
if (config_filename) {
return; // Do not create custom config file
}
assert (asprintf (&config_filename, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, CONFIG_FILE) >= 0);
config_filename = make_full_path (config_filename);
struct stat *config_file_stat = NULL; struct stat *config_file_stat = NULL;
int config_file_fd; int config_file_fd;
char *config_directory = get_config_directory (); char *config_directory = get_config_directory ();
char *config_filename = get_config_filename (); //char *downloads_directory = get_downloads_directory ();
char *downloads_directory = get_downloads_directory ();
if (mkdir (config_directory, CONFIG_DIRECTORY_MODE) != 0) { if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) {
return;
} else {
printf ("\nRunning " PROGNAME " for first time!!\n");
printf ("[%s] created\n", config_directory); printf ("[%s] created\n", config_directory);
} }
@ -192,21 +180,92 @@ void running_for_first_time (void) {
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
close (config_file_fd); close (config_file_fd);
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600); /*int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
int x = -1; int x = -1;
assert (write (auth_file_fd, &x, 4) == 4); assert (write (auth_file_fd, &x, 4) == 4);
close (auth_file_fd); close (auth_file_fd);
printf ("[%s] created\n", config_filename); printf ("[%s] created\n", config_filename);*/
/* create downloads directory */ /* create downloads directory */
if (mkdir (downloads_directory, 0755) !=0) { /*if (mkdir (downloads_directory, 0755) !=0) {
perror ("creating download directory"); perror ("creating download directory");
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
}*/
} }
}
void parse_config_val (config_t *conf, char **s, char *param_name, const char *default_name, const char *path) {
static char buf[1000];
int l = 0;
if (prefix) {
l = strlen (prefix);
memcpy (buf, prefix, l);
buf[l ++] = '.';
}
*s = 0;
const char *r = 0;
strcpy (buf + l, param_name);
config_lookup_string (conf, buf, &r);
if (r) {
if (path) {
assert (asprintf (s, "%s/%s", path, r) >= 0);
} else {
*s = strdup (r);
}
} else {
if (path) {
assert (asprintf (s, "%s/%s", path, default_name) >= 0);
} else {
*s = strdup (default_name);
}
}
}
void parse_config (void) {
config_filename = make_full_path (config_filename);
config_t conf;
config_init (&conf);
if (config_read_file (&conf, config_filename) != CONFIG_TRUE) {
fprintf (stderr, "Can not read config '%s': error '%s' on the line %d\n", config_filename, config_error_text (&conf), config_error_line (&conf));
exit (2);
} }
set_setup_mode (); if (!prefix) {
config_lookup_string (&conf, "default_profile", (void *)&prefix);
}
static char buf[1000];
int l = 0;
if (prefix) {
l = strlen (prefix);
memcpy (buf, prefix, l);
buf[l ++] = '.';
}
test_dc = 0;
strcpy (buf + l, "test");
config_lookup_bool (&conf, buf, &test_dc);
if (!msg_num_mode) {
strcpy (buf + l, "msg_num");
config_lookup_bool (&conf, buf, &msg_num_mode);
}
parse_config_val (&conf, &config_directory, "config_directory", CONFIG_DIRECTORY, 0);
config_directory = make_full_path (config_directory);
parse_config_val (&conf, &auth_file_name, "auth_file", AUTH_KEY_FILE, config_directory);
parse_config_val (&conf, &state_file_name, "state_file", STATE_FILE, config_directory);
parse_config_val (&conf, &secret_chat_file_name, "secret", SECRET_CHAT_FILE, config_directory);
parse_config_val (&conf, &downloads_directory, "downloads", DOWNLOADS_DIRECTORY, config_directory);
if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) {
printf ("[%s] created\n", config_directory);
}
if (!mkdir (downloads_directory, CONFIG_DIRECTORY_MODE)) {
printf ("[%s] created\n", downloads_directory);
}
} }
void inner_main (void) { void inner_main (void) {
@ -214,7 +273,7 @@ void inner_main (void) {
} }
void usage (void) { void usage (void) {
printf ("%s [-u username] [-h] [-k public key name]\n", PROGNAME); printf ("%s [-u username] [-h] [-k public key name] [-N] [-v]\n", PROGNAME);
exit (1); exit (1);
} }
@ -224,7 +283,7 @@ extern int default_dc_num;
void args_parse (int argc, char **argv) { void args_parse (int argc, char **argv) {
int opt = 0; int opt = 0;
while ((opt = getopt (argc, argv, "u:hk:vn:N")) != -1) { while ((opt = getopt (argc, argv, "u:hk:vn:Nc:p:")) != -1) {
switch (opt) { switch (opt) {
case 'u': case 'u':
set_default_username (optarg); set_default_username (optarg);
@ -235,12 +294,16 @@ void args_parse (int argc, char **argv) {
case 'v': case 'v':
verbosity ++; verbosity ++;
break; break;
case 'n':
default_dc_num = atoi (optarg);
break;
case 'N': case 'N':
msg_num_mode ++; msg_num_mode ++;
break; break;
case 'c':
config_filename = strdup (optarg);
break;
case 'p':
prefix = strdup (optarg);
assert (strlen (prefix) <= 100);
break;
case 'h': case 'h':
default: default:
usage (); usage ();
@ -266,18 +329,20 @@ void sig_handler (int signum) {
int main (int argc, char **argv) { int main (int argc, char **argv) {
signal (SIGSEGV, sig_handler); signal (SIGSEGV, sig_handler);
signal (SIGABRT, sig_handler); signal (SIGABRT, sig_handler);
running_for_first_time ();
args_parse (argc, argv);
printf ( printf (
"Telegram-client version " TG_VERSION ", Copyright (C) 2013 Vitaly Valtman\n" "Telegram-client version " TG_VERSION ", Copyright (C) 2013 Vitaly Valtman\n"
"Telegram-client comes with ABSOLUTELY NO WARRANTY; for details type `show_license'.\n" "Telegram-client comes with ABSOLUTELY NO WARRANTY; for details type `show_license'.\n"
"This is free software, and you are welcome to redistribute it\n" "This is free software, and you are welcome to redistribute it\n"
"under certain conditions; type `show_license' for details.\n" "under certain conditions; type `show_license' for details.\n"
); );
running_for_first_time ();
parse_config ();
get_terminal_attributes (); get_terminal_attributes ();
args_parse (argc, argv);
inner_main (); inner_main ();

View File

@ -1361,8 +1361,9 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc,
double st = get_server_time (DC); double st = get_server_time (DC);
assert (this_server_time >= st - 300 && this_server_time <= st + 30); assert (this_server_time >= st - 300 && this_server_time <= st + 30);
//assert (enc->msg_id > server_last_msg_id && (enc->msg_id & 3) == 1); //assert (enc->msg_id > server_last_msg_id && (enc->msg_id & 3) == 1);
if (verbosity >= 2) { if (verbosity >= 1) {
logprintf ( "received mesage id %016llx\n", enc->msg_id); logprintf ( "received mesage id %016llx\n", enc->msg_id);
hexdump_in ();
} }
server_last_msg_id = enc->msg_id; server_last_msg_id = enc->msg_id;
@ -1390,10 +1391,10 @@ int rpc_execute (struct connection *c, int op, int len) {
if (verbosity) { if (verbosity) {
logprintf ( "outbound rpc connection #%d : received rpc answer %d with %d content bytes\n", c->fd, op, len); logprintf ( "outbound rpc connection #%d : received rpc answer %d with %d content bytes\n", c->fd, op, len);
} }
if (op < 0) { /* if (op < 0) {
assert (read_in (c, Response, Response_len) == Response_len); assert (read_in (c, Response, Response_len) == Response_len);
return 0; return 0;
} }*/
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) { if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
logprintf ( "answer too long (%d bytes), skipping\n", len); logprintf ( "answer too long (%d bytes), skipping\n", len);

5
net.c
View File

@ -146,7 +146,7 @@ int read_in (struct connection *c, void *data, int len) {
int x = 0; int x = 0;
while (len) { while (len) {
int y = c->in_head->wptr - c->in_head->rptr; int y = c->in_head->wptr - c->in_head->rptr;
if (y >= len) { if (y > len) {
memcpy (data, c->in_head->rptr, len); memcpy (data, c->in_head->rptr, len);
c->in_head->rptr += len; c->in_head->rptr += len;
c->in_bytes -= len; c->in_bytes -= len;
@ -185,6 +185,7 @@ int read_in_lookup (struct connection *c, void *data, int len) {
memcpy (data, b->rptr, y); memcpy (data, b->rptr, y);
x += y; x += y;
data += y; data += y;
len -= y;
b = b->next; b = b->next;
} }
} }
@ -405,7 +406,7 @@ void hexdump_buf (struct connection_buffer *b) {
void try_rpc_read (struct connection *c) { void try_rpc_read (struct connection *c) {
assert (c->in_head); assert (c->in_head);
if (verbosity >= 4) { if (verbosity >= 1) {
hexdump_buf (c->in_head); hexdump_buf (c->in_head);
} }

2
net.h
View File

@ -23,7 +23,7 @@
struct dc; struct dc;
#include "queries.h" #include "queries.h"
#define TG_SERVER "173.240.5.1" #define TG_SERVER "173.240.5.1"
//#define TG_SERVER "95.142.192.66" #define TG_SERVER_TEST "173.240.5.253"
#define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74" #define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74"
#define TG_APP_ID 2899 #define TG_APP_ID 2899
#define TG_BUILD "203" #define TG_BUILD "203"

View File

@ -1159,6 +1159,9 @@ int send_file_on_answer (struct query *q UU) {
} }
int send_encr_file_on_answer (struct query *q UU) { int send_encr_file_on_answer (struct query *q UU) {
if (prefetch_int () != (int)CODE_messages_sent_encrypted_file) {
hexdump_in ();
}
assert (fetch_int () == (int)CODE_messages_sent_encrypted_file); assert (fetch_int () == (int)CODE_messages_sent_encrypted_file);
struct message *M = q->extra; struct message *M = q->extra;
M->date = fetch_int (); M->date = fetch_int ();
@ -1649,40 +1652,9 @@ void load_next_part (struct download *D);
int download_on_answer (struct query *q) { int download_on_answer (struct query *q) {
assert (fetch_int () == (int)CODE_upload_file); assert (fetch_int () == (int)CODE_upload_file);
unsigned x = fetch_int (); unsigned x = fetch_int ();
assert (x);
struct download *D = q->extra; struct download *D = q->extra;
if (D->fd == -1) { if (D->fd == -1) {
static char buf[100];
sprintf (buf, "%s/tmp_%ld_%ld", get_downloads_directory (), lrand48 (), lrand48 ());
int l = strlen (buf);
switch (x) {
case CODE_storage_file_unknown:
break;
case CODE_storage_file_jpeg:
sprintf (buf + l, "%s", ".jpg");
break;
case CODE_storage_file_gif:
sprintf (buf + l, "%s", ".gif");
break;
case CODE_storage_file_png:
sprintf (buf + l, "%s", ".png");
break;
case CODE_storage_file_mp3:
sprintf (buf + l, "%s", ".mp3");
break;
case CODE_storage_file_mov:
sprintf (buf + l, "%s", ".mov");
break;
case CODE_storage_file_partial:
sprintf (buf + l, "%s", ".part");
break;
case CODE_storage_file_mp4:
sprintf (buf + l, "%s", ".mp4");
break;
case CODE_storage_file_webp:
sprintf (buf + l, "%s", ".webp");
break;
}
D->name = strdup (buf);
D->fd = open (D->name, O_CREAT | O_WRONLY, 0640); D->fd = open (D->name, O_CREAT | O_WRONLY, 0640);
} }
fetch_int (); // mtime fetch_int (); // mtime
@ -1719,7 +1691,27 @@ struct query_methods download_methods = {
void load_next_part (struct download *D) { void load_next_part (struct download *D) {
if (!D->offset) { if (!D->offset) {
static char buf[1000];
if (!D->id) {
sprintf (buf, "%s/download_%lld_%d", get_downloads_directory (), D->volume, D->local_id);
} else {
sprintf (buf, "%s/download_%lld", get_downloads_directory (), D->id);
}
D->name = strdup (buf);
struct stat st;
if (stat (buf, &st) >= 0) {
D->offset = st.st_size;
if (D->offset >= D->size) {
cur_downloading_bytes += D->size; cur_downloading_bytes += D->size;
cur_downloaded_bytes += D->offset;
rprintf ("Already downloaded\n");
end_load (D);
return;
}
}
cur_downloading_bytes += D->size;
cur_downloaded_bytes += D->offset;
update_prompt (); update_prompt ();
} }
clear_packet (); clear_packet ();