/* * Copyright (C) 1999 Peter Amstutz * * 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; either version 2 of *the * License, or (at your option) any later version. * * 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., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "tcpcore.h" #include "log.h" /* Function: tcpListen() Purpose: Create a listening socket on the specified port. */ int tcpListen(unsigned short int port) { struct sockaddr_in sa; int sock, set = 1; memset(&sa, 0, sizeof(struct sockaddr_in)); sa.sin_port = htons(port); sa.sin_family = AF_INET; sa.sin_addr.s_addr = INADDR_ANY; if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { logPrintf(CRITICAL, "Error creating socket: %s\n", strerror(errno)); return -1; } setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(int)); if(bind(sock, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) { logPrintf(CRITICAL, "Error binding socket: %s\n", strerror(errno)); return -1; } if(listen(sock, 10) < 0) { logPrintf(CRITICAL, "Error listening to socket: %s\n", strerror(errno)); return -1; } /* fcntl(sock, F_SETFL, O_NONBLOCK); */ return sock; } /* Function: tcpGetNewConnection() Purpose: gets the next queued connection on a tcp/ip listen socket */ int tcpGetNewConnection(int listener) { int ret; if(listener < 0 || (ret = accept(listener, NULL, 0)) < 0) { return -1; } return ret; } void tcpGetExact(int sock, char *store, int size) { int gotten = 0; do { gotten = recv(sock, store, size, 0); store += gotten; size -= gotten; } while(size > 0); } /* Function: tcpGetPacket() Purpose: retrives the next packet waiting from a connection */ int tcpGetPacket(int sock, char *store, int maxlen) { unsigned short int size; if(sock < 0 || store == NULL) return -1; tcpGetExact(sock, (char *) &size, 2); size = ntohs(size); tcpGetExact(sock, store, size > maxlen ? maxlen : size); return size; } /* Function: tcpSendPacket() Purpose: sends a packet out to a certain connection */ int tcpSendPacket(int sock, char *store, int datalen) { char *data; short unsigned int len; int ret; if(sock < 0 || store == NULL) return -1; data = (char *) malloc(datalen + 2); len = htons(datalen); memcpy(data, &len, 2); memcpy(data + 2, store, datalen); ret = send(sock, data, datalen + 2, 0); free(data); return ret; } /* Function: tcpSendPacket() Purpose: sends a "typed" packet out to a certain connection */ int tcpSendTypedPacket(int sock, char *type, char *store, int datalen) { char *data; short unsigned int len, tlen = strlen(type); int ret; if(sock < 0 || store == NULL) return -1; data = (char *) malloc(datalen + 2 + tlen); len = htons(datalen + tlen); memcpy(data, &len, 2); memcpy(data + 2, type, tlen); memcpy(data + 2 + tlen, store, datalen); ret = send(sock, data, datalen + 2 + tlen, 0); free(data); return ret; } /* Function: tcpDial() Purpose: establish a TCP/IP connection to some host */ int tcpDial(char *host, unsigned short int port) { struct hostent *hp; struct sockaddr_in sa; int sock; if(host == NULL) return -1; if((hp = gethostbyname(host)) == NULL) return -1; memset(&sa, 0, sizeof(struct sockaddr_in)); sa.sin_port = htons(port); sa.sin_family = AF_INET; sa.sin_addr = *((struct in_addr *) hp->h_addr); if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 || connect(sock, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)) < 0) { return -1; } return sock; } int tcpDataReady(int sock) { fd_set rfds; struct timeval tv; FD_ZERO(&rfds); FD_SET(sock, &rfds); tv.tv_sec = 0; tv.tv_usec = 0; select(sock + 1, &rfds, NULL, NULL, &tv); return FD_ISSET(sock, &rfds); }