00001 #include <string>
00002 #include <sstream>
00003 #include <iostream>
00004 #include <errno.h>
00005 #include <sys/types.h>
00006 #include <unistd.h>
00007 #include <sys/socket.h>
00008 #include <netinet/in.h>
00009 #include <arpa/inet.h>
00010 #include <sys/select.h>
00011 #include <fcntl.h>
00012
00013 using namespace std;
00014
00015
00016 typedef string NetworkError;
00017
00019 class IPAddress
00020 {
00021 public:
00022 u_int32_t byte;
00023
00025 IPAddress()
00026 {
00027 byte=0;
00028 }
00030 IPAddress(const string &remote)
00031 {
00032 struct in_addr addr;
00033 if(!inet_aton(remote.c_str(), &addr))
00034 throw NetworkError("Could not convert '"+remote+"' to an IP address");
00035 byte=addr.s_addr;
00036 }
00037
00039 string asString() const
00040 {
00041 ostringstream o;
00042 const unsigned char *n=reinterpret_cast<const unsigned char*>(&byte);
00043 o<<(unsigned int)*n++<<".";
00044 o<<(unsigned int)*n++<<".";
00045 o<<(unsigned int)*n++<<".";
00046 o<<(int)*n++;
00047 return o.str();
00048 }
00049 };
00050
00051 typedef u_int16_t IPPort;
00052
00054 class IPEndpoint
00055 {
00056 public:
00057
00058 IPEndpoint(){}
00059 IPEndpoint(const string &remote, IPPort aport=0) : address(remote), port(aport){}
00060 IPAddress address;
00061 IPPort port;
00062 enum PortTypes {ANY=0};
00063 };
00064
00065
00066 enum AddressFamily {InterNetwork=AF_INET};
00067 enum SocketType {Datagram=SOCK_DGRAM,Stream=SOCK_STREAM};
00068 typedef int ProtocolType;
00069
00071 class Socket
00072 {
00073 private:
00074 Socket(const Socket &);
00075 Socket &operator=(const Socket &);
00076
00077 Socket(int fd)
00078 {
00079 d_buflen=1024;
00080 d_buffer=new char[d_buflen];
00081 d_socket=fd;
00082 }
00083 public:
00085 Socket(AddressFamily af, SocketType st, ProtocolType pt=0)
00086 {
00087 d_family=af;
00088 if((d_socket=socket(af,st, pt))<0)
00089 throw NetworkError(strerror(errno));
00090 d_buflen=1024;
00091 d_buffer=new char[d_buflen];
00092 }
00093
00094 ~Socket()
00095 {
00096 close(d_socket);
00097 delete[] d_buffer;
00098 }
00099
00101 Socket *accept()
00102 {
00103 struct sockaddr_in remote;
00104 socklen_t remlen=sizeof(remote);
00105 int s=::accept(d_socket,(sockaddr *)&remote, &remlen);
00106 if(s<0) {
00107 if(errno==EAGAIN)
00108 return 0;
00109
00110 throw NetworkError("Accepting a connection: "+string(strerror(errno)));
00111 }
00112 return new Socket(s);
00113 }
00114
00116 void setNonBlocking()
00117 {
00118 int flags=fcntl(d_socket,F_GETFL,0);
00119 if(flags<0 || fcntl(d_socket, F_SETFL,flags|O_NONBLOCK) <0)
00120 throw NetworkError("Setting socket to nonblocking: "+string(strerror(errno)));
00121 }
00122
00124 void bind(const IPEndpoint &ep)
00125 {
00126 struct sockaddr_in local;
00127 memset(reinterpret_cast<char *>(&local),0,sizeof(local));
00128 local.sin_family=d_family;
00129 local.sin_addr.s_addr=ep.address.byte;
00130 local.sin_port=htons(ep.port);
00131
00132 int tmp=1;
00133 if(setsockopt(d_socket,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0)
00134 throw NetworkError(string("Setsockopt failed: ")+strerror(errno));
00135
00136 if(::bind(d_socket,(struct sockaddr *)&local,sizeof(local))<0)
00137 throw NetworkError(strerror(errno));
00138 }
00139
00141
00144 void recvFrom(string &dgram, IPEndpoint &ep)
00145 {
00146 struct sockaddr_in remote;
00147 socklen_t remlen=sizeof(remote);
00148 int bytes;
00149 if((bytes=recvfrom(d_socket, d_buffer, d_buflen, 0, (sockaddr *)&remote, &remlen))<0)
00150 throw NetworkError(strerror(errno));
00151
00152 dgram.assign(d_buffer,bytes);
00153 ep.address.byte=remote.sin_addr.s_addr;
00154 ep.port=ntohs(remote.sin_port);
00155 }
00156
00158
00161 void sendTo(const string &dgram, const IPEndpoint &ep)
00162 {
00163 struct sockaddr_in remote;
00164 remote.sin_family=d_family;
00165 remote.sin_addr.s_addr=ep.address.byte;
00166 remote.sin_port=ntohs(ep.port);
00167
00168 if(sendto(d_socket, dgram.c_str(), dgram.size(), 0, (sockaddr *)&remote, sizeof(remote))<0)
00169 throw NetworkError(strerror(errno));
00170 }
00171
00173 void writen(const string &data)
00174 {
00175 int toWrite=data.length();
00176 int res;
00177 const char *ptr=data.c_str();
00178 do {
00179 res=::write(d_socket,ptr,toWrite);
00180 if(res<0)
00181 throw NetworkError("Writing to a socket: "+string(strerror(errno)));
00182 toWrite-=res;
00183 }while(toWrite);
00184 }
00185
00187
00191 unsigned int tryWrite(const char *ptr, int toWrite)
00192 {
00193 int res;
00194 res=::write(d_socket,ptr,toWrite);
00195 if(res==0)
00196 throw NetworkError("EOF on writing to a socket");
00197
00198 if(res>0)
00199 return res;
00200
00201 if(errno==EAGAIN)
00202 return 0;
00203
00204 throw NetworkError("Writing to a socket: "+string(strerror(errno)));
00205 }
00206
00208
00209 unsigned int write(const char *ptr, int toWrite)
00210 {
00211 int res;
00212 res=::write(d_socket,ptr,toWrite);
00213 if(res<0) {
00214 throw NetworkError("Writing to a socket: "+string(strerror(errno)));
00215 }
00216 return res;
00217 }
00218
00219
00221 int getchar()
00222 {
00223 char c;
00224
00225 int res=::read(d_socket,&c,1);
00226 if(res)
00227 return c;
00228 return -1;
00229 }
00230
00232 void read(string &data)
00233 {
00234 int res=::read(d_socket,d_buffer,d_buflen);
00235 if(res<0)
00236 throw NetworkError("Reading from a socket: "+string(strerror(errno)));
00237 data.assign(d_buffer,res);
00238 }
00239
00241 int read(char *buffer, int bytes)
00242 {
00243 int res=::read(d_socket,buffer,bytes);
00244 if(res<0)
00245 throw NetworkError("Reading from a socket: "+string(strerror(errno)));
00246 return res;
00247
00248 }
00249
00251 void listen(unsigned int length=10)
00252 {
00253 if(::listen(d_socket,length)<0)
00254 throw NetworkError("Setting socket to listen: "+string(strerror(errno)));
00255 }
00256
00258 int getHandle() const
00259 {
00260 return d_socket;
00261 }
00262
00263 private:
00264 int d_socket;
00265 char *d_buffer;
00266 int d_buflen;
00267 int d_family;
00268 };
00269
00271 class UDPListener
00272 {
00273 public:
00275 UDPListener(const IPEndpoint &ep)
00276 {
00277 d_ep=ep;
00278 initSocket();
00279 }
00281 UDPListener(IPPort port)
00282 {
00283 d_ep.address.byte=0;
00284 d_ep.port=port;
00285 initSocket();
00286 }
00288 UDPListener()
00289 {
00290 d_ep.address.byte=0;
00291 d_ep.port=0;
00292 initSocket();
00293 }
00294 ~UDPListener()
00295 {
00296 delete d_socket;
00297 }
00299 void recvFrom(string &dgram, IPEndpoint &remote)
00300 {
00301 d_socket->recvFrom(dgram,remote);
00302 }
00303
00305 void sendTo(const string &dgram, const IPEndpoint &remote)
00306 {
00307 d_socket->sendTo(dgram,remote);
00308 }
00309
00310 private:
00311 void initSocket()
00312 {
00313 d_socket=new Socket(InterNetwork, Datagram);
00314 d_socket->bind(d_ep);
00315 }
00316
00317
00318
00319 private:
00320 UDPListener(const UDPListener &);
00321 UDPListener &operator=(const UDPListener &);
00322 IPEndpoint d_ep;
00323 Socket *d_socket;
00324
00325 };