static void return_free_node(lua_State *L, int pool, struct socket_buffer *sb) { struct buffer_node *free_node = sb->head; sb->offset = 0; sb->head = free_node->next; if (sb->head == NULL) { sb->tail = NULL; } lua_rawgeti(L,pool,1); free_node->next = lua_touserdata(L,-1); lua_pop(L,1); skynet_free(free_node->msg); free_node->msg = NULL; free_node->sz = 0; lua_pushlightuserdata(L, free_node); lua_rawseti(L, pool, 1); }
void skynet_mq_pushmt(struct skynet_mq *mq, struct skynet_message_package *pack) { struct skynet_mq expand; if (perpare_space(mq, &expand)) { rwlock_wlock(&mq->lock); void * ptr = mq->q; if (mq->head < expand.head) { // the head changes (some one pop in another thread) between perpare_space and rwlock_wlock mq->head += mq->cap; } mq->q = expand.q; mq->cap = expand.cap; mq->tail = expand.tail; rwlock_wunlock(&mq->lock); skynet_free(ptr); } push_message(mq, pack); }
// 释放缓冲区池 static int lfreepool(lua_State *L) { // 获取第一个参数,缓冲区池 struct buffer_node * pool = lua_touserdata(L, 1); // lua_rawlen 获取该用户数据分配的内存块的大小 // sizeof(*pool) 为单个buffer_node结构占用内存块大小 // sz 为缓冲池的长度 int sz = lua_rawlen(L,1) / sizeof(*pool); int i; // 遍历 for (i=0;i<sz;i++) { struct buffer_node *node = &pool[i]; if (node->msg) { skynet_free(node->msg); node->msg = NULL; } } return 0; }
static int ltrash(lua_State *L) { int t = lua_type(L,1); switch (t) { case LUA_TSTRING: { break; } case LUA_TLIGHTUSERDATA: { void * msg = lua_touserdata(L,1); luaL_checkinteger(L,2); skynet_free(msg); break; } default: luaL_error(L, "skynet.trash invalid param %s", lua_typename(L,t)); } return 0; }
/** * 存储 name, handle 在 before 位置 * @param s handle_storage * @param name 名字 * @param handle handle * @param before 插入的位置 */ static void _insert_name_before(struct handle_storage *s, char *name, uint32_t handle, int before) { // 如果当前的数量已经满了, 那么需要分配新的空间 if (s->name_count >= s->name_cap) { // 扩大两倍 s->name_cap *= 2; assert(s->name_cap <= MAX_SLOT_SIZE); // 申请新的内存空间 struct handle_name * n = skynet_malloc(s->name_cap * sizeof(struct handle_name)); // 将 before 之前的数据复制 int i; for (i=0;i<before;i++) { n[i] = s->name[i]; } // 将 before 之后的数据复制 for (i=before;i<s->name_count;i++) { n[i+1] = s->name[i]; } // 释放掉之前的内存空间 skynet_free(s->name); // 保留新的内存空间 s->name = n; } else { // 移动 before 之后的数据 int i; for (i=s->name_count;i>before;i--) { s->name[i] = s->name[i-1]; } } // 在 before 位置插入数据 s->name[before].name = name; s->name[before].handle = handle; s->name_count ++; }
static void push_queue_msg(struct msg_queue * queue, struct msg * m) { // If there is only 1 free slot which is reserved to distinguish full/empty // of circular buffer, expand it. if (((queue->tail + 1) % queue->size) == queue->head) { struct msg * new_buffer = skynet_malloc(queue->size * 2 * sizeof(struct msg)); int i; for (i=0;i<queue->size-1;i++) { new_buffer[i] = queue->data[(i+queue->head) % queue->size]; } skynet_free(queue->data); queue->data = new_buffer; queue->head = 0; queue->tail = queue->size - 1; queue->size *= 2; } struct msg * slot = &queue->data[queue->tail]; *slot = *m; queue->tail = (queue->tail + 1) % queue->size; }
// 把lua table连接成字符串 static void concat_table(lua_State *L, int index, void *buffer, size_t tlen) { char *ptr = buffer; int i; for (i=1;lua_geti(L, index, i) != LUA_TNIL; ++i) { size_t len; const char * str = lua_tolstring(L, -1, &len); if (str == NULL || tlen < len) { break; } memcpy(ptr, str, len); ptr += len; tlen -= len; lua_pop(L,1); } if (tlen != 0) { skynet_free(buffer); luaL_error(L, "Invalid strings table"); } lua_pop(L,1); }
void skynet_mq_releasefixed(struct skynet_mq_fixed *mq) { int head = mq->head; int tail = mq->tail; if (tail < head) { tail += MQ_LENGTH; } while(head < tail) { int index = head; if (index >= MQ_LENGTH) { index -= MQ_LENGTH; } struct skynet_message_package *pack = &mq->q[head]; if (pack->msg) { skynet_message_release(pack->msg); } ++head; } spin_lock_destory(mq); skynet_free(mq); }
static int lclear(lua_State *L) { struct queue * q = lua_touserdata(L, 1); if (q == NULL) { return 0; } int i; for (i=0;i<HASHSIZE;i++) { clear_list(q->hash[i]); q->hash[i] = NULL; } if (q->head > q->tail) { q->tail += q->cap; } for (i=q->head;i<q->tail;i++) { struct netpack *np = &q->queue[i % q->cap]; skynet_free(np->buffer); } q->head = q->tail = 0; return 0; }
int skynet_handle_retire(uint32_t handle) { int ret = 0; struct handle_storage *s = H; rwlock_wlock(&s->lock); uint32_t hash = handle & (s->slot_size-1); struct skynet_context * ctx = s->slot[hash]; if (ctx != NULL && skynet_context_handle(ctx) == handle) { s->slot[hash] = NULL; ret = 1; int i; int j=0, n=s->name_count; for (i=0; i<n; ++i) { if (s->name[i].handle == handle) { skynet_free(s->name[i].name); continue; } else if (i!=j) { s->name[j] = s->name[i]; } ++j; } s->name_count = j; } else { ctx = NULL; } rwlock_wunlock(&s->lock); if (ctx) { // release ctx may call skynet_handle_* , so wunlock first. skynet_context_release(ctx); } return ret; }
static inline void timer_execute(struct timer *T) { int idx = T->time & TIME_NEAR_MASK; while (T->near[idx].head.next) { struct timer_node *current = link_clear(&T->near[idx]); do { struct timer_event * event = (struct timer_event *)(current+1); struct skynet_message message; message.source = 0; message.session = event->session; message.data = NULL; message.sz = PTYPE_RESPONSE << HANDLE_REMOTE_SHIFT; skynet_context_push(event->handle, &message); struct timer_node * temp = current; current=current->next; skynet_free(temp); } while (current); } }
static void socket_message(struct skynet_context *ctx, struct package *P, const struct skynet_socket_message * smsg) { switch (smsg->type) { case SKYNET_SOCKET_TYPE_CONNECT: if (P->init == 0 && smsg->id == P->fd) { skynet_send(ctx, 0, P->manager, PTYPE_TEXT, 0, "SUCC", 4); P->init = 1; } break; case SKYNET_SOCKET_TYPE_CLOSE: case SKYNET_SOCKET_TYPE_ERROR: if (P->init == 0 && smsg->id == P->fd) { skynet_send(ctx, 0, P->manager, PTYPE_TEXT, 0, "FAIL", 4); P->init = 1; } if (smsg->id != P->fd) { skynet_error(ctx, "Invalid fd (%d), should be (%d)", smsg->id, P->fd); } else { // todo: log when SKYNET_SOCKET_TYPE_ERROR response(ctx, P); service_exit(ctx, P); } break; case SKYNET_SOCKET_TYPE_DATA: new_message(P, (const uint8_t *)smsg->buffer, smsg->ud); skynet_free(smsg->buffer); response(ctx, P); break; case SKYNET_SOCKET_TYPE_WARNING: skynet_error(ctx, "Overload on %d", P->fd); break; default: // ignore break; } }
static void _push_queue(struct msg_queue * queue, const void * buffer, size_t sz, struct remote_message_header * header) { // If there is only 1 free slot which is reserved to distinguish full/empty // of circular buffer, expand it. if (((queue->tail + 1) % queue->size) == queue->head) { struct msg * new_buffer = (struct msg*)skynet_malloc(queue->size * 2 * sizeof(struct msg)); int i; for (i=0;i<queue->size-1;i++) { new_buffer[i] = queue->data[(i+queue->head) % queue->size]; } skynet_free(queue->data); queue->data = new_buffer; queue->head = 0; queue->tail = queue->size - 1; queue->size *= 2; } struct msg * slot = &queue->data[queue->tail]; queue->tail = (queue->tail + 1) % queue->size; slot->buffer = (uint8_t *)skynet_malloc(sz + sizeof(*header)); memcpy(slot->buffer, buffer, sz); memcpy(slot->buffer + sz, header, sizeof(*header)); slot->size = sz + sizeof(*header); }
static void _release(struct message_queue *q) { skynet_free(q->queue); skynet_free(q); }
/// 删除监视 /// \param[in] *sm 监视的结构 /// \return void void skynet_monitor_delete(struct skynet_monitor *sm) { skynet_free(sm); // 释放结构分配的内存 }
static int _mainloop(struct skynet_context * context, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) { struct harbor * h = (struct harbor *)ud; switch (type) { case PTYPE_SOCKET: { const struct skynet_socket_message * message = (const struct skynet_socket_message *)msg; switch(message->type) { case SKYNET_SOCKET_TYPE_DATA: skynet_free(message->buffer); skynet_error(context, "recv invalid socket message (size=%d)", message->ud); break; case SKYNET_SOCKET_TYPE_ACCEPT: skynet_error(context, "recv invalid socket accept message"); break; case SKYNET_SOCKET_TYPE_ERROR: case SKYNET_SOCKET_TYPE_CLOSE: close_harbor(h, message->id); break; case SKYNET_SOCKET_TYPE_CONNECT: open_harbor(h, message->id); break; } return 0; } case PTYPE_HARBOR: { // remote message in const char * cookie = (const char *)msg; cookie += sz - 12; struct remote_message_header header; _message_to_header((const uint32_t *)cookie, &header); if (header.source == 0) { if (header.destination < REMOTE_MAX) { // 1 byte harbor id (0~255) // update remote harbor address //char ip [sz - 11]; char ip [100]; memcpy(ip, msg, sz-12); ip[sz-11] = '\0'; _update_remote_address(h, header.destination, ip); } else { // update global name if (sz - 12 > GLOBALNAME_LENGTH) { //char name[sz-11]; char name[100]; memcpy(name, msg, sz-12); name[sz-11] = '\0'; skynet_error(context, "Global name is too long %s", name); } _update_remote_name(h, (const char*)msg, header.destination); } } else { uint32_t destination = header.destination; int type = (destination >> HANDLE_REMOTE_SHIFT) | PTYPE_TAG_DONTCOPY; destination = (destination & HANDLE_MASK) | ((uint32_t)h->id << HANDLE_REMOTE_SHIFT); skynet_send(context, header.source, destination, type, (int)header.session, (void *)msg, sz-12); return 1; } return 0; } case PTYPE_SYSTEM: { // register name message const struct remote_message *rmsg = (const struct remote_message *)msg; assert (sz == sizeof(rmsg->destination)); _remote_register_name(h, rmsg->destination.name, rmsg->destination.handle); return 0; } default: { // remote message out const struct remote_message *rmsg = (const struct remote_message *)msg; if (rmsg->destination.handle == 0) { if (_remote_send_name(h, source , rmsg->destination.name, type, session, (const char*)rmsg->message, rmsg->sz)) { return 0; } } else { if (_remote_send_handle(h, source , rmsg->destination.handle, type, session, (const char *)rmsg->message, rmsg->sz)) { return 0; } } skynet_free((void *)rmsg->message); return 0; } } }
static void queue_exit(struct queue *q) { skynet_free(q->buffer); q->buffer = NULL; }
void skynet_handle_exit() { // todo : delete all the service skynet_free(G); }
uint32_t skynet_handle_register(struct skynet_context *ctx) { struct handle_storage *s = H; // 线程上锁, 保证线程安全 rwlock_wlock(&s->lock); for (;;) { // 注意, 这里是一个无限循环, 必须拿到一个可用的 handle int i; // 从头开始循环遍历 for (i=0;i<s->slot_size;i++) { uint32_t handle = (i+s->handle_index) & HANDLE_MASK; // 获得从右到左 3 个字节的数据, 最左的低 4 个字节(高 8 位)用来表示 harbor int hash = handle & (s->slot_size-1); // 获得实际的索引, hash 的值不超出 slot_size 的范围 // 当有可用的 slot 放入 ctx if (s->slot[hash] == NULL) { // 记录注册的 ctx s->slot[hash] = ctx; // handle_index 自增 s->handle_index = handle + 1; // 已经存储了 ctx 了, 可以解锁让其他线程使用了 rwlock_wunlock(&s->lock); // 新的 handle 需要使用高 8 位记录当前 handle 所属的 harbor handle |= s->harbor; return handle; } } // 当前进程不能超过 HANDLE_MASK 的数量 assert((s->slot_size*2 - 1) <= HANDLE_MASK); // 如果没有可用的空间, 扩展容量 // 申请新的内存空间, slot_size * 2 struct skynet_context ** new_slot = skynet_malloc(s->slot_size * 2 * sizeof(struct skynet_context *)); // 重置内存数据 memset(new_slot, 0, s->slot_size * 2 * sizeof(struct skynet_context *)); // 将原来的内容进行复制 for (i = 0; i < s->slot_size; i++) { // 获得在当前分配的空间中可用的索引, 注意这里是使用 (slot_size * 2 - 1) 在进行为操作. int hash = skynet_context_handle(s->slot[i]) & (s->slot_size * 2 - 1); assert(new_slot[hash] == NULL); // 这里为什么不是直接 new_slot[i] = s->slot[i] 呢, 而要绕个弯拿到 hash, 然后 new_slot[hash] = s->slot[i] // 解答, 很有意思的小细节: // 首先说 handle_index 从 1 开始计数, 而且都是不断的增加, 返回的时候使用的是 return handle |= s->harbor; 这就决定了返回值不会为 0 // 在上面的查询 slot, 并且分配 handle 的过程中, 索引是 hash, 返回值是 handle, handle 可以大于 slot_size. // 这里获得的 hash 可以是大于 slot_size 的, 那么现在可以举例: hash = 4, i = 0 // new_slot[4] = s->slot[0], 如果使用 new_slot[i] = s->slot[i] 这种方式, 那么对于结果上来说是没有什么影响的, 但是会出现这样一种情况: // 例如: 原来的 slot_size 是 7, 这时 handle_index 16, 全部的 slot 正在被使用. 那么现在需要扩展空间, slot_size 扩展到 16, 那么现在来看看 // new_slot 的分配情况是如何的: // 原来的 slot 是 [0, slot1, slot2, slot3, slot4, slot5, slot6, slot7] // 现在的 slot 是 [0, 0, 0, 0, 0, 0, 0, 0, 0, slot1, slot2, slot3, slot4, slot5, slot6, slot7] new_slot[hash] = s->slot[i]; } // 释放之前的数据 skynet_free(s->slot); // 记录新的数据 s->slot = new_slot; s->slot_size *= 2; } }
/// 从 buffer 读取数据, 返回 lua 函数返回值的个数, 函数的第一个返回值是 queue. static int filter_data_(lua_State *L, int fd, uint8_t * buffer, int size) { struct queue *q = lua_touserdata(L, 1); struct uncomplete * uc = find_uncomplete(q, fd); // 注意, 这里将 uncomplete 从 queue.hash 中移除了 if (uc) { // fill uncomplete // 填充 uncomplete if (uc->read < 0) { // 当包头还未完整读取的情况 // read size assert(uc->read == -1); // 获得数据内容大小 int pack_size = *buffer; pack_size |= uc->header << 8 ; // 偏移到实际数据内容指针开始位置 ++buffer; // 实际的数据内容大小 --size; uc->pack.size = pack_size; // 记录实际需要读取的内容大小 uc->pack.buffer = skynet_malloc(pack_size); // 分配内存空间 uc->read = 0; // 标记还未开始读取数据内容 } // 计算需要读取的数据 int need = uc->pack.size - uc->read; if (size < need) { // 如果 buffer 待读取的数据还不足, 尽可能读取能够读取的数据 // 读取可读的数据 memcpy(uc->pack.buffer + uc->read, buffer, size); uc->read += size; // 再次压入到 queue.hash 中 int h = hash_fd(fd); uc->next = q->hash[h]; q->hash[h] = uc; return 1; } // 读取完整的数据内容 memcpy(uc->pack.buffer + uc->read, buffer, need); // 跳过已经读取的内容 buffer += need; // 计算剩余的可读取数据大小 size -= need; // buffer 中的数据恰好足够读取 if (size == 0) { lua_pushvalue(L, lua_upvalueindex(TYPE_DATA)); // macro TYPE_DATA lua_pushinteger(L, fd); // socket id lua_pushlightuserdata(L, uc->pack.buffer); // buffer lua_pushinteger(L, uc->pack.size); // buffer size skynet_free(uc); return 5; } // more data // buffer 有更多的数据可读, 将数据压入 queue.queue 中 push_data(L, fd, uc->pack.buffer, uc->pack.size, 0); skynet_free(uc); push_more(L, fd, buffer, size); // 继续读取剩下的数据 lua_pushvalue(L, lua_upvalueindex(TYPE_MORE)); // macro TYPE_MORE return 2; } else { if (size == 1) { // 仅读取包头的 1 个数据 struct uncomplete * uc = save_uncomplete(L, fd); uc->read = -1; uc->header = *buffer; return 1; } // 读取包头的数据 int pack_size = read_size(buffer); buffer+=2; size-=2; // 如果 buffer 的数据不够读, 将 buffer 数据全部读取 if (size < pack_size) { struct uncomplete * uc = save_uncomplete(L, fd); uc->read = size; uc->pack.size = pack_size; uc->pack.buffer = skynet_malloc(pack_size); memcpy(uc->pack.buffer, buffer, size); return 1; } // 如果 buffer 的数据恰好是 1 个包的数据大小, 将 buffer 数据全部读取 if (size == pack_size) { // just one package lua_pushvalue(L, lua_upvalueindex(TYPE_DATA)); // macro TYPE_DATA lua_pushinteger(L, fd); // socket id void * result = skynet_malloc(pack_size); memcpy(result, buffer, size); lua_pushlightuserdata(L, result); // buffer lua_pushinteger(L, size); // buffer size return 5; } // more data // 如果 buffer 的数据大于 1 个包的数据大小, 那么继续读取 buffer 里面的数据 push_data(L, fd, buffer, pack_size, 1); buffer += pack_size; size -= pack_size; push_more(L, fd, buffer, size); lua_pushvalue(L, lua_upvalueindex(TYPE_MORE)); // macro TYPE_MORE return 2; } }
void dummy_release(struct dummy *d) { _hash_delete(d->map); skynet_free(d); }
void skynet_monitor_delete(struct skynet_monitor *sm) { // 释放内存资源 skynet_free(sm); }
void snlua_release(struct snlua *l) { lua_close(l->L); skynet_free(l); }
static void dispatch_socket_msg(struct otu *u, const struct skynet_socket_message * message, int sz) { struct skynet_context * ctx = u->ctx; switch(message->type) { case SKYNET_SOCKET_TYPE_CONNECT: { assert (message->id == u->service_id); break; } case SKYNET_SOCKET_TYPE_UDP: { char* pkt = message->buffer; int pkt_sz = message->ud; int addr_sz = 0; const char * addr = skynet_socket_udp_address(message, &addr_sz); char* last_err = NULL; //Ver len check if(pkt_sz < sizeof(ot_pkt_hdr_t)){ last_err = "1.ShortHdr."; goto exit_drop; } ot_pkt_hdr_t *hdr = (ot_pkt_hdr_t *)pkt; u16_t hdr_len = ntohs(hdr->len); if(hdr_len > pkt_sz || hdr_len < sizeof(ot_pkt_hdr_t) || hdr_len > OT_PACKET_SIZE_MAX){ //len check last_err = "2.HdrLenErr."; goto exit_drop; } if(hdr->proto_ver != OT_PROTO_VER_V3A){ last_err = "3.HdrVerErr."; goto exit_drop; } #define HDR_ONLY (hdr_len == sizeof(ot_pkt_hdr_t)) #define DID_IS_BROADCAST (IS_ALL_FF(hdr->did.byte, sizeof(hdr->did.byte))) if(HDR_ONLY){ //时间戳请求处理 if(DID_IS_BROADCAST){ hdr->ts = htonl(skynet_now()/100 + skynet_starttime()); //int err = skynet_socket_udp_send(ctx, message->id, addr, pkt, pkt_sz); } //保活 else { uint64_t did64 = ntohll(hdr->did.u64); int idx = hashid64_lookup(&u->hash, did64); if (idx >= 0) { struct udp_peer *p = &u->peer[idx]; (void)p; //dispatch_msg(u, p, message->id, message->buffer, message->ud); goto exit_drop; } else { //todo 提交DID未知请求 goto exit_drop; } } } break; //get key, decrypt packet. //dispatch_msg exit_drop: skynet_free(message->buffer); break; } default: skynet_error(ctx, "OTU: unknown type(%d)", message->type); break; } }
static void dispatch_socket_message(struct gate *g, const struct skynet_socket_message * message, int sz) { struct skynet_context * ctx = g->ctx; switch(message->type) { case SKYNET_SOCKET_TYPE_DATA: { int id = hashid_lookup(&g->hash, message->id); if (id>=0) { struct connection *c = &g->conn[id]; dispatch_message(g, c, message->id, message->buffer, message->ud); } else { skynet_error(ctx, "Drop unknown connection %d message", message->id); skynet_socket_close(ctx, message->id); skynet_free(message->buffer); } break; } case SKYNET_SOCKET_TYPE_CONNECT: { if (message->id == g->listen_id) { // start listening break; } int id = hashid_lookup(&g->hash, message->id); if (id<0) { skynet_error(ctx, "Close unknown connection %d", message->id); skynet_socket_close(ctx, message->id); } break; } case SKYNET_SOCKET_TYPE_CLOSE: case SKYNET_SOCKET_TYPE_ERROR: { int id = hashid_remove(&g->hash, message->id); if (id>=0) { struct connection *c = &g->conn[id]; databuffer_clear(&c->buffer,&g->mp); memset(c, 0, sizeof(*c)); c->id = -1; _report(g, "%d close", message->id); } break; } case SKYNET_SOCKET_TYPE_ACCEPT: // report accept, then it will be get a SKYNET_SOCKET_TYPE_CONNECT message assert(g->listen_id == message->id); if (hashid_full(&g->hash)) { skynet_socket_close(ctx, message->ud); } else { struct connection *c = &g->conn[hashid_insert(&g->hash, message->ud)]; if (sz >= sizeof(c->remote_name)) { sz = sizeof(c->remote_name) - 1; } c->id = message->ud; memcpy(c->remote_name, message+1, sz); c->remote_name[sz] = '\0'; _report(g, "%d open %d %s:0",c->id, c->id, c->remote_name); skynet_error(ctx, "socket open: %x", c->id); } break; case SKYNET_SOCKET_TYPE_WARNING: skynet_error(ctx, "fd (%d) send buffer (%d)K", message->id, message->ud); break; } }
//是否monitor void skynet_monitor_delete(struct skynet_monitor *sm) { skynet_free(sm); }
/* [lua_api] 将套接字发送过来的数据返回给 Lua 层使用. 函数首先将检查 queue 的不完整数据包哈希表中是否存在套接字 fd 的 * 不完整数据包, 如果有则检查其已经读取的内容长度, 并将剩余部分复制过去, 如果刚好是一个数据包大小就直接返回 "data" 字符 * 串和数据包给 Lua 层, 如果复制后多于一个数据包, 则将这些数据包一起插入到 queue 中, 并返回 "more" 字符串给 Lua 层. * 在不足一个数据包的情况下, 将不完整包重新插入到哈希表中. 对于之前没有不完整包的情况执行相同的流程. 当返回 "more" 时, * 可以通过 lpop 函数取得 queue 中的数据包. buffer 中的内容会复制到新的内存块中, 因而在调用完此函数之后需要释放 buffer 的内存; * * 参数: L 是虚拟机栈, 其位置一就是 queue 数据结构; fd 是套接字 id; buffer 是数据内容; size 是数据大小; * * 返回: userdata[1] 为 queue 数据结构; string/nil[2] 为 "more" 或者 "data" 表示有数据, nil 表示数据不完整; * int[3] 为套接字 id, 仅在 "data" 下返回; lightuserdata[4] 为数据内容, 仅在 "data" 下返回; * int[5] 为数据大小, 仅在 "data" 下返回; */ static int filter_data_(lua_State *L, int fd, uint8_t * buffer, int size) { struct queue *q = lua_touserdata(L,1); struct uncomplete * uc = find_uncomplete(q, fd); if (uc) { // fill uncomplete if (uc->read < 0) { // read size assert(uc->read == -1); int pack_size = *buffer; pack_size |= uc->header << 8 ; ++buffer; --size; uc->pack.size = pack_size; uc->pack.buffer = skynet_malloc(pack_size); uc->read = 0; } int need = uc->pack.size - uc->read; if (size < need) { memcpy(uc->pack.buffer + uc->read, buffer, size); uc->read += size; int h = hash_fd(fd); uc->next = q->hash[h]; q->hash[h] = uc; return 1; } memcpy(uc->pack.buffer + uc->read, buffer, need); buffer += need; size -= need; if (size == 0) { lua_pushvalue(L, lua_upvalueindex(TYPE_DATA)); lua_pushinteger(L, fd); lua_pushlightuserdata(L, uc->pack.buffer); lua_pushinteger(L, uc->pack.size); skynet_free(uc); return 5; } // more data push_data(L, fd, uc->pack.buffer, uc->pack.size, 0); skynet_free(uc); push_more(L, fd, buffer, size); lua_pushvalue(L, lua_upvalueindex(TYPE_MORE)); return 2; } else { if (size == 1) { struct uncomplete * uc = save_uncomplete(L, fd); uc->read = -1; uc->header = *buffer; return 1; } int pack_size = read_size(buffer); buffer+=2; size-=2; if (size < pack_size) { struct uncomplete * uc = save_uncomplete(L, fd); uc->read = size; uc->pack.size = pack_size; uc->pack.buffer = skynet_malloc(pack_size); memcpy(uc->pack.buffer, buffer, size); return 1; } if (size == pack_size) { // just one package lua_pushvalue(L, lua_upvalueindex(TYPE_DATA)); lua_pushinteger(L, fd); void * result = skynet_malloc(pack_size); memcpy(result, buffer, size); lua_pushlightuserdata(L, result); lua_pushinteger(L, size); return 5; } // more data push_data(L, fd, buffer, pack_size, 1); buffer += pack_size; size -= pack_size; push_more(L, fd, buffer, size); lua_pushvalue(L, lua_upvalueindex(TYPE_MORE)); return 2; } }
static __inline void buffer_destroy(struct buffer *b) { if (b->ptr != b->buffer) { skynet_free(b->ptr); } }