Exemplo n.º 1
0
/* 删除与套接字 fd 相关的不完整的数据包. 这个函数只会在套接字发生错误或者关闭时调用.
 * 参数: L 是 Lua 虚拟机栈, 其位置一就是 queue 数据结构; fd 是套接字 id; */
static void
close_uncomplete(lua_State *L, int fd) {
	struct queue *q = lua_touserdata(L,1);
	struct uncomplete * uc = find_uncomplete(q, fd);
	if (uc) {
		skynet_free(uc->pack.buffer);
		skynet_free(uc);
	}
}
Exemplo n.º 2
0
/* [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;
	}
}
Exemplo n.º 3
0
/// 从 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;
	}
}