int socket_server_udp(struct socket_server *ss, uintptr_t opaque, const char * addr, int port) { int fd; int family; if (port != 0 || addr != NULL) { // bind fd = do_bind(addr, port, IPPROTO_UDP, &family); if (fd < 0) { return -1; } } else { family = AF_INET; fd = socket(family, SOCK_DGRAM, 0); if (fd < 0) { return -1; } } sp_nonblocking(fd); int id = reserve_id(ss); if (id < 0) { close(fd); return -1; } struct request_package request; request.u.udp.id = id; request.u.udp.fd = fd; request.u.udp.opaque = opaque; request.u.udp.family = family; send_request(ss, &request, 'U', sizeof(request.u.udp)); return id; }
// return 0 when failed static int report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) { union sockaddr_all u; socklen_t len = sizeof(u); int client_fd = accept(s->fd, &u.s, &len); if (client_fd < 0) { return 0; } int id = reserve_id(ss); if (id < 0) { close(client_fd); return 0; } sp_nonblocking(client_fd); struct socket *ns = new_fd(ss, id, client_fd, s->opaque, false); if (ns == NULL) { close(client_fd); return 0; } ns->type = SOCKET_TYPE_PACCEPT; result->opaque = s->opaque; result->id = s->id; result->ud = id; result->data = NULL; void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr; if (inet_ntop(u.s.sa_family, sin_addr, ss->buffer, sizeof(ss->buffer))) { result->data = ss->buffer; } return 1; }
int socket_server_bind(struct socket_server *ss, uintptr_t opaque, int fd) { struct request_package request; int id = reserve_id(ss); request.u.bind.opaque = opaque; request.u.bind.id = id; request.u.bind.fd = fd; send_request(ss, &request, 'B', sizeof(request.u.bind)); return id; }
int socket_server::server_bind(uintptr_t opaque, int fd) { struct request_package request; int id = reserve_id(); if (id < 0) { return -1; } request.u.bind.opaque = opaque; request.u.bind.id = id; request.u.bind.fd = fd; send_request(&request, 'B', sizeof(request.u.bind)); return id; }
int socket_server_listen(struct socket_server *ss, uintptr_t opaque, const char * addr, int port, int backlog) { int fd = do_listen(addr, port, backlog); if (fd < 0) { return -1; } struct request_package request; int id = reserve_id(ss); request.u.listen.opaque = opaque; request.u.listen.id = id; request.u.listen.fd = fd; send_request(ss, &request, 'L', sizeof(request.u.listen)); return id; }
// return 0 when failed, or -1 when file limit // static int report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) { union sockaddr_all u; socklen_t len = sizeof(u); // 生成被动套接字 int client_fd = accept(s->fd, &u.s, &len); if (client_fd < 0) { if (errno == EMFILE || errno == ENFILE) { result->opaque = s->opaque; result->id = s->id; result->ud = 0; result->data = strerror(errno); return -1; } else { return 0; } } // 分配id int id = reserve_id(ss); if (id < 0) { close(client_fd); return 0; } // 设置keepalive和非阻塞 socket_keepalive(client_fd); sp_nonblocking(client_fd); // 创建socket实例 struct socket *ns = new_fd(ss, id, client_fd, PROTOCOL_TCP, s->opaque, false); if (ns == NULL) { close(client_fd); return 0; } // 设置socket类型为PACCEPT ns->type = SOCKET_TYPE_PACCEPT; result->opaque = s->opaque; result->id = s->id; // 服务器套接字id result->ud = id; // 被动套接字id result->data = NULL; // 连接客户端ip地址:port端口 void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr; int sin_port = ntohs((u.s.sa_family == AF_INET) ? u.v4.sin_port : u.v6.sin6_port); char tmp[INET6_ADDRSTRLEN]; if (inet_ntop(u.s.sa_family, sin_addr, tmp, sizeof(tmp))) { snprintf(ss->buffer, sizeof(ss->buffer), "%s:%d", tmp, sin_port); result->data = ss->buffer; } return 1; }
static int open_request(struct socket_server *ss, struct request_package *req, uintptr_t opaque, const char *addr, int port) { int len = strlen(addr); if (len + sizeof(req->u.open) > 256) { fprintf(stderr, "socket-server : Invalid addr %s.\n",addr); return 0; } int id = reserve_id(ss); req->u.open.opaque = opaque; req->u.open.id = id; req->u.open.port = port; memcpy(req->u.open.host, addr, len); req->u.open.host[len] = '\0'; return len; }
// new a net socket node // the add parametic means that let fd add to eventfd immediately or not static struct net_socket* net_socket_new(struct net_pool* np, int fd, bool add) { log_debug("net_socket_new\n"); // judge the capacity is full or not if(np->count >= np->cap) { net_expand(np); } // get the unique id for fd int id = reserve_id(np); if(id < 0) { log_error("reserve id failure"); return NULL; } struct net_socket* ns = np->ns[id % np->cap]; // TODO: use assert? // assert(ns->status == SOCKET_STATUS_RESERVE); if(ns->status != SOCKET_STATUS_RESERVE) { log_error("get allocid failure"); return NULL; } // add to eventfd or not if(add) { if(poll_add(np->eventfd, fd, ns)) { log_error("add fd to eventfd failure"); ns->status = SOCKET_STATUS_INVALID; return NULL; } } ns->fd = fd; np->count++; log_debug("[current client count] : %d\n", np->count); return ns; }
int socket_server::server_listen(uintptr_t opaque, const char *addr, int port, int backlog) { int fd = do_listen(addr, port, backlog); if (fd < 0) { printf("do listen failed\n"); return -1; } printf("run listen success!\n"); struct request_package request; int id = reserve_id(); if (id < 0) { close(fd); return id; } request.u.listen.opaque = opaque; request.u.listen.id = id; request.u.listen.fd = fd; send_request(&request, 'L', sizeof(request.u.listen)); return id; }
// return 0 when failed static int report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) { union sockaddr_all u; socklen_t len = sizeof(u); int client_fd = accept(s->fd, &u.s, &len); if (client_fd < 0) { //printf("accept error : %s\n", strerror(errno)); return 0; } int id = reserve_id(ss); if (id < 0) { close(client_fd); return 0; } socket_keepalive(client_fd); sp_nonblocking(client_fd); struct socket *ns = new_fd(ss, id, client_fd, s->opaque, false); if (ns == NULL) { close(client_fd); return 0; } ns->type = SOCKET_TYPE_PACCEPT; result->opaque = s->opaque; result->id = s->id; result->ud = id; result->data = NULL; void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr; int sin_port = ntohs((u.s.sa_family == AF_INET) ? u.v4.sin_port : u.v6.sin6_port); char tmp[INET6_ADDRSTRLEN]; if (inet_ntop(u.s.sa_family, sin_addr, tmp, sizeof(tmp))) { snprintf(ss->buffer, sizeof(ss->buffer), "%s:%d", tmp, sin_port); result->data = ss->buffer; } return 1; }
int socket_server::report_accept(struct socket *s, struct socket_message *result) { union sockaddr_all u; socklen_t len = sizeof(u); int client_fd = accept(s->fd, &u.s, &len); if (client_fd < 0) { return 0; } int id = reserve_id(); if (id < 0) { close(client_fd); return 0; } keepalive(client_fd); nonblocking(client_fd); struct socket *ns = new_socket(id, client_fd, PROTOCOL_TCP, s->opaque, false); if (ns == nullptr) { close(client_fd); return 0; } ns->type = SOCKET_TYPE_PACCEPT; result->opaque = s->opaque; result->id = s->id; result->ud = id; result->data = nullptr; void * sin_addr = (u.s.sa_family == AF_INET) ? (void *)&u.v4.sin_addr : (void *)&u.v6.sin6_addr; int sin_port = ntohs((u.s.sa_family == AF_INET) ? u.v4.sin_port : u.v6.sin6_port); char tmp[INET6_ADDRSTRLEN]; if (inet_ntop(u.s.sa_family, sin_addr, tmp, sizeof(tmp))) { snprintf(buffer, sizeof(buffer), "%s:%d", tmp, sin_port); result->data = buffer; } return 1; }