static void mylock(pthread_mutex_t *mutex, int increment) { volatile int *cnt = (int *) mutex; while(1) { retry: if(*cnt == 0) { // try to lock the counter (*cnt) += increment; if(*cnt > 1) { (*cnt) -= increment; goto retry; // another process also wanted to lock the counter } return; // now we can do it } rlwthread_sleep(1); } }
int rlSocket::connect() { int option; int ret; #ifdef __VMS size_t socklen = sizeof(struct sockaddr); #else socklen_t socklen = sizeof(struct sockaddr); #endif struct sockaddr_in localAddr; struct sockaddr_in remoteAddr; struct hostent *host; struct in_addr RemoteIpAddress; #ifdef AF_INET6_IS_AVAILABLE struct addrinfo hints0, hints1; struct addrinfo *res, *ressave; int n; char portstr[32]; #endif if(port <= 0) return PORT_ERR; if(port >= 256*256) return PORT_ERR; if(active == 0) { // accept calls s = -1; if(rl_ipversion == 4) { if(first == 1) { // create a socket os = socket(AF_INET,SOCK_STREAM,0); if(os == -1) return SOCKET_ERR; // set socket options #ifdef __VMS option = 1; if(setsockopt(os,SOL_SOCKET,SO_KEEPALIVE,&option,sizeof(option)) < 0) { return SETSOCKOPT_ERR; } #endif option = 1; #ifdef RLWIN32 setsockopt(os,SOL_SOCKET,SO_REUSEADDR,(const char *) &option,sizeof(option)); #else setsockopt(os,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option)); #endif // Bind our server to the agreed upon port number. memset(&localAddr,0,sizeof(localAddr)); localAddr.sin_port = htons((short) port); localAddr.sin_family = AF_INET; bind: ret = bind(os, (struct sockaddr *) &localAddr, sizeof(localAddr)); if(ret == -1) { rlwthread_sleep(1000); goto bind; } // Prepare to accept client connections. Allow up to 5 pending // connections. ret = listen(os, 5); if(ret == -1) return LISTEN_ERR; } first = 0; // accept connections s = accept(os, (struct sockaddr *) &sockaddr[0], &socklen); if(s == -1) return ACCEPT_ERR; } else if(rl_ipversion == 6) { #ifdef AF_INET6_IS_AVAILABLE if(first == 1) { memset(&hints0,0,sizeof(hints0)); hints0.ai_flags = AI_PASSIVE; //hints0.ai_family = AF_UNSPEC; hints0.ai_family = AF_INET6; hints0.ai_socktype = SOCK_STREAM; sprintf(portstr,"%d",port); //::printf("server getaddrinfo(%s,%s)\n", adr, portstr); n = getaddrinfo(adr, portstr, &hints0, &res); if(n != 0) { #ifndef RLWIN32 ::printf("rlSocket:tcp_listen error for %s port=%s : %s\n", adr, portstr, gai_strerror(n)); #endif return -1; } //::printf("done\n"); ressave = res; bindv6: do { os = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if(os < 0) continue; // error, try next one #ifdef __VMS option = 1; if(setsockopt(os,SOL_SOCKET,SO_KEEPALIVE,&option,sizeof(option)) < 0) { return SETSOCKOPT_ERR; } #endif option = 1; #ifdef RLWIN32 setsockopt(os,SOL_SOCKET,SO_REUSEADDR,(const char *) &option,sizeof(option)); #else setsockopt(os,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option)); #endif if(bind(os, res->ai_addr, res->ai_addrlen) == 0) break; // success s = os; disconnect(); // bind error, close and try next one } while((res = res->ai_next) != NULL); if(res == NULL) // errno from final socket() or bind() { ::printf("warning: could not bind to port=%d\n", port); rlwthread_sleep(1000); goto bindv6; } // Prepare to accept client connections. Allow up to 5 pending // connections ret = listen(os, 5); freeaddrinfo(ressave); if(ret == -1) return LISTEN_ERR; } first = 0; // accept connections s = accept(os, (struct sockaddr *) &sockaddr[0], &socklen); if(s == -1) return ACCEPT_ERR; #else ::printf("rlSocket:ERROR IPV6 not available on this platform\n"); #endif } else { ::printf("rlSocket:ERROR: rl_ipversion=%d not known\n", rl_ipversion); } } // end active == 0 else if(active == 1) { disconnect(); //::printf("debug: adr=%s port=%d\n",adr,port); s = -1; if(rl_ipversion == 4) { os = socket(AF_INET,SOCK_STREAM,0); if(os == -1) return SOCKET_ERR; s = os; //::printf("debug: gethostbyname\n"); // fill destblk structure host = gethostbyname(adr); if(host == NULL) { // See if the host is specified in "dot address" form RemoteIpAddress.s_addr = inet_addr(adr); if(RemoteIpAddress.s_addr == INADDR_NONE) { s = -1; return INET_ADDR_ERR; // -1 } } else { memcpy(&RemoteIpAddress,host->h_addr,host->h_length); } memset(&remoteAddr,0,sizeof(remoteAddr)); remoteAddr.sin_family = AF_INET; remoteAddr.sin_port = htons((short) port); remoteAddr.sin_addr = RemoteIpAddress; //::printf("debug: connect\n"); ret = ::connect(s, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr)); //::printf("debug: connect ret=%d\n",ret); if(ret == -1) { disconnect(); // close s = os return CONNECT_ERR; } } else if(rl_ipversion == 6) { #ifdef AF_INET6_IS_AVAILABLE sprintf(portstr,"%d",port); memset(&hints1, 0, sizeof(hints1)); hints1.ai_family = AF_UNSPEC; hints1.ai_socktype = SOCK_STREAM; n = getaddrinfo(adr, portstr, &hints1, &res); if(n != 0) { #ifndef RLWIN32 ::printf("rlSocket:tcp_connect error for %s port=%s : %s\n", adr, portstr, gai_strerror(n)); #endif return -1; } ressave = res; do { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if(s < 0) continue; // ignore this one if(::connect(s, res->ai_addr, res->ai_addrlen) == 0) break; // success disconnect(); // ignore this one } while((res = res->ai_next) != NULL); if(res == NULL) ::printf("rlSocket:tcp_connect error for %s port=%s\n", adr, portstr); freeaddrinfo(ressave); #else ::printf("rlSocket:ERROR IPV6 not available on this platform\n"); #endif } else { ::printf("rlSocket:ERROR: rl_ipversion=%d not known\n", rl_ipversion); } } return s; }