|
rllib
1
|
00001 /*************************************************************************** 00002 rlsocket.cpp - description 00003 ------------------- 00004 begin : Tue Jan 02 2001 00005 copyright : (C) 2001 by Rainer Lehrig 00006 email : lehrig@t-online.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This library is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as * 00013 * published by the Free Software Foundation * 00014 * * 00015 ***************************************************************************/ 00016 #include "rldefine.h" 00017 00018 #ifndef IS_OLD_MSVCPP 00019 #ifndef __VMS 00020 #define AF_INET6_IS_AVAILABLE 00021 #endif 00022 #endif 00023 00024 #ifdef RLWIN32 00025 #include <windows.h> 00026 #ifdef IS_OLD_MSVCPP 00027 #include <winsock.h> 00028 #else 00029 //#if (_WIN32_WINNT < 0x0501) 00030 //#warning mingw does not have helpers modify mingw header in ws2tcpip.h 00031 #include <winsock2.h> 00032 #include <ws2tcpip.h> 00033 void WSAAPI freeaddrinfo(struct addrinfo*); 00034 int WSAAPI getaddrinfo(const char*,const char*,const struct addrinfo*, struct addrinfo**); 00035 int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD, char*,DWORD,int); 00036 //#undef AF_INET6_IS_AVAILABLE 00037 //#endif 00038 #endif 00039 #include <io.h> 00040 #include <direct.h> 00041 #define MSG_NOSIGNAL 0 00042 #else 00043 #include <sys/time.h> 00044 #include <sys/socket.h> 00045 #include <netinet/in.h> 00046 #include <arpa/inet.h> 00047 #include <netdb.h> 00048 #include "unistd.h" 00049 #endif 00050 00051 #ifdef __VMS 00052 #define MSG_NOSIGNAL 0 00053 #endif 00054 00055 #ifdef PVMAC 00056 #define MSG_NOSIGNAL 0 00057 #endif 00058 00059 #include <stdio.h> 00060 #include <stdarg.h> 00061 #include <string.h> 00062 #include "rlsocket.h" 00063 #include "rlwthread.h" 00064 #include "rlcutil.h" 00065 00066 /* windows stuff */ 00067 int rlwsa() 00068 { 00069 #ifdef RLWIN32 00070 static int first = 1; 00071 WORD wVersionRequested; 00072 WSADATA wsadata; 00073 int err; 00074 00075 if(first == 1) 00076 { 00077 #ifdef IS_OLD_MSVCPP 00078 wVersionRequested = MAKEWORD(1,1); 00079 #else 00080 wVersionRequested = MAKEWORD(2,0); 00081 #endif 00082 err = WSAStartup(wVersionRequested, &wsadata); 00083 if(err != 0) 00084 { 00085 ::printf("Startup error=%d on windows\n",err); 00086 exit(0); 00087 } 00088 first = 0; 00089 } 00090 #endif 00091 return 0; 00092 } 00093 00094 rlSocket::rlSocket(const char *a, int p, int act) 00095 { 00096 rlwsa(); // init sockets on windows 00097 setAdr(a); 00098 port = p; 00099 active = act; 00100 s = -1; 00101 os = -1; 00102 first = 1; 00103 rl_ipversion = 4; 00104 memset(sockaddr,0,sizeof(sockaddr)); 00105 } 00106 00107 rlSocket::rlSocket(int socket) 00108 { 00109 adr[0] = '\0'; 00110 port = -1; 00111 active = 0; 00112 s = socket; 00113 os = -1; 00114 first = 0; 00115 rl_ipversion = 4; 00116 memset(sockaddr,0,sizeof(sockaddr)); 00117 } 00118 00119 rlSocket::~rlSocket() 00120 { 00121 disconnect(); 00122 if(os != -1 && active == 0) 00123 { 00124 #ifdef RLWIN32 00125 closesocket(os); 00126 #else 00127 close(os); 00128 #endif 00129 } 00130 } 00131 00132 void rlSocket::setAdr(const char *a) 00133 { 00134 adr[0] = '\0'; 00135 if(a == NULL) return; 00136 if((strlen(a)+1) > sizeof(adr)) return; 00137 strcpy(adr,a); 00138 } 00139 00140 void rlSocket::setPort(int p) 00141 { 00142 port = p; 00143 } 00144 00145 int rlSocket::getPort() 00146 { 00147 return port; 00148 } 00149 00150 void rlSocket::setActive(int act) 00151 { 00152 active = act; 00153 } 00154 00155 int rlSocket::read(void *buf, int len, int timeout) 00156 { 00157 int i,ret; 00158 char *cbuf; 00159 00160 if(s == -1) return -1; 00161 if(select(timeout) == 0) return 0; // timeout 00162 00163 cbuf = (char *) buf; 00164 i = 0; 00165 while(i < len) 00166 { 00167 ret = recv(s,&cbuf[i],len-i,0); 00168 if(ret <= 0) 00169 { 00170 disconnect(); 00171 return -1; 00172 } 00173 i += ret; 00174 if(i < len) 00175 { 00176 if(select(timeout) == 0) return 0; // timeout 00177 } 00178 } 00179 00180 return i; 00181 } 00182 00183 int rlSocket::readStr(char *buf, int len, int timeout) 00184 { 00185 int ret,i; 00186 00187 if(s == -1) return -1; 00188 if(select(timeout) == 0) return 0; // timeout 00189 00190 i = 0; 00191 while(1) 00192 { 00193 #ifdef RLWIN32 00194 tryagain: 00195 #endif 00196 ret = recv(s,&buf[i],1,0); 00197 if(ret <= 0) 00198 { 00199 #ifdef RLWIN32 00200 if(WSAEWOULDBLOCK == WSAGetLastError()) goto tryagain; 00201 #endif 00202 disconnect(); 00203 buf[i] = '\0'; 00204 return -1; 00205 } 00206 if(buf[i] == '\n') 00207 { 00208 buf[i+1] = '\0'; 00209 return i+1; 00210 } 00211 if(i >= len-1) 00212 { 00213 buf[i+1] = '\0'; 00214 return i+1; 00215 } 00216 i++; 00217 } 00218 } 00219 00220 int rlSocket::write(const void *buf, int len) 00221 { 00222 int ret,bytes_left,first_byte; 00223 const char *cbuf; 00224 00225 if(s == -1) return -1; 00226 cbuf = (char *) buf; 00227 bytes_left = len; 00228 first_byte = 0; 00229 00230 while(bytes_left > 0) 00231 { 00232 ret = send(s,&cbuf[first_byte],bytes_left,MSG_NOSIGNAL); 00233 if(ret <= 0) 00234 { 00235 disconnect(); 00236 return -1; 00237 } 00238 bytes_left -= ret; 00239 first_byte += ret; 00240 } 00241 00242 return first_byte; 00243 } 00244 00245 int rlSocket::connect() 00246 { 00247 int option; 00248 int ret; 00249 #ifdef __VMS 00250 size_t socklen = sizeof(struct sockaddr); 00251 #else 00252 socklen_t socklen = sizeof(struct sockaddr); 00253 #endif 00254 struct sockaddr_in localAddr; 00255 struct sockaddr_in remoteAddr; 00256 struct hostent *host; 00257 struct in_addr RemoteIpAddress; 00258 #ifdef AF_INET6_IS_AVAILABLE 00259 struct addrinfo hints0, hints1; 00260 struct addrinfo *res, *ressave; 00261 int n; 00262 char portstr[32]; 00263 #endif 00264 00265 if(port <= 0) return PORT_ERR; 00266 if(port >= 256*256) return PORT_ERR; 00267 if(active == 0) 00268 { // accept calls 00269 s = -1; 00270 if(rl_ipversion == 4) 00271 { 00272 if(first == 1) 00273 { 00274 // create a socket 00275 os = socket(AF_INET,SOCK_STREAM,0); 00276 if(os == -1) return SOCKET_ERR; 00277 // set socket options 00278 #ifdef __VMS 00279 option = 1; 00280 if(setsockopt(os,SOL_SOCKET,SO_KEEPALIVE,&option,sizeof(option)) < 0) 00281 { 00282 return SETSOCKOPT_ERR; 00283 } 00284 #endif 00285 option = 1; 00286 #ifdef RLWIN32 00287 setsockopt(os,SOL_SOCKET,SO_REUSEADDR,(const char *) &option,sizeof(option)); 00288 #else 00289 setsockopt(os,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option)); 00290 #endif 00291 // Bind our server to the agreed upon port number. 00292 memset(&localAddr,0,sizeof(localAddr)); 00293 localAddr.sin_port = htons((short) port); 00294 localAddr.sin_family = AF_INET; 00295 bind: 00296 ret = bind(os, (struct sockaddr *) &localAddr, sizeof(localAddr)); 00297 if(ret == -1) 00298 { 00299 rlwthread_sleep(1000); 00300 goto bind; 00301 } 00302 // Prepare to accept client connections. Allow up to 5 pending 00303 // connections. 00304 ret = listen(os, 5); 00305 if(ret == -1) return LISTEN_ERR; 00306 } 00307 first = 0; 00308 00309 // accept connections 00310 s = accept(os, (struct sockaddr *) &sockaddr[0], &socklen); 00311 if(s == -1) return ACCEPT_ERR; 00312 } 00313 else if(rl_ipversion == 6) 00314 { 00315 #ifdef AF_INET6_IS_AVAILABLE 00316 if(first == 1) 00317 { 00318 memset(&hints0,0,sizeof(hints0)); 00319 hints0.ai_flags = AI_PASSIVE; 00320 //hints0.ai_family = AF_UNSPEC; 00321 hints0.ai_family = AF_INET6; 00322 hints0.ai_socktype = SOCK_STREAM; 00323 sprintf(portstr,"%d",port); 00324 //::printf("server getaddrinfo(%s,%s)\n", adr, portstr); 00325 n = getaddrinfo(adr, portstr, &hints0, &res); 00326 if(n != 0) 00327 { 00328 #ifndef RLWIN32 00329 ::printf("rlSocket:tcp_listen error for %s port=%s : %s\n", adr, portstr, gai_strerror(n)); 00330 #endif 00331 return -1; 00332 } 00333 //::printf("done\n"); 00334 ressave = res; 00335 bindv6: 00336 do 00337 { 00338 os = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 00339 if(os < 0) continue; // error, try next one 00340 #ifdef __VMS 00341 option = 1; 00342 if(setsockopt(os,SOL_SOCKET,SO_KEEPALIVE,&option,sizeof(option)) < 0) 00343 { 00344 return SETSOCKOPT_ERR; 00345 } 00346 #endif 00347 option = 1; 00348 #ifdef RLWIN32 00349 setsockopt(os,SOL_SOCKET,SO_REUSEADDR,(const char *) &option,sizeof(option)); 00350 #else 00351 setsockopt(os,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option)); 00352 #endif 00353 if(bind(os, res->ai_addr, res->ai_addrlen) == 0) break; // success 00354 s = os; 00355 disconnect(); // bind error, close and try next one 00356 } 00357 while((res = res->ai_next) != NULL); 00358 if(res == NULL) // errno from final socket() or bind() 00359 { 00360 ::printf("warning: could not bind to port=%d\n", port); 00361 rlwthread_sleep(1000); 00362 goto bindv6; 00363 } 00364 // Prepare to accept client connections. Allow up to 5 pending 00365 // connections 00366 ret = listen(os, 5); 00367 freeaddrinfo(ressave); 00368 if(ret == -1) return LISTEN_ERR; 00369 } 00370 first = 0; 00371 // accept connections 00372 s = accept(os, (struct sockaddr *) &sockaddr[0], &socklen); 00373 if(s == -1) return ACCEPT_ERR; 00374 #else 00375 ::printf("rlSocket:ERROR IPV6 not available on this platform\n"); 00376 #endif 00377 } 00378 else 00379 { 00380 ::printf("rlSocket:ERROR: rl_ipversion=%d not known\n", rl_ipversion); 00381 } 00382 } // end active == 0 00383 else if(active == 1) 00384 { 00385 disconnect(); 00386 //::printf("debug: adr=%s port=%d\n",adr,port); 00387 s = -1; 00388 if(rl_ipversion == 4) 00389 { 00390 os = socket(AF_INET,SOCK_STREAM,0); 00391 if(os == -1) return SOCKET_ERR; 00392 s = os; 00393 00394 //::printf("debug: gethostbyname\n"); 00395 // fill destblk structure 00396 host = gethostbyname(adr); 00397 if(host == NULL) 00398 { 00399 // See if the host is specified in "dot address" form 00400 RemoteIpAddress.s_addr = inet_addr(adr); 00401 if(RemoteIpAddress.s_addr == INADDR_NONE) 00402 { 00403 s = -1; 00404 return INET_ADDR_ERR; // -1 00405 } 00406 } 00407 else 00408 { 00409 memcpy(&RemoteIpAddress,host->h_addr,host->h_length); 00410 } 00411 00412 memset(&remoteAddr,0,sizeof(remoteAddr)); 00413 remoteAddr.sin_family = AF_INET; 00414 remoteAddr.sin_port = htons((short) port); 00415 remoteAddr.sin_addr = RemoteIpAddress; 00416 00417 //::printf("debug: connect\n"); 00418 ret = ::connect(s, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr)); 00419 //::printf("debug: connect ret=%d\n",ret); 00420 if(ret == -1) 00421 { 00422 s = -1; 00423 return CONNECT_ERR; 00424 } 00425 } 00426 else if(rl_ipversion == 6) 00427 { 00428 #ifdef AF_INET6_IS_AVAILABLE 00429 sprintf(portstr,"%d",port); 00430 memset(&hints1, 0, sizeof(hints1)); 00431 hints1.ai_family = AF_UNSPEC; 00432 hints1.ai_socktype = SOCK_STREAM; 00433 n = getaddrinfo(adr, portstr, &hints1, &res); 00434 if(n != 0) 00435 { 00436 #ifndef RLWIN32 00437 ::printf("rlSocket:tcp_connect error for %s port=%s : %s\n", adr, portstr, gai_strerror(n)); 00438 #endif 00439 return -1; 00440 } 00441 ressave = res; 00442 do 00443 { 00444 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 00445 if(s < 0) continue; // ignore this one 00446 if(::connect(s, res->ai_addr, res->ai_addrlen) == 0) break; // success 00447 disconnect(); // ignore this one 00448 } 00449 while((res = res->ai_next) != NULL); 00450 if(res == NULL) ::printf("rlSocket:tcp_connect error for %s port=%s\n", adr, portstr); 00451 freeaddrinfo(ressave); 00452 #else 00453 ::printf("rlSocket:ERROR IPV6 not available on this platform\n"); 00454 #endif 00455 } 00456 else 00457 { 00458 ::printf("rlSocket:ERROR: rl_ipversion=%d not known\n", rl_ipversion); 00459 } 00460 } 00461 return s; 00462 } 00463 00464 int rlSocket::disconnect() 00465 { 00466 if(s != -1) 00467 { 00468 #ifdef RLWIN32 00469 closesocket(s); 00470 #else 00471 close(s); 00472 #endif 00473 } 00474 s = -1; 00475 return 0; 00476 } 00477 00478 int rlSocket::isConnected() 00479 { 00480 if(s == -1) return 0; 00481 return 1; 00482 } 00483 00484 int rlSocket::select(int timeout) 00485 { 00486 struct timeval timout; 00487 fd_set wset,rset,eset; 00488 int ret,maxfdp1; 00489 00490 if(timeout == 0) return 1; 00491 /* setup sockets to read */ 00492 maxfdp1 = s+1; 00493 FD_ZERO(&rset); 00494 FD_SET (s,&rset); 00495 FD_ZERO(&wset); 00496 FD_ZERO(&eset); 00497 timout.tv_sec = timeout / 1000; 00498 timout.tv_usec = (timeout % 1000) * 1000; 00499 00500 ret = ::select(maxfdp1,&rset,&wset,&eset,&timout); 00501 if(ret == 0) return 0; /* timeout */ 00502 return 1; 00503 } 00504 00505 int rlSocket::printf(const char *format, ...) 00506 { 00507 int ret; 00508 char message[rl_PRINTF_LENGTH]; // should be big enough 00509 00510 va_list ap; 00511 va_start(ap,format); 00512 ret = rlvsnprintf(message, rl_PRINTF_LENGTH - 1, format, ap); 00513 va_end(ap); 00514 if(ret < 0) return ret; 00515 return write(message,strlen(message)); 00516 } 00517 00518 int rlSocket::sendProcessViewBrowserButtonEvent(int id) 00519 { 00520 return printf("QPushButton(%d)\n",id); 00521 } 00522 00523 int rlSocket::setIPVersion(int version) 00524 { 00525 if(version == 6) rl_ipversion = 6; 00526 else rl_ipversion = 4; 00527 return rl_ipversion; 00528 } 00529 00530 int rlSocket::getIPVersion() 00531 { 00532 return rl_ipversion; 00533 } 00534
1.7.5.1