Esempio n. 1
0
/* 向数据包队列中插入数据, 这些数据会按照数据包的结构, 即两个字节的长度紧跟着内容, 分析这些数据有多少个数据包.
 * 对于其中的完整数据包将插入到完整包队列中去, 对于其中不完整的包将插入到不完整数据包的哈希表中去. 特别是对于
 * 长度只有 1 个字节的不完整包, 此时已经无法计算出数据包的长度, 因而不完整数据包的 read 为 -1 , 而 header 为此一个字节值.
 * 当下一次套接字中接收到数据时会判断 read 的长度, 从而正确拼接数据包.
 *
 * 参数: L 是虚拟机栈; fd 是数据所属的套接字 id; buffer 是数据内容; size 是数据大小;
 * 函数无返回值 */
static void
push_more(lua_State *L, int fd, uint8_t *buffer, int size) {
	if (size == 1) {
		struct uncomplete * uc = save_uncomplete(L, fd);
		uc->read = -1;
		uc->header = *buffer;
		return;
	}
	int pack_size = read_size(buffer);
	buffer += 2;
	size -= 2;

	/* 虽然数据包的内容是不完整的, 但是给 pack.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;
	}
	push_data(L, fd, buffer, pack_size, 1);

	buffer += pack_size;
	size -= pack_size;
	if (size > 0) {
		push_more(L, fd, buffer, size);
	}
}
Esempio n. 2
0
/// 从 buffer 中读取数据. 如果 buffer 的数据足够, 那么数据内容会压入到 queue.queue 中; 否则会压入到 queue.hash 中.
static void
push_more(lua_State *L, int fd, uint8_t *buffer, int size) {
	// 如果连包头的数据都不足够, 那么先读取包头的第一个字节数据
	if (size == 1) {
		struct uncomplete * uc = save_uncomplete(L, fd);
		uc->read = -1;
		uc->header = *buffer;
		return;
	}

	// 读取数据包数据大小
	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;
	}

	// 如果数据内容能够完全读取, 那么读取数据, 并且压入到 queue.queue 中
	push_data(L, fd, buffer, pack_size, 1);

	// 继续读取剩余的函数
	buffer += pack_size;
	size -= pack_size;
	if (size > 0) {
		push_more(L, fd, buffer, size);
	}
}
Esempio n. 3
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;
	}
}
Esempio n. 4
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;
	}
}