/** * Copyright (C) 2007 Juan José Gutiérrez de Quevedo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * @author Juan José Gutiérrez de Quevedo */ #include "utils.h" extern unsigned long connid; char m_buffer[4096]={0}; /** * reads a string as safely as possible. * * it will read one byte at a time until a '\\n' is read. * we store one char at a time in a static buffer, and when * we find a '\\n', we do an strndup of the buffer. * it might be possible in this special case to just use * a static buffer, return a pointer to it and never assign * any memory with strndup or in any other way. * * @param fd fd to read from * * @return a pointer to the read string */ char *read_string(int fd) { char chr; char *buffer=NULL,*tmpbuf=NULL; unsigned long strsize=0; unsigned long allocsize=0; assert(fd>=0); /* read one byte at a time */ while(1) { if(1!=recv(fd,&chr,1,MSG_NOSIGNAL)) break; if(0==allocsize||allocsize%s",buffer); debug(m_buffer); /* return a new string with new mem */ return buffer; } /** * create a new listening socket. * * with following options: * - SO_REUSEADDR * - INADDR_ANY * * @param port the port to listen on * * @return the new socket fd */ int create_listening_socket(unsigned int port) { int fd_server; struct sockaddr_in address; int i; /* create socket */ if(-1==(fd_server=socket(PF_INET,SOCK_STREAM,0))) { perror("Error creating socket"); return -1; } /* set option for the socket: SO_REUSEADDR (will reuse address between invocations of the same program) */ i=1; if(-1==setsockopt(fd_server,SOL_SOCKET,SO_REUSEADDR,(void *)&i,sizeof(i))) { perror("Error configuring socket reuse"); closeskt(fd_server); return -1; } /* bind to address :ANY */ address.sin_family=AF_INET; address.sin_addr.s_addr=INADDR_ANY; address.sin_port=htons(port); if(-1==bind(fd_server,(struct sockaddr *)&address,sizeof(address))) { perror("Error binding to address"); closeskt(fd_server); return -1; } /* listen on socket */ if(-1==listen(fd_server,10)) { perror("Error listening on socket"); closeskt(fd_server); return -1; } snprintf(m_buffer,sizeof(m_buffer),"Listening on 0.0.0.0:%d",port); debug(m_buffer); return fd_server; } /** * create a socket that is connected to an address. * * @param address address to connect to * @param port port to connect to * * @return fd of the opened connection */ int create_connected_socket(char *address,unsigned int port) { int fd; struct sockaddr_in addr; /* create socket */ if(-1==(fd=socket(PF_INET,SOCK_STREAM,0))) { perror("Error creating socket"); return -1; } /* fill address structure */ addr.sin_family=AF_INET; addr.sin_addr.s_addr=resolve(address); addr.sin_port=htons(port); if(0==addr.sin_addr.s_addr) return -1; /* error resolving name */ /* connect to remote host */ snprintf(m_buffer,sizeof(m_buffer),"Connecting to %s:%d",address,port); debug(m_buffer); if(-1==connect(fd,(struct sockaddr *)&addr,sizeof(addr))) { perror("Error connecting to host"); return -1; } return fd; } unsigned long resolve(char *address) { struct hostent *resolved; struct in_addr addr; if(NULL==(resolved=gethostbyname(address))) { perror("Error resolving"); return 0; } memcpy(&addr,resolved->h_addr,sizeof(addr)); return addr.s_addr; } /** * whether a fd does have data waiting or not. * * @param fd array of fd to ask * @param nfd number of fds * @param time time to wait for data * * @return 1 on data waiting to be read, else return 0 */ unsigned char can_read(int *fd,int nfd,float time) { fd_set rfd; struct timeval timeout; int maxfd=0,i; assert(fd>=0); /* configure timeout */ timeout.tv_sec=(int)time; timeout.tv_usec=(time-(int)time)*1000000; /* configure rfd */ FD_ZERO(&rfd); for(i=0;i0)?1:0; } /** * check whether fd is at eof * @param fd socket to check * * @return true on eof, false otherwise */ unsigned char socketeof(int fd) { unsigned char buffer; return 0==recv(fd,&buffer,1,MSG_PEEK|MSG_DONTWAIT); }