Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

SocketAccessor.cc

Go to the documentation of this file.
00001 /*
00002  * SocketAccessor.cc
00003  *
00004  * Smalltalk like class library for C++
00005  * Accessor to BSD socket.
00006  *
00007  * Copyright (c) 2004 - 2006 Milan Cermak
00008  */
00009 /*
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  */
00024 #include <stlib/net/SocketAccessor.h>
00025 #include <stlib/net/IPSocketAddress.h>
00026 
00027 #include <stlib/net/NetworkError.h>
00028 
00029 #include <stlib/ByteArray.h>
00030 #include <stlib/GenericException.h>
00031 #include <stlib/Number.h>
00032 #include <stlib/String.h>
00033 #include <stlib/OSError.h>
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <unistd.h>
00039 #include <errno.h>
00040 #include <netinet/in.h>
00041 #include <sys/types.h>
00042 #include <sys/socket.h>
00043 
00044 using namespace Net;
00045 
00046 SocketAccessor::SocketAccessor(int family, int type, int protocol)
00047 {
00048     /* Zalozime socket */
00049     sckFamily = family;
00050     descriptor = socket(family, type, 0);
00051     if (descriptor < 0) {
00052         /* Nepodarilo se zalozit socket */
00053         perror(__PRETTY_FUNCTION__);
00054         NetworkError *ex;
00055         ex = new NetworkError(new String("Cannot create new socket."),
00056                               __PRETTY_FUNCTION__);
00057         ex->raiseFrom(this);
00058     }
00059 }
00060 
00061 SocketAccessor::SocketAccessor(int desc)
00062 {
00063     descriptor = desc;
00064 }
00065 
00066 /* Class-accessing protocol */
00067 String *SocketAccessor::className(void) const
00068 {
00069     return new String("SocketAccessor");
00070 }
00071 
00072 /* Instance creation protocol */
00073 SocketAccessor *SocketAccessor::newTCP(void)
00074 {
00075     SocketAccessor *skt;
00076     IPSocketAddress *sa;
00077 
00078     skt = new SocketAccessor(AF_INET, SOCK_STREAM);
00079     try {
00080         sa = IPSocketAddress::thisHostAnyPort();
00081         skt->bindTo(sa);
00082     }
00083     catch (NetworkError *ex) {
00084         skt->close();
00085         ex->pass();
00086     }
00087     return skt;
00088 }
00089 
00090 SocketAccessor *SocketAccessor::newTCPclientToHost(ByteArray *hostAddr, int port)
00091 {
00092     SocketAccessor *skt;
00093     IPSocketAddress *fa;
00094 
00095     skt = new SocketAccessor(AF_INET, SOCK_STREAM);
00096     try {
00097         fa = IPSocketAddress::hostAddress(hostAddr, port);
00098         skt->connectTo(fa);
00099     }
00100     catch (NetworkError *ex) {
00101         skt->close();
00102         ex->pass();
00103     }
00104     return skt;
00105 }
00106 
00107 SocketAccessor *SocketAccessor::newTCPclientToHost(String *hostName, int port)
00108 {
00109     SocketAccessor *skt;
00110     IPSocketAddress *fa;
00111 
00112     skt = new SocketAccessor(AF_INET, SOCK_STREAM);
00113     try {
00114         fa = IPSocketAddress::hostName(hostName, port);
00115         skt->connectTo(fa);
00116     }
00117     catch (NetworkError *ex) {
00118         skt->close();
00119         ex->pass();
00120     }
00121     return skt;
00122 }
00123 
00124 SocketAccessor *SocketAccessor::newTCPserverAtPort(int port)
00125 {
00126     return newTCPserverAt(IPSocketAddress::thisHost(), port);
00127 }
00128 
00129 SocketAccessor *SocketAccessor::newTCPserverAt(ByteArray *addr, int port)
00130 {
00131     SocketAccessor *skt;
00132     IPSocketAddress *sa;
00133 
00134     skt = new SocketAccessor(AF_INET, SOCK_STREAM);
00135     try {
00136         sa = IPSocketAddress::hostAddress(addr, port);
00137         skt->bindTo(sa);
00138     }
00139     catch (NetworkError *ex) {
00140         skt->close();
00141         ex->pass();
00142     }
00143     return skt;
00144 }
00145 
00146 SocketAccessor *SocketAccessor::newUDP(void)
00147 {
00148     SocketAccessor *skt;
00149     IPSocketAddress *sa;
00150 
00151     skt = new SocketAccessor(AF_INET, SOCK_DGRAM);
00152     try {
00153         sa = IPSocketAddress::thisHostAnyPort();
00154         skt->bindTo(sa);
00155     }
00156     catch (NetworkError *ex) {
00157         skt->close();
00158         ex->pass();
00159     }
00160     return skt;
00161 }
00162 
00163 
00164 SocketAccessor *SocketAccessor::newUDPclientToHost(ByteArray *hostAddr, int port)
00165 {
00166     SocketAccessor *skt;
00167     IPSocketAddress *fa;
00168 
00169     skt = new SocketAccessor(AF_INET, SOCK_DGRAM);
00170     try {
00171         fa = IPSocketAddress::hostAddress(hostAddr, port);
00172         skt->connectTo(fa);
00173     }
00174     catch (NetworkError *ex) {
00175         skt->close();
00176         ex->pass();
00177     }
00178     return skt;
00179 }
00180 
00181 SocketAccessor *SocketAccessor::newUDPclientToHost(String *hostName, int port)
00182 {
00183     SocketAccessor *skt;
00184     IPSocketAddress *fa;
00185 
00186     skt = new SocketAccessor(AF_INET, SOCK_DGRAM);
00187     try {
00188         fa = IPSocketAddress::hostName(hostName, port);
00189         skt->connectTo(fa);
00190     }
00191     catch (NetworkError *ex) {
00192         skt->close();
00193         ex->pass();
00194     }
00195     return skt;
00196 }
00197 
00198 SocketAccessor *SocketAccessor::newUDPserverAtPort(int port)
00199 {
00200     return newUDPserverAt(IPSocketAddress::thisHost(), port);
00201 }
00202 
00203 SocketAccessor *SocketAccessor::newUDPserverAt(ByteArray *addr, int port)
00204 {
00205     SocketAccessor *skt;
00206     IPSocketAddress *sa;
00207 
00208     skt = new SocketAccessor(AF_INET, SOCK_DGRAM);
00209     try {
00210         sa = IPSocketAddress::hostAddress(addr, port);
00211         skt->bindTo(sa);
00212     }
00213     catch (NetworkError *ex) {
00214         skt->close();
00215         ex->pass();
00216     }
00217     return skt;
00218 }
00219 
00220 /* Class-accessing protocol */
00221 String *SocketAccessor::getHostname(void)
00222 {
00223     return new String(getenv("HOSTNAME"));
00224 }
00225 
00226 /* Initialize-release protocol */
00227 void SocketAccessor::close(void)
00228 {
00229     ::close(descriptor);
00230 }
00231 
00232 /* Accessing protocol */
00233 long SocketAccessor::bufferSize(void)
00234 {
00235     return 20480;
00236 }
00237 
00238 IPSocketAddress *SocketAccessor::myAddress(void)
00239 {
00240     struct sockaddr_in addr;
00241     socklen_t addrLength = sizeof(addr);
00242     int retCode;
00243 
00244     retCode = getsockname(descriptor, (struct sockaddr *) &addr, &addrLength);
00245     if (retCode == 0) {
00246         union {
00247             long int number;
00248             char array[4];
00249         } converter;
00250         converter.number = addr.sin_addr.s_addr;
00251         ByteArray *baAddr = new ByteArray(converter.array, 4);
00252         return IPSocketAddress::hostAddress(baAddr, ntohs(addr.sin_port));
00253     }
00254     return nil;
00255 }
00256 
00257 IPSocketAddress *SocketAccessor::peerAddress(void)
00258 {
00259     struct sockaddr_in addr;
00260     socklen_t addrLength = sizeof(addr);
00261     int retCode;
00262 
00263     retCode = getpeername(descriptor, (struct sockaddr *) &addr, &addrLength);
00264     if (retCode == 0) {
00265         union {
00266             long int number;
00267             char array[4];
00268         } converter;
00269         converter.number = addr.sin_addr.s_addr;
00270         ByteArray *baAddr = new ByteArray(converter.array, 4);
00271         return IPSocketAddress::hostAddress(baAddr, ntohs(addr.sin_port));
00272     }
00273     return nil;
00274 }
00275 
00276 /* Data transfer protocol */
00277 int SocketAccessor::readInto(ByteArray *buffer, long startIndex, long count)
00278 {
00279     unsigned char bytes[count + 1];
00280     int retCode;
00281 
00282     do {
00283         retCode = recv(descriptor, bytes, count, 0);
00284     } while (retCode == -1 && errno == EINTR);
00285 
00286     if (retCode < 0) {
00287         (new OSError(new String(sys_errlist[errno]), __PRETTY_FUNCTION__))
00288             ->raiseFrom(this);
00289     }
00290 
00291     if (retCode > 0) {
00292         buffer->replace(startIndex, startIndex+retCode, bytes);
00293     }
00294     return retCode;
00295 }
00296 
00297 int SocketAccessor::writeFrom(ByteArray *buffer, long startIndex, long count)
00298 {
00299     int retCode = send(descriptor, &(buffer->rawBytesReadOnly())[startIndex], count, MSG_NOSIGNAL);
00300     if (retCode < 0) {
00301         /* Vyhodit nejakou chybu */
00302         (new OSError(new String(sys_errlist[errno]), __PRETTY_FUNCTION__))
00303             ->raiseFrom(this);
00304     }
00305     return retCode;
00306 }
00307 
00308 /* Positioning protocol */
00309 void SocketAccessor::seekTo(long position)
00310 {
00311     shouldNotImplement(__PRETTY_FUNCTION__);
00312 }
00313 
00314 /* Synchronization protocol */
00315 void SocketAccessor::readWait(void)
00316 {
00317     fd_set rfds;
00318     int retCode;
00319 
00320     /* Watch for event on socket */
00321     FD_ZERO(&rfds);
00322     FD_SET(descriptor, &rfds);
00323     do {
00324         retCode = select(descriptor+1, &rfds, NULL, NULL, NULL);
00325     } while (retCode == -1 && errno == EINTR);
00326 
00327     if (retCode < 0)
00328         (new OSError(new String(sys_errlist[errno]), __PRETTY_FUNCTION__))
00329             ->raiseFrom(this);
00330 }
00331 
00332 bool SocketAccessor::readWaitWithTimeout(int milliseconds)
00333 {
00334     fd_set rfds;
00335     struct timeval tv;
00336     int retCode;
00337 
00338     /* Watch for event on socket */
00339     FD_ZERO(&rfds);
00340     FD_SET(descriptor, &rfds);
00341     tv.tv_sec = milliseconds / 1000;
00342     tv.tv_usec = (milliseconds % 1000) * 1000;
00343     retCode = select(descriptor+1, &rfds, NULL, NULL, &tv);
00344 
00345     if (retCode < 0) {
00346         /* Report stop-by-interrupt as timeout */
00347         if (errno == EINTR) return true;
00348         /* Otherwise raise an exception */
00349         (new OSError(new String(sys_errlist[errno]), __PRETTY_FUNCTION__))
00350             ->raiseFrom(this);
00351     }
00352 
00353     return (retCode > 0 && FD_ISSET(descriptor, &rfds)) ? false : true;
00354 }
00355 
00356 void SocketAccessor::writeWait(void)
00357 {
00358     fd_set wfds;
00359     int retCode;
00360 
00361     /* Watch for event on socket */
00362     FD_ZERO(&wfds);
00363     FD_SET(descriptor, &wfds);
00364     do {
00365         retCode = select(descriptor+1, NULL, &wfds, NULL, NULL);
00366     } while (retCode == -1 && errno == EINTR);
00367 
00368     if (retCode < 0)
00369         (new OSError(new String(sys_errlist[errno]), __PRETTY_FUNCTION__))
00370             ->raiseFrom(this);
00371 }
00372 
00373 bool SocketAccessor::writeWaitWithTimeout(int milliseconds)
00374 {
00375     fd_set wfds;
00376     struct timeval tv;
00377     int retCode;
00378 
00379     /* Watch for event on socket */
00380     FD_ZERO(&wfds);
00381     FD_SET(descriptor, &wfds);
00382     tv.tv_sec = milliseconds / 1000;
00383     tv.tv_usec = (milliseconds % 1000) * 1000;
00384     retCode = select(descriptor+1, NULL, &wfds, NULL, &tv);
00385 
00386     if (retCode < 0) {
00387         /* Report stop-by-interrupt as timeout */
00388         if (errno == EINTR) return true;
00389         /* Otherwise raise an exception */
00390         (new OSError(new String(sys_errlist[errno]), __PRETTY_FUNCTION__))
00391             ->raiseFrom(this);
00392     }
00393 
00394     return (retCode > 0 && FD_ISSET(descriptor, &wfds)) ? false : true;
00395 }
00396 
00397 /* State transitions protocol */
00398 void SocketAccessor::bindTo(IPSocketAddress *address)
00399 {
00400     struct sockaddr_in IPaddr;
00401     int result;
00402 
00403     bzero(&IPaddr, sizeof(IPaddr));
00404     IPaddr.sin_family = sckFamily;
00405     IPaddr.sin_addr.s_addr = htonl(address->hostAddress()->asInteger());
00406     IPaddr.sin_port = htons(address->port());
00407     result = bind(descriptor, (struct sockaddr *) &IPaddr, sizeof(IPaddr));
00408     if (result < 0) {
00409         /* Socketu se nepodarilo priradit jmeno */
00410         perror(__PRETTY_FUNCTION__);
00411         NetworkError *ex;
00412         ex = new NetworkError(new String("Cannot bind socket to machine."),
00413                               __PRETTY_FUNCTION__, address);
00414         ex->raiseFrom(this);
00415     }
00416 }
00417 
00418 void SocketAccessor::connectTo(IPSocketAddress *address)
00419 {
00420     struct sockaddr_in IPaddr;
00421     int result;
00422 
00423     /* Pripojime se k serveru */
00424     bzero((char *) &IPaddr, sizeof(IPaddr));
00425     IPaddr.sin_family = sckFamily;
00426     IPaddr.sin_addr.s_addr = htonl(address->hostAddress()->asInteger());
00427     IPaddr.sin_port = htons(address->port());
00428     result = connect(descriptor, (struct sockaddr *) &IPaddr, sizeof(IPaddr));
00429     if (result < 0) {
00430         /* Nepodarilo se navazat spojeni */
00431         NetworkError *ex;
00432         ex = new NetworkError(new String("Cannot open connection to remote machine."),
00433                               __PRETTY_FUNCTION__, address);
00434         ex->raiseFrom(this);
00435     }
00436 }
00437 
00438 void SocketAccessor::listenFor(int queueLength)
00439 {
00440     int result = listen(descriptor, queueLength);
00441     if (result < 0) {
00442         /* Nepodarilo se navazat spojeni */
00443         perror(__PRETTY_FUNCTION__);
00444         NetworkError *ex;
00445         ex = new NetworkError(new String("Socket cannot listen on the port."),
00446                               __PRETTY_FUNCTION__);
00447         ex->raiseFrom(this);
00448     }
00449 }
00450 
00451 /* Instance creation protocol */
00452 SocketAccessor *SocketAccessor::accept(void)
00453 {
00454     int result;
00455 
00456     do {
00457         result = ::accept(descriptor, NULL, NULL);
00458     } while (result == -1 && errno == EINTR);
00459 
00460     if (result < 0) {
00461         perror(__PRETTY_FUNCTION__);
00462         NetworkError *ex;
00463         ex = new NetworkError(new String("Accept failed."), __PRETTY_FUNCTION__);
00464         ex->raiseFrom(this);
00465     }
00466     return new SocketAccessor(result);
00467 }

Generated on Mon Nov 27 09:47:55 2006 for Smalltalk like C++ Class Library by  doxygen 1.4.2