// Добавляем новое соединение в epoll int acceptConnection() { struct sockaddr addr; socklen_t addrlen = sizeof(addr); int connectionfd = accept(socketfd, &addr, &addrlen); if (connectionfd == -1) { perror("acception connection error"); return -1; } if (setNonBlock(connectionfd) == -1) { fprintf(stderr, "Making connection descriptor %d non-block error\n", connectionfd); return -1; } if (addToEpoll(epollfd, connectionfd, EPOLLET | EPOLLIN) == -1) { fprintf(stderr, "Adding connection to epoll\n"); return -1; } addConnectionIntoList(connectionfd); return connectionfd; }
// прием соединения, если новых соединений нет или произошла ошибка то connectionfd == -1 int acceptConnection(int epollfd, int socketfd, struct UserParams userParams){ struct sockaddr addr; socklen_t addrlen = sizeof addr; int connectionfd = accept(socketfd, &addr, &addrlen); if (connectionfd == -1){ perror ("failed to accept connection"); return -1; } char host[NI_MAXHOST]; char service[NI_MAXSERV]; //резервирование символьного адреса и имени сервиса if(!getnameinfo(&addr, addrlen, host, sizeof host, service, sizeof service, NI_NUMERICHOST | NI_NUMERICSERV)){ //вывод информации о полльзователе printf("new connection: %s:%s\n", host, service); } if (setNonBlock(connectionfd) == -1){ fprintf(stderr, "failed to set socket %d nonblock", connectionfd); return -1; } //добавление в epol if (addToEpoll(epollfd, connectionfd) == -1){ fprintf(stderr, "failed to add socket %d to epoll", connectionfd); return -1; } dprintf(connectionfd,"Enter login: "******"%d",connectionfd); DictInsert(userParams.login, conBuf, ""); snprintf(conBuf, 4,"%d",connectionfd); DictInsert(userParams.fLogin, conBuf, "0"); return 0; }
/////////////////////////////////////////////////////////////////////////////// // // MAIN // /////////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { // Обработка сигнала struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = handleSigInt; sigaction(SIGINT, &act, 0); // Проверка количества аргументов if (argc < 4) { fprintf(stderr, "Too few arguments\n"); exit(EXIT_FAILURE); } // Количество потоков - 1й параметр запуска int numberOfWorkers = atoi(argv[1]); // Порт - 2й параметр запуска char port[4]; strcpy(port, argv[2]); // Путь к файлу с паролями - 3й параметр запуска readPasswordsFromFile(argv[3]); // Инициализация connections memset(connections, 0, sizeof(connections)); struct addrinfo* addresses = getAvailableAddresses(port); if (!addresses) exit(EXIT_FAILURE); // Получаем дескриптор сокета int _socketfd = getSocket(addresses); if (_socketfd == -1) { exit(EXIT_FAILURE); } setSocketFd(_socketfd); // Начинаем слушать сокет if (listen(socketfd, SOMAXCONN) == -1) { perror("listen\n"); exit(EXIT_FAILURE); } // Создаём потоки pthread_t workers[numberOfWorkers]; pthread_mutex_t mutex; pthread_mutexattr_t mutexattr; pthread_mutexattr_init(&mutexattr); pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK); pthread_mutex_init(&mutex, &mutexattr); pthread_mutex_init(&connectionsMutex, &mutexattr); pthread_cond_t condition; pthread_cond_init(&condition, NULL); // Создаём отдельный поток для отслеживания таймаута соединений pthread_t timeoutWatcher; pthread_create(&timeoutWatcher, NULL, watchTimeout, NULL); // Создаём очередь struct Queue queue; initQueue(&queue, sizeof(struct epoll_event)); struct WorkerArgs workerArgs; initWorkerArgs(&workerArgs, &queue, &mutex, &condition); for (int i = 0; i < sizeof(workers) / sizeof(pthread_t); i++) { pthread_create(&workers[i], NULL, worker, (void *) &workerArgs); } // Создаём epoll int _epollfd = epoll_create1(0); if (_epollfd == -1) { perror("epoll_create error\n"); exit(EXIT_FAILURE); } setEpollFd(_epollfd); // Добавляем сокет в epoll if (addToEpoll(epollfd, socketfd, EPOLLET | EPOLLIN) == -1) exit(EXIT_FAILURE); int maxEventNum = numberOfWorkers; struct epoll_event events[maxEventNum]; int timeout = -1; printf("Main thread: %d\n", (int)pthread_self()); while(!done) { int eventsNumber = epoll_wait(epollfd, events, maxEventNum, timeout); if (!eventsNumber) printf("No events\n"); for (int i = 0; i < eventsNumber; i++) { pthread_mutex_lock(&mutex); pushQueue(&queue, &events[i]); pthread_cond_signal(&condition); pthread_mutex_unlock(&mutex); } } // Освобождение ресурсов pthread_mutex_destroy(&connectionsMutex); pthread_mutex_destroy(&mutex); pthread_mutexattr_destroy(&mutexattr); free(passPairs); destroyQueue(&queue); close(socketfd); close(epollfd); printf("DONE!!!"); return 0; }
int createPty(struct Connection *connection) { int ptm, pts; ptm = posix_openpt(O_RDWR); if (ptm == -1) { perror("creating new plm"); return -1; } if (grantpt(ptm) == -1) { perror("granting pt access"); return -1; } if (unlockpt(ptm) == -1) { perror("unlocking pt"); return -1; } pts = open(ptsname(ptm), O_RDWR); if (pts == -1) { perror("opening pts"); return -1; } if (setNonBlock(ptm) == -1) { fprintf(stderr, "Error: making ptm non-block\n"); return -1; } if (setNonBlock(pts) == -1) { fprintf(stderr, "Error: making pts non-block\n"); return -1; } connection->ptm = ptm; if (addToEpoll(epollfd, ptm, EPOLLET | EPOLLIN) == -1) { fprintf(stderr, "Error: adding ptm to epoll\n"); return -1; } if (fork()) { if (close(pts) == -1) { perror("closing pts in parent process"); return -1; } } else { if (close(ptm) == -1) { perror("closing ptm in child process"); return -1; } struct termios oldSettings, newSettings; if (tcgetattr(pts, &oldSettings) == -1) { perror("getting old terminal settings\n"); return -1; } newSettings = oldSettings; cfmakeraw(&newSettings); if (tcsetattr(pts, TCSANOW, &newSettings) == -1) { perror("setting new terminal settings\n"); return -1; } close(0); close(1); close(2); dup(pts); dup(pts); dup(pts); close(pts); setsid(); ioctl(0, TIOCSCTTY, 1); execvp("/bin/bash", NULL); } return 0; }
int main (int argc, char *argv[]){ /*int c; FILE *pp; extern FILE *popen(); if ( !(pp=popen("ls -l", "r")) ) return 1; while ( (c=fgetc(pp)) != EOF ) { putc(c, stdout); fflush(pp); } pclose(pp);*/ //пользовательскике данные struct UserParams userParams; Dict login = DictCreate(); Dict fLogin = DictCreate(); Dict location = DictCreate();; userParams.login = login; userParams.fLogin = fLogin; userParams.location = location; //параметры адреса printf("starting server\n"); struct addrinfo hints; memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; // получаение списка доступных адресов char* port = "8080"; struct addrinfo* addresses = getAvilableAddresses(&hints, port); if(!addresses) return EXIT_FAILURE; //коннект сокета int socketfd = assignSocket(addresses); if(!socketfd) return EXIT_FAILURE; if (setNonBlock(socketfd) == -1){ perror("non_block"); return EXIT_FAILURE; } if (listen (socketfd, SOMAXCONN) == -1){ perror ("listen"); return EXIT_FAILURE; } printf("listening port %s\n", port); //создание epoll int epollfd = epoll_create1(0); if (epollfd == -1){ perror ("epoll_create"); return EXIT_FAILURE; } if (addToEpoll(epollfd, socketfd) == -1) return EXIT_FAILURE; //регистрация обработчика событий signal(SIGINT, handleSignal); int maxEventNum = 8; struct epoll_event events[maxEventNum * sizeof(struct epoll_event)]; //заполнение параметров для потоков struct Params params; pthread_mutex_init(¶ms.mutex, NULL); pthread_cond_init(¶ms.condvar, NULL); params.end = 0; params.currrent = 0; params.epollfd = epollfd; params.events = events; params.socketfd = socketfd; params.userParams = userParams; pthread_t working[WORKING_THREADS_COUNT]; for(int i = 0; i<WORKING_THREADS_COUNT; i++){ pthread_create(&working[i], NULL, workThread, ¶ms); } //обработка событий int timeout = -1 ; while(!done){ if(params.currrent >= params.end){ printf("waiting new events\n"); int eventsNumber = epoll_wait(epollfd, events, maxEventNum, timeout); params.currrent = 0; params.end = eventsNumber; printf("Send\n"); pthread_cond_signal(¶ms.condvar); } } printf("server is going down\n"); printf("closing connections\n"); close(socketfd); close(epollfd); printf("done\n"); return EXIT_SUCCESS; }