/* Copyright (c) 1996, Ruslan R. Laishev (@RRL) */ #include "nntp.h" #include "nntp_log.h" #include "nntp_rms.h" #include "nntp_worker.h" #include "nntp_commands.h" WorkerContext *Wctxp0 [ NNTP_inpWorker ]; pthread_mutex_t Wctxm0; int MainSocketHnd, SocketHnd; struct sockaddr_in MainSocket, SockAddr; struct hostent MainHostEnt, HostEnt, *pHostEnt; struct in_addr inaddr; static char hostname[256]; int namelength; /* *-------------------------------------------------------------------------------- */ void NNTP_WorkerClient (WorkerContext *Wctxp) { long status; int (*nntp_fun) (WorkerContext *); nntp_log(logd,(stdout,"[Th:%d,Ch:%d]Started.",Wctxp->indx,Wctxp->chan)); sprintf(Wctxp->bufp,"200 %s is ready (Posing Ok)\r\n",ID$ID); if ( 0 > send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp), 0) ) NNTP_WorkerStop (Wctxp); while (1) { pthread_mutex_lock(&Wctxp->mutex); time (&Wctxp->time); Wctxp->time += 300; pthread_mutex_unlock(&Wctxp->mutex); if ( 0 > nntp_cmd_get(Wctxp->chan,Wctxp->bufp ,512) ) { nntp_log(logw,(stdout,"[Th:%d,Ch:%d]'recv' error.", Wctxp->indx,Wctxp->chan)); NNTP_WorkerStop (Wctxp); } pthread_mutex_lock(&Wctxp->mutex); time (&Wctxp->time); Wctxp->time += 6000; pthread_mutex_unlock(&Wctxp->mutex); if ( nntp_fun = nntp_cmd_parse (Wctxp) ) { if ( nntp_fun (Wctxp) ) NNTP_WorkerStop (Wctxp); } else { sprintf(Wctxp->bufp,"500 UnRecognized command\r\n"); send(Wctxp->chan,Wctxp->bufp,strlen(Wctxp->bufp),0); } } } /* *-------------------------------------------------------------------------------- */ void NNTP_WorkerStop (WorkerContext *Wctxp) { pthread_mutex_lock(&Wctxm0); Wctxp0 [ Wctxp->indx ] = NULL; pthread_mutex_unlock(&Wctxm0); pthread_mutex_lock(&Wctxp->mutex); MsgDBclose_stream (&Wctxp->Msgrab); GrpDBclose_stream (&Wctxp->Grprab); NNTP_SockShut(Wctxp->chan); pthread_mutex_unlock(&Wctxp->mutex); nntp_log(loge,(stdout,"[Th:%d,Ch:%d]End.", Wctxp->indx,Wctxp->chan)); free(Wctxp); pthread_exit ((pthread_addr_t) 0); } /* *-------------------------------------------------------------------------------- */ void *NNTP_WorkerInit (void) { long status; WorkerContext *Wctxp; if ( NULL == (Wctxp = calloc(1,sizeof (WorkerContext))) ) { nntp_log(loge,(stdout,"[WorkerInit]'calloc' memory-Error.")); return NULL; } nntp_log(logd,(stdout,"[WorkerInit]'calloc' memory (%d b)-Ok.", sizeof(WorkerContext))); status = pthread_mutex_init (&Wctxp->mutex,pthread_mutexattr_default); if (-1 == status) { nntp_log(loge,(stdout,"[WorkerInit]Init mutex-Error.")); free (Wctxp); return NULL; } if ( MsgDBopen_stream (&Wctxp->Msgrab) ) { nntp_log(loge,(stdout,"[WorkerInit]open MsgStream-Error.")); free (Wctxp); return NULL; } if ( GrpDBopen_stream (&Wctxp->Grprab) ) { nntp_log(loge,(stdout,"[WorkerInit]open GrpStream-Error.")); MsgDBclose_stream(&Wctxp->Msgrab); free (Wctxp); return NULL; } nntp_log(logd,(stdout,"[WorkerInit]-Ok.")); return (void *) Wctxp; } /* *-------------------------------------------------------------------------------- */ void NNTP_SockShut (int sock) { shutdown(sock,0); close(sock); } /* *-------------------------------------------------------------------------------- */ void NNTP_InBoss (void) { long status; pthread_t thread; int chan; int indx; WorkerContext *Wctxp; status = pthread_mutex_init (&Wctxm0,pthread_mutexattr_default); if (-1 == status) { nntp_log_err (errno); nntp_log(loge,(stdout,"[Th:InBoss]Init Wctxm mutex-Error.")); pthread_exit ((pthread_addr_t) 0); } if ( -1 == (MainSocketHnd = socket (AF_INET, SOCK_STREAM, 0)) ) { nntp_log_err (errno); nntp_log(logf,(stdout,"[Th:InBoss]'socket' error-End.")); pthread_exit ((pthread_addr_t) 0); } if ( -1 == gethostname(hostname,sizeof (hostname)) ) { nntp_log_err (errno); nntp_log(logf,(stdout,"[Th:InBoss]'gethostname' error-End.")); pthread_exit ((pthread_addr_t) 0); } if ( NULL == (pHostEnt = gethostbyname (hostname)) ) { nntp_log_err (errno); nntp_log(logf,(stdout,"[Th:InBoss]'gethostbyname' error-End.")); pthread_exit ((pthread_addr_t) 0); } else nntp_log(logi,(stdout,"[Th:InBoss]Local Host = %s",pHostEnt->h_name)); MainHostEnt = *pHostEnt; MainSocket.sin_family = AF_INET; MainSocket.sin_port = htons(NNTP_tcpPort); MainSocket.sin_addr.s_addr = INADDR_ANY; if ( -1 == setsockopt(MainSocketHnd,SOL_SOCKET,SO_REUSEADDR,(char *)&status, sizeof (status)) ) { nntp_log_err (errno); nntp_log(logf,(stdout,"[Th:InBoss]'setsockopt' error-End.")); pthread_exit ((pthread_addr_t) 0); } /* * Bind MainSocket to MainSocketHnd */ if ( -1 == bind (MainSocketHnd,(struct sockaddr *) &MainSocket, sizeof (MainSocket)) ) { nntp_log_err (errno); nntp_log(logf,(stdout,"[Th:InBoss]'bind' error-End.")); pthread_exit ((pthread_addr_t) 0); } if ( -1 == listen (MainSocketHnd, 5) ) { nntp_log_err (errno); nntp_log(logf,(stdout,"[Th:InBoss]'listen' error-End.")); pthread_exit ((pthread_addr_t) 0); } while (1) { nntp_log(logd,(stdout,"[Th:InBoss]Check free Wctx.")); pthread_mutex_lock(&Wctxm0); for (indx = 0;indx < NNTP_inpWorker;indx++) if ( NULL == Wctxp0[indx] ) break; pthread_mutex_unlock(&Wctxm0); nntp_log(logd,(stdout,"[Th:InBoss]Check free Wctx-Found.")); if ( indx >= NNTP_inpWorker ) { nntp_log(logd,(stdout,"[Th:InBoss]No free Wctx-Wait 1 sec.")); sleep (1); continue; } if ( 0 > (chan = accept(MainSocketHnd, (struct sockaddr *) &MainSocket,&namelength)) ) { nntp_log_err (errno); nntp_log(logf,(stdout,"[Th:InBoss]'accept' error-Skip request.")); continue; } nntp_log(logd,(stdout,"[Th:InBoss]Incoming connection request,chan=%d",chan)); if ( !(Wctxp = NNTP_WorkerInit()) ) { NNTP_SockShut(chan); nntp_log(logd,(stdout,"[Th:InBoss]No free Wctx-Wait 1 sec.")); sleep (1); continue; } nntp_log(logd,(stdout,"[Th:InBoss]Fill Wctx [Th:%d,Ch:%d].",indx,chan)); Wctxp->type = T_Clnt; Wctxp->stat = S_Work; Wctxp->chan = chan; Wctxp->indx = indx; time(&Wctxp->time); Wctxp->time+= 600; nntp_log(logd,(stdout,"[Th:InBoss]Start Worker [Th:%d,Ch:%d].", Wctxp->indx,Wctxp->chan)); status = pthread_create(&Wctxp->tid,pthread_attr_default, NNTP_WorkerClient, (pthread_addr_t) Wctxp); if (status == -1) { nntp_log_err (errno); continue; } pthread_mutex_lock(&Wctxm0); Wctxp0[indx] = Wctxp; pthread_mutex_unlock(&Wctxm0); nntp_log(logd,(stdout,"[Th:InBoss]Start Worker-Ok.")); } }