utils.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /**
  2. * Copyright (C) 2007 Juan José Gutiérrez de Quevedo <juanjo@iteisa.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; version 2 of the License
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. *
  17. * @author Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
  18. */
  19. #include "utils.h"
  20. extern unsigned long connid;
  21. char m_buffer[4096]={0};
  22. /**
  23. * reads a string as safely as possible.
  24. *
  25. * it will read one byte at a time until a '\\n' is read.
  26. * we store one char at a time in a static buffer, and when
  27. * we find a '\\n', we do an strndup of the buffer.
  28. * it might be possible in this special case to just use
  29. * a static buffer, return a pointer to it and never assign
  30. * any memory with strndup or in any other way.
  31. *
  32. * @param fd fd to read from
  33. *
  34. * @return a pointer to the read string
  35. */
  36. char *read_string(int fd)
  37. {
  38. char chr;
  39. char *buffer=NULL,*tmpbuf=NULL;
  40. unsigned long strsize=0;
  41. unsigned long allocsize=0;
  42. assert(fd>=0);
  43. /* read one byte at a time */
  44. while(1)
  45. {
  46. if(1!=recv(fd,&chr,1,MSG_NOSIGNAL))
  47. break;
  48. if(0==allocsize||allocsize<strsize+2)
  49. {
  50. allocsize=MAX(allocsize+512,strsize+2);
  51. if(NULL==(tmpbuf=realloc(buffer,allocsize)))
  52. {
  53. debug("Error reserving memory");
  54. condfree(buffer);
  55. break;
  56. }
  57. else
  58. buffer=tmpbuf;
  59. }
  60. if(10==chr) break;
  61. if(13!=chr)
  62. buffer[strsize++]=chr;
  63. }
  64. if(NULL==buffer) return NULL;
  65. /* finalize string */
  66. buffer[strsize]='\0';
  67. snprintf(m_buffer,sizeof(m_buffer),"r>%s",buffer);
  68. debug(m_buffer);
  69. /* return a new string with new mem */
  70. return buffer;
  71. }
  72. /**
  73. * create a new listening socket.
  74. *
  75. * with following options:
  76. * - SO_REUSEADDR
  77. * - INADDR_ANY
  78. *
  79. * @param port the port to listen on
  80. *
  81. * @return the new socket fd
  82. */
  83. int create_listening_socket(unsigned int port)
  84. {
  85. int fd_server;
  86. struct sockaddr_in address;
  87. int i;
  88. /* create socket */
  89. if(-1==(fd_server=socket(PF_INET,SOCK_STREAM,0))) { perror("Error creating socket"); return -1; }
  90. /* set option for the socket: SO_REUSEADDR (will reuse address between invocations of the same program) */
  91. i=1;
  92. if(-1==setsockopt(fd_server,SOL_SOCKET,SO_REUSEADDR,(void *)&i,sizeof(i))) { perror("Error configuring socket reuse"); closeskt(fd_server); return -1; }
  93. /* bind to address :ANY */
  94. address.sin_family=AF_INET;
  95. address.sin_addr.s_addr=INADDR_ANY;
  96. address.sin_port=htons(port);
  97. if(-1==bind(fd_server,(struct sockaddr *)&address,sizeof(address))) { perror("Error binding to address"); closeskt(fd_server); return -1; }
  98. /* listen on socket */
  99. if(-1==listen(fd_server,10)) { perror("Error listening on socket"); closeskt(fd_server); return -1; }
  100. snprintf(m_buffer,sizeof(m_buffer),"Listening on 0.0.0.0:%d",port);
  101. debug(m_buffer);
  102. return fd_server;
  103. }
  104. /**
  105. * create a socket that is connected to an address.
  106. *
  107. * @param address address to connect to
  108. * @param port port to connect to
  109. *
  110. * @return fd of the opened connection
  111. */
  112. int create_connected_socket(char *address,unsigned int port)
  113. {
  114. int fd;
  115. struct sockaddr_in addr;
  116. /* create socket */
  117. if(-1==(fd=socket(PF_INET,SOCK_STREAM,0))) { perror("Error creating socket"); return -1; }
  118. /* fill address structure */
  119. addr.sin_family=AF_INET;
  120. addr.sin_addr.s_addr=resolve(address);
  121. addr.sin_port=htons(port);
  122. if(0==addr.sin_addr.s_addr) return -1; /* error resolving name */
  123. /* connect to remote host */
  124. snprintf(m_buffer,sizeof(m_buffer),"Connecting to %s:%d",address,port);
  125. debug(m_buffer);
  126. if(-1==connect(fd,(struct sockaddr *)&addr,sizeof(addr))) { perror("Error connecting to host"); return -1; }
  127. return fd;
  128. }
  129. unsigned long resolve(char *address)
  130. {
  131. struct hostent *resolved;
  132. struct in_addr addr;
  133. if(NULL==(resolved=gethostbyname(address))) { perror("Error resolving"); return 0; }
  134. memcpy(&addr,resolved->h_addr,sizeof(addr));
  135. return addr.s_addr;
  136. }
  137. /**
  138. * whether a fd does have data waiting or not.
  139. *
  140. * @param fd array of fd to ask
  141. * @param nfd number of fds
  142. * @param time time to wait for data
  143. *
  144. * @return 1 on data waiting to be read, else return 0
  145. */
  146. unsigned char can_read(int *fd,int nfd,float time)
  147. {
  148. fd_set rfd;
  149. struct timeval timeout;
  150. int maxfd=0,i;
  151. assert(fd>=0);
  152. /* configure timeout */
  153. timeout.tv_sec=(int)time;
  154. timeout.tv_usec=(time-(int)time)*1000000;
  155. /* configure rfd */
  156. FD_ZERO(&rfd);
  157. for(i=0;i<nfd;i++)
  158. {
  159. FD_SET(fd[i],&rfd);
  160. maxfd=MAX(maxfd,fd[i]);
  161. }
  162. return (select(maxfd+1,&rfd,NULL,NULL,time<0?NULL:&timeout)>0)?1:0;
  163. }
  164. /**
  165. * check whether fd is at eof
  166. * @param fd socket to check
  167. *
  168. * @return true on eof, false otherwise
  169. */
  170. unsigned char socketeof(int fd)
  171. {
  172. unsigned char buffer;
  173. return 0==recv(fd,&buffer,1,MSG_PEEK|MSG_DONTWAIT);
  174. }