struct NetBase * MallocConnector(const char * ip, const int port) { s32 fd; struct timeval tv; struct sockaddr_in addr; struct NetBase * connecter; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); if (inet_pton(AF_INET, ip, &addr.sin_addr) <= 0) { printf("inet_pton error %s\n", ip); return NULL; } if (-1 == (fd = socket(AF_INET, SOCK_STREAM, 0))) { printf("socket create error %s\n", strerror(errno)); return NULL; } if (0 != SetNonBlocking(fd) || 0 != SetReuse(fd) || 0 != SetNonNegal(fd)) { close(fd); return NULL; } s32 ret = connect(fd, (struct sockaddr *) &addr, sizeof(addr)); if (ret < 0 && errno != EINPROGRESS) { printf("connect error %s\n", strerror(errno)); close(fd); return NULL; } else { connecter = (struct NetBase *)MALLOC(sizeof(struct NetBase)); connecter->fd = fd; connecter->type = BNEV_CONNECT; connecter->looper = NULL; return connecter; } }
void Connector::OnOut() { OASSERT(_recvSize > 0 && _sendSize > 0, "buff size is zero"); SetHardClose(_fd); SetNonNegal(_fd); Connection * connection = Connection::Create(_fd); OASSERT(connection != nullptr, "wtf"); connection->SetParser(_parser); connection->SetBufferSize(_sendSize, _recvSize); sockaddr_in local; socklen_t len = sizeof(local); getsockname(_fd, (sockaddr*)&local, &len); connection->SetLocalIp(inet_ntoa(local.sin_addr)); connection->SetLocalPort(ntohs(local.sin_port)); connection->SetRemoteIp(_ip); connection->SetRemotePort(_port); _session->SetFactory(nullptr); connection->SetSession(_session); NetEngine::Instance()->Del(this, EPOLLOUT); NetEngine::Instance()->Remove(this); NetEngine::Instance()->Add(connection); NetEngine::Instance()->Add(connection, EPOLLIN | EPOLLOUT); NetWorker * worker = NetEngine::Instance()->GetWorker(); worker->Add(connection); connection->OnConnected(); DEL this; }
s32 DispatchLooper(struct NetLooper * looper, const s32 millisecond) { struct epoll_event * events = (struct epoll_event *)alloca(sizeof(struct epoll_event) * looper->size); memset(events, 0, sizeof(struct epoll_event) * looper->size); s32 retCount = epoll_wait(looper->fd, events, looper->size, millisecond); if (retCount == -1) { if (errno != EINTR) { printf("epoll_wait error %d\n", errno); } return; } if (retCount == 0) return; s32 i = 0; for (i = 0; i < retCount; i++) { s32 code; s32 fd; struct sockaddr_in addr; socklen_t len = sizeof(addr); char type = ((struct NetBase *)events[i].data.ptr)->type; switch (type) { case BNEV_ACCEPT: { struct NetBase * accepter = events[i].data.ptr; if (events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) { code = -1; OASSERT(0, "wtf"); } else if (events[i].events & EPOLLIN) { memset(&addr, 0, sizeof(addr)); s32 i = 0; while (i++ < 30 && (fd = accept(accepter->fd, (struct sockaddr *)&addr, &len)) >= 0) { if (0 == SetNonBlocking(fd) && 0 == SetSendBuf(fd, 0) && 0 == SetNonNegal(fd)) { struct NetBase * base = (struct NetBase *)MALLOC(sizeof(struct NetBase)); base->fd = fd; base->type = BNEV_IO; base->looper = NULL; base->maxRecvSize = accepter->maxRecvSize; base->maxSendSize = accepter->maxSendSize; if (0 != (*looper->fnAccept)(accepter, base)) { FreeBase(base); } } else { close(fd); } } } break; } case BNEV_CONNECT: { struct NetBase * connecter = events[i].data.ptr; if (events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) code = -1; else if (events[i].events & EPOLLOUT) code = 0; if (UnbindLooper(connecter) != 0) { printf("epoll add fd error %s\n", strerror(errno)); //return; OASSERT(0, "wtf"); } connecter->type = BNEV_IO; (*looper->fnConnect)(connecter, code); if (-1 == code) FreeBase(connecter); break; } case BNEV_IO: { struct NetBase * base = events[i].data.ptr; if (events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) { UnbindLooper(base); (*looper->fnRecv)(base, -1, NULL, 0); FreeBase(base); break; } if (events[i].events & EPOLLIN) { s32 res = 0; while (1) { u32 size = 0; s32 len = 0; char * buf = RingBufferWrite(base->recvBuff, &size); if (buf && size > 0) { len = recv(base->fd, buf, size, 0); if (len < 0 && errno == EAGAIN) break; } else len = -1; if (len <= 0) { UnbindLooper(base); (*looper->fnRecv)(base, -1, NULL, 0); FreeBase(base); res = -1; break; } if (-1 == (*looper->fnRecv)(base, 0, buf, len)) { UnbindLooper(base); FreeBase(base); res = -1; break; } } if (-1 == res) break; } if (events[i].events & EPOLLOUT) { if (0 != (*looper->fnSend)(base)) { UnbindLooper(base); FreeBase(base); } } break; } default: OASSERT(0, "wtf"); break; } } }