// File: rellla[P]E3DC-Rscp/RscpMain.cpp
// Function: main
int main(int argc, char *argv[])
{
    int iConnected = 0;
    int conn_retry = MAX_CONN_RETRY;
    int opt;
    int requests = 0;

    // get conf parameters
    FILE *fp = fopen(CONF_FILE, "r");
    char var[128], value[128], line[256];
    e3dc_config_t e3dc_config;
    if(fp) {
	while (fgets(line, sizeof(line), fp)) {
	    memset(var, 0, sizeof(var));
	    memset(value, 0, sizeof(value));
	    if(sscanf(line, "%[^ \t=]%*[\t ]=%*[\t ]%[^\n]", var, value) == 2) {
		if(strcmp(var, "server_ip") == 0)
		    strcpy(e3dc_config.server_ip, value);
		else if(strcmp(var, "server_port") == 0)
		    e3dc_config.server_port = atoi(value);
		else if(strcmp(var, "e3dc_user") == 0)
		    strcpy(e3dc_config.e3dc_user, value);
		else if(strcmp(var, "e3dc_password") == 0)
		    strcpy(e3dc_config.e3dc_password, value);
		else if(strcmp(var, "aes_password") == 0)
		    strcpy(e3dc_config.aes_password, value);
	    }
	}
	fclose(fp);
    }

    // get commandline parameters
    while (1) {
	static struct option long_options[] = {
	    {"help",		no_argument,		0, 'h'},
	    {"battery",		no_argument,		0, 'b'},
	    {"ems",		no_argument,		0, 'e'},
	    {"time",		no_argument,		0, 't'},
	    {"settime",		no_argument,		0, 's'},
	    {"weather",		required_argument,	0, 'w' },
	};
	int option_index = 0;
	opt = getopt_long(argc, argv, "hbetsw:", long_options, &option_index);

	if(opt == -1)
	    break;

	switch (opt){
	case 'h': {
	    showhelp(argv[0]);
	    return 0;
	    break;
	    }
	case 'b': {
	    requests |= TAG_BATTERY;
	    break;
	    }
	case 'e': {
	    requests |= TAG_EMS;
	    break;
	    }
	case 't': {
	    requests |= TAG_GET_IDLE_PERIODS;
	    break;
	    }
	case 's': {
	    requests |= TAG_SET_IDLE_PERIODS;
	    break;
	    }
	case 'w': {
	    requests |= TAG_WEATHER_ENABLE;
	    if (atoi(optarg) == 1)
		requests |= TAG_WEATHER_ENABLE_F;
	    else if (atoi(optarg) == 0)
		requests &= ~TAG_WEATHER_ENABLE_F;
	    else
		requests &= ~TAG_WEATHER_ENABLE;
	    break;
	    }
	default:
	    printf("%s: option '-%c' is invalid: ignored\n", argv[0], optopt);
	    break;
	}
    }

    if(requests & TAG_BATTERY)
	printf("Get battery details\n");
    if(requests & TAG_EMS)
	printf("Get ems details\n");
    if(requests & TAG_GET_IDLE_PERIODS)
	printf("Get idle periods details\n");
    if(requests & TAG_SET_IDLE_PERIODS)
	printf("Set idle periods details\n");
    if(requests & TAG_WEATHER_ENABLE)
	printf("Set weather enable option\n");

    // connect to server
    while (!iConnected && (conn_retry + 1) > 0) {
	printf("Connecting to server %s:%i\n", e3dc_config.server_ip, e3dc_config.server_port);
	iSocket = SocketConnect(e3dc_config.server_ip, e3dc_config.server_port);
	if (iSocket < 0) {
	    printf("Connection failed\n");
	    sleep(1);
	    conn_retry--;
	    continue;
	}
	iConnected = 1;
	printf("Connection success\n");

    }
    if (!iConnected) {
	printf("Connection failed due to timeout\n");
	return -1;
    }
    // create AES key and set AES parameters
    {
	// initialize AES encryptor and decryptor IV
	memset(ucDecryptionIV, 0xff, AES_BLOCK_SIZE);
	memset(ucEncryptionIV, 0xff, AES_BLOCK_SIZE);

	// limit password length to AES_KEY_SIZE
	int iPasswordLength = strlen(e3dc_config.aes_password);
	if (iPasswordLength > AES_KEY_SIZE)
	    iPasswordLength = AES_KEY_SIZE;

	// copy up to 32 bytes of AES key password
	uint8_t ucAesKey[AES_KEY_SIZE];
	memset(ucAesKey, 0xff, AES_KEY_SIZE);
	memcpy(ucAesKey, e3dc_config.aes_password, iPasswordLength);

	// set encryptor and decryptor parameters
	aesDecrypter.SetParameters(AES_KEY_SIZE * 8, AES_BLOCK_SIZE * 8);
	aesEncrypter.SetParameters(AES_KEY_SIZE * 8, AES_BLOCK_SIZE * 8);
	aesDecrypter.StartDecryption(ucAesKey);
	aesEncrypter.StartEncryption(ucAesKey);
    }

    authLoop(&e3dc_config);
    if (iAuthenticated) {
	printf("Authentication success\n");
	// enter the main transmit / receive loop
	mainLoop(requests);
    } else {
	printf("Authentication failed\n");
	// close socket connection
	SocketClose(iSocket);
	iSocket = -1;
	return -1;
    }

    // close socket connection
    SocketClose(iSocket);
    iSocket = -1;

    return 0;
}

