nanohttp-socket.c

Go to the documentation of this file.
00001 /******************************************************************
00002 *  $Id: nanohttp-socket.c,v 1.70 2007/01/23 23:21:47 m0gg Exp $
00003 *
00004 * CSOAP Project:  A http client/server library in C
00005 * Copyright (C) 2003  Ferhat Ayaz
00006 *
00007 * This library is free software; you can redistribute it and/or
00008 * modify it under the terms of the GNU Library General Public
00009 * License as published by the Free Software Foundation; either
00010 * version 2 of the License, or (at your option) any later version.
00011 *
00012 * This library is distributed in the hope that it will be useful,
00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 * Library General Public License for more details.
00016 *
00017 * You should have received a copy of the GNU Library General Public
00018 * License along with this library; if not, write to the
00019 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020 * Boston, MA  02111-1307, USA.
00021 *
00022 * Email: ferhatayaz@yahoo.com
00023 ******************************************************************/
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #ifdef HAVE_SYS_TYPES_H
00029 #include <sys/types.h>
00030 #endif
00031 
00032 #ifdef HAVE_SYS_WAIT_H
00033 #include <sys/wait.h>
00034 #endif
00035 
00036 #ifdef HAVE_SYS_SOCKET_H
00037 #include <sys/socket.h>
00038 #endif
00039 
00040 #ifdef HAVE_NETINET_IN_H
00041 #include <netinet/in.h>
00042 #endif
00043 
00044 #ifdef HAVE_ARPA_INET_H
00045 #include <arpa/inet.h>
00046 #endif
00047 
00048 #ifdef HAVE_FCNTL_H
00049 #include <fcntl.h>
00050 #endif
00051 
00052 #ifdef HAVE_NETDB_H
00053 #include <netdb.h>
00054 #endif
00055 
00056 #ifdef HAVE_UNISTD_H
00057 #include <unistd.h>
00058 #endif
00059 
00060 #ifdef HAVE_STDIO_H
00061 #include <stdio.h>
00062 #endif
00063 
00064 #ifdef HAVE_ERRNO_H
00065 #include <errno.h>
00066 #endif
00067 
00068 #ifdef HAVE_STRING_H
00069 #include <string.h>
00070 #endif
00071 
00072 #ifdef WIN32
00073 #include "wsockcompat.h"
00074 #include <winsock2.h>
00075 #include <process.h>
00076 
00077 #ifndef __MINGW32__
00078 typedef int ssize_t;
00079 #endif
00080 
00081 #undef errno
00082 #define errno WSAGetLastError()
00083 
00084 #endif
00085 
00086 #include "nanohttp-error.h"
00087 #include "nanohttp-logging.h"
00088 
00089 #include "nanohttp-common.h"
00090 #include "nanohttp-socket.h"
00091 #ifdef HAVE_SSL
00092 #ifdef HAVE_OPENSSL_SSL_H
00093 #include <openssl/ssl.h>
00094 #endif
00095 #include "nanohttp-ssl.h"
00096 #endif
00097 
00098 #define HSOCKET_FREE    -1
00099 
00100 static int _hsocket_timeout = 10;
00101 
00102 #ifdef WIN32
00103 static herror_t
00104 _hsocket_sys_accept(struct hsocket_t * sock, struct hsocket_t * dest)
00105 {
00106   struct hsocket_t sockfd;
00107   int asize;
00108 
00109   asize = sizeof(struct sockaddr_in);
00110   while (1)
00111   {
00112     sockfd.sock = accept(sock->sock, (struct sockaddr *) &(dest->addr), &asize);
00113     if (sockfd.sock == INVALID_SOCKET)
00114     {
00115       if (WSAGetLastError() != WSAEWOULDBLOCK)
00116         return herror_new("hsocket_accept", HSOCKET_ERROR_ACCEPT, "Socket error (%s)", strerror(errno));
00117     }
00118     else
00119     {
00120       break;
00121     }
00122   }
00123 
00124   dest->sock = sockfd.sock;
00125 
00126   return H_OK;
00127 }
00128 
00129 static void
00130 _hsocket_sys_close(struct hsocket_t * sock)
00131 {
00132   char junk[10];
00133 
00134   /* shutdown(sock,SD_RECEIVE); */
00135 
00136   shutdown(sock->sock, SD_SEND);
00137   while (recv(sock->sock, junk, sizeof(junk), 0) > 0);
00138     /* nothing */
00139   closesocket(sock->sock);
00140 
00141   return;
00142 }
00143 
00144 static void
00145 _hsocket_module_sys_init(int argc, char **argv)
00146 {
00147   struct WSAData info;
00148   WSAStartup(MAKEWORD(2, 2), &info);
00149 
00150   return;
00151 }
00152 
00153 static void
00154 _hsocket_module_sys_destroy(void)
00155 {
00156   WSACleanup();
00157 
00158   return;
00159 }
00160 #else
00161 static inline void
00162 _hsocket_module_sys_init(int argc, char **argv)
00163 {
00164   return;
00165 }
00166 
00167 static inline void
00168 _hsocket_module_sys_destroy(void)
00169 {
00170   return;
00171 }
00172 
00173 static herror_t
00174 _hsocket_sys_accept(struct hsocket_t * sock, struct hsocket_t * dest)
00175 {
00176   socklen_t len;
00177 
00178   len = sizeof(struct sockaddr_in);
00179 
00180   if ((dest->sock = accept(sock->sock, (struct sockaddr *) &(dest->addr), &len)) == -1)
00181   {
00182     log_warn2("accept failed (%s)", strerror(errno));
00183     return herror_new("hsocket_accept", HSOCKET_ERROR_ACCEPT, "Cannot accept network connection (%s)", strerror(errno));
00184   }
00185 
00186   return H_OK;
00187 }
00188 
00189 static inline void
00190 _hsocket_sys_close(struct hsocket_t * sock)
00191 {
00192   shutdown(sock->sock, SHUT_RDWR);
00193 
00194   close(sock->sock);
00195 
00196   return;
00197 }
00198 #endif
00199 
00200 herror_t
00201 hsocket_module_init(int argc, char **argv)
00202 {
00203 #ifdef HAVE_SSL
00204   herror_t status;
00205 #endif
00206 
00207   _hsocket_module_sys_init(argc, argv);
00208 
00209 #ifdef HAVE_SSL
00210   if ((status = hssl_module_init(argc, argv)) != H_OK)
00211   {
00212     log_error2("hssl_module_init failed (%s)", herror_message(status));
00213     return status;
00214   }
00215 #endif
00216 
00217   return H_OK;
00218 }
00219 
00220 void
00221 hsocket_module_destroy(void)
00222 {
00223   _hsocket_module_sys_destroy();
00224 
00225   return;
00226 }
00227 
00228 herror_t
00229 hsocket_init(struct hsocket_t * sock)
00230 {
00231   memset(sock, 0, sizeof(struct hsocket_t));
00232   sock->sock = HSOCKET_FREE;
00233 
00234   return H_OK;
00235 }
00236 
00237 void
00238 hsocket_free(struct hsocket_t * sock)
00239 {
00240   /* nop */
00241 
00242   return;
00243 }
00244 
00245 herror_t
00246 hsocket_open(struct hsocket_t * dsock, const char *hostname, int port, int ssl)
00247 {
00248   struct sockaddr_in address;
00249   struct hostent *host;
00250   char *ip;
00251 
00252   if ((dsock->sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0)
00253     return herror_new("hsocket_open", HSOCKET_ERROR_CREATE,
00254                       "Socket error (%s)", strerror(errno));
00255 
00256   /* Get host data */
00257   if (!(host = gethostbyname(hostname)))
00258     return herror_new("hsocket_open", HSOCKET_ERROR_GET_HOSTNAME,
00259                       "Socket error (%s)", strerror(errno));
00260 
00261   ip = inet_ntoa(*(struct in_addr *) *host->h_addr_list);
00262   address.sin_addr.s_addr = inet_addr(ip);
00263 
00264   /* set server addresss */
00265   address.sin_family = host->h_addrtype;
00266   address.sin_port = htons((unsigned short) port);
00267 
00268   log_verbose4("Opening %s://%s:%i", ssl ? "https" : "http", hostname, port);
00269 
00270   /* connect to the server */
00271   if (connect(dsock->sock, (struct sockaddr *) &address, sizeof(address)) != 0)
00272     return herror_new("hsocket_open", HSOCKET_ERROR_CONNECT, "Socket error (%s)", strerror(errno));
00273 
00274   if (ssl)
00275   {
00276 #ifdef HAVE_SSL
00277     herror_t status;
00278 
00279     if ((status = hssl_client_ssl(dsock)) != H_OK)
00280     {
00281       log_error2("hssl_client_ssl failed (%s)", herror_message(status));
00282       return status;
00283     }
00284 #else
00285     return herror_new("hssl_client_ssl", 0, "SSL wasn't enabled at compile time");
00286 #endif
00287   }
00288   return H_OK;
00289 }
00290 
00291 herror_t
00292 hsocket_bind(struct hsocket_t *dsock, unsigned short port)
00293 {
00294   struct hsocket_t sock;
00295   struct sockaddr_in addr;
00296   int opt = 1;
00297 
00298   /* create socket */
00299   if ((sock.sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
00300   {
00301     log_error2("Cannot create socket (%s)", strerror(errno));
00302     return herror_new("hsocket_bind", HSOCKET_ERROR_CREATE,
00303                       "Socket error (%s)", strerror(errno));
00304   }
00305 
00306   setsockopt(sock.sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
00307   /* bind socket */
00308   addr.sin_family = AF_INET;
00309   addr.sin_port = htons(port);
00310   addr.sin_addr.s_addr = INADDR_ANY;
00311   memset(&(addr.sin_zero), '\0', 8);    /* zero the rest of the struct */
00312 
00313   if (bind(sock.sock, (struct sockaddr *) &addr, sizeof(struct sockaddr)) == -1)
00314   {
00315     log_error2("Cannot bind socket (%s)", strerror(errno));
00316     return herror_new("hsocket_bind", HSOCKET_ERROR_BIND, "Socket error (%s)",
00317                       strerror(errno));
00318   }
00319   dsock->sock = sock.sock;
00320   return H_OK;
00321 }
00322 
00323 herror_t
00324 hsocket_accept(struct hsocket_t * sock, struct hsocket_t * dest)
00325 {
00326   herror_t status;
00327 
00328   if (sock->sock < 0)
00329     return herror_new("hsocket_accept", HSOCKET_ERROR_NOT_INITIALIZED,
00330                       "hsocket_t not initialized");
00331 
00332   if ((status = _hsocket_sys_accept(sock, dest)) != H_OK)
00333     return status;
00334 
00335 #ifdef HAVE_SSL
00336   if ((status = hssl_server_ssl(dest)) != H_OK)
00337   {
00338     log_warn2("SSL startup failed (%s)", herror_message(status));
00339     return status;
00340   }
00341 #endif
00342 
00343   log_verbose3("accepting connection from '%s' socket=%d",
00344                SAVE_STR(((char *) inet_ntoa(dest->addr.sin_addr))),
00345                dest->sock);
00346 
00347   return H_OK;
00348 }
00349 
00350 herror_t
00351 hsocket_listen(struct hsocket_t * sock)
00352 {
00353   if (sock->sock < 0)
00354     return herror_new("hsocket_listen", HSOCKET_ERROR_NOT_INITIALIZED,
00355                       "Called hsocket_listen before initializing!");
00356 
00357   if (listen(sock->sock, 15) == -1)
00358   {
00359     log_error2("listen failed (%s)", strerror(errno));
00360     return herror_new("hsocket_listen", HSOCKET_ERROR_LISTEN,
00361                       "Cannot listen on this socket (%s)", strerror(errno));
00362   }
00363 
00364   return H_OK;
00365 }
00366 
00367 void
00368 hsocket_close(struct hsocket_t * sock)
00369 {
00370   log_verbose3("closing socket %p (%d)...", sock, sock->sock);
00371 
00372 #ifdef HAVE_SSL
00373   hssl_cleanup(sock);
00374 #endif
00375 
00376   _hsocket_sys_close(sock);
00377 
00378   sock->bytes_received = 0;
00379   sock->bytes_transmitted = 0;
00380 
00381   log_verbose1("socket closed");
00382 
00383   return;
00384 }
00385 
00386 herror_t
00387 hsocket_send(struct hsocket_t * sock, const unsigned char * bytes, int n)
00388 {
00389 #ifdef HAVE_SSL
00390   herror_t status;
00391 #endif
00392   size_t total = 0;
00393   size_t size;
00394 
00395   if (sock->sock < 0)
00396     return herror_new("hsocket_send", HSOCKET_ERROR_NOT_INITIALIZED,
00397                       "hsocket not initialized");
00398 
00399   /* log_verbose2( "SENDING %s", bytes ); */
00400 
00401   while (1)
00402   {
00403 #ifdef HAVE_SSL
00404     if ((status = hssl_write(sock, bytes + total, n, &size)) != H_OK)
00405     {
00406       log_warn2("hssl_write failed (%s)", herror_message(status));
00407       return status;
00408     }
00409 #else
00410     if ((size = send(sock->sock, bytes + total, n, 0)) == -1)
00411       return herror_new("hsocket_send", HSOCKET_ERROR_SEND, "send failed (%s)", strerror(errno));
00412 #endif
00413     sock->bytes_received += size;
00414 
00415     n -= size;
00416     total += size;
00417     if (n <= 0)
00418       break;
00419   }
00420 
00421   return H_OK;
00422 }
00423 
00424 herror_t
00425 hsocket_send_string(struct hsocket_t * sock, const char *str)
00426 {
00427   return hsocket_send(sock, str, strlen(str));
00428 }
00429 
00430 int
00431 hsocket_select_recv(int sock, char *buf, size_t len)
00432 {
00433   struct timeval timeout;
00434   fd_set fds;
00435 
00436   FD_ZERO(&fds);
00437   FD_SET(sock, &fds);
00438 
00439   timeout.tv_sec = _hsocket_timeout;
00440   timeout.tv_usec = 0;
00441 
00442   if (select(sock + 1, &fds, NULL, NULL, &timeout) == 0)
00443   {
00444     errno = ETIMEDOUT;
00445     log_verbose2("Socket %d timed out", sock);
00446     return -1;
00447   }
00448 
00449   return recv(sock, buf, len, 0);
00450 }
00451 
00452 herror_t
00453 hsocket_recv(struct hsocket_t * sock, unsigned char * buffer, int total, int force, int *received)
00454 {
00455   herror_t status;
00456   size_t totalRead;
00457   size_t count;
00458 
00459 /* log_verbose3("Entering hsocket_recv(total=%d,force=%d)", total, force); */
00460 
00461   totalRead = 0;
00462   do
00463   {
00464 
00465 #ifdef HAVE_SSL
00466     if ((status = hssl_read(sock, buffer + totalRead, (size_t) total - totalRead, &count)) != H_OK)
00467     {
00468       log_warn2("hssl_read failed (%s)", herror_message(status));
00469       return status;
00470     }
00471 #else
00472     if ((count = hsocket_select_recv(sock->sock, buffer + totalRead, (size_t) total - totalRead)) == -1)
00473       return herror_new("hsocket_recv", HSOCKET_ERROR_RECEIVE, "recv failed (%s)", strerror(errno));
00474 #endif
00475     sock->bytes_received += count;
00476 
00477     if (!force)
00478     {
00479       /* log_verbose3("Leaving !force (received=%d)(status=%d)", *received,
00480          status); */
00481       *received = count;
00482       return H_OK;
00483     }
00484 
00485     totalRead += count;
00486 
00487     if (totalRead == total)
00488     {
00489       *received = totalRead;
00490       /* 
00491          log_verbose4("Leaving totalRead == total
00492          (received=%d)(status=%d)(totalRead=%d)", *received, status,
00493          totalRead); */
00494       return H_OK;
00495     }
00496   }
00497   while (1);
00498 }
00499 
00500 int
00501 hsocket_get_timeout(void)
00502 {
00503   return _hsocket_timeout;
00504 }
00505 
00506 void
00507 hsocket_set_timeout(int secs)
00508 {
00509   _hsocket_timeout = secs;
00510 
00511   return;
00512 }

Generated on Thu Jan 25 23:36:03 2007 for csoap by  doxygen 1.4.6