// // package.c // mcc@exe // // Created by Finn Behrens on 27.02.21. // #include #include "package.h" #include "protocol.h" void mc_package_print(mc_package_header_t *header) { printf("cmd 0x%02x, length: %d (without header)", header->cmd, header->length); print_hex(header->data, header->length); printf("\n"); } int mc_package_serialize(mc_package_header_t *header, uint8_t **buffer) { int cmd_buffer_counter = 0; uint8_t cmd_buffer[5]; int size_buffer_counter = 0; uint8_t size_buffer[5]; #ifdef DEBUG mc_package_print(header); #endif cmd_buffer_counter = write_var_int(header->cmd, (uint8_t*)&cmd_buffer); if (cmd_buffer_counter < 0) return cmd_buffer_counter; size_buffer_counter = write_var_int(header->length + cmd_buffer_counter, (uint8_t*)&size_buffer); if (size_buffer_counter < 0) return size_buffer_counter; *buffer = calloc(header->length + size_buffer_counter + cmd_buffer_counter, sizeof(uint8_t)); if (*buffer == NULL) return -ENOMEM; memcpy(*buffer, &size_buffer, size_buffer_counter); memcpy((*buffer)+size_buffer_counter, &cmd_buffer, cmd_buffer_counter); memcpy((*buffer)+size_buffer_counter+cmd_buffer_counter, header->data, header->length); return header->length + size_buffer_counter + cmd_buffer_counter; } int mc_package_parse(mc_package_header_t *header, uint8_t *src) { int size_buffer_counter = 0, cmd_buffer_counter = 0; int size, cmd; size_buffer_counter = read_var_int(&size, src); if (size_buffer_counter < 0) return size_buffer_counter; cmd_buffer_counter = read_var_int(&cmd, src + size_buffer_counter); if (cmd_buffer_counter < 0) return cmd_buffer_counter; header->cmd = cmd; header->length = size - cmd_buffer_counter; // package size = cmd + data, header.size only data header->data = calloc(header->length, sizeof(uint8_t)); if (header->data == NULL) return -ENOMEM; memcpy(header->data, src+size_buffer_counter + cmd_buffer_counter, header->length); return header->length + size_buffer_counter + cmd_buffer_counter; } mc_package_header_t *mc_package_new() { mc_package_header_t *header; header = calloc(1, sizeof(mc_package_header_t)); if (header == NULL) return NULL; header->data = NULL; header->length = 0; header->cmd = 0; return header; } void mc_package_free(mc_package_header_t *header) { if (header->length != 0) free(header->data); free(header); } int mc_package_get_var_int(mc_package_header_t *header, size_t offset, int *size) { int ret; *size = read_var_int(&ret, header->data + offset); return ret; } char *mc_package_read_string(mc_package_header_t *header, size_t offset, int *size) { int ret; char* buffer; ret = mc_package_get_var_int(header, offset, size); if (size < 0) { return NULL; } buffer = calloc(ret+1, sizeof(char)); if (buffer == NULL) { *size = -ENOMEM; return NULL; } memcpy(buffer, mc_package_data(header, offset+(*size)), ret); *size += ret; return buffer; } int mc_package_put_var_int(mc_package_header_t *header, int data) { uint8_t data_buffer[5]; int data_buffer_counter; uint8_t *new_buffer; data_buffer_counter = write_var_int(data, (uint8_t*)&data_buffer); if (data_buffer_counter < 0) return data_buffer_counter; new_buffer = calloc(header->length + data_buffer_counter, sizeof(uint8_t)); if (new_buffer == NULL) return -ENOMEM; if (header->length != 0) memcpy(new_buffer, header->data, header->length); memcpy(new_buffer+header->length, &data_buffer, data_buffer_counter); if (header->length != 0) free(header->data); header->length += data_buffer_counter; header->data = new_buffer; return data_buffer_counter; } int mc_package_put_string(mc_package_header_t *header, const char* str) { const int size = strlen(str); uint8_t size_buffer[5]; int size_buffer_counter = 0; uint8_t *new_buffer; size_buffer_counter = write_var_int(size, (uint8_t*)&size_buffer); if (size_buffer_counter < 0) return size_buffer_counter; new_buffer = calloc(header->length + size_buffer_counter + size, sizeof(uint8_t)); if (new_buffer == NULL) return -ENOMEM; if (header->length != 0) memcpy(new_buffer, header->data, header->length); memcpy(new_buffer+header->length, &size_buffer, size_buffer_counter); memcpy(new_buffer+header->length+size_buffer_counter, str, size); if (header->length != 0) free(header->data); header->data = new_buffer; header->length = header->length + size_buffer_counter + size; return size_buffer_counter + size; } int mc_package_put(mc_package_header_t *header, int size, const void *data) { uint8_t *new_buffer; int err; void *own_data = calloc(size, sizeof(uint8_t)); if (own_data == NULL) return -ENOMEM; switch (size) { case 1: *(uint8_t*)own_data = *(uint8_t*)data; break; case 2: *(uint16_t*)own_data = H_TO_BE16(*(uint16_t*)data); break; case 4: *(uint16_t*)own_data = H_TO_BE32(*(uint32_t*)data); break; case 8: *(uint64_t*)own_data = H_TO_BE64(*(uint64_t*)data); break; default: memcpy(own_data, data, size); break; }; new_buffer = calloc(header->length+size, sizeof(uint8_t)); if (new_buffer == NULL) { err = -ENOMEM; goto out; } if (header->length != 0) memcpy(new_buffer, header->data, header->length); memcpy(new_buffer+header->length, own_data, size); if (header->length != 0) free(header->data); header->data = new_buffer; header->length += size; err = size; out: free(own_data); return err; } mc_play_user_t *mc_play_user_new() { mc_play_user_t *user; user = calloc(1, sizeof(mc_play_user_t)); if (user == NULL) return NULL; user->gamemode = MC_PLAY_GAMEMODE_SURVIVAL; // TODO: from config? user->ping = -1; return user; } void mc_play_user_free(mc_play_user_t *user) { if (user->display_name != NULL) free(user->display_name); if (user->name != NULL) free(user->name); if(user->uuid) free(user->uuid); free(user); } int mc_package_put_user(mc_package_header_t *header, mc_play_user_t *user, int action) { int err; if (action == 0) { err = mc_package_put_uuid(header, user->uuid); if (err < 0) return err; err = mc_package_put_string(header, user->name); if (err < 0) return err; // FIXME: properties err = mc_package_put_var_int(header, 0); if (err < 0) return err; err = mc_package_put_var_int(header, user->gamemode); if (err < 0) return err; err = mc_package_put_var_int(header, user->ping); if (err < 0) return err; err = mc_package_put_bool(header, user->display_name != NULL); if (err < 0) return err; if (user->display_name != NULL) { printf("display_name not yet implemented\n"); return -EFAULT; } return 0; } return -EFAULT; }