Exemple #1
0
static void
_report(struct gate *g, struct skynet_context * ctx, const char * data, ...) {
	if (g->watchdog == 0) {
		return;
	}
	va_list ap;
	va_start(ap, data);
	char tmp[1024];
	int n = vsnprintf(tmp, sizeof(tmp), data, ap);
	va_end(ap);

	skynet_send(ctx, 0, g->watchdog, 0, tmp, n, 0);
}
static void
response(struct skynet_context *ctx, struct package *P) {
	while (!queue_empty(&P->request)) {
		if (queue_empty(&P->response)) {
			break;
		}
		struct request req;
		struct response resp;
		queue_pop(&P->request, &req);
		queue_pop(&P->response, &resp);
		skynet_send(ctx, 0, req.source, PTYPE_RESPONSE | PTYPE_TAG_DONTCOPY, req.session, resp.msg, resp.sz);
	}
}
Exemple #3
0
static int
_send(lua_State *L) {
	struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
	int session = 0;
	int index = 0;
	const char * dest = luaL_checkstring(L,1);

	if (lua_type(L,2) == LUA_TNUMBER) {
		session = lua_tointeger(L,2);
		++index;
	}
	if (lua_gettop(L) == index + 1) {
		session = skynet_send(context, dest, session , NULL, 0);
	} else {
		int type = lua_type(L,index+2);
		if (type == LUA_TSTRING) {
			size_t len = 0;
			void * msg = (void *)lua_tolstring(L,index+2,&len);
			void * message = malloc(len);
			memcpy(message, msg, len);
			session = skynet_send(context, dest, session , message, len);
		} else if (type == LUA_TNIL) {
			session = skynet_send(context, dest, session , NULL, 0);
		} else {
			void * msg = lua_touserdata(L,index+2);
			if (msg == NULL) {
				return luaL_error(L, "skynet.send need userdata or string (%s)", lua_typename(L,type));
			}
			int size = luaL_checkinteger(L,index+3);
			session = skynet_send(context, dest, session, msg, size);
		}
	}
	if (session < 0) {
		return luaL_error(L, "skynet.send drop the message to %s", dest);
	}
	lua_pushinteger(L,session);
	return 1;
}
Exemple #4
0
int
master_init(struct master *m, struct skynet_context *ctx, const char * args) {
	char tmp[strlen(args) + 32];
	sprintf(tmp,"gate L ! %s %d %d 0",args,PTYPE_HARBOR,REMOTE_MAX);
	const char * gate_addr = skynet_command(ctx, "LAUNCH", tmp);
	if (gate_addr == NULL) {
		skynet_error(ctx, "Master : launch gate failed");
		return 1;
	}
	uint32_t gate = strtoul(gate_addr+1, NULL, 16);
	if (gate == 0) {
		skynet_error(ctx, "Master : launch gate invalid %s", gate_addr);
		return 1;
	}
	const char * self_addr = skynet_command(ctx, "REG", NULL);
	int n = sprintf(tmp,"broker %s",self_addr);
	skynet_send(ctx, 0, gate, PTYPE_TEXT, 0, tmp, n);
	skynet_send(ctx, 0, gate, PTYPE_TEXT, 0, "start", 5);

	skynet_callback(ctx, m, _mainloop);

	return 0;
}
Exemple #5
0
static int
check_wsz(struct skynet_context *ctx, int id, void *buffer, int64_t wsz) {
	if (wsz < 0) {
		return -1;
	} else if (wsz > 1024 * 1024) {
		struct skynet_socket_message tmp;
		tmp.type = SKYNET_SOCKET_TYPE_WARNING;
		tmp.id = id;
		tmp.ud = (int)(wsz / 1024);
		tmp.buffer = NULL;
		skynet_send(ctx, 0, skynet_context_handle(ctx), PTYPE_SOCKET, 0 , &tmp, sizeof(tmp));
//		skynet_error(ctx, "%d Mb bytes on socket %d need to send out", (int)(wsz / (1024 * 1024)), id);
	}
	return 0;
}
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;
	}
}
Exemple #7
0
//初始化某个snlua服务,snlua在create时创建了一个lua虚拟机
//l, 服务实例
//ctx,与服务实例关联的一些上下文配置资源
//args,参数{通常为脚本名}
int
snlua_init(struct snlua *l, struct skynet_context *ctx, const char * args) {
	//复制参数
	int sz = strlen(args);
	char * tmp = skynet_malloc(sz);
	memcpy(tmp, args, sz);
	//设置启动回调
	skynet_callback(ctx, l , launch_cb);
	//注册一个服务名称,如果没用字符串,直接返回16进制格式返回服务":唯一ID"
	//否则注册一个字符串格式的名字
	const char * self = skynet_command(ctx, "REG", NULL);
	uint32_t handle_id = strtoul(self+1, NULL, 16);
	// it must be first message
	//由框架向目标服务handle_id投递一个消息,必须保证这是服务的接收的第一条消息, 消息的内容是调用参数{脚本名,session设置为0表示不需要回应}
	skynet_send(ctx, 0, handle_id, PTYPE_TAG_DONTCOPY,0, tmp, sz);
	return 0;
}
static void
report_info(struct skynet_context *ctx, struct package *P, int session, uint32_t source) {
	int uncomplete;
	int uncomplete_sz;
	if (P->header_sz != 0) {
		uncomplete = -1;
		uncomplete_sz = 0;
	} else if (P->uncomplete_sz == 0) {
		uncomplete = 0;
		uncomplete_sz = 0;
	} else {
		uncomplete = P->uncomplete_sz;
		uncomplete_sz = P->uncomplete.sz;
	}
	char tmp[128];
	int n = sprintf(tmp,"req=%d resp=%d uncomplete=%d/%d", queue_size(&P->request), queue_size(&P->response),uncomplete,uncomplete_sz);
	skynet_send(ctx, 0, source, PTYPE_RESPONSE, session, tmp, n);
}
Exemple #9
0
static void
_del(struct connection_server * server, int fd) {
	int i;
	for (i=0;i<server->max_connection;i++) {
		struct connection * c = &server->conn[i];
		if (c->fd == fd) {
			if (c->close == 0) {
				skynet_send(server->ctx, 0, c->address, PTYPE_CLIENT | PTYPE_TAG_DONTCOPY, 0, NULL, 0);
				connection_del(server->pool, fd);
			}
			c->address = 0;
			c->fd = 0;
			c->close = 0;
			close(fd);
			return;
		}
	}

	skynet_error(server->ctx, "[connection] Delete invalid handle %d", fd);
}
Exemple #10
0
static int
_cb(struct skynet_context * context, void * ud, int session, uint32_t source, const void * msg, size_t sz) {
	struct broker * b = ud;
	if (b->init < DEFAULT_NUMBER) {
		if (source != b->launcher)
			return 0;
		char addr[sz+1];
		memcpy(addr, msg, sz);
		addr[sz] = '\0';
		uint32_t address = strtoul(addr+1, NULL, 16);
		assert(address != 0);
		_init(b, session, address);
		if (b->init == DEFAULT_NUMBER) {
			skynet_command(context, "REG", b->name);
			skynet_send(context, 0, b->launcher, 0, NULL, 0, 0);
		}
	} else {
		_forward(b, context);
	}

	return 0;
}
Exemple #11
0
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 = ud;
	switch (type) {
	case PTYPE_HARBOR: {
		// remote message in
		const char * cookie = 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];
				memcpy(ip, msg, sz-12);
				ip[sz-11] = '\0';
				_update_remote_address(context, h, header.destination, ip);
			} else {
				// update global name
				if (sz - 12 > GLOBALNAME_LENGTH) {
					char name[sz-11];
					memcpy(name, msg, sz-12);
					name[sz-11] = '\0';
					skynet_error(context, "Global name is too long %s", name);
				}
				_update_remote_name(h, context, 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 = msg;
		assert (sz == sizeof(rmsg->destination));
		_remote_register_name(h, context, rmsg->destination.name, rmsg->destination.handle);
		return 0;
	}
	default: {
		// remote message out
		const struct remote_message *rmsg = msg;
		if (rmsg->destination.handle == 0) {
			if (_remote_send_name(h, context, source , rmsg->destination.name, type, session, rmsg->message, rmsg->sz)) {
				return 0;
			}
		} else {
			if (_remote_send_handle(h, context, source , rmsg->destination.handle, type, session, rmsg->message, rmsg->sz)) {
				return 0;
			}
		}
		free((void *)rmsg->message);
		return 0;
	}
	}
}
Exemple #12
0
/*
	unsigned address
	 string address
	integer type
	integer session
	string message
	 lightuserdata message_ptr
	 integer len
 */