// Assembly:
subq $0x3f8, %rsp            # imm = 0x3F8
movl $0x0, 0x3f4(%rsp)
movl %edi, 0x3f0(%rsp)
movq %rsi, 0x3e8(%rsp)
movl $0x0, 0x3e4(%rsp)
movl $0x3, 0x3e0(%rsp)
movl $0x0, 0x3d8(%rsp)
leaq 0x1b5ea(%rip), %rdi     # 0x20653
leaq 0x1b666(%rip), %rsi     # 0x206d6
callq 0x21b0
movq %rax, 0x3d0(%rsp)
cmpq $0x0, 0x3d0(%rsp)
je 0x521b
jmp 0x508e
leaq 0x1d0(%rsp), %rdi
movq 0x3d0(%rsp), %rdx
movl $0x100, %esi            # imm = 0x100
callq 0x2240
cmpq $0x0, %rax
je 0x520e
leaq 0x350(%rsp), %rdi
xorl %esi, %esi
movl $0x80, %edx
callq 0x20e0
leaq 0x2d0(%rsp), %rdi
xorl %esi, %esi
movl $0x80, %edx
callq 0x20e0
leaq 0x1d0(%rsp), %rdi
leaq 0x350(%rsp), %rdx
leaq 0x2d0(%rsp), %rcx
leaq 0x1b569(%rip), %rsi     # 0x20662
movb $0x0, %al
callq 0x2170
cmpl $0x2, %eax
jne 0x5209
leaq 0x350(%rsp), %rdi
leaq 0x1b564(%rip), %rsi     # 0x2067c
callq 0x2210
cmpl $0x0, %eax
jne 0x5139
leaq 0x38(%rsp), %rdi
leaq 0x2d0(%rsp), %rsi
callq 0x2160
jmp 0x5207
leaq 0x350(%rsp), %rdi
leaq 0x1b53e(%rip), %rsi     # 0x20686
callq 0x2210
cmpl $0x0, %eax
jne 0x5168
leaq 0x2d0(%rsp), %rdi
callq 0x2230
movl %eax, 0x4c(%rsp)
jmp 0x5205
leaq 0x350(%rsp), %rdi
leaq 0x1b51b(%rip), %rsi     # 0x20692
callq 0x2210
cmpl $0x0, %eax
jne 0x5199
leaq 0x38(%rsp), %rdi
addq $0x18, %rdi
leaq 0x2d0(%rsp), %rsi
callq 0x2160
jmp 0x5203
leaq 0x350(%rsp), %rdi
leaq 0x1b4f4(%rip), %rsi     # 0x2069c
callq 0x2210
cmpl $0x0, %eax
jne 0x51cd
leaq 0x38(%rsp), %rdi
addq $0x98, %rdi
leaq 0x2d0(%rsp), %rsi
callq 0x2160
jmp 0x5201
leaq 0x350(%rsp), %rdi
leaq 0x1b4ce(%rip), %rsi     # 0x206aa
callq 0x2210
cmpl $0x0, %eax
jne 0x51ff
leaq 0x38(%rsp), %rdi
addq $0x118, %rdi            # imm = 0x118
leaq 0x2d0(%rsp), %rsi
callq 0x2160
jmp 0x5201
jmp 0x5203
jmp 0x5205
jmp 0x5207
jmp 0x5209
jmp 0x508e
movq 0x3d0(%rsp), %rdi
callq 0x2180
jmp 0x521d
movl $0x0, 0x34(%rsp)
movl 0x3f0(%rsp), %edi
movq 0x3e8(%rsp), %rsi
leaq 0x1b49d(%rip), %rdx     # 0x206d8
leaq 0x1ef5e(%rip), %rcx     # 0x241a0
leaq 0x34(%rsp), %r8
callq 0x2290
movl %eax, 0x3dc(%rsp)
cmpl $-0x1, 0x3dc(%rsp)
jne 0x5262
jmp 0x53a4
movl 0x3dc(%rsp), %eax
addl $-0x62, %eax
movl %eax, %ecx
movq %rcx, 0x8(%rsp)
subl $0x15, %eax
ja 0x537d
movq 0x8(%rsp), %rax
leaq 0x1adb4(%rip), %rcx     # 0x2003c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x3e8(%rsp), %rax
movq (%rax), %rdi
callq 0x4fa0
movl $0x0, 0x3f4(%rsp)
jmp 0x5656
movl 0x3d8(%rsp), %eax
orl $0x1, %eax
movl %eax, 0x3d8(%rsp)
jmp 0x539f
movl 0x3d8(%rsp), %eax
orl $0x2, %eax
movl %eax, 0x3d8(%rsp)
jmp 0x539f
movl 0x3d8(%rsp), %eax
orl $0x4, %eax
movl %eax, 0x3d8(%rsp)
jmp 0x539f
movl 0x3d8(%rsp), %eax
orl $0x20, %eax
movl %eax, 0x3d8(%rsp)
jmp 0x539f
movl 0x3d8(%rsp), %eax
orl $0x8, %eax
movl %eax, 0x3d8(%rsp)
movq 0x1ecaf(%rip), %rax     # 0x23fd0
movq (%rax), %rdi
callq 0x2230
cmpl $0x1, %eax
jne 0x5341
movl 0x3d8(%rsp), %eax
orl $0x10, %eax
movl %eax, 0x3d8(%rsp)
jmp 0x537b
movq 0x1ec88(%rip), %rax     # 0x23fd0
movq (%rax), %rdi
callq 0x2230
cmpl $0x0, %eax
jne 0x5368
movl 0x3d8(%rsp), %eax
andl $-0x11, %eax
movl %eax, 0x3d8(%rsp)
jmp 0x5379
movl 0x3d8(%rsp), %eax
andl $-0x9, %eax
movl %eax, 0x3d8(%rsp)
jmp 0x537b
jmp 0x539f
movq 0x3e8(%rsp), %rax
movq (%rax), %rsi
movq 0x1ec51(%rip), %rax     # 0x23fe0
movl (%rax), %edx
leaq 0x1b348(%rip), %rdi     # 0x206e0
movb $0x0, %al
callq 0x2040
jmp 0x521d
movl 0x3d8(%rsp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x53c1
leaq 0x1b34c(%rip), %rdi     # 0x20706
movb $0x0, %al
callq 0x2040
movl 0x3d8(%rsp), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x53de
leaq 0x1b344(%rip), %rdi     # 0x2071b
movb $0x0, %al
callq 0x2040
movl 0x3d8(%rsp), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x53fb
leaq 0x1b338(%rip), %rdi     # 0x2072c
movb $0x0, %al
callq 0x2040
movl 0x3d8(%rsp), %eax
andl $0x20, %eax
cmpl $0x0, %eax
je 0x5418
leaq 0x1b335(%rip), %rdi     # 0x20746
movb $0x0, %al
callq 0x2040
movl 0x3d8(%rsp), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x5435
leaq 0x1b332(%rip), %rdi     # 0x20760
movb $0x0, %al
callq 0x2040
jmp 0x5437
xorl %eax, %eax
cmpl $0x0, 0x3e4(%rsp)
movb %al, 0x7(%rsp)
jne 0x545b
movl 0x3e0(%rsp), %eax
addl $0x1, %eax
cmpl $0x0, %eax
setg %al
movb %al, 0x7(%rsp)
movb 0x7(%rsp), %al
testb $0x1, %al
jne 0x5468
jmp 0x54e8
leaq 0x38(%rsp), %rsi
movl 0x4c(%rsp), %edx
leaq 0x1b303(%rip), %rdi     # 0x2077b
movb $0x0, %al
callq 0x2040
leaq 0x38(%rsp), %rdi
movl 0x4c(%rsp), %esi
callq 0x1f4d0
movl %eax, 0x1ecfd(%rip)     # 0x24190
cmpl $0x0, 0x1ecf6(%rip)     # 0x24190
jge 0x54ca
leaq 0x1b2f4(%rip), %rdi     # 0x20797
movb $0x0, %al
callq 0x2040
movl $0x1, %edi
callq 0x2110
movl 0x3e0(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x3e0(%rsp)
jmp 0x5437
movl $0x1, 0x3e4(%rsp)
leaq 0x1b2ce(%rip), %rdi     # 0x207aa
movb $0x0, %al
callq 0x2040
jmp 0x5437
cmpl $0x0, 0x3e4(%rsp)
jne 0x5510
leaq 0x1b2c5(%rip), %rdi     # 0x207be
movb $0x0, %al
callq 0x2040
movl $0xffffffff, 0x3f4(%rsp) # imm = 0xFFFFFFFF
jmp 0x5656
leaq 0x1f1a9(%rip), %rdi     # 0x246c0
movl $0xff, %esi
movl $0x20, %edx
callq 0x20e0
leaq 0x1f173(%rip), %rdi     # 0x246a0
movl $0xff, %esi
movl $0x20, %edx
callq 0x20e0
leaq 0x38(%rsp), %rdi
addq $0x118, %rdi            # imm = 0x118
callq 0x20b0
movl %eax, 0x30(%rsp)
cmpl $0x20, 0x30(%rsp)
jle 0x5560
movl $0x20, 0x30(%rsp)
leaq 0x10(%rsp), %rdi
movl $0xff, %esi
movl $0x20, %edx
callq 0x20e0
leaq 0x10(%rsp), %rdi
leaq 0x38(%rsp), %rsi
addq $0x118, %rsi            # imm = 0x118
movslq 0x30(%rsp), %rdx
callq 0x2130
leaq 0x1eef6(%rip), %rdi     # 0x2448c
movl $0x100, %edx            # imm = 0x100
movl %edx, %esi
callq 0xab50
leaq 0x1ecd7(%rip), %rdi     # 0x24280
movl $0x100, %edx            # imm = 0x100
movl %edx, %esi
callq 0xab50
leaq 0x10(%rsp), %rsi
leaq 0x1eecb(%rip), %rdi     # 0x2448c
callq 0x14680
leaq 0x10(%rsp), %rsi
leaq 0x1ecae(%rip), %rdi     # 0x24280
callq 0xaca0
leaq 0x38(%rsp), %rdi
callq 0x4730
cmpl $0x0, 0x1f0b0(%rip)     # 0x24698
je 0x5606
leaq 0x1b1ef(%rip), %rdi     # 0x207e0
movb $0x0, %al
callq 0x2040
movl 0x3d8(%rsp), %edi
callq 0x5670
jmp 0x5636
leaq 0x1b1eb(%rip), %rdi     # 0x207f8
movb $0x0, %al
callq 0x2040
movl 0x1eb76(%rip), %edi     # 0x24190
callq 0x1f680
movl $0xffffffff, 0x1eb67(%rip) # imm = 0xFFFFFFFF
movl $0xffffffff, 0x3f4(%rsp) # imm = 0xFFFFFFFF
jmp 0x5656
movl 0x1eb54(%rip), %edi     # 0x24190
callq 0x1f680
movl $0xffffffff, 0x1eb45(%rip) # imm = 0xFFFFFFFF
movl $0x0, 0x3f4(%rsp)
movl 0x3f4(%rsp), %eax
addq $0x3f8, %rsp            # imm = 0x3F8
retq
nopw %cs:(%rax,%rax)