tcp.c

Go to the documentation of this file.
00001 #include "tcp.h"
00002 
00003 #ifndef WINSOCK
00004 #       include <netdb.h>
00005 #       include <netinet/in.h>
00006 #       include <fcntl.h>
00007 #else
00008 static int initialized = 0;
00009 static WSADATA wsaData;
00010 
00011 /** Initialize Winsock.
00012  * @return 0 on success, TCP_ERROR on failure.
00013  */
00014 static inline int initialize() {
00015         if(!initialized) {
00016                 if(WSAStartup(MAKEWORD(1, 1), &wsaData)) {
00017                         return TCP_ERROR;
00018                 }
00019         }
00020         return 0;
00021 }
00022 #endif /* WINSOCK */
00023 
00024 /** Set the IP address and port number in a sockaddr_in struct.
00025  * @param addr The structure whose fields will be set.
00026  * @param host The host to set. If NULL, the socket address will be
00027  *             INADDR_ANY, meaning all local addresses. If not NULL,
00028  *             the host must be an IPv4 address in dotted quad notation,
00029  *             or a hostname, which will be resolved to an IP address.
00030  * @param port The port number to set.
00031  *
00032  * @return 0 on success, TCP_ERROR on failure.
00033  */
00034 static int set_sockaddr(struct sockaddr_in *addr,
00035         const char *host, int port) {
00036         struct hostent *he;
00037 
00038         if(host) {
00039                 /* Lookup hostname */
00040                 he = gethostbyname(host);
00041                 if(!he) {
00042                         return TCP_ERROR;
00043                 }
00044 
00045                 /* Copy address into struct */
00046                 memcpy(&addr->sin_addr, he->h_addr, he->h_length);
00047         } else {
00048                 /* No hostname given, use all local addresses */
00049                 addr->sin_addr.s_addr = INADDR_ANY;
00050         }
00051 
00052         /* Initialize rest of struct */
00053         addr->sin_family = AF_INET;
00054         addr->sin_port = htons((short) port);
00055         
00056         return 0;
00057 }
00058 
00059 /** Make a new TCP socket.
00060  * @return The new TCP_SOCKET on success; TCP_ERROR on failure.
00061  */
00062 static TCP_SOCKET make_socket() {
00063         TCP_SOCKET sock;
00064 
00065         /* Create socket */
00066         sock = socket(AF_INET, SOCK_STREAM, 0);
00067 #       ifdef WINSOCK
00068         if(sock == INVALID_SOCKET) return TCP_ERROR;
00069 #       else
00070         if(sock < 0) return TCP_ERROR;
00071 #       endif
00072         
00073         return sock;
00074 }
00075 
00076 /** Make a TCP connection to the specified host on the specified port.
00077  * @param host The host (name or IP address) of the machine to connect to.
00078  * @param port The port number to connect to.
00079  *
00080  * @return The new TCP_CONNECTION on success; TCP_ERROR on failure.
00081  */
00082 TCP_CONNECTION tcp_connect(const char *host, int port) {
00083         struct sockaddr_in addr;
00084         int sock;
00085 
00086 #       ifdef WINSOCK
00087         /* Initialize library, if necessary */
00088         if(initialize() == TCP_ERROR) return TCP_ERROR;
00089 #       endif
00090 
00091         /* Initialize socket address */
00092         if(set_sockaddr(&addr, host, port) == TCP_ERROR) return TCP_ERROR;
00093 
00094         /* Create socket */
00095         sock = make_socket();
00096         if(sock == TCP_ERROR) return TCP_ERROR;
00097 
00098         /* Connect */
00099 #       ifdef WINSOCK
00100         if(connect(sock, (struct sockaddr*) &addr, sizeof(addr)) ==
00101                 SOCKET_ERROR) {
00102 #       else
00103         if(connect(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0) {
00104 #       endif /* WINSOCK */
00105                 tcp_close(sock);
00106                 return TCP_ERROR;
00107         }
00108 
00109         return sock;
00110 }
00111 
00112 /** Close a TCP connection.
00113  * @param conn The connection to close.
00114  * @return 0 on success. Any other value indicates failure.
00115  */
00116 int tcp_close(TCP_CONNECTION conn) {
00117 #       ifdef WINSOCK
00118         return closesocket(conn);
00119 #       else
00120         return close(conn);
00121 #endif
00122 }
00123 
00124 /** Read from a TCP connection.
00125  * Up to @a len bytes are read and placed into @a buf. Note that the number
00126  * of bytes read may be less than @a len.
00127  *
00128  * @param conn The connection to read from.
00129  * @param buf The buffer to place the bytes into.
00130  * @param len The maximum number of bytes to read; typically equal to
00131  *            the size of buf.
00132  *
00133  * @return The number of bytes actually read on success; a negative
00134  *         value on failure. A return value of 0 indicates the end of
00135  *         the transmission.
00136  */
00137 int tcp_read(TCP_CONNECTION conn, void *buf, int len) {
00138         return tcp_recv(conn, buf, len, 0);
00139 }
00140 
00141 /** Write to a TCP connection.
00142  * Writes up to @a len bytes from @a buf to the connection @a conn.
00143  * Note that fewer than @a len bytes may be written. Always check the
00144  * return value, which indicates the number of bytes actually written.
00145  *
00146  * @param conn The connection to write to.
00147  * @param buf The buffer containing the bytes to be written.
00148  * @param len The maximum number of bytes to write.
00149  *
00150  * @return The number of bytes written on success; a negative value on
00151  *         failure.
00152  */
00153 int tcp_write(TCP_CONNECTION conn, const void *buf, int len) {
00154         return tcp_send(conn, buf, len, 0);
00155 }
00156 
00157 /** Make a connection blocking on nonblocking.
00158  * Blocking affects what happens when a read is performed on a
00159  * connection when there are not currently any bytes available to be
00160  * read. A blocking connection will block the read until bytes are
00161  * available. A non-blocking connection will signal an error and set
00162  * errno to EAGAIN.
00163  *
00164  * A blocking connection should be used when you want to read bytes from the
00165  * connection and, if none are currently available, wait until they are.
00166  *
00167  * Non-blocking connections should be used when you want to read bytes
00168  * from a connection, but, if none are currently available, do
00169  * something else instead.
00170  *
00171  * @param conn The connection to adjust.
00172  * @param blocking 0 to make the connection blocking, any other value
00173  *                 to make it nonblocking. 
00174  *
00175  * @return 0 on success, TCP_ERROR on failure.
00176  */
00177 int tcp_setblocking(TCP_CONNECTION conn, int blocking) {
00178 #       ifdef WINSOCK
00179         u_long arg = !blocking;
00180 
00181         return ioctlsocket(conn, FIONBIO, &arg);
00182 #       else
00183         int flags;
00184 
00185         flags = fcntl(conn, F_GETFL, 0);
00186         if(flags < 0) return TCP_ERROR;
00187         return fcntl(conn, F_SETFL, blocking ?
00188                 flags | O_NONBLOCK :
00189                 flags & ~(O_NONBLOCK));
00190 #       endif   
00191 }
00192 
00193 /** Listen for incoming connections.
00194  * @param host The address to listen on. Use NULL to listen on all
00195  *             local adresses.
00196  * @param port The port to listen on.
00197  *
00198  * @return A new TCP_SOCKET on success, TCP_ERROR on failure.
00199  */
00200 TCP_SOCKET tcp_listen(const char *host, int port) {
00201         struct hostent *he;
00202         struct sockaddr_in addr;
00203         int sock;
00204 
00205 #       ifdef WINSOCK
00206         /* Initialize library, if necessary */
00207         if(initialize() == TCP_ERROR) return TCP_ERROR;
00208 #       endif
00209 
00210         /* Initialize socket address */
00211         if(set_sockaddr(&addr, host, port) == TCP_ERROR) return TCP_ERROR;
00212 
00213         /* Create socket */
00214         sock = make_socket();
00215         if(sock == TCP_ERROR) return TCP_ERROR;
00216 
00217         /* Bind and start listening */
00218 #       ifdef WINSOCK
00219         if(bind(sock, (struct sockaddr*) &addr, sizeof(addr)) ==
00220                 SOCKET_ERROR || listen(sock, 3) == SOCKET_ERROR) {
00221 #       else
00222         if(bind(sock, (struct sockaddr*) &addr, sizeof(addr)) < 0 ||
00223                 listen(sock, 3) < 0) {
00224 #       endif /* WINSOCK */
00225                 tcp_close(sock);
00226                 return TCP_ERROR;
00227         }
00228 
00229         return sock;
00230 }
00231 
00232 /** Accept an incoming connection.
00233  * @param sock The socket to accept the connection on.
00234  * @return The new connection.
00235  */
00236 TCP_CONNECTION tcp_accept(TCP_SOCKET sock) {
00237 #       ifdef WINSOCK
00238         return accept(sock, 0, 0);
00239 #       else
00240         int conn;
00241 
00242         conn = accept(sock, 0, 0);
00243         return conn < 0 ? TCP_ERROR : conn;
00244 #       endif /* WINSOCK */
00245 }

Generated on Tue Dec 25 09:41:11 2007 for libtcp by  doxygen 1.5.1