static int
_send(lua_State *L) {
	struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1));
	int addr_type = lua_type(L,1);
	uint32_t dest = 0;
	switch(addr_type) {
	case LUA_TNUMBER:
		dest = lua_tounsigned(L,1);
		break;
	case LUA_TSTRING: {
		const char * addrname = lua_tostring(L,1);
		if (addrname[0] == '.' || addrname[0] == ':') {
			dest = skynet_queryname(context, addrname);
			if (dest == 0) {
				luaL_error(L, "Invalid name %s", addrname);
			}
		} else if ('0' <= addrname[0] && addrname[0] <= '9') {
			luaL_error(L, "Invalid name %s: must not start with a digit", addrname);
		} else {
			return _sendname(L, context, addrname);
		}
		break;
	}
	default:
		return luaL_error(L, "address must be number or string, got %s",lua_typename(L,addr_type));
	}

	int type = luaL_checkinteger(L, 2);
	int session = 0;
	if (lua_isnil(L,3)) {
		type |= PTYPE_TAG_ALLOCSESSION;
	} else {
		session = luaL_checkinteger(L,3);
	}

	int mtype = lua_type(L,4);
	switch (mtype) {
	case LUA_TSTRING: {
		size_t len = 0;
		void * msg = (void *)lua_tolstring(L,4,&len);
		if (len == 0) {
			msg = NULL;
		}
		session = skynet_send(context, 0, dest, type, session , msg, len);
		break;
	}
	case LUA_TLIGHTUSERDATA: {
		void * msg = lua_touserdata(L,4);
		int size = luaL_checkinteger(L,5);
		session = skynet_send(context, 0, dest, type | PTYPE_TAG_DONTCOPY, session, msg, size);
		break;
	}
	default:
		luaL_error(L, "skynet.send invalid param %s", lua_typename(L, lua_type(L,4)));
	}
	if (session < 0) {
		// send to invalid address
		// todo: maybe throw error is better
		return 0;
	}
	lua_pushinteger(L,session);
	return 1;
}
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;
	}
	}
}