static void report_accept(struct silly_socket *ss, struct socket *listen) { const char *str; struct socket *s; struct sockaddr_in addr; struct silly_message_socket *sa; char buff[INET_ADDRSTRLEN]; assert(ADDRLEN >= INET_ADDRSTRLEN + 8); socklen_t len = sizeof(struct sockaddr); int fd = accept(listen->fd, (struct sockaddr *)&addr, &len); if (fd < 0) return ; sa = silly_malloc(sizeof(*sa) + ADDRLEN); sa->data = (uint8_t *)(sa + 1); sa->type = SILLY_SACCEPT; str = inet_ntop(addr.sin_family, &addr.sin_addr, buff, sizeof(buff)); snprintf((char *)sa->data, ADDRLEN, "%s:%d", str, ntohs(addr.sin_port)); nonblock(fd); keepalive(fd); nodelay(fd); s = newsocket(ss, NULL, fd, STYPE_SOCKET, NULL); if (s == NULL) return; sa->sid = s->sid; sa->ud = listen->sid; silly_worker_push(tocommon(sa)); return ; }
static int forward_msg_tcp(struct silly_socket *ss, struct socket *s) { ssize_t sz; ssize_t presize = s->presize; uint8_t *buff = (uint8_t *)silly_malloc(presize); sz = readn(s->fd, buff, presize); //half close socket need no data if (sz > 0 && s->type != STYPE_HALFCLOSE) { report_data(ss, s, SILLY_SDATA, buff, sz); //to predict the pakcet size if (sz == presize) { s->presize *= 2; } else if (presize > MIN_READBUFF_LEN) { //s->presize at leatest is 2 * MIN_READBUFF_LEN int half = presize / 2; if (sz < half) s->presize = half; } } else { silly_free(buff); if (sz < 0) { report_close(ss, s, errno); delsocket(ss, s); return -1; } return 0; } return sz; }
static inline struct node * newnode() { struct node *n = silly_malloc(sizeof(*n)); uint32_t session = silly_worker_genid(); n->session = session; return n; }
void silly_worker_init() { W = (struct silly_worker *)silly_malloc(sizeof(*W)); memset(W, 0, sizeof(*W)); W->maxmsg = 128; W->queue = silly_queue_create(); return ; }
struct silly_queue * silly_queue_create() { struct silly_queue *q = (struct silly_queue *)silly_malloc(sizeof(*q)); q->lock = 0; q->size = 0; q->head.next = NULL; q->tail = &q->head; return q; }
static void report_data(struct silly_socket *ss, struct socket *s, int type, uint8_t *data, size_t sz) { (void)ss; assert(s->type == STYPE_SOCKET || s->type == STYPE_UDPBIND); struct silly_message_socket *sd = silly_malloc(sizeof(*sd)); assert(type == SILLY_SDATA || type == SILLY_SUDP); sd->type = type; sd->sid = s->sid; sd->ud = sz; sd->data = data; silly_worker_push(tocommon(sd)); return ; };
static void wlist_append(struct socket *s, uint8_t *buff, size_t offset, size_t size, const struct sockaddr *addr) { struct wlist *w; w = (struct wlist *)silly_malloc(sizeof(*w)); w->offset = offset; w->size = size; w->buff = buff; w->next = NULL; if (addr) w->udpaddress = *addr; s->wltail->next = w; s->wltail = w; return ; }
static int forward_msg_udp(struct silly_socket *ss, struct socket *s) { ssize_t n; uint8_t *data; struct sockaddr addr; socklen_t len = sizeof(addr); n = readudp(s->fd, ss->udpbuff, MAX_UDP_PACKET, &addr, &len); if (n < 0) return 0; data = (uint8_t *)silly_malloc(n + sizeof(addr)); memcpy(data, ss->udpbuff, n); memcpy(data + n, &addr, sizeof(addr)); report_data(ss, s, SILLY_SUDP, data, n); return n; }
static void socketpool_init(struct silly_socket *ss) { int i; struct socket *pool = silly_malloc(sizeof(*pool) * MAX_SOCKET_COUNT); ss->socketpool = pool; ss->reserveid = -1; for (i = 0; i < MAX_SOCKET_COUNT; i++) { pool->sid = -1; pool->fd = -1; pool->type = STYPE_RESERVE; pool->presize = MIN_READBUFF_LEN; pool->wlhead.next = NULL; pool->wltail = &pool->wlhead; pool++; } return ; }
static void report_connected(struct silly_socket *ss, struct socket *s) { int err; err = checkconnected(s->fd); if (err < 0) { //check ok report_close(ss, s, errno); delsocket(ss, s); return ; } struct silly_message_socket *sc = silly_malloc(sizeof(*sc)); sc->type = SILLY_SCONNECTED; sc->sid = s->sid; if (wlist_empty(s)) sp_write_enable(ss->spfd, s->fd, s, 0); silly_worker_push(tocommon(sc)); return ; }
int silly_socket_init() { int err; sp_t spfd = SP_INVALID; int fd[2] = {-1, -1}; struct socket *s = NULL; struct silly_socket *ss = silly_malloc(sizeof(*ss)); memset(ss, 0, sizeof(*ss)); socketpool_init(ss); spfd = sp_create(EVENT_SIZE); if (spfd == SP_INVALID) goto end; s = allocsocket(ss, STYPE_CTRL, PROTOCOL_PIPE); assert(s); err = pipe(fd); //use the pipe and not the socketpair because the pipe will be automatic when the data size small than BUFF_SIZE if (err < 0) goto end; err = sp_add(spfd, fd[0], s); if (err < 0) goto end; ss->spfd = spfd; ss->ctrlsendfd = fd[1]; ss->ctrlrecvfd = fd[0]; ss->eventindex = 0; ss->eventcount = 0; resize_eventbuff(ss, EVENT_SIZE); FD_ZERO(&ss->ctrlfdset); SSOCKET = ss; return 0; end: if (s) freesocket(ss, s); if (spfd != SP_INVALID) sp_free(spfd); if (fd[0] >= 0) close(fd[0]); if (fd[1] >= 0) close(fd[0]); if (ss) silly_free(ss); return -errno; }
static void report_close(struct silly_socket *ss, struct socket *s, int err) { (void)ss; int or; struct silly_message_socket *sc; if (s->type == STYPE_HALFCLOSE)//don't notify the active close return ; or = s->type == STYPE_LISTEN ? 1 : 0; or += s->type == STYPE_SOCKET ? 1 : 0; or += s->type == STYPE_CONNECTING ? 1 : 0; or += s->type == STYPE_ALLOCED ? 1 : 0; assert(or > 0); sc = silly_malloc(sizeof(*sc)); sc->type = SILLY_SCLOSE; sc->sid = s->sid; sc->ud = err; silly_worker_push(tocommon(sc)); return ; }
static void * _debug(void *arg) { char buff[1024]; while (run) { int n; struct silly_message *msg; char *sz; fgets(buff, 1024, stdin); n = strlen(buff); msg = (struct silly_message *)silly_malloc(sizeof(*msg) + n + 1); sz = (char *)(msg + 1); msg->type = SILLY_DEBUG; strcpy(sz, buff); silly_server_push(0, msg); } return NULL; }