00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <stdio.h>
00038
00039 #include <sys/types.h>
00040 #include <sys/time.h>
00041 #include <sys/stat.h>
00042 #include <fcntl.h>
00043 #include <unistd.h>
00044 #include <errno.h>
00045
00046 #ifdef __WIN32__
00047 #include <winsock.h>
00048 #else
00049 #include <sys/socket.h>
00050 #include <netdb.h>
00051 #include <netinet/in.h>
00052 #endif
00053
00054 #include <FileDescriptor.h>
00055 #include <SocketDescriptor.h>
00056
00057 #if defined(hpux) || defined(__WIN32__)
00058
00059
00060 typedef int socklen_t;
00061 #endif
00062
00063
00064
00065 #ifdef __WIN32__
00066
00067 class Win32SocketManager {
00068 public:
00069 Win32SocketManager() {
00070 WSADATA wsaData;
00071 int result = WSAStartup(1, &wsaData);
00072 if (result) {
00073 fprintf(stderr, "Could not initialise winsock (WSAStartup returned %d)\n",
00074 result);
00075 exit(1);
00076 }
00077 }
00078
00079 ~Win32SocketManager() {
00080 WSACleanup();
00081 }
00082 };
00083
00084 static Win32SocketManager win32SocketManager;
00085
00086 #endif
00087
00088
00089
00090 int SocketDescriptor::lowlevel_read(int fd, char *buf, int len) {
00091 #ifdef __WIN32__
00092 int result = ::recv(getFd(), buf, len, 0);
00093
00094 if (result != SOCKET_ERROR) {
00095 return result;
00096 }
00097
00098 int sockerrno = WSAGetLastError();
00099 switch (sockerrno) {
00100 case WSAECONNRESET:
00101
00102 return 0;
00103
00104 case WSAEWOULDBLOCK:
00105
00106
00107
00108
00109 errno = EAGAIN;
00110 return -1;
00111
00112 default:
00113 fprintf(stderr, "SocketDescriptor::lowlevel_read: Got WSAGetLastError of %d (0x%x)\n",
00114 sockerrno, sockerrno);
00115 return 0;
00116 }
00117
00118 #else
00119 return ::read(getFd(), buf, len);
00120 #endif
00121 }
00122
00123 int SocketDescriptor::lowlevel_write(int fd, char const *buf, int len) {
00124 #ifdef linux
00125 return ::send(getFd(), buf, len, MSG_NOSIGNAL);
00126 #else
00127 # ifdef __WIN32__
00128 return ::send(getFd(), buf, len, 0);
00129 # else
00130 return ::write(getFd(), buf, len);
00131 # endif
00132 #endif
00133 }
00134
00135 #ifdef __WIN32__
00136 int SocketDescriptor::lowlevel_close(int fd) {
00137 return ::closesocket(fd);
00138 }
00139 #endif
00140
00141 void SocketDescriptor::close() {
00142 shutdown(getFd(), 2);
00143 FileDescriptor::close();
00144 }
00145
00146
00147
00148 static bool getAddrByName(string const &name, unsigned int &addr) {
00149 #ifdef __WIN32__
00150
00151 unsigned long dottedAddr = inet_addr(name.c_str());
00152 if (dottedAddr != INADDR_NONE) {
00153 addr = dottedAddr;
00154 return true;
00155 }
00156 #endif
00157
00158 struct hostent *he = gethostbyname(name.c_str());
00159
00160 if (he == NULL)
00161 return false;
00162
00163 addr = * (int *) he->h_addr_list[0];
00164 return true;
00165 }
00166
00167 static string getNameByAddr(char const *addr) {
00168 struct hostent *h = gethostbyaddr(addr, 4, AF_INET);
00169
00170 if (h == NULL) {
00171 char buf[20];
00172 sprintf(buf, "%u.%u.%u.%u",
00173 ((unsigned char *) addr)[0],
00174 ((unsigned char *) addr)[1],
00175 ((unsigned char *) addr)[2],
00176 ((unsigned char *) addr)[3]);
00177 return buf;
00178 }
00179
00180 return h->h_name;
00181 }
00182
00183
00184
00185 ClientSocketDescriptor::ClientSocketDescriptor(ref<FileDescriptorManager> const &_fdMgr,
00186 string const &_hostname, int _port)
00187 : SocketDescriptor(_fdMgr, socket(PF_INET, SOCK_STREAM, 0))
00188 {
00189 if (!isOpen())
00190 throw Exception("Could not create socket in ClientSocketDescriptor ctor", errno);
00191
00192 int sock = getFd();
00193
00194 setRemoteAddr(_hostname, _port);
00195
00196 unsigned int connectaddr;
00197 if (!getAddrByName(_hostname, connectaddr)) {
00198 close();
00199 throw Exception("Host " + _hostname + " not found in ClientSocketDescriptor ctor");
00200 }
00201
00202 struct sockaddr_in addr;
00203 addr.sin_family = AF_INET;
00204 addr.sin_port = htons(_port);
00205 addr.sin_addr.s_addr = connectaddr;
00206
00207 if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00208 int savedErrno = errno;
00209 close();
00210 throw Exception("Could not connect() in ClientSocketDescriptor ctor", savedErrno);
00211 }
00212
00213
00214 socklen_t addrlen = sizeof(addr);
00215 if (getsockname(sock, (struct sockaddr *) &addr, &addrlen) != -1) {
00216 setLocalAddr(getNameByAddr((char *) &addr.sin_addr.s_addr), ntohs(addr.sin_port));
00217 }
00218 }
00219
00220
00221
00222 ServerSocketDescriptor::ServerSocketDescriptor(ref<FileDescriptorManager> const &_fdMgr,
00223 int _port = 0, string const &_hostname = "")
00224 : SocketDescriptor(_fdMgr, socket(PF_INET, SOCK_STREAM, 0))
00225 {
00226 if (!isOpen())
00227 throw Exception("Could not create socket in ServerSocketDescriptor ctor", errno);
00228
00229 int fd = getFd();
00230
00231 {
00232 int i = 1;
00233
00234 #ifdef __WIN32__
00235 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &i, sizeof(i));
00236 #else
00237 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
00238 #endif
00239 }
00240
00241 unsigned int bindaddr;
00242 unsigned int localaddr;
00243
00244 if (_hostname != "") {
00245
00246
00247 if (!getAddrByName(_hostname, bindaddr)) {
00248 close();
00249 throw Exception("Host " + _hostname + " not found in ServerSocketDescriptor ctor");
00250 }
00251 localaddr = bindaddr;
00252 } else {
00253
00254
00255 char buf[256];
00256 if (gethostname(buf, 256) < 0) {
00257 close();
00258 throw Exception("Could not determine local hostname using gethostname(2)");
00259 }
00260
00261 bindaddr = INADDR_ANY;
00262 if (!getAddrByName(buf, localaddr)) {
00263 localaddr = INADDR_ANY;
00264 }
00265 }
00266
00267 struct sockaddr_in sa;
00268 sa.sin_family = AF_INET;
00269 sa.sin_port = htons(_port);
00270 sa.sin_addr.s_addr = bindaddr;
00271
00272 if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
00273 char nbuf[40];
00274 sprintf(nbuf, "%d", _port);
00275 close();
00276 throw Exception("Could not bind to " + _hostname + ":" + nbuf);
00277 }
00278
00279 if (listen(fd, 50) < 0) {
00280 close();
00281 throw Exception("Could not listen on socket");
00282 }
00283
00284
00285
00286 socklen_t socknamelen = sizeof(sa);
00287
00288 if (getsockname(fd, (struct sockaddr *) &sa, &socknamelen) < 0) {
00289 close();
00290 throw Exception("Could not determine local ServerSocket name");
00291 }
00292
00293 {
00294 char addrbuf[100];
00295 sprintf(addrbuf, "%u.%u.%u.%u:%d",
00296 ((unsigned char *) &localaddr)[0],
00297 ((unsigned char *) &localaddr)[1],
00298 ((unsigned char *) &localaddr)[2],
00299 ((unsigned char *) &localaddr)[3],
00300 ntohs(sa.sin_port));
00301
00302 canonicalAddress = addrbuf;
00303 setLocalAddr(getNameByAddr((char *) &localaddr), ntohs(sa.sin_port));
00304 }
00305 }
00306
00307 ref<SocketDescriptor> ServerSocketDescriptor::accept() {
00308 struct sockaddr_in sa;
00309 socklen_t salen = sizeof(sa);
00310
00311 int newfd = ::accept(getFd(), (struct sockaddr *) &sa, &salen);
00312 if (newfd == -1) {
00313 throw Exception("Could not accept() on ServerSocket", errno);
00314 }
00315
00316 ref<SocketDescriptor> sock = new SocketDescriptor(getFdMgr(), newfd);
00317 sock->setRemoteAddr(getNameByAddr((char *) &sa.sin_addr.s_addr), ntohs(sa.sin_port));
00318
00319 salen = sizeof(sa);
00320 if (getsockname(sock->getFd(), (struct sockaddr *) &sa, &salen) == -1) {
00321 throw Exception("Could not determine local ServerSocket name");
00322 }
00323
00324 sock->setLocalAddr(getNameByAddr((char *) &sa.sin_addr.s_addr), ntohs(sa.sin_port));
00325
00326 return sock;
00327 }