/* * PSYC Manager Daemon, src/net.cc * Copyright (C) 2001 Mark Ralf Thomson * Concept: Mark Ralf Thomson */ #include "psycm.h" #include "net.h" #include "classes.h" #include "parse.h" #include "extern.h" #include "msg.h" #include "user.h" /* makes a socket for UDP or TCP over ipv4 or ipv6, "*" binds to all ipv4/ipv6 domains */ int mkSocket(bool type,char *uaddr,char *port) { struct addrinfo *ai = NULL; struct addrinfo **pai = &ai; struct addrinfo hints; struct sockaddr *ptype; struct sockaddr_in sock4addr; struct sockaddr_in6 sock6addr; struct in6_addr in6addr_any2 = IN6ADDR_ANY_INIT; int result=0; bool multi=false,ipv6=false; int sock; if (uaddr[0] == '*') { multi = true; if(uaddr[1] == '4') ipv6=false; else if (uaddr[1] == '6') ipv6=true; else { cout<<"Error: mkSocket-addr : Invalid\n"; return -2; } } memset(&hints, 0, sizeof(hints)); hints.ai_socktype = (type ? SOCK_STREAM : SOCK_DGRAM); hints.ai_flags = AI_PASSIVE; if( (result = getaddrinfo((multi ? NULL : uaddr),port,&hints,pai) )) { cout<<"Error getaddrino: "<ai_family == AF_INET6) ipv6=true; if(multi) { if(!ipv6 && (sock = socket(AF_INET,ai->ai_socktype,0)) < 0) { cout<<"Errror socket4: "<ai_family<<" "<ai_socktype<<" "<ai_protocol<<"\n"; return 0; } if(ipv6 && (sock = socket(PF_INET6,ai->ai_socktype,0)) < 0) { cout<<"Errror socket6: "<ai_family<<" "<ai_socktype<<" "<ai_protocol<<"\n"; return 0; } } else { if((sock = socket(ai->ai_family,ai->ai_socktype,0)) < 0) { cout<<"Errror socket0: "<ai_family<<" "<ai_socktype<<" "<ai_protocol<<"\n"; return 0; } } if (multi) { if(!ipv6) { bzero (&sock4addr,sizeof(sock4addr)); sock4addr.sin_family = AF_INET; sock4addr.sin_port = htonl((unsigned short int)atoi(port)); sock4addr.sin_addr.s_addr = htons (INADDR_ANY); ptype = (struct sockaddr *)&sock4addr; if( bind(sock, ptype, sizeof(sock4addr))) { cout<<"Errror bind4: "<ai_addr, ai->ai_addrlen)) { cout<<"Errror bind6: "<h_addr_list; if (q_writeback) { result = getnameinfo(addr,sizeof(*addr),ipaddr,IPLEN,NULL,0, NI_NUMERICHOST); if(result != 0) cout<<"Error getnameinfo: "<target); ii = strlen(buf)+1; while((stringp = va_arg(vl, char *)) != NULL) { if(stringp == NULL) break; stringp2 = va_arg(vl, char *); tlen = strlen(stringp); tlen2 = strlen(stringp2); if (len+tlen+tlen2 >= BUFLEN) { cout<<"Error send: max BUFLEN reached\n"; break; } if (tlen < 1 || tlen2 < 1) break; if (client_proto == PT_PSYC && v->find("_verbose")) long2short(stringp); psycsprintf(BUFLEN-ii,buf+ii,"%s\t%s\n",stringp,stringp2); ii += tlen+tlen2+1; } va_end(vl); if (client_proto == PT_PSYC && v->find("_verbose")) long2short(stringp); psycsprintf(BUFLEN-ii,buf+ii,"%s %s\n.\n",first,body2); } else psycsprintf(BUFLEN,buf,":_source psyc://%s/%s\n:_target psyc://%s\n\n.\n", me.name,(source ? source : LEER),this->target); if(this->client_proto != PT_PSYC) if((z = this->pt_trans(buf,this,FROM_PSYC)) < 0) /* translate that message to a clientprotocol spec.message */ { cout<<"Error pt_trans:"<sendQ.bytes + len) >= SendQSize) this->exit(); /* TODO: exit client (max sendQ exeeded) */ this->sendQ.add(buf,len); return; } int person::rsend() { char buf[MaxPacketSize]; int k; int retval; k = this->sendQ.getpacket(buf,client_proto); /* get a packet from queue and copy it into buffer */ retval = ::send(this->conn.fd,buf,(size_t)k+1,0); if(retval != k || retval == ENOBUFS) { this->exit(); /* Max SendQ exeeded */ return -1; } if(retval == EAGAIN || retval ==EWOULDBLOCK) { return -2; /* Write error */ } if(retval== ENOMEM) exeption("NO MEM ON SEND!",1); this->sendQ.cut(k); /* cut the k first bytes from queue */ return 1; } /*---------------------------------------------------------------------- Portable function to set a socket into nonblocking mode. ----------------------------------------------------------------------*/ void setNonblocking(int fd) { int flags; if (-1 == (flags = fcntl(fd, F_GETFL, 0))) flags = 0; fcntl(fd, F_SETFL, flags | O_NONBLOCK); }