#include "work.h" #include "accept.h" #include "basin/packet.h" #include "login_stage_handler.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int connection_read(struct netmgr_connection* netmgr_conn, uint8_t* read_buf, size_t read_buf_len) { struct connection* conn = netmgr_conn->extra; if (conn->disconnect) { return 1; } if (conn->aes_ctx_dec != NULL) { int decrypted_length = (int) (read_buf_len + 32); // 16 extra just in case void* decrypted = pmalloc(netmgr_conn->read_buffer.pool, (size_t) decrypted_length); if (EVP_DecryptUpdate(conn->aes_ctx_dec, decrypted, &decrypted_length, read_buf, (int) read_buf_len) != 1) { pprefree(netmgr_conn->read_buffer.pool, decrypted); return 1; } if (decrypted_length == 0) return 0; buffer_push(&netmgr_conn->read_buffer, decrypted, (size_t) decrypted_length); pprefree(netmgr_conn->read_buffer.pool, read_buf); } else { buffer_push(&netmgr_conn->read_buffer, read_buf, read_buf_len); } while (netmgr_conn->read_buffer.size > 4) { uint8_t peek_buf[8]; buffer_peek(&netmgr_conn->read_buffer, 5, peek_buf); int32_t length = 0; if (!readVarInt(&length, peek_buf, 5)) { return 0; } int ls = getVarIntSize(length); if (netmgr_conn->read_buffer.size - ls < length) { return 0; } buffer_skip(&netmgr_conn->read_buffer, (size_t) ls); struct mempool* packet_pool = mempool_new(); pchild(conn->pool, packet_pool); uint8_t* packet_buf = pmalloc(packet_pool, (size_t) length); buffer_pop(&netmgr_conn->read_buffer, (size_t) length, packet_buf); struct packet* packet = pmalloc(packet_pool, sizeof(struct packet)); packet->pool = packet_pool; ssize_t read_packet_length = packet_read(conn, packet_buf, (size_t) length, packet); if (read_packet_length == -1) goto ret_error; if (conn->protocol_state == STATE_HANDSHAKE && packet->id == PKT_HANDSHAKE_SERVER_HANDSHAKE) { if (handle_packet_handshake(conn, packet)) { goto ret_error; } } else if (conn->protocol_state == STATE_STATUS) { if (handle_packet_status(conn, packet)) { goto ret_error; } } else if (conn->protocol_state == STATE_LOGIN) { if (handle_packet_login(conn, packet)) { goto ret_error; } } else if (conn->protocol_state == STATE_PLAY) { queue_push(conn->player->incoming_packets, packet); } else { goto ret_error; } goto ret; ret_error: ; pfree(packet->pool); return 1; ret: ; pfree(packet->pool); } return 0; } void connection_on_closed(struct netmgr_connection* netmgr_conn) { struct connection* conn = netmgr_conn->extra; if (conn->player != NULL) { player_broadcast("yellow", "%s has left the server!", conn->player->name); conn->player->conn = NULL; } pfree(conn->pool); }