#include "skynet.h" #include "skynet_socket.h" #include "socket_server.h" #include "skynet_server.h" #include "skynet_mq.h" #include "skynet_harbor.h" #include #include #include #include static struct socket_server * SOCKET_SERVER = NULL; void skynet_socket_init() { SOCKET_SERVER = socket_server_create(skynet_now()); } void skynet_socket_exit() { socket_server_exit(SOCKET_SERVER); } void skynet_socket_free() { socket_server_release(SOCKET_SERVER); SOCKET_SERVER = NULL; } void skynet_socket_updatetime() { socket_server_updatetime(SOCKET_SERVER, skynet_now()); } // mainloop thread static void forward_message(int type, bool padding, struct socket_message * result) { struct skynet_socket_message *sm; size_t sz = sizeof(*sm); if (padding) { if (result->data) { size_t msg_sz = strlen(result->data); if (msg_sz > 128) { msg_sz = 128; } sz += msg_sz; } 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 | ((size_t)PTYPE_SOCKET << MESSAGE_TYPE_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); } } int skynet_socket_poll() { struct socket_server *ss = SOCKET_SERVER; assert(ss); struct socket_message result; int more = 1; int type = socket_server_poll(ss, &result, &more); switch (type) { case SOCKET_EXIT: return 0; case SOCKET_DATA: forward_message(SKYNET_SOCKET_TYPE_DATA, false, &result); break; case SOCKET_CLOSE: forward_message(SKYNET_SOCKET_TYPE_CLOSE, false, &result); break; case SOCKET_OPEN: forward_message(SKYNET_SOCKET_TYPE_CONNECT, true, &result); break; case SOCKET_ERR: forward_message(SKYNET_SOCKET_TYPE_ERROR, true, &result); break; case SOCKET_ACCEPT: forward_message(SKYNET_SOCKET_TYPE_ACCEPT, true, &result); break; case SOCKET_UDP: forward_message(SKYNET_SOCKET_TYPE_UDP, false, &result); break; case SOCKET_WARNING: forward_message(SKYNET_SOCKET_TYPE_WARNING, false, &result); break; default: skynet_error(NULL, "Unknown socket message type %d.",type); return -1; } if (more) { return -1; } return 1; } int skynet_socket_sendbuffer(struct skynet_context *ctx, struct socket_sendbuffer *buffer) { return socket_server_send(SOCKET_SERVER, buffer); } int skynet_socket_sendbuffer_lowpriority(struct skynet_context *ctx, struct socket_sendbuffer *buffer) { return socket_server_send_lowpriority(SOCKET_SERVER, buffer); } int skynet_socket_listen(struct skynet_context *ctx, const char *host, int port, int backlog) { uint32_t source = skynet_context_handle(ctx); return socket_server_listen(SOCKET_SERVER, source, host, port, backlog); } int skynet_socket_connect(struct skynet_context *ctx, const char *host, int port) { uint32_t source = skynet_context_handle(ctx); return socket_server_connect(SOCKET_SERVER, source, host, port); } int skynet_socket_bind(struct skynet_context *ctx, int fd) { uint32_t source = skynet_context_handle(ctx); return socket_server_bind(SOCKET_SERVER, source, fd); } void skynet_socket_close(struct skynet_context *ctx, int id) { uint32_t source = skynet_context_handle(ctx); socket_server_close(SOCKET_SERVER, source, id); } void skynet_socket_shutdown(struct skynet_context *ctx, int id) { uint32_t source = skynet_context_handle(ctx); socket_server_shutdown(SOCKET_SERVER, source, id); } void skynet_socket_start(struct skynet_context *ctx, int id) { uint32_t source = skynet_context_handle(ctx); socket_server_start(SOCKET_SERVER, source, id); } void skynet_socket_pause(struct skynet_context *ctx, int id) { uint32_t source = skynet_context_handle(ctx); socket_server_pause(SOCKET_SERVER, source, id); } void skynet_socket_nodelay(struct skynet_context *ctx, int id) { socket_server_nodelay(SOCKET_SERVER, id); } int skynet_socket_udp(struct skynet_context *ctx, const char * addr, int port) { uint32_t source = skynet_context_handle(ctx); return socket_server_udp(SOCKET_SERVER, source, addr, port); } int skynet_socket_udp_connect(struct skynet_context *ctx, int id, const char * addr, int port) { return socket_server_udp_connect(SOCKET_SERVER, id, addr, port); } int skynet_socket_udp_sendbuffer(struct skynet_context *ctx, const char * address, struct socket_sendbuffer *buffer) { return socket_server_udp_send(SOCKET_SERVER, (const struct socket_udp_address *)address, buffer); } const char * skynet_socket_udp_address(struct skynet_socket_message *msg, int *addrsz) { if (msg->type != SKYNET_SOCKET_TYPE_UDP) { return NULL; } struct socket_message sm; sm.id = msg->id; sm.opaque = 0; sm.ud = msg->ud; sm.data = msg->buffer; return (const char *)socket_server_udp_address(SOCKET_SERVER, &sm, addrsz); } struct socket_info * skynet_socket_info() { return socket_server_info(SOCKET_SERVER); }