/************************************************************************ * PSYC Manager Daemon, src/psycm.cc * Copyright (C) 2001/02 Mark Ralf Thomson * Programmer: Mark Ralf Thomson * Conceptor : Carlo von Loesch */ #include "psycm.h" #include "net.h" #include "classes.h" #include "parse.h" #include "msg.h" #include "pdb.h" #include "int_functions.h" #include "Poller_poll.h" int udp_fd, tcp_fd; struct sockaddr servaddr,absender; int length = sizeof(absender); bool todo; HashTable u(HASH_USER_PN); /* ip-port -> userobjekt hashtable */ HashTable ni(HASH_USER_PN); /* nicknames -> userobj hashtable */ HashTable ndb(NDB_SIZE); /* nickname -> nick database obj */ HashTable cm(H_MAXCOM); /* cmds and tokens -> commands obj. */ HashTable pa(H_MAXPARA); /* parameters -> parameter struct*/ self me; void die(int lineno, char *method) { cout <<"Error: PsycM '"<::R> *table; list::R>::iterator b; int counter=0; int uSize=0; int k; char buffer[MaxPacketSize]; person *p; bool todo2; todo2=false; table=u.getTable(); uSize = u.getSize(); while (counter <= uSize) { b = table[counter].begin(); while( b != table[counter].end() ) { p = (*b).attr; if(p == NULL) { b++; continue; } cout<<"!USER! "<< p->recvQ.bytes<<"\n"; if( p->recvQ.bytes > 1) { k = p->recvQ.getpacket(buffer,p->client_proto); /* get a packet from queue and copy it into buffer */ if (k > 0) { p->recvQ.cut(k); /* cut the k first bytes from queue */ cout<<"cut :-)\n"; if (p->recvQ.bytes >1) todo2 = true; parse_data(buffer,p); /* parse, extract and execute command */ } else cout<<"Error: getpacket failed "<sendQ.bytes > 1) { if(CanWrite(p->events)) { p->rsend(); /* send the Queue (or , if Q to big, parts of them) out */ if (p->sendQ.bytes >1) todo2 = true; } else todo2 = true; } b++; } counter ++; } if (todo2 == true) todo = true; else todo = false; } void io_loop (void) { char ip[IPLEN]; char id[IDLEN]; char port_c[PORTLEN]; unsigned short int port; person *p=NULL; Poller_poll p_read; Poller_poll p_write; PollEvent event; int new_fd,msecs; int retval,anzahl; // unsigned int k; char buffer[8000]; int err = p_read.init(); if (err) DIE("init p_read"); setNonblocking(udp_fd); setNonblocking(tcp_fd); p_read.add(udp_fd,(new Client(P_UDP_B, PT_PSYC)),POLLMASK); p_read.add(tcp_fd,(new Client(P_TCP_B, PT_PSYC)),POLLMASK); /* TODO: specify portnumber and IP (or *) and kind of protocol for a portline in configfile */ while (1) { cout<<"->1\n"; if (todo == false) msecs = (STD_WAIT_MSECS * 100); else msecs = STD_WAIT_MSECS; retval = p_read.waitForEvents(msecs); // 500 ms cout<<"->2\n"; if (retval == 0) { cout<<"->3\n"; err = p_read.getNextEvent(&event); if (err) break; /* TODO: send to ops that an error occured */ if (event.client->ctype == P_UDP_B) /* something to read from user */ { cout<<"->4\n"; bzero (&absender,sizeof(absender)); anzahl = recvfrom(event.fd,buffer, RecvQSize,0, &absender, (socklen_t*) &length); buffer[anzahl]='\0'; if(getIPport(&absender,ip,port_c,&port) != 0) { cout<<"Error bei IPport\n"; continue; } psycsprintf(IDLEN,id,"%s-%s",ip,port_c); /* make id; form: "127.0.0.1-2221" */ p = FindClient(id); if(!p) { new_fd = connect(event.fd,&absender,(socklen_t)sizeof(absender)); if(new_fd < 0) continue; /* error on connecting, what should i do? -> ignore that connect */ setNonblocking(new_fd); p = new person(ip,port,P_UDP_C,new_fd); u.insert(id,p); p_read.add(new_fd,(new Client(P_UDP_C,p)),POLLMASK); p_write.add(new_fd,(new Client(P_UDP_C,p)),POLLOUT); p->client_proto = event.client->client_proto; if(p->client_proto != PT_PSYC) if(p->client_proto == PT_TELNET) p->pt_trans = PT_TRANS_TELNET; } p->recvQ.add(buffer,anzahl); if(anzahl == 8000) p->exit(); /* todo: exit with code or so (max recv reached) */ if((p->recvQ.bytes + anzahl) >= RecvQSize) p->exit(); /* todo: exit with code or so (max recv exeeded) */ p->recvQ.add(buffer,anzahl); } else if (event.client->ctype == P_TCP_C ||event.client->ctype == P_UDP_C ) /* something to read from user */ { cout<<"->5\n"; event.client->pers->events = event.revents; if(CanRead(event.revents)) { anzahl = recv(event.fd,buffer,8000,0); buffer[anzahl]='\0'; if(anzahl == 8000) event.client->pers->exit(); /* todo: exit with code or so (max recv reached) */ if((event.client->pers->recvQ.bytes + anzahl) >= RecvQSize) event.client->pers->exit(); /* todo: exit with code or so (max recv exeeded) */ } event.client->pers->recvQ.add(buffer,anzahl); } else if (event.client->ctype == P_TCP_B) /* new TCP Cconnection */ { cout<<"->6\n"; struct sockaddr sockstr; socklen_t socksize=sizeof(sockstr); p = NULL; bzero(&sockstr,sizeof(sockstr)); new_fd = accept(event.fd,&sockstr,&socksize); if(new_fd == -1 || new_fd == EAGAIN) continue; setNonblocking(new_fd); if(getIPport(&sockstr,ip,port_c,&port) != 0) { cout<<"Error bei IPport\n"; continue; } psycsprintf(IDLEN,id,"%s-%s",ip,port_c); /* make id; form: "127.0.0.1-2221" */ p = FindClient(id); /* TODO: check against connection flood, * * because Client can change its port with each SYN * * (how many p_read entrys with EACH ip?) */ if(p != NULL) /* does a connection exists? THEN ignore the new one */ continue; p = new person(ip,port,P_TCP_C,new_fd); p_read.add(new_fd,(new Client(P_TCP_C,p)),POLLMASK); p_write.add(new_fd,(new Client(P_TCP_C,p)),POLLOUT); p->client_proto = event.client->client_proto; if(p->client_proto != PT_PSYC) { if(p->client_proto == PT_TELNET) p->pt_trans = PT_TRANS_TELNET; } else p->pt_trans = PT_TRANS_PSYC; /* not important */ u.insert(id,p); } } else { cout<<"->saven\n"; saveout_nickdb(&ndb); cout<<"->saven2\n"; } cout<<"->7\n"; p_write.waitForEvents(100); p_write.CopyMask(); pobj_loop(); cout<<"->8\n"; /* -> continue io_loop with waitForEvents */ } } int main() { init_coms(); init_params(); if (!readin_nickdb(&ndb)) { cout <<"Fatale Error: NICK DB kann nicht gelesen werden!\n"; exit(0); } srand((unsigned int)getpid()); udp_fd = mkSocket(false,"::1",LISTENPORT); // siehe funktion mkSocket tcp_fd = mkSocket(true,"::1",LISTENPORT); io_loop(); return (0); } void ExeptionHandler(int lineno, char *method,bool ifexit) { cout<<"Exeptionsituation: Z:"<