Exemple #1
0
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);
}
Exemple #2
0
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);
}
Exemple #3
0
// 释放缓冲区池
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;
}
Exemple #4
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;
}
Exemple #5
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 ++;
}
Exemple #6
0
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;
}
Exemple #7
0
// 把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);
}
Exemple #8
0
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);
}
Exemple #9
0
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;
}
Exemple #10
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;
}
Exemple #11
0
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);
}
Exemple #14
0
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;
}
Exemple #18
0
void
skynet_handle_exit() {
	// todo : delete all the service
	skynet_free(G);
}
Exemple #19
0
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;
	}
}
Exemple #20
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;
	}
}
Exemple #21
0
void
dummy_release(struct dummy *d) {
	_hash_delete(d->map);
	skynet_free(d);
}
Exemple #22
0
void 
skynet_monitor_delete(struct skynet_monitor *sm) {
	// 释放内存资源
	skynet_free(sm);
}
void
snlua_release(struct snlua *l) {
	lua_close(l->L);
	skynet_free(l);
}
Exemple #24
0
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;
	}
}
Exemple #25
0
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;
	}
}
Exemple #26
0
//是否monitor
void skynet_monitor_delete(struct skynet_monitor *sm)
{
	skynet_free(sm);
}
Exemple #27
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;
	}
}
Exemple #28
0
static __inline void
buffer_destroy(struct buffer *b) {
	if (b->ptr != b->buffer) {
		skynet_free(b->ptr);
	}
}