int process_clip_msg(local_fd_type fd, client_t* client, msg_t* msg, size_t* room_id) { size_t i; unsigned int ident = ntohl(msg->ident); size_t all_len = msg_data_length(msg); msg_group_t* group = msg_group_lookup(&client->recv_table, ident); if (!msg->zone.clip) return 0; if (group == NULL) { group = group_pool_room_alloc(&qtun->group_pool, sizeof(msg_group_t)); if (group == NULL) { SYSLOG(LOG_ERR, "Not enough memory"); return 0; } group->count = (unsigned short)ceil((double)all_len / client->max_length); group->elements = group_pool_room_alloc(&qtun->group_pool, sizeof(msg_t*) * group->count); memset(group->elements, 0, sizeof(msg_t*) * group->count); group->ident = ident; group->ttl_start = qtun->msg_ttl; if (!hash_set(&client->recv_table, (void*)(unsigned long)ident, sizeof(ident), group, sizeof(msg_group_t))) return 0; } if (qtun->msg_ttl - group->ttl_start > MSG_MAX_TTL) return 0; // expired for (i = 0; i < group->count; ++i) { if (group->elements[i] == NULL) // 收包顺序可能与发包顺序不同 { size_t this_len = sizeof(msg_t) + (msg->zone.last ? all_len % client->max_length : client->max_length); msg_t* dup = group_pool_room_alloc(&qtun->group_pool, this_len); if (dup == NULL) break; memcpy(dup, msg, this_len); group->elements[i] = dup; if (i == group->count - 1) { void* buffer = NULL; unsigned short len = 0; if (parse_msg_group(client->max_length, group, &buffer, &len, room_id)) { ssize_t written; #ifdef WIN32 WriteFile(fd, buffer, len, &written, NULL); #else written = write(fd, buffer, len); #endif SYSLOG(LOG_INFO, "write local length: %ld", written); pool_room_free(&qtun->pool, *room_id); } else SYSLOG(LOG_WARNING, "Parse message error"); hash_del(&client->recv_table, (void*)(unsigned long)ident, sizeof(ident)); } break; } } return 1; }
void* group_pool_room_realloc(group_pool_t* p, void* ptr, size_t len) { group_pool_zone_t* zone = (group_pool_zone_t*)((char*)ptr - sizeof(group_pool_room_t*)); group_pool_room_t* node = zone->node; void* ret; if (node->capacity >= len) { node->length = len; return ptr; } ret = group_pool_room_alloc(p, len); if (ret == NULL) return NULL; memcpy(ret, ptr, node->length); group_pool_room_free(p, ptr); return ret; }
static void accept_and_check() { struct sockaddr_in srcaddr; socklen_t addrlen = sizeof(srcaddr); int fd = (int)accept(this.remotefd, (struct sockaddr*)&srcaddr, &addrlen); client_t* client; #ifdef WIN32 char flag = 1; #else int flag = 1; #endif hash_functor_t functor = { msg_ident_hash, msg_ident_compare, hash_dummy_dup, hash_dummy_dup, msg_group_free_hash, msg_group_free_hash_val }; if (fd == -1) return; if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)) == -1) { perror("setsockopt"); } client = malloc(sizeof(*client)); if (client == NULL) { SYSLOG(LOG_ERR, "Not enough memory"); close(fd); return; } client->remote_ip = srcaddr.sin_addr.s_addr; client->remote_port = srcaddr.sin_addr.s_addr; client->fd = fd; client->addr = srcaddr; client->keepalive = (unsigned int)time(NULL); client->status = CLIENT_STATUS_CHECKLOGIN | CLIENT_STATUS_WAITING_HEADER; client->want = sizeof(msg_t); client->buffer = client->read = group_pool_room_alloc(&this.group_pool, client->want); client->buffer_len = client->want; if (client->buffer == NULL) { SYSLOG(LOG_ERR, "Not enough memory"); free(client); close(fd); return; } if (!hash_init(&client->recv_table, functor, 11)) { SYSLOG(LOG_ERR, "hash_init failed"); group_pool_room_free(&this.group_pool, client->buffer); free(client); close(fd); return; } if (!active_vector_append(&this.clients, client, sizeof(*client))) { SYSLOG(LOG_ERR, "append to clients error"); free(client); close(fd); } }