Exemple #1
0
// mainloop thread
static void
forward_message(int type, bool padding, struct socket_message * result) {
	struct skynet_socket_message *sm;
	int sz = sizeof(*sm);
	if (padding) {
		if (result->data) {
			sz += strlen(result->data);
		} else {
			result->data = "";
		}
	}
	sm = (struct skynet_socket_message *)skynet_malloc(sz);
	sm->type = type;
	sm->id = result->id;
	sm->ud = result->ud;
	if (padding) {
		sm->buffer = NULL;
		memcpy(sm+1, result->data, sz - sizeof(*sm));
	} else {
		sm->buffer = result->data;
	}

	struct skynet_message message;
	message.source = 0;
	message.session = 0;
	message.data = sm;
	message.sz = sz | PTYPE_SOCKET << HANDLE_REMOTE_SHIFT;
	
	if (skynet_context_push((uint32_t)result->opaque, &message)) {
		// todo: report somewhere to close socket
		// don't call skynet_socket_close here (It will block mainloop)
		skynet_free(sm->buffer);
		skynet_free(sm);
	}
}
Exemple #2
0
void
skynet_error(struct skynet_context * context, const char *msg, ...)
{
	static uint32_t logger = 0;
	if (logger == 0)
	{
		logger = skynet_handle_findname("logger");
	}
	if (logger == 0)
	{
		return;
	}

	char tmp[LOG_MESSAGE_SIZE];
	char *data = NULL;

	va_list ap;

	va_start(ap, msg);
	int len = vsnprintf(tmp, LOG_MESSAGE_SIZE, msg, ap);
	va_end(ap);
	if (len < LOG_MESSAGE_SIZE)
	{
		data = skynet_strdup(tmp);
	}
	else
	{
		int max_size = LOG_MESSAGE_SIZE;
		for (;;)
		{
			max_size *= 2;
			data = skynet_malloc(max_size);
			va_start(ap, msg);
			len = vsnprintf(data, max_size, msg, ap);
			va_end(ap);
			if (len < max_size)
			{
				break;
			}
			skynet_free(data);
		}
	}


	struct skynet_message smsg;
	if (context == NULL)
	{
		smsg.source = 0;
	}
	else
	{
		smsg.source = skynet_context_handle(context);
	}
	smsg.session = 0;
	smsg.data = data;
	smsg.sz = len | (PTYPE_TEXT << HANDLE_REMOTE_SHIFT);
	skynet_context_push(logger, &smsg);
}
Exemple #3
0
static void 
timer_execute(struct timer *T)
{
	while (__sync_lock_test_and_set(&T->lock,1)) {};
	int idx=T->time & TIME_NEAR_MASK;
	struct timer_node *current;
	int mask,i,time;
	
	while (T->near[idx].head.next) {
		current=link_clear(&T->near[idx]);
		
		do {
			struct timer_event * event = (struct timer_event *)(current+1);
			struct skynet_message message;
			message.source = SKYNET_SYSTEM_TIMER;
			message.session = event->session;
			message.data = NULL;
			message.sz = 0;

			skynet_context_push(event->handle, &message);
			
			struct timer_node * temp = current;
			current=current->next;
			free(temp);	
		} while (current);
	}
	
	++T->time;
	
	mask = TIME_NEAR;
	time = T->time >> TIME_NEAR_SHIFT;
	i=0;
	
	while ((T->time & (mask-1))==0) {
		idx=time & TIME_LEVEL_MASK;
		if (idx!=0) {
			--idx;
			current=link_clear(&T->t[i][idx]);
			while (current) {
				struct timer_node *temp=current->next;
				add_node(T,current);
				current=temp;
			}
			break;				
		}
		mask <<= TIME_LEVEL_SHIFT;
		time >>= TIME_LEVEL_SHIFT;
		++i;
	}	
	__sync_lock_release(&T->lock);
}
Exemple #4
0
/* 分发整个定时触发列表中的定时事件, 此函数要求列表中至少有一个定时事件节点.
 * 投递的消息类型为 PTYPE_RESPONSE, session 为注册定时器时传入的值,
 * 到 handle 也为注册定时器时传入的值为地址的服务中去.
 * 此函数同时负责将回收为 struct timer_node 结构分配的内存. */
static inline void
dispatch_list(struct timer_node *current) {
	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 = (size_t)PTYPE_RESPONSE << MESSAGE_TYPE_SHIFT;

		skynet_context_push(event->handle, &message);
		
		struct timer_node * temp = current;
		current=current->next;
		skynet_free(temp);	
	} while (current);
}
Exemple #5
0
int
skynet_timeout(uint32_t handle, int time, int session) {
	if (time == 0) {
		struct skynet_message message;
		message.source = SKYNET_SYSTEM_TIMER;
		message.session = session;
		message.data = NULL;
		message.sz = 0;

		if (skynet_context_push(handle, &message)) {
			return -1;
		}
	} else {
		struct timer_event event;
		event.handle = handle;
		event.session = session;
		timer_add(TI, &event, sizeof(event), time);
	}

	return session;
}
Exemple #6
0
/* 为一个服务的某次会话注册一个定时器事件. 如果传入的时间小于等于 0 将会立即发送
 * 类型为 PTYPE_RESPONSE 的消息给该服务会话, 否则将以线程安全的方式添加到触发列表集中.
 * 参数 handle 是服务地址, time 是距离现在的触发时间单位是厘秒, session 是服务中的会话.
 * 此函数是线程安全的. */
int
skynet_timeout(uint32_t handle, int time, int session) {
	if (time <= 0) {
		struct skynet_message message;
		message.source = 0;
		message.session = session;
		message.data = NULL;
		message.sz = (size_t)PTYPE_RESPONSE << MESSAGE_TYPE_SHIFT;

		if (skynet_context_push(handle, &message)) {
			return -1;
		}
	} else {
		struct timer_event event;
		event.handle = handle;
		event.session = session;
		timer_add(TI, &event, sizeof(event), time);
	}

	return session;
}
Exemple #7
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);
	}
}