// File: sidscrazy[P]Paxos/paxos_node.cpp
// Function: PaxosNode::process_message(message*)
void process_message (message *m){
		if (m == NULL){
			return;
		}

		int reponse_code; 
		switch (m->type){
			case MSG_PREPARE: {
				if (m->round > n) {
					n = m->round;
				} 
				state = PREPARING;
				message response (id, m->sender, v, n, MSG_PREPARE_ACK);
				network_lock.lock ();
				send_message (0, &response);
				network_lock.unlock ();
				break; 
			}

			case MSG_PREPARE_ACK: {

				if (m->round > n){
					n = m->round;
					state = NO_VALUE;
					clear_responses ();
				} else if (m->round == n){
					bool already_voted = false;
					for (int i = 0; i < prepare_acks.size (); i++){
						if (prepare_acks [i] == m->sender){
							already_voted = true;
							break;
						}
					}
					if (!already_voted){
						prepare_acks.push_back (m->sender);
						if (v < m->value && !proposed_v){
							v = m->value;
						}
					}

				} else {
					message response (id, m->sender, NO_VALUE, n, MSG_UPDATE);
					network_lock.lock ();
					send_message (0, &response);
					network_lock.unlock ();
					 
				}
				break;
			}

			case MSG_PROPOSE: {
				if (m->round == n && state == PREPARING &&
					((m->value >= v && !proposed_v) || (m->value == v && proposed_v)) ){
					v = m->value;
					state = PROPOSING;
					proposed_v = true;
				} 
				message response (id, m->sender, v, n, MSG_PROPOSE_ACK);
				network_lock.lock ();
				send_message (0, &response);
				network_lock.unlock ();
				break;
			}

			case MSG_PROPOSE_ACK: {
				if (m->round > n){
					n = m->round;
					state = NO_VALUE;
					clear_responses ();
				} else if (m->round < n){
					message response (id, m->sender, NO_VALUE, n, MSG_UPDATE);
					network_lock.lock ();
					send_message (0, &response);
					network_lock.unlock ();

				} else {
					vote *vo = (vote *) malloc (sizeof (vote));
					vo->node = m->sender;
					vo->n = m->round;
					vo->v = m->value;
					votes.push_back (vo);
				} 
				break;
			}

			case MSG_UPDATE: {
				if (m->round > n){
					n = m->round;
					state = NO_VALUE;
					clear_responses ();
				}
				break; 
			}

			case MSG_CONSENSUS: {
				safe_exit (m);
				break;
			}

			case MSG_TEARDOWN: {
				safe_exit (m);
				break;
			}

			default: 
				break;
		}

		free (m);
		if (!(role & PROPOSER)){
			simulate_crash ();
		}
		
	}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xb0(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0x3e1a
jmp 0x429d
movq -0x10(%rbp), %rax
movl 0x10(%rax), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0xb8(%rbp)
subl $0x7, %eax
ja 0x4274
movq -0xb8(%rbp), %rax
leaq 0x41c1(%rip), %rcx      # 0x8004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0xb0(%rbp), %rcx
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
cmpl 0x10(%rcx), %eax
jle 0x3e70
movq -0xb0(%rbp), %rax
movq -0x10(%rbp), %rcx
movl 0xc(%rcx), %ecx
movl %ecx, 0x10(%rax)
movq -0xb0(%rbp), %rax
movl $0xfffffffc, 0x14(%rax) # imm = 0xFFFFFFFC
movl (%rax), %esi
movq -0x10(%rbp), %rcx
movl (%rcx), %edx
movl 0xc(%rax), %ecx
movl 0x10(%rax), %r8d
leaq -0x38(%rbp), %rdi
movl $0x2, %r9d
callq 0x5600
movq -0xb0(%rbp), %rdi
addq $0x28, %rdi
callq 0x3d40
movq -0xb0(%rbp), %rdi
xorl %esi, %esi
leaq -0x38(%rbp), %rdx
callq 0x5640
movq -0xb0(%rbp), %rdi
addq $0x28, %rdi
callq 0x3dd0
jmp 0x4276
movq -0xb0(%rbp), %rcx
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
cmpl 0x10(%rcx), %eax
jle 0x3f08
movq -0xb0(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, 0x10(%rdi)
movl $0xffffffff, 0x14(%rdi) # imm = 0xFFFFFFFF
callq 0x58d0
jmp 0x4038
movq -0xb0(%rbp), %rcx
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
cmpl 0x10(%rcx), %eax
jne 0x3fdd
movb $0x0, -0x39(%rbp)
movl $0x0, -0x40(%rbp)
movq -0xb0(%rbp), %rdi
movslq -0x40(%rbp), %rax
movq %rax, -0xc0(%rbp)
addq $0xe0, %rdi
callq 0x5980
movq %rax, %rcx
movq -0xc0(%rbp), %rax
cmpq %rcx, %rax
jae 0x3f8b
movq -0xb0(%rbp), %rdi
addq $0xe0, %rdi
movslq -0x40(%rbp), %rsi
callq 0x59a0
movl (%rax), %eax
movq -0x10(%rbp), %rcx
cmpl (%rcx), %eax
jne 0x3f7e
movb $0x1, -0x39(%rbp)
jmp 0x3f8b
jmp 0x3f80
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x3f2a
testb $0x1, -0x39(%rbp)
jne 0x3fdb
movq -0xb0(%rbp), %rdi
addq $0xe0, %rdi
movq -0x10(%rbp), %rsi
callq 0x59c0
movq -0xb0(%rbp), %rax
movl 0xc(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x8(%rcx), %eax
jge 0x3fd9
movq -0xb0(%rbp), %rax
testb $0x1, 0x18(%rax)
jne 0x3fd9
movq -0xb0(%rbp), %rax
movq -0x10(%rbp), %rcx
movl 0x8(%rcx), %ecx
movl %ecx, 0xc(%rax)
jmp 0x3fdb
jmp 0x4036
movq -0xb0(%rbp), %rax
movl (%rax), %esi
movq -0x10(%rbp), %rcx
movl (%rcx), %edx
movl 0x10(%rax), %r8d
leaq -0x60(%rbp), %rdi
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movl $0x5, %r9d
callq 0x5600
movq -0xb0(%rbp), %rdi
addq $0x28, %rdi
callq 0x3d40
movq -0xb0(%rbp), %rdi
xorl %esi, %esi
leaq -0x60(%rbp), %rdx
callq 0x5640
movq -0xb0(%rbp), %rdi
addq $0x28, %rdi
callq 0x3dd0
jmp 0x4038
jmp 0x4276
movq -0xb0(%rbp), %rcx
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
cmpl 0x10(%rcx), %eax
jne 0x40b9
movq -0xb0(%rbp), %rax
cmpl $-0x4, 0x14(%rax)
jne 0x40b9
movq -0xb0(%rbp), %rcx
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
cmpl 0xc(%rcx), %eax
jl 0x407d
movq -0xb0(%rbp), %rax
testb $0x1, 0x18(%rax)
je 0x409d
movq -0xb0(%rbp), %rcx
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
cmpl 0xc(%rcx), %eax
jne 0x40b9
movq -0xb0(%rbp), %rax
testb $0x1, 0x18(%rax)
je 0x40b9
movq -0xb0(%rbp), %rax
movq -0x10(%rbp), %rcx
movl 0x8(%rcx), %ecx
movl %ecx, 0xc(%rax)
movl $0xfffffffb, 0x14(%rax) # imm = 0xFFFFFFFB
movb $0x1, 0x18(%rax)
movq -0xb0(%rbp), %rax
movl (%rax), %esi
movq -0x10(%rbp), %rcx
movl (%rcx), %edx
movl 0xc(%rax), %ecx
movl 0x10(%rax), %r8d
leaq -0x80(%rbp), %rdi
movl $0x4, %r9d
callq 0x5600
movq -0xb0(%rbp), %rdi
addq $0x28, %rdi
callq 0x3d40
movq -0xb0(%rbp), %rdi
xorl %esi, %esi
leaq -0x80(%rbp), %rdx
callq 0x5640
movq -0xb0(%rbp), %rdi
addq $0x28, %rdi
callq 0x3dd0
jmp 0x4276
movq -0xb0(%rbp), %rcx
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
cmpl 0x10(%rcx), %eax
jle 0x414a
movq -0xb0(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, 0x10(%rdi)
movl $0xffffffff, 0x14(%rdi) # imm = 0xFFFFFFFF
callq 0x58d0
jmp 0x421c
movq -0xb0(%rbp), %rcx
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
cmpl 0x10(%rcx), %eax
jge 0x41be
movq -0xb0(%rbp), %rax
movl (%rax), %esi
movq -0x10(%rbp), %rcx
movl (%rcx), %edx
movl 0x10(%rax), %r8d
leaq -0xa0(%rbp), %rdi
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movl $0x5, %r9d
callq 0x5600
movq -0xb0(%rbp), %rdi
addq $0x28, %rdi
callq 0x3d40
movq -0xb0(%rbp), %rdi
xorl %esi, %esi
leaq -0xa0(%rbp), %rdx
callq 0x5640
movq -0xb0(%rbp), %rdi
addq $0x28, %rdi
callq 0x3dd0
jmp 0x421a
movl $0xc, %edi
callq 0x2260
movq -0xb0(%rbp), %rdi
movq %rax, -0xa8(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %ecx
movq -0xa8(%rbp), %rax
movl %ecx, (%rax)
movq -0x10(%rbp), %rax
movl 0xc(%rax), %ecx
movq -0xa8(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %ecx
movq -0xa8(%rbp), %rax
movl %ecx, 0x8(%rax)
addq $0xc8, %rdi
leaq -0xa8(%rbp), %rsi
callq 0x5a30
jmp 0x421c
jmp 0x4276
movq -0xb0(%rbp), %rcx
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
cmpl 0x10(%rcx), %eax
jle 0x424e
movq -0xb0(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, 0x10(%rdi)
movl $0xffffffff, 0x14(%rdi) # imm = 0xFFFFFFFF
callq 0x58d0
jmp 0x4276
movq -0xb0(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x5aa0
jmp 0x4276
movq -0xb0(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x5aa0
jmp 0x4276
jmp 0x4276
movq -0x10(%rbp), %rdi
callq 0x2220
movq -0xb0(%rbp), %rax
movl 0x8(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x429d
movq -0xb0(%rbp), %rdi
callq 0x5b20
addq $0xc0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)